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 001/383] 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 002/383] 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 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 003/383] 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 004/383] 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 005/383] 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 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 006/383] 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 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 007/383] 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 88d419c03fa3badc9a46029086c6a7476b23575a Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Sun, 14 Jun 2026 10:06:17 +0000 Subject: [PATCH 008/383] Revert "Send SVG images as files (#4595)" --- .../io/element/android/libraries/core/mimetype/MimeTypes.kt | 1 - .../libraries/mediaupload/impl/AndroidMediaPreProcessor.kt | 6 +----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/libraries/core/src/main/kotlin/io/element/android/libraries/core/mimetype/MimeTypes.kt b/libraries/core/src/main/kotlin/io/element/android/libraries/core/mimetype/MimeTypes.kt index e7962f8bd6..73c05ffcef 100644 --- a/libraries/core/src/main/kotlin/io/element/android/libraries/core/mimetype/MimeTypes.kt +++ b/libraries/core/src/main/kotlin/io/element/android/libraries/core/mimetype/MimeTypes.kt @@ -26,7 +26,6 @@ object MimeTypes { const val Jpeg = "image/jpeg" const val Gif = "image/gif" const val WebP = "image/webp" - const val Svg = "image/svg+xml" const val Videos = "video/*" const val Mp4 = "video/mp4" 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 2ab1cd0619..8c5bab459f 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 @@ -67,7 +67,7 @@ class AndroidMediaPreProcessor( */ private const val IMAGE_SCALE_REF_SIZE = 640 - private val notCompressibleImageTypes = listOf(MimeTypes.Gif, MimeTypes.WebP, MimeTypes.Svg) + private val notCompressibleImageTypes = listOf(MimeTypes.Gif, MimeTypes.WebP) } private val contentResolver = context.contentResolver @@ -83,10 +83,6 @@ class AndroidMediaPreProcessor( ): Result = withContext(coroutineDispatchers.computation) { runCatchingExceptions { val result = when { - // Special case for SVG, since Android can't read its metadata or create a thumbnail, it must be sent as a file - mimeType == MimeTypes.Svg -> { - processFile(uri, mimeType) - } mimeType.isMimeTypeImage() -> { val shouldBeCompressed = mediaOptimizationConfig.compressImages && mimeType !in notCompressibleImageTypes processImage(uri, mimeType, shouldBeCompressed) From 5b53686c3e1ab23d04f71ce721b32a97e017e754 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Sun, 14 Jun 2026 10:06:17 +0000 Subject: [PATCH 009/383] Add full SVG support --- gradle/libs.versions.toml | 1 + .../libraries/core/mimetype/MimeTypes.kt | 1 + .../matrix/api/exception/ClientException.kt | 3 + .../matrix/impl/media/RustMediaLoader.kt | 6 +- libraries/matrixmedia/impl/build.gradle.kts | 1 + .../matrix/ui/media/CoilMediaFetcher.kt | 19 ++++- .../matrix/ui/media/ImageLoaderFactories.kt | 4 + .../impl/AndroidMediaPreProcessor.kt | 82 ++++++++++++++++++- .../impl/src/test/assets/image.svg | 3 + .../impl/AndroidMediaPreProcessorTest.kt | 48 +++++++++++ .../libraries/mediaupload/impl/Asset.kt | 11 +++ 11 files changed, 173 insertions(+), 6 deletions(-) create mode 100644 libraries/mediaupload/impl/src/test/assets/image.svg diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 163a583597..2cdda307c2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -190,6 +190,7 @@ coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } coil_network_okhttp = { module = "io.coil-kt.coil3:coil-network-okhttp", version.ref = "coil" } coil_compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" } coil_gif = { module = "io.coil-kt.coil3:coil-gif", version.ref = "coil" } +coil_svg = { module = "io.coil-kt.coil3:coil-svg", version.ref = "coil" } coil_test = { module = "io.coil-kt.coil3:coil-test", version.ref = "coil" } datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "datetime" } serialization_json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization_json" } diff --git a/libraries/core/src/main/kotlin/io/element/android/libraries/core/mimetype/MimeTypes.kt b/libraries/core/src/main/kotlin/io/element/android/libraries/core/mimetype/MimeTypes.kt index 73c05ffcef..e7962f8bd6 100644 --- a/libraries/core/src/main/kotlin/io/element/android/libraries/core/mimetype/MimeTypes.kt +++ b/libraries/core/src/main/kotlin/io/element/android/libraries/core/mimetype/MimeTypes.kt @@ -26,6 +26,7 @@ object MimeTypes { const val Jpeg = "image/jpeg" const val Gif = "image/gif" const val WebP = "image/webp" + const val Svg = "image/svg+xml" const val Videos = "video/*" const val Mp4 = "video/mp4" diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/exception/ClientException.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/exception/ClientException.kt index 565dc59614..3a1f0825f4 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/exception/ClientException.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/exception/ClientException.kt @@ -22,3 +22,6 @@ sealed class ClientException(message: String, val details: String?, cause: Throw fun ClientException.isNetworkError(): Boolean { return this is ClientException.Generic && message?.contains("error sending request for url", ignoreCase = true) == true } + +fun Throwable.isNetworkError(): Boolean = + (this as? ClientException)?.isNetworkError() == true diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/media/RustMediaLoader.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/media/RustMediaLoader.kt index 81946980e3..d1401d2624 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/media/RustMediaLoader.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/media/RustMediaLoader.kt @@ -9,11 +9,13 @@ package io.element.android.libraries.matrix.impl.media import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.core.extensions.mapFailure import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.core.mimetype.MimeTypes 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.impl.exception.mapClientException import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.Client import org.matrix.rustcomponents.sdk.use @@ -37,7 +39,7 @@ class RustMediaLoader( source.toRustMediaSource().use { source -> innerClient.getMediaContent(source) } - } + }.mapFailure { it.mapClientException() } } override suspend fun loadMediaThumbnail( @@ -54,7 +56,7 @@ class RustMediaLoader( height = height.toULong() ) } - } + }.mapFailure { it.mapClientException() } } override suspend fun downloadMediaFile( diff --git a/libraries/matrixmedia/impl/build.gradle.kts b/libraries/matrixmedia/impl/build.gradle.kts index 56ccc79afc..62799b5eaa 100644 --- a/libraries/matrixmedia/impl/build.gradle.kts +++ b/libraries/matrixmedia/impl/build.gradle.kts @@ -26,6 +26,7 @@ dependencies { implementation(projects.libraries.designsystem) implementation(libs.coil.compose) implementation(libs.coil.gif) + implementation(libs.coil.svg) implementation(libs.coil.network.okhttp) testCommonDependencies(libs, true) diff --git a/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt b/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt index 39f67b41d7..b1f72976e0 100644 --- a/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt +++ b/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt @@ -13,6 +13,7 @@ import coil3.decode.ImageSource import coil3.fetch.FetchResult import coil3.fetch.Fetcher import coil3.fetch.SourceFetchResult +import io.element.android.libraries.matrix.api.exception.isNetworkError import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.media.toFile @@ -34,7 +35,19 @@ internal class CoilMediaFetcher( } return when (val kind = mediaData.kind) { is MediaRequestData.Kind.Content -> fetchContent(mediaSource) - is MediaRequestData.Kind.Thumbnail -> fetchThumbnail(mediaSource, kind) + is MediaRequestData.Kind.Thumbnail -> { + val thumbnailResult = fetchThumbnail(mediaSource, kind) + if (thumbnailResult.isSuccess) { + thumbnailResult.getOrThrow() + } else { + val error = thumbnailResult.exceptionOrNull() + if (error?.isNetworkError() == true) { + null + } else { + fetchContent(mediaSource) + } + } + } is MediaRequestData.Kind.File -> fetchFile(mediaSource, kind) } } @@ -74,7 +87,7 @@ internal class CoilMediaFetcher( }.getOrNull() } - private suspend fun fetchThumbnail(mediaSource: MediaSource, kind: MediaRequestData.Kind.Thumbnail): FetchResult? { + private suspend fun fetchThumbnail(mediaSource: MediaSource, kind: MediaRequestData.Kind.Thumbnail): Result { return mediaLoader.loadMediaThumbnail( source = mediaSource, width = kind.width, @@ -83,7 +96,7 @@ internal class CoilMediaFetcher( byteArray.asSourceResult() }.onFailure { Timber.e(it) - }.getOrNull() + } } private fun ByteArray.asSourceResult(): SourceFetchResult { 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 ef654a4cf7..c74a819ecd 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 @@ -14,6 +14,7 @@ import coil3.ImageLoader import coil3.gif.AnimatedImageDecoder import coil3.gif.GifDecoder import coil3.network.okhttp.OkHttpNetworkFetcherFactory +import coil3.svg.SvgDecoder import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import io.element.android.libraries.di.annotations.ApplicationContext @@ -41,6 +42,7 @@ class DefaultImageLoaderFactory( return ImageLoader.Builder(context) .components { add(okHttpNetworkFetcherFactory) + add(SvgDecoder.Factory()) } .build() } @@ -49,6 +51,8 @@ class DefaultImageLoaderFactory( return ImageLoader.Builder(context) .components { add(okHttpNetworkFetcherFactory) + // Add svg support + add(SvgDecoder.Factory()) // Add gif support if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { add(AnimatedImageDecoder.Factory()) 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 8c5bab459f..11e5e7e65e 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 @@ -12,6 +12,7 @@ import android.content.Context import android.graphics.BitmapFactory import android.media.MediaMetadataRetriever import android.net.Uri +import android.util.Xml import androidx.exifinterface.media.ExifInterface import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding @@ -42,6 +43,7 @@ import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.withContext +import org.xmlpull.v1.XmlPullParser import timber.log.Timber import java.io.File import java.io.InputStream @@ -67,7 +69,10 @@ class AndroidMediaPreProcessor( */ private const val IMAGE_SCALE_REF_SIZE = 640 - private val notCompressibleImageTypes = listOf(MimeTypes.Gif, MimeTypes.WebP) + private const val SVG_DEFAULT_WIDTH = 640L + private const val SVG_DEFAULT_HEIGHT = 480L + + private val notCompressibleImageTypes = listOf(MimeTypes.Gif, MimeTypes.WebP, MimeTypes.Svg) } private val contentResolver = context.contentResolver @@ -156,6 +161,11 @@ class AndroidMediaPreProcessor( private suspend fun processImage(uri: Uri, mimeType: String, shouldBeCompressed: Boolean): MediaUploadInfo { Timber.d("Processing image ${uri.path.orEmpty().hash()}") + + if (mimeType == MimeTypes.Svg) { + return processSvgImage(uri, mimeType) + } + suspend fun processImageWithCompression(): MediaUploadInfo { // Read the orientation metadata from its own stream. Trying to reuse this stream for compression will fail. val orientation = contentResolver.openInputStream(uri).use { input -> @@ -216,6 +226,76 @@ class AndroidMediaPreProcessor( } } + private suspend fun processSvgImage(uri: Uri, mimeType: String): MediaUploadInfo { + Timber.d("Processing SVG image ${uri.path.orEmpty().hash()}") + val file = copyToTmpFile(uri) + val (width, height) = extractSvgDimensions(file) + val imageInfo = ImageInfo( + width = width, + height = height, + mimetype = mimeType, + size = file.length(), + thumbnailInfo = null, + thumbnailSource = null, + blurhash = null, + ) + return MediaUploadInfo.Image( + file = file, + imageInfo = imageInfo, + thumbnailFile = null, + ) + } + + private fun extractSvgDimensions(file: File): Pair { + return file.inputStream().use { inputStream -> + try { + val parser = Xml.newPullParser() + parser.setInput(inputStream, null) + var eventType = parser.eventType + while (eventType != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.START_TAG && parser.name.equals("svg", ignoreCase = true)) { + val width = parser.getAttributeValue(null, "width") + val height = parser.getAttributeValue(null, "height") + val viewBox = parser.getAttributeValue(null, "viewBox") + + val parsedWidth = width?.let { parseSvgLength(it) } + val parsedHeight = height?.let { parseSvgLength(it) } + + if (parsedWidth != null && parsedHeight != null) { + return parsedWidth to parsedHeight + } + + if (viewBox != null) { + val parts = viewBox.trim().split("\\s+".toRegex()).map { it.toFloatOrNull() } + if (parts.size == 4 && parts[2] != null && parts[3] != null) { + val vbWidth = parts[2]!!.toLong().coerceAtLeast(1) + val vbHeight = parts[3]!!.toLong().coerceAtLeast(1) + return vbWidth to vbHeight + } + } + + return (parsedWidth ?: SVG_DEFAULT_WIDTH) to (parsedHeight ?: SVG_DEFAULT_HEIGHT) + } + eventType = parser.next() + } + SVG_DEFAULT_WIDTH to SVG_DEFAULT_HEIGHT + } catch (_: Exception) { + SVG_DEFAULT_WIDTH to SVG_DEFAULT_HEIGHT + } + } + } + + private fun parseSvgLength(value: String): Long? { + val trimmed = value.trim() + if (trimmed.isEmpty()) return null + return try { + val numericPart = trimmed.replace(Regex("[^\\d.]"), "") + if (numericPart.isEmpty()) null else numericPart.toFloat().toLong().coerceAtLeast(1) + } catch (_: NumberFormatException) { + null + } + } + private suspend fun processVideo(uri: Uri, mimeType: String?, videoCompressionPreset: VideoCompressionPreset): MediaUploadInfo { Timber.d("Processing video ${uri.path.orEmpty().hash()}") val resultFile = runCatchingExceptions { diff --git a/libraries/mediaupload/impl/src/test/assets/image.svg b/libraries/mediaupload/impl/src/test/assets/image.svg new file mode 100644 index 0000000000..03a3fb275b --- /dev/null +++ b/libraries/mediaupload/impl/src/test/assets/image.svg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:97a22915f50ba62605a8e3f6ba8e8099c1d601d2aa929c2879197b41531ce4dc +size 210 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 57726ac5a2..cf82f4f7ae 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 @@ -401,6 +401,54 @@ class AndroidMediaPreProcessorTest { ) } + @Test + fun `test processing svg`() = runTest { + val mediaUploadInfo = process( + asset = assetImageSvg, + mediaOptimizationConfig = MediaOptimizationConfig( + compressImages = true, + videoCompressionPreset = VideoCompressionPreset.STANDARD, + ), + ) + val info = mediaUploadInfo as MediaUploadInfo.Image + assertThat(info.imageInfo).isEqualTo( + ImageInfo( + width = 800, + height = 600, + mimetype = MimeTypes.Svg, + size = 210, + thumbnailInfo = null, + thumbnailSource = null, + blurhash = null, + ) + ) + assertThat(info.thumbnailFile).isNull() + } + + @Test + fun `test processing svg without compression`() = runTest { + val mediaUploadInfo = process( + asset = assetImageSvg, + mediaOptimizationConfig = MediaOptimizationConfig( + compressImages = false, + videoCompressionPreset = VideoCompressionPreset.STANDARD, + ), + ) + val info = mediaUploadInfo as MediaUploadInfo.Image + assertThat(info.imageInfo).isEqualTo( + ImageInfo( + width = 800, + height = 600, + mimetype = MimeTypes.Svg, + size = 210, + thumbnailInfo = null, + thumbnailSource = null, + blurhash = null, + ) + ) + assertThat(info.thumbnailFile).isNull() + } + @Test fun `test processing audio`() = runTest { val mediaUploadInfo = process( diff --git a/libraries/mediaupload/impl/src/test/kotlin/io/element/android/libraries/mediaupload/impl/Asset.kt b/libraries/mediaupload/impl/src/test/kotlin/io/element/android/libraries/mediaupload/impl/Asset.kt index 4dad31a784..7b70244852 100644 --- a/libraries/mediaupload/impl/src/test/kotlin/io/element/android/libraries/mediaupload/impl/Asset.kt +++ b/libraries/mediaupload/impl/src/test/kotlin/io/element/android/libraries/mediaupload/impl/Asset.kt @@ -83,3 +83,14 @@ val assetAnimatedGif = Asset( width = 800, height = 600, ) + +/** + * "image.svg" is an 800 x 600 SVG image with a size of 210 bytes. + */ +val assetImageSvg = Asset( + filename = "image.svg", + mimeType = MimeTypes.Svg, + size = 210, + width = 800, + height = 600, +) From ddd72ec526fffa36aa9a1eec36c95beacbbf1078 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 18 Jun 2026 12:16:31 +0200 Subject: [PATCH 010/383] feat(call): Active call timeline rendering --- .../features/messages/impl/MessagesView.kt | 3 + .../pinned/list/PinnedMessagesListView.kt | 1 + .../messages/impl/timeline/TimelineView.kt | 3 + .../TimelineViewMessageShieldPreview.kt | 1 + .../components/ActiveCallTimelineItemView.kt | 373 ++++++++++++++++++ .../components/TimelineItemCallNotifyView.kt | 12 +- .../TimelineItemGroupedEventsRow.kt | 1 + .../timeline/components/TimelineItemRow.kt | 31 +- .../event/TimelineItemContentFactory.kt | 26 +- .../event/TimelineItemEventFactory.kt | 2 +- .../TimelineItemRtcNotificationContent.kt | 20 +- .../DefaultMessageSummaryFormatter.kt | 3 +- .../components/avatar/AvatarSize.kt | 3 +- .../api/timeline/item/event/EventContent.kt | 5 +- .../item/event/TimelineEventContentMapper.kt | 5 +- .../src/main/res/values/localazy.xml | 7 + 16 files changed, 471 insertions(+), 25 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt 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 b299ea42a9..781ef932fe 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 @@ -283,6 +283,7 @@ fun MessagesView( onSwipeToReply = { targetEvent -> state.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Reply, targetEvent)) }, + onJoinCallClick = onJoinCallClick, forceJumpToBottomVisibility = forceJumpToBottomVisibility, onViewAllPinnedMessagesClick = onViewAllPinnedMessagesClick, knockRequestsBannerView = knockRequestsBannerView, @@ -462,6 +463,7 @@ private fun MessagesViewContent( onSendLocationClick: () -> Unit, onCreatePollClick: () -> Unit, onViewAllPinnedMessagesClick: () -> Unit, + onJoinCallClick: (isAudioCall: Boolean) -> Unit, forceJumpToBottomVisibility: Boolean, onSwipeToReply: (TimelineItem.Event) -> Unit, modifier: Modifier = Modifier, @@ -516,6 +518,7 @@ private fun MessagesViewContent( onReactionLongClick = onReactionLongClick, onMoreReactionsClick = onMoreReactionsClick, onReadReceiptClick = onReadReceiptClick, + onJoinCallClick = onJoinCallClick, forceJumpToBottomVisibility = forceJumpToBottomVisibility, 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 bfed13028b..a0767ad990 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 @@ -234,6 +234,7 @@ 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 0a306aea1c..66a3fbaf9e 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 @@ -103,6 +103,7 @@ 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, @@ -185,6 +186,7 @@ fun TimelineView( onMoreReactionsClick = onMoreReactionsClick, onReadReceiptClick = onReadReceiptClick, onSwipeToReply = onSwipeToReply, + onJoinCallClick = onJoinCallClick, eventSink = state.eventSink, ) } @@ -426,6 +428,7 @@ internal fun TimelineViewPreview( onSwipeToReply = {}, onReactionClick = { _, _ -> }, onReactionLongClick = { _, _ -> }, + onJoinCallClick = {}, onMoreReactionsClick = {}, onReadReceiptClick = {}, 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 f0a11081e1..5f9c3d0364 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,6 +49,7 @@ 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/ActiveCallTimelineItemView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt new file mode 100644 index 0000000000..8a5fc925d2 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt @@ -0,0 +1,373 @@ +/* + * 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 + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.Row +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.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableLongStateOf +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.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.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 +import io.element.android.libraries.dateformatter.api.toHumanReadableDuration +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.AvatarRow +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +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.PreviewWithLargeHeight +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_CAROL +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_JOHN_DOE +import io.element.android.libraries.designsystem.theme.components.Button +import io.element.android.libraries.designsystem.theme.components.ButtonSize +import io.element.android.libraries.designsystem.utils.CommonDrawables +import io.element.android.libraries.matrix.api.notification.CallIntent +import io.element.android.libraries.matrix.ui.components.aMatrixUser +import io.element.android.libraries.ui.strings.CommonPlurals +import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.delay +import kotlin.time.Duration.Companion.seconds + +@Composable +internal fun ActiveCallTimelineItemView( + timelineRoomInfo: TimelineRoomInfo, + event: TimelineItem.Event, + state: RtcNotificationState.Active, + isLastOutgoingMessage: Boolean, + onLongClick: (TimelineItem.Event) -> Unit, + onReadReceiptsClick: (TimelineItem.Event) -> Unit, + onJoinCallClick: (isAudioCall: Boolean) -> Unit, + modifier: Modifier = Modifier +) { + var currentTime by remember { mutableLongStateOf(System.currentTimeMillis()) } + + LaunchedEffect(Unit) { + while (true) { + delay(1.seconds) + currentTime = System.currentTimeMillis() + } + } + + val elapsedMillis = (currentTime - state.callStartTsMillis).coerceAtLeast(0) + val formattedDuration = elapsedMillis.toHumanReadableDuration() + + Column(modifier = modifier) { + Row( + modifier = Modifier + .fillMaxWidth() + .height(IntrinsicSize.Min) + .padding(start = 16.dp, end = 16.dp, top = 16.dp) + .border(1.dp, ElementTheme.colors.borderInteractivePrimary, RoundedCornerShape(8.dp)) + .combinedClickable( + enabled = true, + onClick = {}, + onLongClick = { onLongClick(event) }, + onLongClickLabel = stringResource(CommonStrings.action_open_context_menu), + ) + .onKeyboardContextMenuAction { onLongClick(event) } + .padding(start = 12.dp, end = 12.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + modifier = Modifier + .padding(top = 12.dp, bottom = 12.dp) + .size(40.dp) + .background(ElementTheme.colors.bgSubtleSecondary, RoundedCornerShape(8.dp)) + .padding(10.dp), + imageVector = if (state.callIntent == CallIntent.AUDIO) CompoundIcons.VoiceCallSolid() else CompoundIcons.VideoCallSolid(), + contentDescription = null, + tint = ElementTheme.colors.iconPrimary, + ) + + if (timelineRoomInfo.isDm) { + DirectMessageCallBody(state, Modifier.weight(1f)) + } else { + GroupCallBody( + event, + state, + Modifier.weight(1f) + .padding(top = 12.dp, bottom = 12.dp) + ) + } + + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.padding(top = 12.dp, bottom = 12.dp) + ) { + if (!state.isJoined) { + Button( + text = "Join", + size = ButtonSize.Small, + onClick = { onJoinCallClick(state.callIntent == CallIntent.AUDIO) } + ) + } + Text( + text = "($formattedDuration)", + style = ElementTheme.typography.fontBodyXsRegular, + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + } + + TimelineItemReadReceiptView( + state = ReadReceiptViewState( + sendState = event.localSendState, + isLastOutgoingMessage = isLastOutgoingMessage, + receipts = event.readReceiptState.receipts, + ), + onReadReceiptsClick = { onReadReceiptsClick(event) }, + modifier = Modifier.padding(top = 4.dp), + ) + } +} + +@Composable +private fun DirectMessageCallBody(state: RtcNotificationState.Active, modifier: Modifier) { + Row( + verticalAlignment = Alignment.Top, + modifier = modifier + ) { + if (state.joinedMembers.size == 1) { + val caller = state.joinedMembers.first() + Avatar( + avatarData = AvatarData( + id = caller.userId.value, + name = caller.displayName, + url = caller.avatarUrl, + size = AvatarSize.ActiveCallItem, + ), + avatarType = AvatarType.User + ) + Text( + modifier = Modifier.padding(start = 6.dp), + text = "${caller.displayName ?: caller.userId} started a call", + style = ElementTheme.typography.fontBodyMdMedium, + color = ElementTheme.colors.textPrimary, + ) + } else { + AvatarRow( + avatarDataList = state.joinedMembers + .map { user -> + AvatarData( + id = user.userId.value, + name = user.displayName, + url = user.avatarUrl, + size = AvatarSize.ActiveCallItem + ) + }.toImmutableList(), + avatarType = AvatarType.User, + overlapRatio = 0.5f, + lastOnTop = true, + ) + Text( + modifier = Modifier.padding(start = 6.dp), + text = stringResource(CommonStrings.common_call_in_progress), + style = ElementTheme.typography.fontBodyMdMedium, + color = ElementTheme.colors.textPrimary, + ) + } + } +} + +@Composable +private fun GroupCallBody(event: TimelineItem.Event, state: RtcNotificationState.Active, modifier: Modifier) { + Column(modifier = modifier) { + Text( + text = stringResource(CommonStrings.common_group_call_in_progress), + style = ElementTheme.typography.fontBodyMdMedium, + color = ElementTheme.colors.textPrimary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + Row( + verticalAlignment = Alignment.CenterVertically + ) { + if (state.joinedMembers.size == 1) { + val caller = state.joinedMembers.first() + Avatar( + avatarData = AvatarData( + id = caller.userId.value, + name = caller.displayName, + url = caller.avatarUrl, + size = AvatarSize.ActiveCallItem, + ), + avatarType = AvatarType.User + ) + // Only show started a call if the last remaining user in the call + // is really the one who started the call + if (caller.userId == event.senderId) { + Text( + modifier = Modifier.padding(start = 6.dp), + text = stringResource(CommonStrings.common_user_started_a_call, caller.displayName ?: caller.userId), + style = ElementTheme.typography.fontBodySmRegular, + color = ElementTheme.colors.textSecondary, + ) + } + } else { + val membersToShowCount = 4 + // Keep the one with avatar first but maintain + // the first user as it might be the call creator + val sortedMembers = remember(state.joinedMembers) { + if (state.joinedMembers.isEmpty()) return@remember emptyList() + val first = state.joinedMembers.first() + val rest = state.joinedMembers.drop(1).sortedByDescending { it.avatarUrl != null } + listOf(first) + rest + } + val displayMembers = sortedMembers.take(membersToShowCount) + val extraCount = state.joinedMembers.size - membersToShowCount + + AvatarRow( + avatarDataList = displayMembers + .map { user -> + AvatarData( + id = user.userId.value, + name = user.displayName, + url = user.avatarUrl, + size = AvatarSize.ActiveCallItem + ) + }.toImmutableList(), + avatarType = AvatarType.User, + overlapRatio = 0.5f, + lastOnTop = true, + ) + if (extraCount > 0) { + Text( + text = pluralStringResource(CommonPlurals.screen_timeline_active_call_extra_joined_count, count = state.joinedMembers.size, extraCount), + style = ElementTheme.typography.fontBodySmRegular, + color = ElementTheme.colors.textSecondary, + ) + } + } + } + } +} + +@PreviewsDayNight +@PreviewWithLargeHeight +@Composable +internal fun ActiveCallTimelineItemViewPreview() = ElementPreview( + drawableFallbackForImages = CommonDrawables.sample_avatar +) { + val readReceiptState = mutableListOf( + aTimelineItemReadReceipts( + receipts = List(3) { aReadReceiptData(it) }, + ) + ) + Column(modifier = Modifier.padding(bottom = 16.dp)) { + listOf(CallIntent.AUDIO, CallIntent.VIDEO).forEach { callIntent -> + listOf( + RtcNotificationState.Active( + listOf(aMatrixUser(displayName = USER_NAME_ALICE, avatarUrl = "anUrl")), + isJoined = true, + callStartTsMillis = System.currentTimeMillis() - 60_000, + callIntent = callIntent + ) to true, + RtcNotificationState.Active( + listOf( + aMatrixUser(displayName = USER_NAME_ALICE, avatarUrl = "anUrl"), + aMatrixUser(displayName = USER_NAME_BOB) + ), + isJoined = true, + callStartTsMillis = System.currentTimeMillis() - 60_000, + callIntent = callIntent + ) to true, + RtcNotificationState.Active( + listOf( + aMatrixUser(displayName = USER_NAME_ALICE), + aMatrixUser(displayName = USER_NAME_BOB, avatarUrl = "anUrlB"), + aMatrixUser(displayName = USER_NAME_CAROL), + aMatrixUser(displayName = USER_NAME_DAVID), + aMatrixUser(displayName = USER_NAME_CHARLIE), + aMatrixUser(displayName = USER_NAME_JOHN_DOE, avatarUrl = "anUrlC"), + ), + isJoined = true, + callStartTsMillis = System.currentTimeMillis(), + callIntent = callIntent + ) to false, + // Group call only one member still in call, but it is not the creator + RtcNotificationState.Active( + listOf( + aMatrixUser(displayName = USER_NAME_ALICE, avatarUrl = "aliceURl"), + ), + isJoined = true, + callStartTsMillis = System.currentTimeMillis(), + callIntent = callIntent + ) to false, + // Group call only one member that is the call creator + RtcNotificationState.Active( + listOf( + aMatrixUser( + id = "@senderId:domain", + displayName = "Sender" + ), + ), + isJoined = true, + callStartTsMillis = System.currentTimeMillis(), + callIntent = callIntent + ) to false, + ).forEach { (state, isDm) -> + val content = TimelineItemRtcNotificationContent(callIntent, state) + ActiveCallTimelineItemView( + timelineRoomInfo = aTimelineRoomInfo(isDm = isDm), + event = aTimelineItemEvent( + content = content, + // Only display read receipts for the first item + readReceiptState = readReceiptState.removeFirstOrNull() ?: aTimelineItemReadReceipts(), + ), + state, + isLastOutgoingMessage = false, + onLongClick = {}, + onReadReceiptsClick = {}, + onJoinCallClick = {}, + ) + } + } + } +} 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 a7ab44db54..6c86767dd4 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,6 +52,7 @@ internal fun TimelineItemCallNotifyView( timelineRoomInfo: TimelineRoomInfo, event: TimelineItem.Event, content: TimelineItemRtcNotificationContent, + state: RtcNotificationState.Tombstoned, isLastOutgoingMessage: Boolean, onLongClick: (TimelineItem.Event) -> Unit, onReadReceiptsClick: (TimelineItem.Event) -> Unit, @@ -83,7 +84,7 @@ internal fun TimelineItemCallNotifyView( Text( modifier = Modifier.weight(1f), - text = stringResource(getTextRes(timelineRoomInfo, content)), + text = stringResource(getTextRes(timelineRoomInfo, state)), style = ElementTheme.typography.fontBodyMdRegular, color = ElementTheme.colors.textSecondary, maxLines = 1, @@ -114,13 +115,13 @@ internal fun TimelineItemCallNotifyView( @StringRes private fun getTextRes( timelineRoomInfo: TimelineRoomInfo, - content: TimelineItemRtcNotificationContent + state: RtcNotificationState.Tombstoned ): Int = if (timelineRoomInfo.isDm) { - when (content.state) { + when (state) { is RtcNotificationState.Declined -> { - if (content.state.byMe) CommonStrings.common_call_you_declined else CommonStrings.common_call_declined + if (state.byMe) CommonStrings.common_call_you_declined else CommonStrings.common_call_declined } - RtcNotificationState.Started -> CommonStrings.common_call_started + else -> CommonStrings.common_call_started } } else { // In Rooms, do not show declined info. @@ -166,6 +167,7 @@ internal fun TimelineItemCallNotifyViewPreview() = ElementPreview { readReceiptState = readReceiptState.removeFirstOrNull() ?: aTimelineItemReadReceipts(), ), content = content, + state, isLastOutgoingMessage = false, onLongClick = {}, onReadReceiptsClick = {}, 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 b41e66ae82..f18843241b 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 @@ -183,6 +183,7 @@ private fun TimelineItemGroupedEventsRowContent( onReactionLongClick = onReactionLongClick, onMoreReactionsClick = onMoreReactionsClick, onReadReceiptClick = onReadReceiptClick, + onJoinCallClick = {}, onSwipeToReply = {}, 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 0229d2220b..442c560a94 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 @@ -31,6 +31,7 @@ import io.element.android.features.messages.impl.timeline.TimelineRoomInfo import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData 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.TimelineItemLegacyCallInviteContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent @@ -70,6 +71,7 @@ internal fun TimelineItemRow( onReactionLongClick: (key: String, TimelineItem.Event) -> Unit, onMoreReactionsClick: (TimelineItem.Event) -> Unit, onReadReceiptClick: (TimelineItem.Event) -> Unit, + onJoinCallClick: (isAudioCall: Boolean) -> Unit, onSwipeToReply: (TimelineItem.Event) -> Unit, eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, modifier: Modifier = Modifier, @@ -121,14 +123,27 @@ internal fun TimelineItemRow( ) } is TimelineItemRtcNotificationContent -> { - TimelineItemCallNotifyView( - timelineRoomInfo = timelineRoomInfo, - event = timelineItem, - content = timelineItem.content, - isLastOutgoingMessage = isLastOutgoingMessage, - onLongClick = onLongClick, - onReadReceiptsClick = onReadReceiptClick, - ) + when (timelineItem.content.state) { + is RtcNotificationState.Active -> ActiveCallTimelineItemView( + timelineRoomInfo = timelineRoomInfo, + event = timelineItem, + state = timelineItem.content.state, + isLastOutgoingMessage = isLastOutgoingMessage, + onLongClick = onLongClick, + onReadReceiptsClick = onReadReceiptClick, + onJoinCallClick = onJoinCallClick, + ) + is RtcNotificationState.Started, is RtcNotificationState.Declined -> + TimelineItemCallNotifyView( + timelineRoomInfo = timelineRoomInfo, + event = timelineItem, + content = timelineItem.content, + state = timelineItem.content.state, + isLastOutgoingMessage = isLastOutgoingMessage, + onLongClick = onLongClick, + onReadReceiptsClick = onReadReceiptClick, + ) + } } else -> { val a11yVoiceMessage = stringResource(CommonStrings.a11y_voice_message) 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 3b3e5118d6..d5367c872d 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 @@ -21,6 +21,8 @@ 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 +import io.element.android.libraries.matrix.api.room.RoomMember +import io.element.android.libraries.matrix.api.room.toMatrixUser import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent import io.element.android.libraries.matrix.api.timeline.item.event.EventContent import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem @@ -39,6 +41,7 @@ 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.matrix.api.user.MatrixUser import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.toolbox.api.strings.StringProvider @@ -58,13 +61,14 @@ class TimelineItemContentFactory( private val dateFormatter: DateFormatter, private val stringProvider: StringProvider, ) { - suspend fun create(eventTimelineItem: EventTimelineItem): TimelineItemEventContent { + suspend fun create(eventTimelineItem: EventTimelineItem, roomMembers: List): TimelineItemEventContent { return create( itemContent = eventTimelineItem.content, eventId = eventTimelineItem.eventId, isEditable = eventTimelineItem.isEditable, sender = eventTimelineItem.sender, senderProfile = eventTimelineItem.senderProfile, + roomMembers = roomMembers, ) } @@ -74,6 +78,7 @@ class TimelineItemContentFactory( isEditable: Boolean, sender: UserId, senderProfile: ProfileDetails, + roomMembers: List = emptyList(), ): TimelineItemEventContent { val isOutgoing = sessionId == sender return when (itemContent) { @@ -106,10 +111,23 @@ class TimelineItemContentFactory( is UnableToDecryptContent -> utdFactory.create(itemContent) is CallNotifyContent -> TimelineItemRtcNotificationContent( callIntent = itemContent.callIntent, - state = if (itemContent.declinedBy.isEmpty()) { - RtcNotificationState.Started + state = if (itemContent.activeMembers.isNotEmpty()) { + RtcNotificationState.Active( + joinedMembers = itemContent.activeMembers.map { active -> + roomMembers.find { + it.userId == active + }?.toMatrixUser() ?: MatrixUser(active) + }, + isJoined = itemContent.isJoined, + callStartTsMillis = itemContent.callStartTsMillis, + callIntent = itemContent.callIntent + ) } else { - RtcNotificationState.Declined(itemContent.declinedBy.any { it == sessionId }) + if (itemContent.declinedBy.isEmpty()) { + RtcNotificationState.Started + } else { + RtcNotificationState.Declined(itemContent.declinedBy.any { it == sessionId }) + } } ) is UnknownContent -> TimelineItemUnknownContent 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 a36755dc09..f29f23e903 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 @@ -108,7 +108,7 @@ class TimelineItemEventFactory( senderId = currentSender, senderProfile = senderProfile, senderAvatar = senderAvatarData, - content = contentFactory.create(currentTimelineItem.event), + content = contentFactory.create(currentTimelineItem.event, roomMembers), isMine = currentTimelineItem.event.isOwn, isEditable = currentTimelineItem.event.isEditable, canBeRepliedTo = currentTimelineItem.event.canBeRepliedTo, 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 2359f196a9..7d3ec21817 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,13 +10,27 @@ 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 +import io.element.android.libraries.matrix.api.user.MatrixUser // State of the call, for now only isDeclined but in the future could be missed, active. sealed interface RtcNotificationState { - /** Some users have declined, byMe indicates if the current user is one of them. */ - data class Declined(val byMe: Boolean) : RtcNotificationState + /** Call is currently active **/ + data class Active( + val joinedMembers: List, + val isJoined: Boolean, + val callStartTsMillis: Long, + val callIntent: CallIntent, + ) : RtcNotificationState - object Started : RtcNotificationState + /** Some users have declined, byMe indicates if the current user is one of them. */ + data class Declined(val byMe: Boolean) : RtcNotificationState, Tombstoned + + object Started : RtcNotificationState, Tombstoned + + /** + * Tag for Tombstoned/Past calls. + */ + interface Tombstoned } 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 210e123595..b2f7c70ad8 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 @@ -65,7 +65,8 @@ class DefaultMessageSummaryFormatter( context.getString(CommonStrings.common_call_declined) } } - RtcNotificationState.Started -> context.getString(CommonStrings.common_call_started) + RtcNotificationState.Started, is RtcNotificationState.Active + -> context.getString(CommonStrings.common_call_started) } } // Truncate the message to a safe length to avoid crashes in Compose 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 320457cedd..eb27780073 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 @@ -79,5 +79,6 @@ enum class AvatarSize(val dp: Dp) { LeaveSpaceRoom(32.dp), SelectParentSpace(32.dp), AccountItem(32.dp), - LocationPin(32.dp) + LocationPin(32.dp), + ActiveCallItem(20.dp) } 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 f323b316f7..d61e2f688d 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 @@ -120,7 +120,10 @@ data object LegacyCallInviteContent : EventContent data class CallNotifyContent( val callIntent: CallIntent, - val declinedBy: List + val declinedBy: List, + val activeMembers: List, + val isJoined: Boolean, + val callStartTsMillis: Long, ) : 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 fa671bc546..93f7c608d7 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 @@ -154,7 +154,10 @@ class TimelineEventContentMapper( } else { CallIntent.VIDEO }, - declinedBy = it.declinedBy.map(::UserId) + declinedBy = it.declinedBy.map(::UserId), + activeMembers = it.activeMembers.map(::UserId), + callStartTsMillis = it.callStartTsMillis?.toLong() ?: 0, + isJoined = it.isJoined ) } } diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 75b6ab1ee7..27e6cd40eb 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -214,6 +214,7 @@ "Blocked users" "Bubbles" "Call declined" + "Call in progress" "Call started" "You declined a call" "Chat backup" @@ -258,6 +259,7 @@ Reason: %1$s." "Forward message" "Frequently used" "GIF" + "Group call in progress" "Image" "In reply to %1$s" "Install APK" @@ -400,6 +402,7 @@ Reason: %1$s." "Unmute" "Unsupported call" "Unsupported event" + "%1$s started a call" "Username" "Verification cancelled" "Verification complete" @@ -534,6 +537,10 @@ Are you sure you want to continue?" "Spaces" "Shared %1$s" "On the map" + + "+ %1$d joined" + "+ %1$d joined" + "Message not sent because %1$s’s verified digital identity was reset." "Message not sent because %1$s has not verified all devices." "Message not sent because you have not verified one or more of your devices." From 35dce84c7fe7e7fa86479d8420a0bc7597f3ac92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Mon, 22 Jun 2026 09:17:15 +0200 Subject: [PATCH 011/383] Fix lint issues --- .../impl/timeline/components/customreaction/EmojiItem.kt | 4 +++- .../components/customreaction/picker/SkinTonePicker.kt | 4 +++- 2 files changed, 6 insertions(+), 2 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 ee5055176c..7ea023fe40 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 @@ -59,7 +59,9 @@ import io.element.android.features.messages.impl.timeline.components.customreact 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 kotlinx.collections.immutable.ImmutableSet import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.persistentSetOf @Composable fun EmojiItem( @@ -71,7 +73,7 @@ fun EmojiItem( onLongPress: ((Emoji) -> Unit)? = null, skinPickerEmoji: Emoji? = null, onDismissSkinPicker: (() -> Unit)? = null, - selectedSkinUnicodes: Set = emptySet(), + selectedSkinUnicodes: ImmutableSet = persistentSetOf(), hasSelectedSkin: Boolean = false, ) { val backgroundColor = when { 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 7fdfbfb1a4..c49b07023f 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 @@ -32,7 +32,9 @@ 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.ImmutableSet import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.persistentSetOf val SkinToneSlotSize = 48.dp val SkinToneSlotSpacing = 2.dp @@ -44,7 +46,7 @@ fun SkinTonePicker( onSelect: (Emoji) -> Unit, modifier: Modifier = Modifier, hoveredIndex: Int = -1, - selectedUnicodes: Set = emptySet(), + selectedUnicodes: ImmutableSet = persistentSetOf(), ) { val skins = emoji.skins.orEmpty() val emojiSize = 32.dp.toSp() From 0bda1cd0d02d935f5d61700047ce48d10c89c763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Mon, 22 Jun 2026 12:03:00 +0200 Subject: [PATCH 012/383] Fix double selection of emoji when long-pressing one that doesn't have skin variants --- .../impl/timeline/components/customreaction/EmojiItem.kt | 1 - 1 file changed, 1 deletion(-) 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 7ea023fe40..2dcffe10c8 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 @@ -194,7 +194,6 @@ fun EmojiItem( interactionSource.emit(press) if (tryAwaitRelease()) { interactionSource.emit(PressInteraction.Release(press)) - onSelectEmoji(item) } else { interactionSource.emit(PressInteraction.Cancel(press)) } From b3b8467636002d1fa37689becbbbebeee944c61d Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 22 Jun 2026 12:36:29 +0000 Subject: [PATCH 013/383] Update screenshots --- ....components.customreaction.picker_SkinTonePicker_Day_0_en.png} | 0 ...omponents.customreaction.picker_SkinTonePicker_Night_0_en.png} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/uitests/src/test/snapshots/images/{features.messages.impl.timeline.components.customreaction.picker_SkinTonePickerContent_Day_0_en.png => features.messages.impl.timeline.components.customreaction.picker_SkinTonePicker_Day_0_en.png} (100%) rename tests/uitests/src/test/snapshots/images/{features.messages.impl.timeline.components.customreaction.picker_SkinTonePickerContent_Night_0_en.png => features.messages.impl.timeline.components.customreaction.picker_SkinTonePicker_Night_0_en.png} (100%) 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_SkinTonePicker_Day_0_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction.picker_SkinTonePickerContent_Day_0_en.png rename to tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction.picker_SkinTonePicker_Day_0_en.png 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_SkinTonePicker_Night_0_en.png similarity index 100% rename from tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction.picker_SkinTonePickerContent_Night_0_en.png rename to tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction.picker_SkinTonePicker_Night_0_en.png From c4c0c482f0c6a9620a3fd62466fe870b46b68ca8 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Tue, 23 Jun 2026 14:02:15 +0000 Subject: [PATCH 014/383] Address review --- .../matrix/ui/media/CoilMediaFetcher.kt | 19 +++--- .../matrix/ui/media/ImageLoaderFactories.kt | 1 - .../impl/AndroidMediaPreProcessor.kt | 66 ++---------------- .../mediaupload/impl/SvgDimensionExtractor.kt | 68 +++++++++++++++++++ 4 files changed, 82 insertions(+), 72 deletions(-) create mode 100644 libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/SvgDimensionExtractor.kt diff --git a/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt b/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt index b1f72976e0..713057ecda 100644 --- a/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt +++ b/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt @@ -36,17 +36,16 @@ internal class CoilMediaFetcher( return when (val kind = mediaData.kind) { is MediaRequestData.Kind.Content -> fetchContent(mediaSource) is MediaRequestData.Kind.Thumbnail -> { - val thumbnailResult = fetchThumbnail(mediaSource, kind) - if (thumbnailResult.isSuccess) { - thumbnailResult.getOrThrow() - } else { - val error = thumbnailResult.exceptionOrNull() - if (error?.isNetworkError() == true) { - null - } else { - fetchContent(mediaSource) + fetchThumbnail(mediaSource, kind).fold( + onSuccess = { it }, + onFailure = { error -> + if (error.isNetworkError()) { + null + } else { + fetchContent(mediaSource) + } } - } + ) } is MediaRequestData.Kind.File -> fetchFile(mediaSource, kind) } 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 c74a819ecd..b414560fc9 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 @@ -42,7 +42,6 @@ class DefaultImageLoaderFactory( return ImageLoader.Builder(context) .components { add(okHttpNetworkFetcherFactory) - add(SvgDecoder.Factory()) } .build() } 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 11e5e7e65e..406f4e89bf 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 @@ -12,7 +12,6 @@ import android.content.Context import android.graphics.BitmapFactory import android.media.MediaMetadataRetriever import android.net.Uri -import android.util.Xml import androidx.exifinterface.media.ExifInterface import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding @@ -43,7 +42,6 @@ import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.withContext -import org.xmlpull.v1.XmlPullParser import timber.log.Timber import java.io.File import java.io.InputStream @@ -69,10 +67,7 @@ class AndroidMediaPreProcessor( */ private const val IMAGE_SCALE_REF_SIZE = 640 - private const val SVG_DEFAULT_WIDTH = 640L - private const val SVG_DEFAULT_HEIGHT = 480L - - private val notCompressibleImageTypes = listOf(MimeTypes.Gif, MimeTypes.WebP, MimeTypes.Svg) + private val notCompressibleImageTypes = listOf(MimeTypes.Gif, MimeTypes.WebP) } private val contentResolver = context.contentResolver @@ -88,6 +83,7 @@ class AndroidMediaPreProcessor( ): Result = withContext(coroutineDispatchers.computation) { runCatchingExceptions { val result = when { + mimeType == MimeTypes.Svg -> processSvgImage(uri, mimeType) mimeType.isMimeTypeImage() -> { val shouldBeCompressed = mediaOptimizationConfig.compressImages && mimeType !in notCompressibleImageTypes processImage(uri, mimeType, shouldBeCompressed) @@ -162,10 +158,6 @@ class AndroidMediaPreProcessor( private suspend fun processImage(uri: Uri, mimeType: String, shouldBeCompressed: Boolean): MediaUploadInfo { Timber.d("Processing image ${uri.path.orEmpty().hash()}") - if (mimeType == MimeTypes.Svg) { - return processSvgImage(uri, mimeType) - } - suspend fun processImageWithCompression(): MediaUploadInfo { // Read the orientation metadata from its own stream. Trying to reuse this stream for compression will fail. val orientation = contentResolver.openInputStream(uri).use { input -> @@ -226,10 +218,12 @@ class AndroidMediaPreProcessor( } } + private val svgDimensionExtractor = SvgDimensionExtractor() + private suspend fun processSvgImage(uri: Uri, mimeType: String): MediaUploadInfo { Timber.d("Processing SVG image ${uri.path.orEmpty().hash()}") val file = copyToTmpFile(uri) - val (width, height) = extractSvgDimensions(file) + val (width, height) = svgDimensionExtractor.extractDimensions(file) val imageInfo = ImageInfo( width = width, height = height, @@ -246,56 +240,6 @@ class AndroidMediaPreProcessor( ) } - private fun extractSvgDimensions(file: File): Pair { - return file.inputStream().use { inputStream -> - try { - val parser = Xml.newPullParser() - parser.setInput(inputStream, null) - var eventType = parser.eventType - while (eventType != XmlPullParser.END_DOCUMENT) { - if (eventType == XmlPullParser.START_TAG && parser.name.equals("svg", ignoreCase = true)) { - val width = parser.getAttributeValue(null, "width") - val height = parser.getAttributeValue(null, "height") - val viewBox = parser.getAttributeValue(null, "viewBox") - - val parsedWidth = width?.let { parseSvgLength(it) } - val parsedHeight = height?.let { parseSvgLength(it) } - - if (parsedWidth != null && parsedHeight != null) { - return parsedWidth to parsedHeight - } - - if (viewBox != null) { - val parts = viewBox.trim().split("\\s+".toRegex()).map { it.toFloatOrNull() } - if (parts.size == 4 && parts[2] != null && parts[3] != null) { - val vbWidth = parts[2]!!.toLong().coerceAtLeast(1) - val vbHeight = parts[3]!!.toLong().coerceAtLeast(1) - return vbWidth to vbHeight - } - } - - return (parsedWidth ?: SVG_DEFAULT_WIDTH) to (parsedHeight ?: SVG_DEFAULT_HEIGHT) - } - eventType = parser.next() - } - SVG_DEFAULT_WIDTH to SVG_DEFAULT_HEIGHT - } catch (_: Exception) { - SVG_DEFAULT_WIDTH to SVG_DEFAULT_HEIGHT - } - } - } - - private fun parseSvgLength(value: String): Long? { - val trimmed = value.trim() - if (trimmed.isEmpty()) return null - return try { - val numericPart = trimmed.replace(Regex("[^\\d.]"), "") - if (numericPart.isEmpty()) null else numericPart.toFloat().toLong().coerceAtLeast(1) - } catch (_: NumberFormatException) { - null - } - } - private suspend fun processVideo(uri: Uri, mimeType: String?, videoCompressionPreset: VideoCompressionPreset): MediaUploadInfo { Timber.d("Processing video ${uri.path.orEmpty().hash()}") val resultFile = runCatchingExceptions { diff --git a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/SvgDimensionExtractor.kt b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/SvgDimensionExtractor.kt new file mode 100644 index 0000000000..5ef756a904 --- /dev/null +++ b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/SvgDimensionExtractor.kt @@ -0,0 +1,68 @@ +/* + * 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.mediaupload.impl + +import android.util.Xml +import org.xmlpull.v1.XmlPullParser +import java.io.File + +class SvgDimensionExtractor( + private val defaultWidth: Long = 640L, + private val defaultHeight: Long = 480L, +) { + fun extractDimensions(file: File): Pair { + return file.inputStream().use { inputStream -> + try { + val parser = Xml.newPullParser() + parser.setInput(inputStream, null) + var eventType = parser.eventType + while (eventType != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.START_TAG && parser.name.equals("svg", ignoreCase = true)) { + val width = parser.getAttributeValue(null, "width") + val height = parser.getAttributeValue(null, "height") + val viewBox = parser.getAttributeValue(null, "viewBox") + + val parsedWidth = width?.let { parseLength(it) } + val parsedHeight = height?.let { parseLength(it) } + + if (parsedWidth != null && parsedHeight != null) { + return parsedWidth to parsedHeight + } + + if (viewBox != null) { + val parts = viewBox.trim().split("\\s+".toRegex()).map { it.toFloatOrNull() } + if (parts.size == 4 && parts[2] != null && parts[3] != null) { + val vbWidth = parts[2]!!.toLong().coerceAtLeast(1) + val vbHeight = parts[3]!!.toLong().coerceAtLeast(1) + return vbWidth to vbHeight + } + } + + return (parsedWidth ?: defaultWidth) to (parsedHeight ?: defaultHeight) + } + eventType = parser.next() + } + defaultWidth to defaultHeight + } catch (_: Exception) { + defaultWidth to defaultHeight + } + } + } + + private fun parseLength(value: String): Long? { + val trimmed = value.trim() + if (trimmed.isEmpty()) return null + return try { + val numericPart = trimmed.replace(Regex("[^\\d.]"), "") + if (numericPart.isEmpty()) null else numericPart.toFloat().toLong().coerceAtLeast(1) + } catch (_: NumberFormatException) { + null + } + } +} From 2902549a88f2842614b035c9c5d9fc5eed92152a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 23 Jun 2026 17:14:08 +0200 Subject: [PATCH 015/383] Fix wrong selection behaviour --- .../components/customreaction/EmojiItem.kt | 162 +++++++++--------- 1 file changed, 85 insertions(+), 77 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 2dcffe10c8..d934f53bfb 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 @@ -110,83 +110,6 @@ 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) { - 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 -> - 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 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 - // 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 { - -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 -> @@ -194,6 +117,9 @@ fun EmojiItem( interactionSource.emit(press) if (tryAwaitRelease()) { interactionSource.emit(PressInteraction.Release(press)) + if (hasSkinTones) { + onSelectEmoji(item) + } } else { interactionSource.emit(PressInteraction.Cancel(press)) } @@ -201,6 +127,88 @@ fun EmojiItem( onTap = { onSelectEmoji(item) }, ) } + .then( + // Only detect drag after long press for those items which have a skin tone picker + if (hasSkinTones) { + Modifier.pointerInput(item) { + 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 -> + 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 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 + // 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 { + -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 + }, + ) + } + } else { + Modifier + } + ) .clearAndSetSemantics { contentDescription = description }, From bad32cbbda7dbcba7ddb22f3ddaf10e276d85c1f Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Jun 2026 14:47:21 +0200 Subject: [PATCH 016/383] Add UserStatus and DisplayedStatus types to matrix API --- .../libraries/matrix/api/MatrixClient.kt | 3 +++ .../matrix/api/user/DisplayedStatus.kt | 21 +++++++++++++++++++ .../libraries/matrix/api/user/MatrixUser.kt | 2 ++ .../libraries/matrix/api/user/UserStatus.kt | 17 +++++++++++++++ 4 files changed, 43 insertions(+) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/UserStatus.kt 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 8f482440e8..4147333565 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 @@ -44,6 +44,7 @@ import io.element.android.libraries.matrix.api.sync.SyncService import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.api.user.UserStatus import io.element.android.libraries.matrix.api.verification.SessionVerificationService import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.CoroutineScope @@ -84,6 +85,8 @@ interface MatrixClient { suspend fun setDisplayName(displayName: String): Result suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result suspend fun removeAvatar(): Result + suspend fun setUserStatus(status: UserStatus): Result + suspend fun clearUserStatus(): Result suspend fun joinRoom(roomId: RoomId): Result suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List): Result suspend fun knockRoom(roomIdOrAlias: RoomIdOrAlias, message: String, serverNames: List): Result diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt new file mode 100644 index 0000000000..1b1dd551ff --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.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.api.user + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +sealed interface DisplayedStatus : Parcelable { + /** Status set manually by the user via m.status. */ + @Parcelize + data class UserSet(val status: UserStatus) : DisplayedStatus + + /** Status set automatically when the user is in a call via m.call. */ + @Parcelize + data class InCall(val callJoinedTs: Long) : DisplayedStatus +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/MatrixUser.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/MatrixUser.kt index 53cefa3694..7a8ec739a5 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/MatrixUser.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/MatrixUser.kt @@ -17,4 +17,6 @@ data class MatrixUser( val userId: UserId, val displayName: String? = null, val avatarUrl: String? = null, + val displayedStatus: DisplayedStatus? = null, + val rawStatus: UserStatus? = null, ) : Parcelable diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/UserStatus.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/UserStatus.kt new file mode 100644 index 0000000000..1576940b6f --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/UserStatus.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.libraries.matrix.api.user + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class UserStatus( + val emoji: String, + val text: String, +) : Parcelable From 5697c9664f58a6194ce47f099d5b80d8b70e2c5b Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Jun 2026 14:49:57 +0200 Subject: [PATCH 017/383] Add KDoc to InCall.callJoinedTs and clearUserStatus --- .../io/element/android/libraries/matrix/api/MatrixClient.kt | 1 + .../android/libraries/matrix/api/user/DisplayedStatus.kt | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) 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 4147333565..001bac0d30 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 @@ -86,6 +86,7 @@ interface MatrixClient { suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result suspend fun removeAvatar(): Result suspend fun setUserStatus(status: UserStatus): Result + /** Clears both m.status and m.call profile fields (maps to DELETE on the profile endpoint per MSC4426). */ suspend fun clearUserStatus(): Result suspend fun joinRoom(roomId: RoomId): Result suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List): Result diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt index 1b1dd551ff..046191d7cf 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt @@ -17,5 +17,8 @@ sealed interface DisplayedStatus : Parcelable { /** Status set automatically when the user is in a call via m.call. */ @Parcelize - data class InCall(val callJoinedTs: Long) : DisplayedStatus + data class InCall( + /** Unix timestamp in seconds when the call was joined (from m.call.call_joined_ts). */ + val callJoinedTs: Long, + ) : DisplayedStatus } From 742902ef02e753fe4e051b3aaa0f58dc1820c448 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Jun 2026 14:52:51 +0200 Subject: [PATCH 018/383] Add setUserStatus/clearUserStatus stubs to FakeMatrixClient --- .../libraries/matrix/test/FakeMatrixClient.kt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) 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 cce99e9d09..dce089537f 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 @@ -41,8 +41,10 @@ import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.spaces.SpaceService import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion import io.element.android.libraries.matrix.api.sync.SyncService +import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.api.user.UserStatus import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService import io.element.android.libraries.matrix.test.media.FakeMatrixMediaLoader @@ -128,6 +130,12 @@ class FakeMatrixClient( private set var removeAvatarCalled: Boolean = false private set + var setUserStatusCalled: Boolean = false + private set + var clearUserStatusCalled: Boolean = false + private set + var setUserStatusResult: Result = Result.success(Unit) + var clearUserStatusResult: Result = Result.success(Unit) private val _userProfile: MutableStateFlow = MutableStateFlow(MatrixUser(sessionId, userDisplayName, userAvatarUrl)) override val userProfile: StateFlow = _userProfile @@ -250,6 +258,28 @@ class FakeMatrixClient( return removeAvatarResult } + override suspend fun setUserStatus(status: UserStatus): Result { + setUserStatusCalled = true + if (setUserStatusResult.isSuccess) { + _userProfile.emit(_userProfile.value.copy( + rawStatus = status, + displayedStatus = DisplayedStatus.UserSet(status), + )) + } + return setUserStatusResult + } + + override suspend fun clearUserStatus(): Result { + clearUserStatusCalled = true + if (clearUserStatusResult.isSuccess) { + _userProfile.emit(_userProfile.value.copy( + rawStatus = null, + displayedStatus = null, + )) + } + return clearUserStatusResult + } + override suspend fun joinRoom(roomId: RoomId): Result = joinRoomLambda(roomId) override suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List): Result { From f4c79be3285fb74a0db202ba720d41cfb3336951 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Jun 2026 14:52:51 +0200 Subject: [PATCH 019/383] Stub setUserStatus/clearUserStatus in-memory in RustMatrixClient --- .../libraries/matrix/impl/RustMatrixClient.kt | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) 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 9167b3e2f3..37badadcd4 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 @@ -48,8 +48,10 @@ import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.spaces.SpaceService import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion import io.element.android.libraries.matrix.api.sync.SyncState +import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.api.user.UserStatus import io.element.android.libraries.matrix.impl.encryption.RustEncryptionService import io.element.android.libraries.matrix.impl.exception.mapClientException import io.element.android.libraries.matrix.impl.linknewdevice.RustLinkDesktopHandler @@ -258,6 +260,8 @@ class RustMatrixClient( private var clientDelegateTaskHandle: TaskHandle? = innerClient.setDelegate(sessionDelegate) + private var localUserStatus: UserStatus? = null + private val _userProfile: MutableStateFlow = MutableStateFlow( MatrixUser( userId = sessionId, @@ -443,8 +447,12 @@ class RustMatrixClient( override suspend fun getUserProfile(): Result = getProfile(sessionId) .onSuccess { matrixUser -> - _userProfile.emit(matrixUser) - // Also update our session storage + _userProfile.emit( + matrixUser.copy( + rawStatus = localUserStatus, + displayedStatus = localUserStatus?.let { DisplayedStatus.UserSet(it) }, + ) + ) sessionStore.updateUserProfile( sessionId = sessionId.value, displayName = matrixUser.displayName, @@ -474,6 +482,28 @@ class RustMatrixClient( runCatchingExceptions { innerClient.removeAvatar() } } + override suspend fun setUserStatus(status: UserStatus): Result { + localUserStatus = status + _userProfile.emit( + _userProfile.value.copy( + rawStatus = status, + displayedStatus = DisplayedStatus.UserSet(status), + ) + ) + return Result.success(Unit) + } + + override suspend fun clearUserStatus(): Result { + localUserStatus = null + _userProfile.emit( + _userProfile.value.copy( + rawStatus = null, + displayedStatus = null, + ) + ) + return Result.success(Unit) + } + override suspend fun joinRoom(roomId: RoomId): Result = withContext(sessionDispatcher) { runCatchingExceptions { innerClient.joinRoomById(roomId.value).destroy() From 42966b393f4c20632236c5c0035f78bee91c90b0 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Jun 2026 14:52:51 +0200 Subject: [PATCH 020/383] Add user status string resources and PredefinedUserStatus enum --- .../impl/userstatus/PredefinedUserStatus.kt | 19 +++++++++++++++++++ .../impl/src/main/res/values/temporary.xml | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/PredefinedUserStatus.kt create mode 100644 features/preferences/impl/src/main/res/values/temporary.xml diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/PredefinedUserStatus.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/PredefinedUserStatus.kt new file mode 100644 index 0000000000..78fec19f7a --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/PredefinedUserStatus.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.userstatus + +import androidx.annotation.StringRes +import io.element.android.features.preferences.impl.R + +enum class PredefinedUserStatus(val emoji: String, @StringRes val labelRes: Int) { + IN_A_MEETING("💬", R.string.common_user_status_in_a_meeting), + FOCUS_TIME("💡", R.string.common_user_status_focus_time), + ON_THE_ROAD("🚙", R.string.common_user_status_on_the_road), + BE_RIGHT_BACK("☕", R.string.common_user_status_be_right_back), + AWAY("🌴", R.string.common_user_status_away), +} diff --git a/features/preferences/impl/src/main/res/values/temporary.xml b/features/preferences/impl/src/main/res/values/temporary.xml new file mode 100644 index 0000000000..b22f265891 --- /dev/null +++ b/features/preferences/impl/src/main/res/values/temporary.xml @@ -0,0 +1,18 @@ + + + + In a meeting + Focus time + On the road + Be right back + Away + On a call + Custom… + What\'s your status? + Custom status… + From 1640adcf9d8e9b2006e552be5ccd856d0614c317 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Jun 2026 14:56:41 +0200 Subject: [PATCH 021/383] Fix thread-safety and dispatcher consistency in user status stubs --- .../android/libraries/matrix/impl/RustMatrixClient.kt | 10 +++++----- .../android/libraries/matrix/test/FakeMatrixClient.kt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) 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 37badadcd4..92107f3ac2 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 @@ -260,7 +260,7 @@ class RustMatrixClient( private var clientDelegateTaskHandle: TaskHandle? = innerClient.setDelegate(sessionDelegate) - private var localUserStatus: UserStatus? = null + @Volatile private var localUserStatus: UserStatus? = null private val _userProfile: MutableStateFlow = MutableStateFlow( MatrixUser( @@ -482,7 +482,7 @@ class RustMatrixClient( runCatchingExceptions { innerClient.removeAvatar() } } - override suspend fun setUserStatus(status: UserStatus): Result { + override suspend fun setUserStatus(status: UserStatus): Result = withContext(sessionDispatcher) { localUserStatus = status _userProfile.emit( _userProfile.value.copy( @@ -490,10 +490,10 @@ class RustMatrixClient( displayedStatus = DisplayedStatus.UserSet(status), ) ) - return Result.success(Unit) + Result.success(Unit) } - override suspend fun clearUserStatus(): Result { + override suspend fun clearUserStatus(): Result = withContext(sessionDispatcher) { localUserStatus = null _userProfile.emit( _userProfile.value.copy( @@ -501,7 +501,7 @@ class RustMatrixClient( displayedStatus = null, ) ) - return Result.success(Unit) + Result.success(Unit) } override suspend fun joinRoom(roomId: RoomId): Result = withContext(sessionDispatcher) { 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 dce089537f..a13b4b6ad6 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 @@ -258,7 +258,7 @@ class FakeMatrixClient( return removeAvatarResult } - override suspend fun setUserStatus(status: UserStatus): Result { + override suspend fun setUserStatus(status: UserStatus): Result = simulateLongTask { setUserStatusCalled = true if (setUserStatusResult.isSuccess) { _userProfile.emit(_userProfile.value.copy( @@ -269,7 +269,7 @@ class FakeMatrixClient( return setUserStatusResult } - override suspend fun clearUserStatus(): Result { + override suspend fun clearUserStatus(): Result = simulateLongTask { clearUserStatusCalled = true if (clearUserStatusResult.isSuccess) { _userProfile.emit(_userProfile.value.copy( From eca45b574eab879fffc8062d046436fcbfff7352 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Jun 2026 14:57:39 +0200 Subject: [PATCH 022/383] Add UserStatusState and UserStatusEvent --- .../impl/userstatus/UserStatusEvent.kt | 25 +++++++++++++++++++ .../impl/userstatus/UserStatusState.kt | 25 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt new file mode 100644 index 0000000000..703f8dadae --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt @@ -0,0 +1,25 @@ +/* + * 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.userstatus + +import io.element.android.libraries.matrix.api.user.UserStatus + +sealed interface UserStatusEvent { + /** User tapped the status row — open the picker bottom sheet. */ + data object Open : UserStatusEvent + /** User dismissed the bottom sheet without selecting. */ + data object Dismiss : UserStatusEvent + /** User selected a predefined or confirmed a custom status. */ + data class Set(val status: UserStatus) : UserStatusEvent + /** User tapped "Custom…" in the bottom sheet. */ + data object OpenCustomInput : UserStatusEvent + /** User tapped Cancel in the inline custom input row. */ + data object CancelCustomInput : UserStatusEvent + /** User tapped the clear action on an existing status. */ + data object Clear : UserStatusEvent +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt new file mode 100644 index 0000000000..5ae1537758 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt @@ -0,0 +1,25 @@ +/* + * 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.userstatus + +import io.element.android.libraries.matrix.api.user.DisplayedStatus + +data class UserStatusState( + val displayedStatus: DisplayedStatus?, + val pickerState: UserStatusPickerState, + val eventSink: (UserStatusEvent) -> Unit, +) + +sealed interface UserStatusPickerState { + data object Hidden : UserStatusPickerState + data object ShowingPicker : UserStatusPickerState + data class CustomInput( + val initialEmoji: String = "😀", + val initialText: String = "", + ) : UserStatusPickerState +} From 0528b787c90d0a4fa23635aca5476dd3c1d6c616 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Jun 2026 15:37:28 +0200 Subject: [PATCH 023/383] Add UserStatusPresenter with full test coverage --- .../impl/userstatus/UserStatusPresenter.kt | 63 +++++++++ .../userstatus/UserStatusPresenterTest.kt | 132 ++++++++++++++++++ .../libraries/matrix/test/FakeMatrixClient.kt | 4 +- 3 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt create mode 100644 features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt new file mode 100644 index 0000000000..a20bcd1b56 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt @@ -0,0 +1,63 @@ +/* + * 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.userstatus + +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.Inject +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.user.UserStatus +import kotlinx.coroutines.launch + +@Inject +class UserStatusPresenter( + private val matrixClient: MatrixClient, +) : Presenter { + + @Composable + override fun present(): UserStatusState { + val userProfile by matrixClient.userProfile.collectAsState() + var pickerState by remember { mutableStateOf(UserStatusPickerState.Hidden) } + val coroutineScope = rememberCoroutineScope() + + fun handleEvent(event: UserStatusEvent) { + when (event) { + UserStatusEvent.Open -> pickerState = UserStatusPickerState.ShowingPicker + UserStatusEvent.Dismiss -> pickerState = UserStatusPickerState.Hidden + UserStatusEvent.OpenCustomInput -> { + val raw = userProfile.rawStatus + pickerState = UserStatusPickerState.CustomInput( + initialEmoji = raw?.emoji ?: "😀", + initialText = raw?.text ?: "", + ) + } + is UserStatusEvent.Set -> { + pickerState = UserStatusPickerState.Hidden + coroutineScope.launch { matrixClient.setUserStatus(event.status) } + } + UserStatusEvent.Clear -> { + pickerState = UserStatusPickerState.Hidden + coroutineScope.launch { matrixClient.clearUserStatus() } + } + UserStatusEvent.CancelCustomInput -> pickerState = UserStatusPickerState.Hidden + } + } + + return UserStatusState( + displayedStatus = userProfile.displayedStatus, + pickerState = pickerState, + eventSink = ::handleEvent, + ) + } +} diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt new file mode 100644 index 0000000000..d8187462f8 --- /dev/null +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt @@ -0,0 +1,132 @@ +/* + * 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.userstatus + +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.libraries.matrix.api.user.DisplayedStatus +import io.element.android.libraries.matrix.api.user.UserStatus +import io.element.android.libraries.matrix.test.FakeMatrixClient +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class UserStatusPresenterTest { + + private fun createPresenter(client: FakeMatrixClient = FakeMatrixClient()) = + UserStatusPresenter(matrixClient = client) + + @Test + fun `initial state - no status set`() = runTest { + moleculeFlow(RecompositionMode.Immediate) { + createPresenter().present() + }.test { + val state = awaitItem() + assertThat(state.displayedStatus).isNull() + assertThat(state.pickerState).isEqualTo(UserStatusPickerState.Hidden) + } + } + + @Test + fun `Open event transitions to ShowingPicker`() = runTest { + moleculeFlow(RecompositionMode.Immediate) { + createPresenter().present() + }.test { + val state = awaitItem() + state.eventSink(UserStatusEvent.Open) + assertThat(awaitItem().pickerState).isEqualTo(UserStatusPickerState.ShowingPicker) + } + } + + @Test + fun `Dismiss event from ShowingPicker goes back to Hidden`() = runTest { + moleculeFlow(RecompositionMode.Immediate) { + createPresenter().present() + }.test { + val state = awaitItem() + state.eventSink(UserStatusEvent.Open) + awaitItem() // ShowingPicker + state.eventSink(UserStatusEvent.Dismiss) + assertThat(awaitItem().pickerState).isEqualTo(UserStatusPickerState.Hidden) + } + } + + @Test + fun `Set event calls setUserStatus and transitions to Hidden with updated status`() = runTest { + val client = FakeMatrixClient() + moleculeFlow(RecompositionMode.Immediate) { + createPresenter(client).present() + }.test { + val status = UserStatus(emoji = "💬", text = "In a meeting") + awaitItem().eventSink(UserStatusEvent.Set(status)) + val newState = awaitItem() + assertThat(newState.pickerState).isEqualTo(UserStatusPickerState.Hidden) + assertThat(newState.displayedStatus).isEqualTo(DisplayedStatus.UserSet(status)) + assertThat(client.setUserStatusCalled).isTrue() + } + } + + @Test + fun `OpenCustomInput with no existing status uses defaults`() = runTest { + moleculeFlow(RecompositionMode.Immediate) { + createPresenter().present() + }.test { + awaitItem().eventSink(UserStatusEvent.OpenCustomInput) + val state = awaitItem() + val pickerState = state.pickerState as UserStatusPickerState.CustomInput + assertThat(pickerState.initialEmoji).isEqualTo("😀") + assertThat(pickerState.initialText).isEqualTo("") + } + } + + @Test + fun `OpenCustomInput with existing rawStatus pre-fills values`() = runTest { + val client = FakeMatrixClient() + moleculeFlow(RecompositionMode.Immediate) { + createPresenter(client).present() + }.test { + val status = UserStatus(emoji = "🌴", text = "Away") + awaitItem().eventSink(UserStatusEvent.Set(status)) + // Single emission: pickerState=Hidden and displayedStatus both set in one recomposition + awaitItem().eventSink(UserStatusEvent.OpenCustomInput) + val state = awaitItem() + val pickerState = state.pickerState as UserStatusPickerState.CustomInput + assertThat(pickerState.initialEmoji).isEqualTo("🌴") + assertThat(pickerState.initialText).isEqualTo("Away") + } + } + + @Test + fun `CancelCustomInput goes back to Hidden`() = runTest { + moleculeFlow(RecompositionMode.Immediate) { + createPresenter().present() + }.test { + awaitItem().eventSink(UserStatusEvent.OpenCustomInput) + awaitItem().eventSink(UserStatusEvent.CancelCustomInput) // CustomInput state, fire Cancel + assertThat(awaitItem().pickerState).isEqualTo(UserStatusPickerState.Hidden) + } + } + + @Test + fun `Clear event calls clearUserStatus and clears displayed status`() = runTest { + val client = FakeMatrixClient() + moleculeFlow(RecompositionMode.Immediate) { + createPresenter(client).present() + }.test { + val status = UserStatus(emoji = "☕", text = "Be right back") + awaitItem().eventSink(UserStatusEvent.Set(status)) + // Single emission: pickerState=Hidden and displayedStatus both set in one recomposition + awaitItem().eventSink(UserStatusEvent.Clear) + val clearedState = awaitItem() + assertThat(clearedState.pickerState).isEqualTo(UserStatusPickerState.Hidden) + assertThat(clearedState.displayedStatus).isNull() + assertThat(client.clearUserStatusCalled).isTrue() + } + } +} 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 a13b4b6ad6..dce089537f 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 @@ -258,7 +258,7 @@ class FakeMatrixClient( return removeAvatarResult } - override suspend fun setUserStatus(status: UserStatus): Result = simulateLongTask { + override suspend fun setUserStatus(status: UserStatus): Result { setUserStatusCalled = true if (setUserStatusResult.isSuccess) { _userProfile.emit(_userProfile.value.copy( @@ -269,7 +269,7 @@ class FakeMatrixClient( return setUserStatusResult } - override suspend fun clearUserStatus(): Result = simulateLongTask { + override suspend fun clearUserStatus(): Result { clearUserStatusCalled = true if (clearUserStatusResult.isSuccess) { _userProfile.emit(_userProfile.value.copy( From af5a237b4ac11d1f0312c05c5e738292fe55a29e Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Jun 2026 15:37:28 +0200 Subject: [PATCH 024/383] Add UserStatusView composables with previews --- .../impl/userstatus/UserStatusView.kt | 246 ++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt new file mode 100644 index 0000000000..78f96042e1 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -0,0 +1,246 @@ +/* + * 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.userstatus + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +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.foundation.shape.CircleShape +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ListItem +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +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.res.stringResource +import androidx.compose.ui.text.input.ImeAction +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.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.matrix.api.user.DisplayedStatus +import io.element.android.libraries.matrix.api.user.UserStatus +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun UserStatusRow( + state: UserStatusState, + modifier: Modifier = Modifier, +) { + when (val pickerState = state.pickerState) { + UserStatusPickerState.Hidden, UserStatusPickerState.ShowingPicker -> { + val displayedStatus = state.displayedStatus + if (displayedStatus != null) { + CurrentStatusRow( + displayedStatus = displayedStatus, + onClick = { state.eventSink(UserStatusEvent.Open) }, + onClear = { state.eventSink(UserStatusEvent.Clear) }, + modifier = modifier, + ) + } else { + EmptyStatusRow( + onClick = { state.eventSink(UserStatusEvent.Open) }, + modifier = modifier, + ) + } + if (pickerState == UserStatusPickerState.ShowingPicker) { + UserStatusPickerBottomSheet( + onDismiss = { state.eventSink(UserStatusEvent.Dismiss) }, + onSelectPredefined = { status -> state.eventSink(UserStatusEvent.Set(status)) }, + onSelectCustom = { state.eventSink(UserStatusEvent.OpenCustomInput) }, + ) + } + } + is UserStatusPickerState.CustomInput -> { + CustomStatusInputRow( + initialEmoji = pickerState.initialEmoji, + initialText = pickerState.initialText, + onConfirm = { emoji, text -> + state.eventSink(UserStatusEvent.Set(UserStatus(emoji, text))) + }, + onCancel = { state.eventSink(UserStatusEvent.CancelCustomInput) }, + modifier = modifier, + ) + } + } +} + +@Composable +private fun EmptyStatusRow( + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + ListItem( + headlineContent = { + Text( + text = stringResource(R.string.screen_preferences_user_status_placeholder), + color = ElementTheme.colors.textSecondary, + ) + }, + leadingContent = { + Text(text = "🙂", style = ElementTheme.typography.fontBodyLgRegular) + }, + modifier = modifier.clickable(onClick = onClick), + ) +} + +@Composable +private fun CurrentStatusRow( + displayedStatus: DisplayedStatus, + onClick: () -> Unit, + onClear: () -> Unit, + modifier: Modifier = Modifier, +) { + val (emoji, text) = when (displayedStatus) { + is DisplayedStatus.UserSet -> displayedStatus.status.emoji to displayedStatus.status.text + is DisplayedStatus.InCall -> "🎧" to stringResource(R.string.common_user_status_on_a_call) + } + ListItem( + headlineContent = { Text(text = text) }, + leadingContent = { + Text(text = emoji, style = ElementTheme.typography.fontBodyLgRegular) + }, + trailingContent = { + TextButton(onClick = onClear) { + Text(text = stringResource(CommonStrings.action_clear)) + } + }, + modifier = modifier.clickable(onClick = onClick), + ) +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun UserStatusPickerBottomSheet( + onDismiss: () -> Unit, + onSelectPredefined: (UserStatus) -> Unit, + onSelectCustom: () -> Unit, +) { + ModalBottomSheet(onDismissRequest = onDismiss) { + PredefinedUserStatus.entries.forEach { predefined -> + val label = stringResource(predefined.labelRes) + ListItem( + headlineContent = { Text(text = label) }, + leadingContent = { + Text(text = predefined.emoji, style = ElementTheme.typography.fontBodyLgRegular) + }, + modifier = Modifier.clickable { + onSelectPredefined(UserStatus(emoji = predefined.emoji, text = label)) + }, + ) + } + ListItem( + headlineContent = { + Text(text = stringResource(R.string.common_user_status_custom)) + }, + leadingContent = { + Text(text = "✏️", style = ElementTheme.typography.fontBodyLgRegular) + }, + modifier = Modifier.clickable(onClick = onSelectCustom), + ) + } +} + +@Composable +private fun CustomStatusInputRow( + initialEmoji: String, + initialText: String, + onConfirm: (emoji: String, text: String) -> Unit, + onCancel: () -> Unit, + modifier: Modifier = Modifier, +) { + var emoji by remember { mutableStateOf(initialEmoji) } + var text by remember { mutableStateOf(initialText) } + + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 4.dp), + ) { + Surface( + shape = CircleShape, + color = ElementTheme.colors.bgSubtleSecondary, + modifier = Modifier + .size(40.dp) + .clickable { }, + ) { + Box(contentAlignment = Alignment.Center) { + Text(text = emoji, style = ElementTheme.typography.fontBodyLgRegular) + } + } + OutlinedTextField( + value = text, + onValueChange = { if (it.length <= 30) text = it }, + placeholder = { + Text(text = stringResource(R.string.screen_preferences_user_status_custom_hint)) + }, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), + keyboardActions = KeyboardActions( + onDone = { if (text.isNotBlank()) onConfirm(emoji, text) } + ), + singleLine = true, + modifier = Modifier + .weight(1f) + .padding(horizontal = 8.dp), + ) + TextButton(onClick = onCancel) { + Text(text = stringResource(CommonStrings.action_cancel)) + } + } +} + +@PreviewsDayNight +@Composable +internal fun UserStatusRowEmptyPreview() = ElementPreview { + UserStatusRow( + state = UserStatusState( + displayedStatus = null, + pickerState = UserStatusPickerState.Hidden, + eventSink = {}, + ) + ) +} + +@PreviewsDayNight +@Composable +internal fun UserStatusRowSetPreview() = ElementPreview { + UserStatusRow( + state = UserStatusState( + displayedStatus = DisplayedStatus.UserSet(UserStatus("🌴", "Away")), + pickerState = UserStatusPickerState.Hidden, + eventSink = {}, + ) + ) +} + +@PreviewsDayNight +@Composable +internal fun UserStatusRowCustomInputPreview() = ElementPreview { + UserStatusRow( + state = UserStatusState( + displayedStatus = null, + pickerState = UserStatusPickerState.CustomInput(initialEmoji = "😀", initialText = ""), + eventSink = {}, + ) + ) +} From 6c34d647ca9056b5126f3d799c6905f3a2d43f09 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Jun 2026 15:48:54 +0200 Subject: [PATCH 025/383] Wire UserStatusPresenter and UserStatusRow into PreferencesRoot --- .../impl/root/PreferencesRootPresenter.kt | 4 ++++ .../impl/root/PreferencesRootState.kt | 2 ++ .../impl/root/PreferencesRootStateProvider.kt | 4 ++++ .../impl/root/PreferencesRootView.kt | 11 +++++++--- .../userstatus/UserStatusStateProvider.kt | 20 +++++++++++++++++++ .../impl/root/PreferencesRootPresenterTest.kt | 2 ++ .../impl/root/PreferencesRootViewTest.kt | 11 +++++++--- 7 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.kt 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 f407149007..fa69382cf8 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 @@ -21,6 +21,7 @@ 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.userstatus.UserStatusState import io.element.android.features.preferences.impl.utils.ShowDeveloperSettingsProvider import io.element.android.features.rageshake.api.RageshakeFeatureAvailability import io.element.android.libraries.architecture.Presenter @@ -57,9 +58,11 @@ class PreferencesRootPresenter( private val featureFlagService: FeatureFlagService, private val sessionStore: SessionStore, private val sessionEnterpriseService: SessionEnterpriseService, + private val userStatusPresenter: Presenter, ) : Presenter { @Composable override fun present(): PreferencesRootState { + val userStatusState = userStatusPresenter.present() val coroutineScope = rememberCoroutineScope() val matrixUser = matrixClient.userProfile.collectAsState() LaunchedEffect(Unit) { @@ -137,6 +140,7 @@ class PreferencesRootPresenter( return PreferencesRootState( myUser = matrixUser.value, + userStatusState = userStatusState, version = remember { versionFormatter.get() }, deviceId = matrixClient.deviceId, isMultiAccountEnabled = isMultiAccountEnabled, 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 6474f07a69..8163e4b7a0 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 @@ -9,6 +9,7 @@ package io.element.android.features.preferences.impl.root import io.element.android.features.logout.api.direct.DirectLogoutState +import io.element.android.features.preferences.impl.userstatus.UserStatusState 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 @@ -16,6 +17,7 @@ import kotlinx.collections.immutable.ImmutableList data class PreferencesRootState( val myUser: MatrixUser, + val userStatusState: UserStatusState, val version: String, val deviceId: DeviceId?, val isMultiAccountEnabled: Boolean, 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 d53cd008e4..9e1557fd7b 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 @@ -11,6 +11,8 @@ 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.features.preferences.impl.userstatus.UserStatusState +import io.element.android.features.preferences.impl.userstatus.aUserStatusState 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 @@ -86,6 +88,7 @@ fun aPreferencesRootState( nbOfBlockedUsers: Int = 0, showLabsItem: Boolean = false, directLogoutState: DirectLogoutState = aDirectLogoutState(), + userStatusState: UserStatusState = aUserStatusState(), snackbarMessage: SnackbarMessage? = null, eventSink: (PreferencesRootEvent) -> Unit = {}, ) = PreferencesRootState( @@ -105,6 +108,7 @@ fun aPreferencesRootState( nbOfBlockedUsers = nbOfBlockedUsers, showLabsItem = showLabsItem, directLogoutState = directLogoutState, + userStatusState = userStatusState, 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 4afc2d27bf..d92c1e4613 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 @@ -10,6 +10,7 @@ package io.element.android.features.preferences.impl.root import androidx.compose.foundation.clickable 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.runtime.remember @@ -23,6 +24,7 @@ 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.features.preferences.impl.user.UserPreferences +import io.element.android.features.preferences.impl.userstatus.UserStatusRow 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 @@ -80,15 +82,18 @@ fun PreferencesRootView( }, matrixUser = state.myUser, ) + HorizontalDivider() + UserStatusRow( + state = state.userStatusState, + modifier = Modifier.fillMaxWidth(), + ) + HorizontalDivider() if (state.isMultiAccountEnabled) { MultiAccountSection( state = state, onAddAccountClick = onAddAccountClick, ) - } else { - HorizontalDivider() } - // User status will be added here // 'Account' section ManageAccountSection( state = state, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.kt new file mode 100644 index 0000000000..65ec264cc4 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.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.preferences.impl.userstatus + +import io.element.android.libraries.matrix.api.user.DisplayedStatus + +fun aUserStatusState( + displayedStatus: DisplayedStatus? = null, + pickerState: UserStatusPickerState = UserStatusPickerState.Hidden, + eventSink: (UserStatusEvent) -> Unit = {}, +) = UserStatusState( + displayedStatus = displayedStatus, + pickerState = pickerState, + eventSink = eventSink, +) 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 a6861be12d..0bda80fe0c 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 @@ -15,6 +15,7 @@ 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.userstatus.aUserStatusState import io.element.android.features.preferences.impl.utils.ShowDeveloperSettingsProvider import io.element.android.features.rageshake.api.RageshakeFeatureAvailability import io.element.android.libraries.core.meta.BuildType @@ -346,5 +347,6 @@ class PreferencesRootPresenterTest { featureFlagService = featureFlagService, sessionStore = sessionStore, sessionEnterpriseService = sessionEnterpriseService, + userStatusPresenter = { aUserStatusState() }, ) } 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 aded097059..5c9d81875e 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 @@ -12,8 +12,11 @@ package io.element.android.features.preferences.impl.root import androidx.activity.ComponentActivity import androidx.compose.ui.test.AndroidComposeUiTest import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.hasClickAction +import androidx.compose.ui.test.hasText import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performScrollTo import androidx.compose.ui.test.v2.runAndroidComposeUiTest import io.element.android.features.preferences.impl.R import io.element.android.libraries.matrix.api.user.MatrixUser @@ -281,7 +284,8 @@ class PreferencesRootViewTest : RobolectricTest() { ), onOpenDeveloperSettings = callback, ) - clickOn(CommonStrings.common_developer_options) + val text = activity!!.getString(CommonStrings.common_developer_options) + onNode(hasText(text) and hasClickAction()).performScrollTo().performClick() } } @@ -404,7 +408,8 @@ class PreferencesRootViewTest : RobolectricTest() { ), onDeactivateClick = callback, ) - clickOn(CommonStrings.action_delete_account) + val text = activity!!.getString(CommonStrings.action_delete_account) + onNode(hasText(text) and hasClickAction()).performScrollTo().performClick() } } @@ -430,7 +435,7 @@ class PreferencesRootViewTest : RobolectricTest() { eventSink = eventsRecorder, ), ) - onNodeWithText(version).performClick() + onNodeWithText(version).performScrollTo().performClick() eventsRecorder.assertSingle(PreferencesRootEvent.OnVersionInfoClick) } } From 7309e49286235fa090b33c9bd1f6ff8598e0d1f7 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 12 Jun 2026 16:04:42 +0200 Subject: [PATCH 026/383] Wire UserStatusPresenter and UserStatusRow into PreferencesRoot --- .../impl/userstatus/di/UserStatusModule.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/di/UserStatusModule.kt diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/di/UserStatusModule.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/di/UserStatusModule.kt new file mode 100644 index 0000000000..b2be2d75d4 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/di/UserStatusModule.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.userstatus.di + +import dev.zacsweers.metro.BindingContainer +import dev.zacsweers.metro.Binds +import dev.zacsweers.metro.ContributesTo +import io.element.android.features.preferences.impl.userstatus.UserStatusPresenter +import io.element.android.features.preferences.impl.userstatus.UserStatusState +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.di.SessionScope + +@ContributesTo(SessionScope::class) +@BindingContainer +interface UserStatusModule { + @Binds + fun bindUserStatusPresenter(presenter: UserStatusPresenter): Presenter +} From eeaaac296995ebbd6ff3a7f5cd3d0c1217e175e8 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 15 Jun 2026 15:22:54 +0200 Subject: [PATCH 027/383] Move custom status emoji/text into CustomInput state (MVI) --- .../impl/userstatus/PredefinedUserStatus.kt | 19 --- .../impl/userstatus/UserStatusEvent.kt | 4 + .../impl/userstatus/UserStatusPresenter.kt | 16 ++- .../impl/userstatus/UserStatusState.kt | 14 +- .../impl/userstatus/UserStatusView.kt | 130 ++++++++++-------- .../impl/userstatus/di/UserStatusModule.kt | 23 ---- .../userstatus/UserStatusPresenterTest.kt | 32 ++++- 7 files changed, 133 insertions(+), 105 deletions(-) delete mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/PredefinedUserStatus.kt delete mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/di/UserStatusModule.kt diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/PredefinedUserStatus.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/PredefinedUserStatus.kt deleted file mode 100644 index 78fec19f7a..0000000000 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/PredefinedUserStatus.kt +++ /dev/null @@ -1,19 +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.preferences.impl.userstatus - -import androidx.annotation.StringRes -import io.element.android.features.preferences.impl.R - -enum class PredefinedUserStatus(val emoji: String, @StringRes val labelRes: Int) { - IN_A_MEETING("💬", R.string.common_user_status_in_a_meeting), - FOCUS_TIME("💡", R.string.common_user_status_focus_time), - ON_THE_ROAD("🚙", R.string.common_user_status_on_the_road), - BE_RIGHT_BACK("☕", R.string.common_user_status_be_right_back), - AWAY("🌴", R.string.common_user_status_away), -} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt index 703f8dadae..d78be1607b 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt @@ -20,6 +20,10 @@ sealed interface UserStatusEvent { data object OpenCustomInput : UserStatusEvent /** User tapped Cancel in the inline custom input row. */ data object CancelCustomInput : UserStatusEvent + /** User changed the emoji in the custom input row. */ + data class UpdateCustomEmoji(val emoji: String) : UserStatusEvent + /** User changed the text in the custom input row. */ + data class UpdateCustomText(val text: String) : UserStatusEvent /** User tapped the clear action on an existing status. */ data object Clear : UserStatusEvent } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt index a20bcd1b56..d765f35800 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt @@ -14,13 +14,15 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue +import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.Inject import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.user.UserStatus import kotlinx.coroutines.launch -@Inject +@ContributesBinding(SessionScope::class) class UserStatusPresenter( private val matrixClient: MatrixClient, ) : Presenter { @@ -38,8 +40,8 @@ class UserStatusPresenter( UserStatusEvent.OpenCustomInput -> { val raw = userProfile.rawStatus pickerState = UserStatusPickerState.CustomInput( - initialEmoji = raw?.emoji ?: "😀", - initialText = raw?.text ?: "", + emoji = raw?.emoji ?: "😀", + text = raw?.text ?: "", ) } is UserStatusEvent.Set -> { @@ -51,6 +53,14 @@ class UserStatusPresenter( coroutineScope.launch { matrixClient.clearUserStatus() } } UserStatusEvent.CancelCustomInput -> pickerState = UserStatusPickerState.Hidden + is UserStatusEvent.UpdateCustomEmoji -> { + val current = pickerState as? UserStatusPickerState.CustomInput ?: return + pickerState = current.copy(emoji = event.emoji) + } + is UserStatusEvent.UpdateCustomText -> { + val current = pickerState as? UserStatusPickerState.CustomInput ?: return + pickerState = current.copy(text = event.text) + } } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt index 5ae1537758..df1a97a5e3 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt @@ -7,6 +7,8 @@ package io.element.android.features.preferences.impl.userstatus +import androidx.annotation.StringRes +import io.element.android.features.preferences.impl.R import io.element.android.libraries.matrix.api.user.DisplayedStatus data class UserStatusState( @@ -19,7 +21,15 @@ sealed interface UserStatusPickerState { data object Hidden : UserStatusPickerState data object ShowingPicker : UserStatusPickerState data class CustomInput( - val initialEmoji: String = "😀", - val initialText: String = "", + val emoji: String = "😀", + val text: String = "", ) : UserStatusPickerState } + +enum class PredefinedUserStatus(val emoji: String, @param:StringRes val labelRes: Int) { + IN_A_MEETING("💬", R.string.common_user_status_in_a_meeting), + FOCUS_TIME("💡", R.string.common_user_status_focus_time), + ON_THE_ROAD("🚙", R.string.common_user_status_on_the_road), + BE_RIGHT_BACK("☕", R.string.common_user_status_be_right_back), + AWAY("🌴", R.string.common_user_status_away), +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index 78f96042e1..956400fa63 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -7,6 +7,7 @@ package io.element.android.features.preferences.impl.userstatus +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row @@ -17,26 +18,29 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ListItem -import androidx.compose.material3.ModalBottomSheet -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton 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.res.stringResource import androidx.compose.ui.text.input.ImeAction 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.preferences.impl.R +import io.element.android.libraries.designsystem.components.list.ListItemContent 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.ListItem +import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet +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.components.TextButton +import io.element.android.libraries.designsystem.theme.components.TextField import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.api.user.UserStatus import io.element.android.libraries.ui.strings.CommonStrings @@ -72,11 +76,11 @@ fun UserStatusRow( } is UserStatusPickerState.CustomInput -> { CustomStatusInputRow( - initialEmoji = pickerState.initialEmoji, - initialText = pickerState.initialText, - onConfirm = { emoji, text -> - state.eventSink(UserStatusEvent.Set(UserStatus(emoji, text))) - }, + emoji = pickerState.emoji, + text = pickerState.text, + onEmojiChange = { state.eventSink(UserStatusEvent.UpdateCustomEmoji(it)) }, + onTextChange = { state.eventSink(UserStatusEvent.UpdateCustomText(it)) }, + onConfirm = { state.eventSink(UserStatusEvent.Set(UserStatus(pickerState.emoji, pickerState.text))) }, onCancel = { state.eventSink(UserStatusEvent.CancelCustomInput) }, modifier = modifier, ) @@ -91,14 +95,9 @@ private fun EmptyStatusRow( ) { ListItem( headlineContent = { - Text( - text = stringResource(R.string.screen_preferences_user_status_placeholder), - color = ElementTheme.colors.textSecondary, - ) - }, - leadingContent = { - Text(text = "🙂", style = ElementTheme.typography.fontBodyLgRegular) + Text(text = stringResource(R.string.screen_preferences_user_status_placeholder)) }, + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Reaction())), modifier = modifier.clickable(onClick = onClick), ) } @@ -116,15 +115,14 @@ private fun CurrentStatusRow( } ListItem( headlineContent = { Text(text = text) }, - leadingContent = { - Text(text = emoji, style = ElementTheme.typography.fontBodyLgRegular) - }, - trailingContent = { - TextButton(onClick = onClear) { - Text(text = stringResource(CommonStrings.action_clear)) + leadingContent = ListItemContent.Text(emoji), + trailingContent = ListItemContent.Custom({ + IconButton(onClick = onClear) { + Icon(imageVector = CompoundIcons.Close(), contentDescription = null) } - }, - modifier = modifier.clickable(onClick = onClick), + }), + onClick = onClick, + modifier = modifier, ) } @@ -134,16 +132,15 @@ private fun UserStatusPickerBottomSheet( onDismiss: () -> Unit, onSelectPredefined: (UserStatus) -> Unit, onSelectCustom: () -> Unit, + modifier: Modifier = Modifier, ) { - ModalBottomSheet(onDismissRequest = onDismiss) { + ModalBottomSheet(onDismissRequest = onDismiss, scrollable = true, modifier = modifier) { PredefinedUserStatus.entries.forEach { predefined -> val label = stringResource(predefined.labelRes) ListItem( headlineContent = { Text(text = label) }, - leadingContent = { - Text(text = predefined.emoji, style = ElementTheme.typography.fontBodyLgRegular) - }, - modifier = Modifier.clickable { + leadingContent = ListItemContent.Text(text = predefined.emoji), + onClick = { onSelectPredefined(UserStatus(emoji = predefined.emoji, text = label)) }, ) @@ -152,25 +149,54 @@ private fun UserStatusPickerBottomSheet( headlineContent = { Text(text = stringResource(R.string.common_user_status_custom)) }, - leadingContent = { - Text(text = "✏️", style = ElementTheme.typography.fontBodyLgRegular) - }, - modifier = Modifier.clickable(onClick = onSelectCustom), + leadingContent = ListItemContent.Text(text = "✏️"), + onClick = onSelectCustom, ) } } @Composable private fun CustomStatusInputRow( - initialEmoji: String, - initialText: String, - onConfirm: (emoji: String, text: String) -> Unit, + emoji: String, + text: String, + onEmojiChange: (String) -> Unit, + onTextChange: (String) -> Unit, + onConfirm: () -> Unit, onCancel: () -> Unit, modifier: Modifier = Modifier, ) { - var emoji by remember { mutableStateOf(initialEmoji) } - var text by remember { mutableStateOf(initialText) } + ListItem( + headlineContent = { + TextField( + value = text, + onValueChange = { if (it.length <= 30) onTextChange(it) }, + placeholder = stringResource(R.string.screen_preferences_user_status_custom_hint), + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), + keyboardActions = KeyboardActions( + onDone = { if (text.isNotBlank()) onConfirm() } + ), + singleLine = true, + ) + }, + trailingContent = ListItemContent.Custom({ + TextButton(onClick = onCancel, text = stringResource(CommonStrings.action_cancel)) + }), + leadingContent = ListItemContent.Custom( { + Surface( + shape = CircleShape, + border = BorderStroke(1.dp, ElementTheme.colors.bgSubtleSecondary), + modifier = Modifier + .size(50.dp) + .clickable { }, + ) { + Box(contentAlignment = Alignment.Center) { + Text(text = emoji, style = ElementTheme.typography.fontBodyLgRegular) + } + } + }) + ) + /* Row( verticalAlignment = Alignment.CenterVertically, modifier = modifier @@ -188,25 +214,21 @@ private fun CustomStatusInputRow( Text(text = emoji, style = ElementTheme.typography.fontBodyLgRegular) } } - OutlinedTextField( + TextField( value = text, onValueChange = { if (it.length <= 30) text = it }, - placeholder = { - Text(text = stringResource(R.string.screen_preferences_user_status_custom_hint)) - }, + placeholder = stringResource(R.string.screen_preferences_user_status_custom_hint), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), keyboardActions = KeyboardActions( onDone = { if (text.isNotBlank()) onConfirm(emoji, text) } ), singleLine = true, - modifier = Modifier - .weight(1f) - .padding(horizontal = 8.dp), + modifier = Modifier.weight(1f).padding(horizontal = 8.dp), ) - TextButton(onClick = onCancel) { - Text(text = stringResource(CommonStrings.action_cancel)) - } + TextButton(onClick = onCancel, text = stringResource(CommonStrings.action_cancel)) } + + */ } @PreviewsDayNight @@ -239,7 +261,7 @@ internal fun UserStatusRowCustomInputPreview() = ElementPreview { UserStatusRow( state = UserStatusState( displayedStatus = null, - pickerState = UserStatusPickerState.CustomInput(initialEmoji = "😀", initialText = ""), + pickerState = UserStatusPickerState.CustomInput(emoji = "😀", text = ""), eventSink = {}, ) ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/di/UserStatusModule.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/di/UserStatusModule.kt deleted file mode 100644 index b2be2d75d4..0000000000 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/di/UserStatusModule.kt +++ /dev/null @@ -1,23 +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.preferences.impl.userstatus.di - -import dev.zacsweers.metro.BindingContainer -import dev.zacsweers.metro.Binds -import dev.zacsweers.metro.ContributesTo -import io.element.android.features.preferences.impl.userstatus.UserStatusPresenter -import io.element.android.features.preferences.impl.userstatus.UserStatusState -import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.di.SessionScope - -@ContributesTo(SessionScope::class) -@BindingContainer -interface UserStatusModule { - @Binds - fun bindUserStatusPresenter(presenter: UserStatusPresenter): Presenter -} diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt index d8187462f8..42f1e53323 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt @@ -80,8 +80,8 @@ class UserStatusPresenterTest { awaitItem().eventSink(UserStatusEvent.OpenCustomInput) val state = awaitItem() val pickerState = state.pickerState as UserStatusPickerState.CustomInput - assertThat(pickerState.initialEmoji).isEqualTo("😀") - assertThat(pickerState.initialText).isEqualTo("") + assertThat(pickerState.emoji).isEqualTo("😀") + assertThat(pickerState.text).isEqualTo("") } } @@ -97,8 +97,32 @@ class UserStatusPresenterTest { awaitItem().eventSink(UserStatusEvent.OpenCustomInput) val state = awaitItem() val pickerState = state.pickerState as UserStatusPickerState.CustomInput - assertThat(pickerState.initialEmoji).isEqualTo("🌴") - assertThat(pickerState.initialText).isEqualTo("Away") + assertThat(pickerState.emoji).isEqualTo("🌴") + assertThat(pickerState.text).isEqualTo("Away") + } + } + + @Test + fun `UpdateCustomText updates text in CustomInput state`() = runTest { + moleculeFlow(RecompositionMode.Immediate) { + createPresenter().present() + }.test { + awaitItem().eventSink(UserStatusEvent.OpenCustomInput) + awaitItem().eventSink(UserStatusEvent.UpdateCustomText("Focusing")) + val state = awaitItem() + assertThat((state.pickerState as UserStatusPickerState.CustomInput).text).isEqualTo("Focusing") + } + } + + @Test + fun `UpdateCustomEmoji updates emoji in CustomInput state`() = runTest { + moleculeFlow(RecompositionMode.Immediate) { + createPresenter().present() + }.test { + awaitItem().eventSink(UserStatusEvent.OpenCustomInput) + awaitItem().eventSink(UserStatusEvent.UpdateCustomEmoji("🚀")) + val state = awaitItem() + assertThat((state.pickerState as UserStatusPickerState.CustomInput).emoji).isEqualTo("🚀") } } From 73a8a3d5d88ceb915f57b0a986a8fd7b67afecfc Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 15 Jun 2026 15:29:50 +0200 Subject: [PATCH 028/383] Use TextFieldState in CustomInput state for proper MVI text handling --- .../impl/userstatus/UserStatusEvent.kt | 2 -- .../impl/userstatus/UserStatusPresenter.kt | 15 +++++--- .../impl/userstatus/UserStatusState.kt | 3 +- .../impl/userstatus/UserStatusView.kt | 34 ++++++++++--------- .../userstatus/UserStatusPresenterTest.kt | 17 ++-------- 5 files changed, 33 insertions(+), 38 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt index d78be1607b..80dd02e08a 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt @@ -22,8 +22,6 @@ sealed interface UserStatusEvent { data object CancelCustomInput : UserStatusEvent /** User changed the emoji in the custom input row. */ data class UpdateCustomEmoji(val emoji: String) : UserStatusEvent - /** User changed the text in the custom input row. */ - data class UpdateCustomText(val text: String) : UserStatusEvent /** User tapped the clear action on an existing status. */ data object Clear : UserStatusEvent } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt index d765f35800..0bb626b159 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt @@ -7,6 +7,9 @@ package io.element.android.features.preferences.impl.userstatus +import androidx.compose.foundation.text.input.TextFieldState +import androidx.compose.foundation.text.input.clearText +import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -31,6 +34,7 @@ class UserStatusPresenter( override fun present(): UserStatusState { val userProfile by matrixClient.userProfile.collectAsState() var pickerState by remember { mutableStateOf(UserStatusPickerState.Hidden) } + val customTextFieldState = remember { TextFieldState() } val coroutineScope = rememberCoroutineScope() fun handleEvent(event: UserStatusEvent) { @@ -39,9 +43,14 @@ class UserStatusPresenter( UserStatusEvent.Dismiss -> pickerState = UserStatusPickerState.Hidden UserStatusEvent.OpenCustomInput -> { val raw = userProfile.rawStatus + if (raw != null) { + customTextFieldState.setTextAndPlaceCursorAtEnd(raw.text) + } else { + customTextFieldState.clearText() + } pickerState = UserStatusPickerState.CustomInput( emoji = raw?.emoji ?: "😀", - text = raw?.text ?: "", + textFieldState = customTextFieldState, ) } is UserStatusEvent.Set -> { @@ -57,10 +66,6 @@ class UserStatusPresenter( val current = pickerState as? UserStatusPickerState.CustomInput ?: return pickerState = current.copy(emoji = event.emoji) } - is UserStatusEvent.UpdateCustomText -> { - val current = pickerState as? UserStatusPickerState.CustomInput ?: return - pickerState = current.copy(text = event.text) - } } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt index df1a97a5e3..b1fe11d1ed 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt @@ -8,6 +8,7 @@ package io.element.android.features.preferences.impl.userstatus import androidx.annotation.StringRes +import androidx.compose.foundation.text.input.TextFieldState import io.element.android.features.preferences.impl.R import io.element.android.libraries.matrix.api.user.DisplayedStatus @@ -22,7 +23,7 @@ sealed interface UserStatusPickerState { data object ShowingPicker : UserStatusPickerState data class CustomInput( val emoji: String = "😀", - val text: String = "", + val textFieldState: TextFieldState, ) : UserStatusPickerState } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index 956400fa63..b63ae2630e 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -15,8 +15,10 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.text.input.InputTransformation +import androidx.compose.foundation.text.input.TextFieldLineLimits +import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -32,6 +34,7 @@ import io.element.android.libraries.designsystem.components.list.ListItemContent 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.FilledTextField 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 @@ -40,7 +43,6 @@ import io.element.android.libraries.designsystem.theme.components.ModalBottomShe 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.components.TextButton -import io.element.android.libraries.designsystem.theme.components.TextField import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.api.user.UserStatus import io.element.android.libraries.ui.strings.CommonStrings @@ -77,10 +79,13 @@ fun UserStatusRow( is UserStatusPickerState.CustomInput -> { CustomStatusInputRow( emoji = pickerState.emoji, - text = pickerState.text, + textFieldState = pickerState.textFieldState, onEmojiChange = { state.eventSink(UserStatusEvent.UpdateCustomEmoji(it)) }, - onTextChange = { state.eventSink(UserStatusEvent.UpdateCustomText(it)) }, - onConfirm = { state.eventSink(UserStatusEvent.Set(UserStatus(pickerState.emoji, pickerState.text))) }, + onConfirm = { + state.eventSink( + UserStatusEvent.Set(UserStatus(pickerState.emoji, pickerState.textFieldState.text.toString())) + ) + }, onCancel = { state.eventSink(UserStatusEvent.CancelCustomInput) }, modifier = modifier, ) @@ -158,24 +163,21 @@ private fun UserStatusPickerBottomSheet( @Composable private fun CustomStatusInputRow( emoji: String, - text: String, + textFieldState: TextFieldState, onEmojiChange: (String) -> Unit, - onTextChange: (String) -> Unit, onConfirm: () -> Unit, onCancel: () -> Unit, modifier: Modifier = Modifier, ) { ListItem( headlineContent = { - TextField( - value = text, - onValueChange = { if (it.length <= 30) onTextChange(it) }, - placeholder = stringResource(R.string.screen_preferences_user_status_custom_hint), + FilledTextField( + state = textFieldState, + placeholder = { Text(stringResource(R.string.screen_preferences_user_status_custom_hint)) }, + inputTransformation = InputTransformation { if (length > 30) revertAllChanges() }, keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), - keyboardActions = KeyboardActions( - onDone = { if (text.isNotBlank()) onConfirm() } - ), - singleLine = true, + keyboardActions = { if (textFieldState.text.isNotBlank()) onConfirm() }, + lineLimits = TextFieldLineLimits.SingleLine, ) }, trailingContent = ListItemContent.Custom({ @@ -261,7 +263,7 @@ internal fun UserStatusRowCustomInputPreview() = ElementPreview { UserStatusRow( state = UserStatusState( displayedStatus = null, - pickerState = UserStatusPickerState.CustomInput(emoji = "😀", text = ""), + pickerState = UserStatusPickerState.CustomInput(emoji = "😀", textFieldState = TextFieldState()), eventSink = {}, ) ) diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt index 42f1e53323..349361a61b 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt @@ -16,6 +16,7 @@ import io.element.android.libraries.matrix.api.user.UserStatus import io.element.android.libraries.matrix.test.FakeMatrixClient import kotlinx.coroutines.test.runTest import org.junit.Test +import androidx.compose.foundation.text.input.TextFieldState class UserStatusPresenterTest { @@ -81,7 +82,7 @@ class UserStatusPresenterTest { val state = awaitItem() val pickerState = state.pickerState as UserStatusPickerState.CustomInput assertThat(pickerState.emoji).isEqualTo("😀") - assertThat(pickerState.text).isEqualTo("") + assertThat(pickerState.textFieldState.text.toString()).isEqualTo("") } } @@ -98,19 +99,7 @@ class UserStatusPresenterTest { val state = awaitItem() val pickerState = state.pickerState as UserStatusPickerState.CustomInput assertThat(pickerState.emoji).isEqualTo("🌴") - assertThat(pickerState.text).isEqualTo("Away") - } - } - - @Test - fun `UpdateCustomText updates text in CustomInput state`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - createPresenter().present() - }.test { - awaitItem().eventSink(UserStatusEvent.OpenCustomInput) - awaitItem().eventSink(UserStatusEvent.UpdateCustomText("Focusing")) - val state = awaitItem() - assertThat((state.pickerState as UserStatusPickerState.CustomInput).text).isEqualTo("Focusing") + assertThat(pickerState.textFieldState.text.toString()).isEqualTo("Away") } } From 57617a362a38fd2d9d023f309f56afeeaabe3668 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 15 Jun 2026 16:05:20 +0200 Subject: [PATCH 029/383] Add TextFieldState overload to design system TextField, use it in UserStatusView --- .../impl/userstatus/UserStatusView.kt | 11 ++-- .../theme/components/TextField.kt | 54 +++++++++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index b63ae2630e..efb06a42de 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -34,7 +34,7 @@ import io.element.android.libraries.designsystem.components.list.ListItemContent 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.FilledTextField +import io.element.android.libraries.designsystem.theme.components.TextField 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 @@ -171,12 +171,12 @@ private fun CustomStatusInputRow( ) { ListItem( headlineContent = { - FilledTextField( + TextField( state = textFieldState, - placeholder = { Text(stringResource(R.string.screen_preferences_user_status_custom_hint)) }, + placeholder = stringResource(R.string.screen_preferences_user_status_custom_hint), inputTransformation = InputTransformation { if (length > 30) revertAllChanges() }, keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), - keyboardActions = { if (textFieldState.text.isNotBlank()) onConfirm() }, + onKeyboardAction = { if (textFieldState.text.isNotBlank()) onConfirm() }, lineLimits = TextFieldLineLimits.SingleLine, ) }, @@ -195,7 +195,8 @@ private fun CustomStatusInputRow( Text(text = emoji, style = ElementTheme.typography.fontBodyLgRegular) } } - }) + }), + modifier = modifier, ) /* diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/TextField.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/TextField.kt index 5e0a81ba03..d4e08eacf1 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/TextField.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/TextField.kt @@ -24,6 +24,11 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.text.input.InputTransformation +import androidx.compose.foundation.text.input.KeyboardActionHandler +import androidx.compose.foundation.text.input.TextFieldDecorator +import androidx.compose.foundation.text.input.TextFieldLineLimits +import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.material3.LocalContentColor import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @@ -161,6 +166,55 @@ fun TextField( } } +@Composable +fun TextField( + state: TextFieldState, + modifier: Modifier = Modifier, + label: String? = null, + supportingText: String? = null, + placeholder: String? = null, + leadingIcon: @Composable (() -> Unit)? = null, + trailingIcon: @Composable (() -> Unit)? = null, + validity: TextFieldValidity = TextFieldValidity.None, + enabled: Boolean = true, + readOnly: Boolean = false, + inputTransformation: InputTransformation? = null, + keyboardOptions: KeyboardOptions = KeyboardOptions.Default, + onKeyboardAction: KeyboardActionHandler? = null, + lineLimits: TextFieldLineLimits = TextFieldLineLimits.Default, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, +) { + val isFocused by interactionSource.collectIsFocusedAsState() + BasicTextField( + state = state, + modifier = modifier, + textStyle = textFieldStyle(enabled), + interactionSource = interactionSource, + enabled = enabled, + readOnly = readOnly, + inputTransformation = inputTransformation, + cursorBrush = SolidColor(ElementTheme.colors.textPrimary), + keyboardOptions = keyboardOptions, + onKeyboardAction = onKeyboardAction, + lineLimits = lineLimits, + decorator = TextFieldDecorator { innerTextField -> + DecorationBox( + label = label, + readOnly = readOnly, + enabled = enabled, + isFocused = isFocused, + validity = validity, + leadingIcon = leadingIcon, + placeholder = placeholder, + isTextEmpty = state.text.isEmpty(), + innerTextField = innerTextField, + trailingIcon = trailingIcon, + supportingText = supportingText, + ) + } + ) +} + @Composable private fun DecorationBox( label: String?, From 167c1ced80e30b673597a8d7205f9f1d1af73066 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 15 Jun 2026 17:57:52 +0200 Subject: [PATCH 030/383] Add clear button in custom status text field, toggle Cancel/Save on text presence --- .../impl/userstatus/UserStatusView.kt | 60 +++++++------------ 1 file changed, 23 insertions(+), 37 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index efb06a42de..2f3495ec1e 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -19,9 +19,14 @@ import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.input.InputTransformation import androidx.compose.foundation.text.input.TextFieldLineLimits import androidx.compose.foundation.text.input.TextFieldState +import androidx.compose.foundation.text.input.clearText +import androidx.compose.foundation.text.input.maxLength import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.minimumInteractiveComponentSize 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.res.stringResource @@ -102,6 +107,9 @@ private fun EmptyStatusRow( headlineContent = { Text(text = stringResource(R.string.screen_preferences_user_status_placeholder)) }, + trailingContent = ListItemContent.Custom({ + Box(modifier = Modifier.minimumInteractiveComponentSize()) + }), leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Reaction())), modifier = modifier.clickable(onClick = onClick), ) @@ -169,19 +177,31 @@ private fun CustomStatusInputRow( onCancel: () -> Unit, modifier: Modifier = Modifier, ) { + val hasText by remember { derivedStateOf { textFieldState.text.isNotEmpty() } } ListItem( headlineContent = { TextField( state = textFieldState, placeholder = stringResource(R.string.screen_preferences_user_status_custom_hint), - inputTransformation = InputTransformation { if (length > 30) revertAllChanges() }, + inputTransformation = InputTransformation.maxLength(maxLength = 30), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), - onKeyboardAction = { if (textFieldState.text.isNotBlank()) onConfirm() }, + onKeyboardAction = { if (hasText) onConfirm() }, lineLimits = TextFieldLineLimits.SingleLine, + trailingIcon = if (hasText) { + { + IconButton(onClick = { textFieldState.clearText() }) { + Icon(imageVector = CompoundIcons.Close(), contentDescription = null) + } + } + } else null, ) }, trailingContent = ListItemContent.Custom({ - TextButton(onClick = onCancel, text = stringResource(CommonStrings.action_cancel)) + if (hasText) { + TextButton(onClick = onConfirm, text = stringResource(CommonStrings.action_save)) + } else { + TextButton(onClick = onCancel, text = stringResource(CommonStrings.action_cancel)) + } }), leadingContent = ListItemContent.Custom( { Surface( @@ -198,40 +218,6 @@ private fun CustomStatusInputRow( }), modifier = modifier, ) - - /* - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 4.dp), - ) { - Surface( - shape = CircleShape, - color = ElementTheme.colors.bgSubtleSecondary, - modifier = Modifier - .size(40.dp) - .clickable { }, - ) { - Box(contentAlignment = Alignment.Center) { - Text(text = emoji, style = ElementTheme.typography.fontBodyLgRegular) - } - } - TextField( - value = text, - onValueChange = { if (it.length <= 30) text = it }, - placeholder = stringResource(R.string.screen_preferences_user_status_custom_hint), - keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), - keyboardActions = KeyboardActions( - onDone = { if (text.isNotBlank()) onConfirm(emoji, text) } - ), - singleLine = true, - modifier = Modifier.weight(1f).padding(horizontal = 8.dp), - ) - TextButton(onClick = onCancel, text = stringResource(CommonStrings.action_cancel)) - } - - */ } @PreviewsDayNight From 889fd08b5c20cc2d5b9dd6b61332e95b94d76282 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 16 Jun 2026 11:25:08 +0200 Subject: [PATCH 031/383] Fix button width jitter using rememberTextMeasurer to derive stable min-width --- .../impl/userstatus/UserStatusView.kt | 49 +++++++++++++------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index 2f3495ec1e..0c11faaaec 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -10,10 +10,9 @@ package io.element.android.features.preferences.impl.userstatus import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box -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.foundation.layout.widthIn import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.input.InputTransformation @@ -29,8 +28,10 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons @@ -38,8 +39,6 @@ import io.element.android.features.preferences.impl.R import io.element.android.libraries.designsystem.components.list.ListItemContent 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.TextField 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 @@ -48,6 +47,7 @@ import io.element.android.libraries.designsystem.theme.components.ModalBottomShe 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.components.TextButton +import io.element.android.libraries.designsystem.theme.components.TextField import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.api.user.UserStatus import io.element.android.libraries.ui.strings.CommonStrings @@ -128,7 +128,9 @@ private fun CurrentStatusRow( } ListItem( headlineContent = { Text(text = text) }, - leadingContent = ListItemContent.Text(emoji), + leadingContent = ListItemContent.Custom({ + Text(text = emoji, modifier = Modifier.size(24.dp)) + }), trailingContent = ListItemContent.Custom({ IconButton(onClick = onClear) { Icon(imageVector = CompoundIcons.Close(), contentDescription = null) @@ -178,32 +180,47 @@ private fun CustomStatusInputRow( modifier: Modifier = Modifier, ) { val hasText by remember { derivedStateOf { textFieldState.text.isNotEmpty() } } + val saveLabel = stringResource(CommonStrings.action_save) + val cancelLabel = stringResource(CommonStrings.action_cancel) + val textStyle = ElementTheme.typography.fontBodyLgMedium + val density = LocalDensity.current + val textMeasurer = rememberTextMeasurer() + // Measure both labels and derive a stable min-width so the button never resizes. + // 24.dp = 12.dp start + 12.dp end padding of TextButton (Large, no icon). + val minButtonWidth = remember(textMeasurer, textStyle, saveLabel, cancelLabel) { + val saveWidth = textMeasurer.measure(saveLabel, textStyle).size.width + val cancelWidth = textMeasurer.measure(cancelLabel, textStyle).size.width + with(density) { maxOf(saveWidth, cancelWidth).toDp() } + 24.dp + } ListItem( headlineContent = { TextField( + modifier = Modifier.fillMaxWidth(), state = textFieldState, placeholder = stringResource(R.string.screen_preferences_user_status_custom_hint), inputTransformation = InputTransformation.maxLength(maxLength = 30), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), onKeyboardAction = { if (hasText) onConfirm() }, lineLimits = TextFieldLineLimits.SingleLine, - trailingIcon = if (hasText) { - { - IconButton(onClick = { textFieldState.clearText() }) { - Icon(imageVector = CompoundIcons.Close(), contentDescription = null) + trailingIcon = { + if (hasText) { + Box(modifier = Modifier.clickable { + textFieldState.clearText() + }) { + Icon(imageVector = CompoundIcons.Close(), contentDescription = stringResource(CommonStrings.action_cancel)) } } - } else null, + } ) }, trailingContent = ListItemContent.Custom({ - if (hasText) { - TextButton(onClick = onConfirm, text = stringResource(CommonStrings.action_save)) - } else { - TextButton(onClick = onCancel, text = stringResource(CommonStrings.action_cancel)) - } + TextButton( + onClick = if (hasText) onConfirm else onCancel, + text = if (hasText) saveLabel else cancelLabel, + modifier = Modifier.widthIn(min = minButtonWidth), + ) }), - leadingContent = ListItemContent.Custom( { + leadingContent = ListItemContent.Custom({ Surface( shape = CircleShape, border = BorderStroke(1.dp, ElementTheme.colors.bgSubtleSecondary), From 078b63fd7cc6b8f85d9c8f00af90912bec73b1c5 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 16 Jun 2026 11:32:47 +0200 Subject: [PATCH 032/383] Move preview cases to UserStatusStateProvider, use @PreviewParameter in view --- .../userstatus/UserStatusStateProvider.kt | 14 ++++++++ .../impl/userstatus/UserStatusView.kt | 35 ++----------------- 2 files changed, 17 insertions(+), 32 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.kt index 65ec264cc4..7a7a1d4dac 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.kt @@ -7,7 +7,21 @@ package io.element.android.features.preferences.impl.userstatus +import androidx.compose.foundation.text.input.TextFieldState +import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.matrix.api.user.DisplayedStatus +import io.element.android.libraries.matrix.api.user.UserStatus + +internal class UserStatusStateProvider : PreviewParameterProvider { + override val values get() = sequenceOf( + aUserStatusState(), + aUserStatusState(displayedStatus = DisplayedStatus.UserSet(UserStatus("🌴", "Away"))), + aUserStatusState(displayedStatus = DisplayedStatus.InCall(callJoinedTs = 0L)), + aUserStatusState(pickerState = UserStatusPickerState.ShowingPicker), + aUserStatusState(pickerState = UserStatusPickerState.CustomInput(emoji = "😀", textFieldState = TextFieldState())), + aUserStatusState(pickerState = UserStatusPickerState.CustomInput(emoji = "🚀", textFieldState = TextFieldState("Working on something"))), + ) +} fun aUserStatusState( displayedStatus: DisplayedStatus? = null, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index 0c11faaaec..3c30701834 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -37,6 +37,7 @@ 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.designsystem.components.list.ListItemContent +import androidx.compose.ui.tooling.preview.PreviewParameter 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 @@ -239,36 +240,6 @@ private fun CustomStatusInputRow( @PreviewsDayNight @Composable -internal fun UserStatusRowEmptyPreview() = ElementPreview { - UserStatusRow( - state = UserStatusState( - displayedStatus = null, - pickerState = UserStatusPickerState.Hidden, - eventSink = {}, - ) - ) -} - -@PreviewsDayNight -@Composable -internal fun UserStatusRowSetPreview() = ElementPreview { - UserStatusRow( - state = UserStatusState( - displayedStatus = DisplayedStatus.UserSet(UserStatus("🌴", "Away")), - pickerState = UserStatusPickerState.Hidden, - eventSink = {}, - ) - ) -} - -@PreviewsDayNight -@Composable -internal fun UserStatusRowCustomInputPreview() = ElementPreview { - UserStatusRow( - state = UserStatusState( - displayedStatus = null, - pickerState = UserStatusPickerState.CustomInput(emoji = "😀", textFieldState = TextFieldState()), - eventSink = {}, - ) - ) +internal fun UserStatusRowPreview(@PreviewParameter(UserStatusStateProvider::class) state: UserStatusState) = ElementPreview { + UserStatusRow(state = state) } From 2a0e41652af273fa7a0d435a943ae7ccdbf39c13 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 16 Jun 2026 12:13:58 +0200 Subject: [PATCH 033/383] Match row heights: add vertical padding to plain text rows to align with TextField row --- .../impl/userstatus/UserStatusView.kt | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index 3c30701834..035861f243 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -10,8 +10,9 @@ package io.element.android.features.preferences.impl.userstatus import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.visible import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.KeyboardOptions @@ -32,12 +33,12 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.rememberTextMeasurer +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.preferences.impl.R import io.element.android.libraries.designsystem.components.list.ListItemContent -import androidx.compose.ui.tooling.preview.PreviewParameter 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 @@ -106,7 +107,10 @@ private fun EmptyStatusRow( ) { ListItem( headlineContent = { - Text(text = stringResource(R.string.screen_preferences_user_status_placeholder)) + Text( + text = stringResource(R.string.screen_preferences_user_status_placeholder), + modifier = Modifier.padding(vertical = 16.dp), + ) }, trailingContent = ListItemContent.Custom({ Box(modifier = Modifier.minimumInteractiveComponentSize()) @@ -128,7 +132,7 @@ private fun CurrentStatusRow( is DisplayedStatus.InCall -> "🎧" to stringResource(R.string.common_user_status_on_a_call) } ListItem( - headlineContent = { Text(text = text) }, + headlineContent = { Text(text = text, modifier = Modifier.padding(vertical = 16.dp)) }, leadingContent = ListItemContent.Custom({ Text(text = emoji, modifier = Modifier.size(24.dp)) }), @@ -187,16 +191,15 @@ private fun CustomStatusInputRow( val density = LocalDensity.current val textMeasurer = rememberTextMeasurer() // Measure both labels and derive a stable min-width so the button never resizes. - // 24.dp = 12.dp start + 12.dp end padding of TextButton (Large, no icon). - val minButtonWidth = remember(textMeasurer, textStyle, saveLabel, cancelLabel) { + // 32.dp = 16.dp start + 16.dp end padding of TextButton (Large, no icon). + val actionButtonWidth = remember(textMeasurer, textStyle, saveLabel, cancelLabel) { val saveWidth = textMeasurer.measure(saveLabel, textStyle).size.width val cancelWidth = textMeasurer.measure(cancelLabel, textStyle).size.width - with(density) { maxOf(saveWidth, cancelWidth).toDp() } + 24.dp + with(density) { maxOf(saveWidth, cancelWidth).toDp() } + 32.dp } ListItem( headlineContent = { TextField( - modifier = Modifier.fillMaxWidth(), state = textFieldState, placeholder = stringResource(R.string.screen_preferences_user_status_custom_hint), inputTransformation = InputTransformation.maxLength(maxLength = 30), @@ -204,12 +207,14 @@ private fun CustomStatusInputRow( onKeyboardAction = { if (hasText) onConfirm() }, lineLimits = TextFieldLineLimits.SingleLine, trailingIcon = { - if (hasText) { - Box(modifier = Modifier.clickable { - textFieldState.clearText() - }) { - Icon(imageVector = CompoundIcons.Close(), contentDescription = stringResource(CommonStrings.action_cancel)) - } + Box(modifier = Modifier.clickable(enabled = hasText) { + textFieldState.clearText() + }) { + Icon( + imageVector = CompoundIcons.Close(), + contentDescription = stringResource(CommonStrings.action_cancel), + modifier = Modifier.visible(hasText) + ) } } ) @@ -218,7 +223,7 @@ private fun CustomStatusInputRow( TextButton( onClick = if (hasText) onConfirm else onCancel, text = if (hasText) saveLabel else cancelLabel, - modifier = Modifier.widthIn(min = minButtonWidth), + modifier = Modifier.widthIn(min = actionButtonWidth), ) }), leadingContent = ListItemContent.Custom({ From 553a4785e182739c7e629f9e434a8a0375ecd83c Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 17 Jun 2026 11:05:53 +0200 Subject: [PATCH 034/383] Rename Event --- .../impl/userstatus/UserStatusEvent.kt | 15 ++++----------- .../impl/userstatus/UserStatusPresenter.kt | 14 ++++++-------- .../impl/userstatus/UserStatusState.kt | 2 +- .../preferences/impl/userstatus/UserStatusView.kt | 12 ++++++------ .../impl/userstatus/UserStatusPresenterTest.kt | 15 +++++++-------- 5 files changed, 24 insertions(+), 34 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt index 80dd02e08a..815cd12d66 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusEvent.kt @@ -10,18 +10,11 @@ package io.element.android.features.preferences.impl.userstatus import io.element.android.libraries.matrix.api.user.UserStatus sealed interface UserStatusEvent { - /** User tapped the status row — open the picker bottom sheet. */ - data object Open : UserStatusEvent - /** User dismissed the bottom sheet without selecting. */ - data object Dismiss : UserStatusEvent - /** User selected a predefined or confirmed a custom status. */ - data class Set(val status: UserStatus) : UserStatusEvent - /** User tapped "Custom…" in the bottom sheet. */ + data object OpenPicker : UserStatusEvent + data object DismissPicker : UserStatusEvent + data class SetStatus(val status: UserStatus) : UserStatusEvent data object OpenCustomInput : UserStatusEvent - /** User tapped Cancel in the inline custom input row. */ data object CancelCustomInput : UserStatusEvent - /** User changed the emoji in the custom input row. */ data class UpdateCustomEmoji(val emoji: String) : UserStatusEvent - /** User tapped the clear action on an existing status. */ - data object Clear : UserStatusEvent + data object ClearStatus : UserStatusEvent } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt index 0bb626b159..384e09862a 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt @@ -7,8 +7,8 @@ package io.element.android.features.preferences.impl.userstatus -import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.foundation.text.input.clearText +import androidx.compose.foundation.text.input.rememberTextFieldState import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -18,11 +18,9 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import dev.zacsweers.metro.ContributesBinding -import dev.zacsweers.metro.Inject import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient -import io.element.android.libraries.matrix.api.user.UserStatus import kotlinx.coroutines.launch @ContributesBinding(SessionScope::class) @@ -34,13 +32,13 @@ class UserStatusPresenter( override fun present(): UserStatusState { val userProfile by matrixClient.userProfile.collectAsState() var pickerState by remember { mutableStateOf(UserStatusPickerState.Hidden) } - val customTextFieldState = remember { TextFieldState() } + val customTextFieldState = rememberTextFieldState() val coroutineScope = rememberCoroutineScope() fun handleEvent(event: UserStatusEvent) { when (event) { - UserStatusEvent.Open -> pickerState = UserStatusPickerState.ShowingPicker - UserStatusEvent.Dismiss -> pickerState = UserStatusPickerState.Hidden + UserStatusEvent.OpenPicker -> pickerState = UserStatusPickerState.ShowingPicker + UserStatusEvent.DismissPicker -> pickerState = UserStatusPickerState.Hidden UserStatusEvent.OpenCustomInput -> { val raw = userProfile.rawStatus if (raw != null) { @@ -53,11 +51,11 @@ class UserStatusPresenter( textFieldState = customTextFieldState, ) } - is UserStatusEvent.Set -> { + is UserStatusEvent.SetStatus -> { pickerState = UserStatusPickerState.Hidden coroutineScope.launch { matrixClient.setUserStatus(event.status) } } - UserStatusEvent.Clear -> { + UserStatusEvent.ClearStatus -> { pickerState = UserStatusPickerState.Hidden coroutineScope.launch { matrixClient.clearUserStatus() } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt index b1fe11d1ed..f79ae86d8b 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt @@ -22,7 +22,7 @@ sealed interface UserStatusPickerState { data object Hidden : UserStatusPickerState data object ShowingPicker : UserStatusPickerState data class CustomInput( - val emoji: String = "😀", + val emoji: String, val textFieldState: TextFieldState, ) : UserStatusPickerState } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index 035861f243..e211fb1110 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -65,20 +65,20 @@ fun UserStatusRow( if (displayedStatus != null) { CurrentStatusRow( displayedStatus = displayedStatus, - onClick = { state.eventSink(UserStatusEvent.Open) }, - onClear = { state.eventSink(UserStatusEvent.Clear) }, + onClick = { state.eventSink(UserStatusEvent.OpenPicker) }, + onClear = { state.eventSink(UserStatusEvent.ClearStatus) }, modifier = modifier, ) } else { EmptyStatusRow( - onClick = { state.eventSink(UserStatusEvent.Open) }, + onClick = { state.eventSink(UserStatusEvent.OpenPicker) }, modifier = modifier, ) } if (pickerState == UserStatusPickerState.ShowingPicker) { UserStatusPickerBottomSheet( - onDismiss = { state.eventSink(UserStatusEvent.Dismiss) }, - onSelectPredefined = { status -> state.eventSink(UserStatusEvent.Set(status)) }, + onDismiss = { state.eventSink(UserStatusEvent.DismissPicker) }, + onSelectPredefined = { status -> state.eventSink(UserStatusEvent.SetStatus(status)) }, onSelectCustom = { state.eventSink(UserStatusEvent.OpenCustomInput) }, ) } @@ -90,7 +90,7 @@ fun UserStatusRow( onEmojiChange = { state.eventSink(UserStatusEvent.UpdateCustomEmoji(it)) }, onConfirm = { state.eventSink( - UserStatusEvent.Set(UserStatus(pickerState.emoji, pickerState.textFieldState.text.toString())) + UserStatusEvent.SetStatus(UserStatus(pickerState.emoji, pickerState.textFieldState.text.toString())) ) }, onCancel = { state.eventSink(UserStatusEvent.CancelCustomInput) }, diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt index 349361a61b..455aefe180 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt @@ -16,7 +16,6 @@ import io.element.android.libraries.matrix.api.user.UserStatus import io.element.android.libraries.matrix.test.FakeMatrixClient import kotlinx.coroutines.test.runTest import org.junit.Test -import androidx.compose.foundation.text.input.TextFieldState class UserStatusPresenterTest { @@ -40,7 +39,7 @@ class UserStatusPresenterTest { createPresenter().present() }.test { val state = awaitItem() - state.eventSink(UserStatusEvent.Open) + state.eventSink(UserStatusEvent.OpenPicker) assertThat(awaitItem().pickerState).isEqualTo(UserStatusPickerState.ShowingPicker) } } @@ -51,9 +50,9 @@ class UserStatusPresenterTest { createPresenter().present() }.test { val state = awaitItem() - state.eventSink(UserStatusEvent.Open) + state.eventSink(UserStatusEvent.OpenPicker) awaitItem() // ShowingPicker - state.eventSink(UserStatusEvent.Dismiss) + state.eventSink(UserStatusEvent.DismissPicker) assertThat(awaitItem().pickerState).isEqualTo(UserStatusPickerState.Hidden) } } @@ -65,7 +64,7 @@ class UserStatusPresenterTest { createPresenter(client).present() }.test { val status = UserStatus(emoji = "💬", text = "In a meeting") - awaitItem().eventSink(UserStatusEvent.Set(status)) + awaitItem().eventSink(UserStatusEvent.SetStatus(status)) val newState = awaitItem() assertThat(newState.pickerState).isEqualTo(UserStatusPickerState.Hidden) assertThat(newState.displayedStatus).isEqualTo(DisplayedStatus.UserSet(status)) @@ -93,7 +92,7 @@ class UserStatusPresenterTest { createPresenter(client).present() }.test { val status = UserStatus(emoji = "🌴", text = "Away") - awaitItem().eventSink(UserStatusEvent.Set(status)) + awaitItem().eventSink(UserStatusEvent.SetStatus(status)) // Single emission: pickerState=Hidden and displayedStatus both set in one recomposition awaitItem().eventSink(UserStatusEvent.OpenCustomInput) val state = awaitItem() @@ -133,9 +132,9 @@ class UserStatusPresenterTest { createPresenter(client).present() }.test { val status = UserStatus(emoji = "☕", text = "Be right back") - awaitItem().eventSink(UserStatusEvent.Set(status)) + awaitItem().eventSink(UserStatusEvent.SetStatus(status)) // Single emission: pickerState=Hidden and displayedStatus both set in one recomposition - awaitItem().eventSink(UserStatusEvent.Clear) + awaitItem().eventSink(UserStatusEvent.ClearStatus) val clearedState = awaitItem() assertThat(clearedState.pickerState).isEqualTo(UserStatusPickerState.Hidden) assertThat(clearedState.displayedStatus).isNull() From 1cfd3e4dfb64f2d479098b70f8d06f342a62cb55 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 17 Jun 2026 15:55:49 +0200 Subject: [PATCH 035/383] Improve UI/UX for setting status --- .../impl/userstatus/UserStatusPresenter.kt | 1 + .../impl/userstatus/UserStatusState.kt | 2 + .../userstatus/UserStatusStateProvider.kt | 7 ++ .../impl/userstatus/UserStatusView.kt | 109 ++++++++++++------ .../impl/root/PreferencesRootViewTest.kt | 9 +- 5 files changed, 91 insertions(+), 37 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt index 384e09862a..e5c22fd568 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt @@ -69,6 +69,7 @@ class UserStatusPresenter( return UserStatusState( displayedStatus = userProfile.displayedStatus, + rawStatus = userProfile.rawStatus, pickerState = pickerState, eventSink = ::handleEvent, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt index f79ae86d8b..7cfa03fa81 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt @@ -11,9 +11,11 @@ import androidx.annotation.StringRes import androidx.compose.foundation.text.input.TextFieldState import io.element.android.features.preferences.impl.R import io.element.android.libraries.matrix.api.user.DisplayedStatus +import io.element.android.libraries.matrix.api.user.UserStatus data class UserStatusState( val displayedStatus: DisplayedStatus?, + val rawStatus: UserStatus?, val pickerState: UserStatusPickerState, val eventSink: (UserStatusEvent) -> Unit, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.kt index 7a7a1d4dac..087cb85355 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.kt @@ -18,6 +18,11 @@ internal class UserStatusStateProvider : PreviewParameterProvider Unit = {}, ) = UserStatusState( displayedStatus = displayedStatus, + rawStatus = rawStatus, pickerState = pickerState, eventSink = eventSink, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index e211fb1110..1b0b8a478d 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -12,8 +12,6 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.visible -import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.input.InputTransformation @@ -23,16 +21,22 @@ import androidx.compose.foundation.text.input.clearText import androidx.compose.foundation.text.input.maxLength import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.minimumInteractiveComponentSize +import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.layout.Layout import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction -import androidx.compose.ui.text.rememberTextMeasurer +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.Constraints import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -46,6 +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.ListItem import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet +import io.element.android.libraries.designsystem.theme.components.hide 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.components.TextButton @@ -77,6 +82,7 @@ fun UserStatusRow( } if (pickerState == UserStatusPickerState.ShowingPicker) { UserStatusPickerBottomSheet( + currentRawStatus = state.rawStatus, onDismiss = { state.eventSink(UserStatusEvent.DismissPicker) }, onSelectPredefined = { status -> state.eventSink(UserStatusEvent.SetStatus(status)) }, onSelectCustom = { state.eventSink(UserStatusEvent.OpenCustomInput) }, @@ -87,6 +93,7 @@ fun UserStatusRow( CustomStatusInputRow( emoji = pickerState.emoji, textFieldState = pickerState.textFieldState, + rawStatus = state.rawStatus, onEmojiChange = { state.eventSink(UserStatusEvent.UpdateCustomEmoji(it)) }, onConfirm = { state.eventSink( @@ -134,7 +141,7 @@ private fun CurrentStatusRow( ListItem( headlineContent = { Text(text = text, modifier = Modifier.padding(vertical = 16.dp)) }, leadingContent = ListItemContent.Custom({ - Text(text = emoji, modifier = Modifier.size(24.dp)) + Text(text = emoji, modifier = Modifier.size(24.dp), textAlign = TextAlign.Center) }), trailingContent = ListItemContent.Custom({ IconButton(onClick = onClear) { @@ -149,19 +156,38 @@ private fun CurrentStatusRow( @OptIn(ExperimentalMaterial3Api::class) @Composable private fun UserStatusPickerBottomSheet( + currentRawStatus: UserStatus?, onDismiss: () -> Unit, onSelectPredefined: (UserStatus) -> Unit, onSelectCustom: () -> Unit, modifier: Modifier = Modifier, ) { - ModalBottomSheet(onDismissRequest = onDismiss, scrollable = true, modifier = modifier) { + val sheetState = rememberModalBottomSheetState() + val coroutineScope = rememberCoroutineScope() + ModalBottomSheet( + onDismissRequest = onDismiss, + sheetState = sheetState, + scrollable = true, + modifier = modifier, + ) { PredefinedUserStatus.entries.forEach { predefined -> val label = stringResource(predefined.labelRes) + val predefinedUserStatus = UserStatus(emoji = predefined.emoji, text = label) + val isSelected = currentRawStatus == predefinedUserStatus ListItem( headlineContent = { Text(text = label) }, leadingContent = ListItemContent.Text(text = predefined.emoji), + trailingContent = if (isSelected) ListItemContent.Custom({ + Icon( + imageVector = CompoundIcons.Check(), + contentDescription = null, + tint = ElementTheme.colors.iconAccentPrimary, + ) + }) else null, onClick = { - onSelectPredefined(UserStatus(emoji = predefined.emoji, text = label)) + sheetState.hide(coroutineScope) { + onSelectPredefined(predefinedUserStatus) + } }, ) } @@ -170,7 +196,11 @@ private fun UserStatusPickerBottomSheet( Text(text = stringResource(R.string.common_user_status_custom)) }, leadingContent = ListItemContent.Text(text = "✏️"), - onClick = onSelectCustom, + onClick = { + sheetState.hide(coroutineScope) { + onSelectCustom() + } + }, ) } } @@ -179,52 +209,63 @@ private fun UserStatusPickerBottomSheet( private fun CustomStatusInputRow( emoji: String, textFieldState: TextFieldState, + rawStatus: UserStatus?, onEmojiChange: (String) -> Unit, onConfirm: () -> Unit, onCancel: () -> Unit, modifier: Modifier = Modifier, ) { val hasText by remember { derivedStateOf { textFieldState.text.isNotEmpty() } } + val hasChanges by remember(emoji, rawStatus) { + derivedStateOf { + val text = textFieldState.text.toString() + text.isNotBlank() && UserStatus(emoji, text) != rawStatus + } + } val saveLabel = stringResource(CommonStrings.action_save) val cancelLabel = stringResource(CommonStrings.action_cancel) - val textStyle = ElementTheme.typography.fontBodyLgMedium - val density = LocalDensity.current - val textMeasurer = rememberTextMeasurer() - // Measure both labels and derive a stable min-width so the button never resizes. - // 32.dp = 16.dp start + 16.dp end padding of TextButton (Large, no icon). - val actionButtonWidth = remember(textMeasurer, textStyle, saveLabel, cancelLabel) { - val saveWidth = textMeasurer.measure(saveLabel, textStyle).size.width - val cancelWidth = textMeasurer.measure(cancelLabel, textStyle).size.width - with(density) { maxOf(saveWidth, cancelWidth).toDp() } + 32.dp - } + val focusRequester = remember { FocusRequester() } + LaunchedEffect(Unit) { focusRequester.requestFocus() } ListItem( headlineContent = { TextField( + modifier = Modifier.focusRequester(focusRequester), state = textFieldState, placeholder = stringResource(R.string.screen_preferences_user_status_custom_hint), inputTransformation = InputTransformation.maxLength(maxLength = 30), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), - onKeyboardAction = { if (hasText) onConfirm() }, + onKeyboardAction = { if (hasChanges) onConfirm() }, lineLimits = TextFieldLineLimits.SingleLine, - trailingIcon = { - Box(modifier = Modifier.clickable(enabled = hasText) { - textFieldState.clearText() - }) { - Icon( - imageVector = CompoundIcons.Close(), - contentDescription = stringResource(CommonStrings.action_cancel), - modifier = Modifier.visible(hasText) - ) + trailingIcon = if (hasText) { + { + Box(modifier = Modifier.clickable { textFieldState.clearText() }) { + Icon( + imageVector = CompoundIcons.Close(), + contentDescription = stringResource(CommonStrings.action_cancel), + modifier = Modifier.size(22.dp), + ) + } } - } + } else null ) }, trailingContent = ListItemContent.Custom({ - TextButton( - onClick = if (hasText) onConfirm else onCancel, - text = if (hasText) saveLabel else cancelLabel, - modifier = Modifier.widthIn(min = actionButtonWidth), - ) + // Layout measures both buttons to determine the max natural width, + // then places only the active one — no hardcoded padding values needed. + Layout( + content = { + TextButton(onClick = onConfirm, text = saveLabel) + TextButton(onClick = onCancel, text = cancelLabel) + } + ) { measurables, constraints -> + val placeables = measurables.map { it.measure(Constraints()) } + val maxWidth = placeables.maxOf { it.width } + val maxHeight = placeables.maxOf { it.height } + layout(maxWidth, maxHeight) { + if (hasChanges) placeables[0].placeRelative(0, 0) + else placeables[1].placeRelative(0, 0) + } + } }), leadingContent = ListItemContent.Custom({ Surface( 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 5c9d81875e..bf8bd78bf2 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 @@ -202,7 +202,8 @@ class PreferencesRootViewTest : RobolectricTest() { ), onOpenAnalytics = callback, ) - clickOn(CommonStrings.common_analytics) + val text = activity!!.getString(CommonStrings.common_analytics) + onNode(hasText(text) and hasClickAction()).performScrollTo().performClick() } } @@ -229,7 +230,8 @@ class PreferencesRootViewTest : RobolectricTest() { ), onOpenRageShake = callback, ) - clickOn(CommonStrings.common_report_a_problem) + val text = activity!!.getString(CommonStrings.common_report_a_problem) + onNode(hasText(text) and hasClickAction()).performScrollTo().performClick() } } @@ -393,7 +395,8 @@ class PreferencesRootViewTest : RobolectricTest() { ), onSignOutClick = callback, ) - clickOn(CommonStrings.action_signout) + val text = activity!!.getString(CommonStrings.action_signout) + onNode(hasText(text) and hasClickAction()).performScrollTo().performClick() } } From dd24e14cf61f6f64fa4b139f2b7dad3519acb819 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 17 Jun 2026 17:20:58 +0200 Subject: [PATCH 036/383] Gate user status behind UserStatus feature flag --- .../impl/root/PreferencesRootPresenter.kt | 4 +- .../impl/root/PreferencesRootState.kt | 2 +- .../impl/root/PreferencesRootStateProvider.kt | 2 +- .../impl/root/PreferencesRootView.kt | 39 ++++++++++++++----- .../libraries/featureflag/api/FeatureFlags.kt | 7 ++++ 5 files changed, 40 insertions(+), 14 deletions(-) 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 fa69382cf8..3daeb5aec1 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 @@ -62,20 +62,20 @@ class PreferencesRootPresenter( ) : Presenter { @Composable override fun present(): PreferencesRootState { - val userStatusState = userStatusPresenter.present() val coroutineScope = rememberCoroutineScope() val matrixUser = matrixClient.userProfile.collectAsState() LaunchedEffect(Unit) { // Force a refresh of the profile matrixClient.getUserProfile() } - val isMultiAccountEnabled by remember { featureFlagService.isFeatureEnabledFlow(FeatureFlags.MultiAccount) }.collectAsState(initial = false) val showLinkNewDevice by remember { featureFlagService.isFeatureEnabledFlow(FeatureFlags.QrCodeLogin) }.collectAsState(initial = false) + val isUserStatusEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.UserStatus).collectAsState(initial = false) + val userStatusState = if (isUserStatusEnabled) userStatusPresenter.present() else null val otherSessions by remember { sessionStore.sessionsFlow().map { list -> 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 8163e4b7a0..c415547a80 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 @@ -17,7 +17,7 @@ import kotlinx.collections.immutable.ImmutableList data class PreferencesRootState( val myUser: MatrixUser, - val userStatusState: UserStatusState, + val userStatusState: UserStatusState?, val version: String, val deviceId: DeviceId?, val isMultiAccountEnabled: Boolean, 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 9e1557fd7b..1ac2e1f6f5 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 @@ -88,7 +88,7 @@ fun aPreferencesRootState( nbOfBlockedUsers: Int = 0, showLabsItem: Boolean = false, directLogoutState: DirectLogoutState = aDirectLogoutState(), - userStatusState: UserStatusState = aUserStatusState(), + userStatusState: UserStatusState? = aUserStatusState(), snackbarMessage: SnackbarMessage? = null, eventSink: (PreferencesRootEvent) -> Unit = {}, ) = PreferencesRootState( 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 d92c1e4613..5221c82dda 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 @@ -25,6 +25,7 @@ import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.preferences.impl.R import io.element.android.features.preferences.impl.user.UserPreferences import io.element.android.features.preferences.impl.userstatus.UserStatusRow +import io.element.android.features.preferences.impl.userstatus.UserStatusState 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 @@ -82,15 +83,14 @@ fun PreferencesRootView( }, matrixUser = state.myUser, ) - HorizontalDivider() - UserStatusRow( - state = state.userStatusState, - modifier = Modifier.fillMaxWidth(), - ) - HorizontalDivider() + + if (state.userStatusState != null) { + UserStatusSection(state.userStatusState) + } if (state.isMultiAccountEnabled) { MultiAccountSection( state = state, + showTopDivider = state.userStatusState == null, onAddAccountClick = onAddAccountClick, ) } @@ -135,14 +135,33 @@ fun PreferencesRootView( } @Composable -private fun ColumnScope.MultiAccountSection( - state: PreferencesRootState, - onAddAccountClick: () -> Unit, -) { +private fun ColumnScope.UserStatusSection(userStatusState: UserStatusState) { HorizontalDivider( thickness = 8.dp, color = ElementTheme.colors.bgSubtleSecondary, ) + UserStatusRow( + state = userStatusState, + modifier = Modifier.fillMaxWidth(), + ) + HorizontalDivider( + thickness = 8.dp, + color = ElementTheme.colors.bgSubtleSecondary, + ) +} + +@Composable +private fun ColumnScope.MultiAccountSection( + state: PreferencesRootState, + showTopDivider: Boolean, + onAddAccountClick: () -> Unit, +) { + if(showTopDivider) { + HorizontalDivider( + thickness = 8.dp, + color = ElementTheme.colors.bgSubtleSecondary, + ) + } state.otherSessions.forEach { matrixUser -> MatrixUserRow( modifier = Modifier 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 0127e41c99..b298cd2f16 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 @@ -137,4 +137,11 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), + UserStatus( + key = "feature.user_status", + title = "User status", + description = "Allow users to set a status (e.g. In a meeting, Away) visible to their contacts.", + defaultValue = { false }, + isFinished = false, + ), } From d29dad40f944baccff300caf725c3a7496d41385 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 17 Jun 2026 17:37:21 +0200 Subject: [PATCH 037/383] Extract custom status text max length into a constant --- .../features/preferences/impl/userstatus/UserStatusView.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index 1b0b8a478d..a39c72f0d7 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -205,6 +205,8 @@ private fun UserStatusPickerBottomSheet( } } +private const val CUSTOM_STATUS_TEXT_MAX_LENGTH = 30 + @Composable private fun CustomStatusInputRow( emoji: String, @@ -232,7 +234,7 @@ private fun CustomStatusInputRow( modifier = Modifier.focusRequester(focusRequester), state = textFieldState, placeholder = stringResource(R.string.screen_preferences_user_status_custom_hint), - inputTransformation = InputTransformation.maxLength(maxLength = 30), + inputTransformation = InputTransformation.maxLength(CUSTOM_STATUS_TEXT_MAX_LENGTH), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), onKeyboardAction = { if (hasChanges) onConfirm() }, lineLimits = TextFieldLineLimits.SingleLine, From 061fd82c1ad136be8542f19a8109f28c6eca37be Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 17 Jun 2026 17:37:39 +0200 Subject: [PATCH 038/383] Clip avatar to a circle on the user status screen --- .../features/preferences/impl/userstatus/UserStatusView.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index a39c72f0d7..7856be468a 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.layout.Layout import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction @@ -275,6 +276,7 @@ private fun CustomStatusInputRow( border = BorderStroke(1.dp, ElementTheme.colors.bgSubtleSecondary), modifier = Modifier .size(50.dp) + .clip(CircleShape) .clickable { }, ) { Box(contentAlignment = Alignment.Center) { From be872e6becb360141d4c36c0c86031ba3fd3926d Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 18 Jun 2026 16:42:22 +0200 Subject: [PATCH 039/383] Move user status section below multi-account in preferences --- .../impl/root/PreferencesRootStateProvider.kt | 6 ++- .../impl/root/PreferencesRootView.kt | 48 +++++++++---------- 2 files changed, 29 insertions(+), 25 deletions(-) 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 1ac2e1f6f5..8e931d37be 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 @@ -11,11 +11,14 @@ 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.features.preferences.impl.userstatus.PredefinedUserStatus +import io.element.android.features.preferences.impl.userstatus.UserStatusPickerState import io.element.android.features.preferences.impl.userstatus.UserStatusState import io.element.android.features.preferences.impl.userstatus.aUserStatusState 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.api.user.UserStatus 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 @@ -66,8 +69,9 @@ open class PreferencesRootStateProvider : PreviewParameterProvider Unit, ) { if(showTopDivider) { HorizontalDivider( @@ -162,6 +143,25 @@ private fun ColumnScope.MultiAccountSection( color = ElementTheme.colors.bgSubtleSecondary, ) } + UserStatusRow( + state = userStatusState, + modifier = Modifier.fillMaxWidth(), + ) + HorizontalDivider( + thickness = 1.dp, + color = ElementTheme.colors.bgSubtleSecondary, + ) +} + +@Composable +private fun ColumnScope.MultiAccountSection( + state: PreferencesRootState, + onAddAccountClick: () -> Unit, +) { + HorizontalDivider( + thickness = 8.dp, + color = ElementTheme.colors.bgSubtleSecondary, + ) state.otherSessions.forEach { matrixUser -> MatrixUserRow( modifier = Modifier From 4a143c10537a3c7b1e9b2e8193179371b1b16297 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 18 Jun 2026 20:22:09 +0200 Subject: [PATCH 040/383] Format code --- .../impl/root/PreferencesRootStateProvider.kt | 2 -- .../impl/root/PreferencesRootView.kt | 2 +- .../impl/userstatus/UserStatusPresenter.kt | 1 - .../impl/userstatus/UserStatusView.kt | 29 ++++++++++++------- .../userstatus/UserStatusPresenterTest.kt | 1 - .../libraries/matrix/api/MatrixClient.kt | 1 + 6 files changed, 21 insertions(+), 15 deletions(-) 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 8e931d37be..0abed1f66f 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 @@ -11,14 +11,12 @@ 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.features.preferences.impl.userstatus.PredefinedUserStatus import io.element.android.features.preferences.impl.userstatus.UserStatusPickerState import io.element.android.features.preferences.impl.userstatus.UserStatusState import io.element.android.features.preferences.impl.userstatus.aUserStatusState 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.api.user.UserStatus 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 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 5baf01d960..324f0a9773 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 @@ -137,7 +137,7 @@ private fun ColumnScope.UserStatusSection( userStatusState: UserStatusState, showTopDivider: Boolean, ) { - if(showTopDivider) { + if (showTopDivider) { HorizontalDivider( thickness = 8.dp, color = ElementTheme.colors.bgSubtleSecondary, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt index e5c22fd568..fac82d4505 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt @@ -27,7 +27,6 @@ import kotlinx.coroutines.launch class UserStatusPresenter( private val matrixClient: MatrixClient, ) : Presenter { - @Composable override fun present(): UserStatusState { val userProfile by matrixClient.userProfile.collectAsState() diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index 7856be468a..f7d37f0adf 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -23,22 +23,22 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.minimumInteractiveComponentSize import androidx.compose.material3.rememberModalBottomSheetState 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.runtime.LaunchedEffect import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.layout.Layout import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.Constraints import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons @@ -51,11 +51,11 @@ 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.ModalBottomSheet -import io.element.android.libraries.designsystem.theme.components.hide 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.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextField +import io.element.android.libraries.designsystem.theme.components.hide import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.api.user.UserStatus import io.element.android.libraries.ui.strings.CommonStrings @@ -178,13 +178,17 @@ private fun UserStatusPickerBottomSheet( ListItem( headlineContent = { Text(text = label) }, leadingContent = ListItemContent.Text(text = predefined.emoji), - trailingContent = if (isSelected) ListItemContent.Custom({ + trailingContent = if (isSelected) { + ListItemContent.Custom({ Icon( imageVector = CompoundIcons.Check(), contentDescription = null, tint = ElementTheme.colors.iconAccentPrimary, ) - }) else null, + }) + } else { + null + }, onClick = { sheetState.hide(coroutineScope) { onSelectPredefined(predefinedUserStatus) @@ -249,7 +253,9 @@ private fun CustomStatusInputRow( ) } } - } else null + } else { + null + } ) }, trailingContent = ListItemContent.Custom({ @@ -265,8 +271,11 @@ private fun CustomStatusInputRow( val maxWidth = placeables.maxOf { it.width } val maxHeight = placeables.maxOf { it.height } layout(maxWidth, maxHeight) { - if (hasChanges) placeables[0].placeRelative(0, 0) - else placeables[1].placeRelative(0, 0) + if (hasChanges) { + placeables[0].placeRelative(0, 0) + } else { + placeables[1].placeRelative(0, 0) + } } } }), diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt index 455aefe180..4a03a22607 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt @@ -18,7 +18,6 @@ import kotlinx.coroutines.test.runTest import org.junit.Test class UserStatusPresenterTest { - private fun createPresenter(client: FakeMatrixClient = FakeMatrixClient()) = UserStatusPresenter(matrixClient = client) 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 001bac0d30..e7d010d510 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 @@ -86,6 +86,7 @@ interface MatrixClient { suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result suspend fun removeAvatar(): Result suspend fun setUserStatus(status: UserStatus): Result + /** Clears both m.status and m.call profile fields (maps to DELETE on the profile endpoint per MSC4426). */ suspend fun clearUserStatus(): Result suspend fun joinRoom(roomId: RoomId): Result From 29b8068d4a335f2dd5c73a693d8010b1ae0df727 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 19 Jun 2026 15:14:37 +0200 Subject: [PATCH 041/383] Address quality issues on user status --- .../impl/root/PreferencesRootView.kt | 4 ++-- .../userstatus/UserStatusBindingContainer.kt | 21 +++++++++++++++++++ .../impl/userstatus/UserStatusPresenter.kt | 5 ++--- .../impl/userstatus/UserStatusState.kt | 4 +++- .../impl/userstatus/UserStatusView.kt | 20 ++++++++---------- .../matrix/api/user/DisplayedStatus.kt | 2 ++ .../libraries/matrix/impl/RustMatrixClient.kt | 1 + 7 files changed, 40 insertions(+), 17 deletions(-) create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusBindingContainer.kt 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 324f0a9773..8f272ea8ae 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 @@ -24,8 +24,8 @@ 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.features.preferences.impl.user.UserPreferences -import io.element.android.features.preferences.impl.userstatus.UserStatusRow import io.element.android.features.preferences.impl.userstatus.UserStatusState +import io.element.android.features.preferences.impl.userstatus.UserStatusView 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 @@ -143,7 +143,7 @@ private fun ColumnScope.UserStatusSection( color = ElementTheme.colors.bgSubtleSecondary, ) } - UserStatusRow( + UserStatusView( state = userStatusState, modifier = Modifier.fillMaxWidth(), ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusBindingContainer.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusBindingContainer.kt new file mode 100644 index 0000000000..dfa77483f8 --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusBindingContainer.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.features.preferences.impl.userstatus + +import dev.zacsweers.metro.BindingContainer +import dev.zacsweers.metro.Binds +import dev.zacsweers.metro.ContributesTo +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.di.SessionScope + +@ContributesTo(SessionScope::class) +@BindingContainer +interface UserStatusBindingContainer { + @Binds + fun bindUserStatusPresenter(presenter: UserStatusPresenter): Presenter +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt index fac82d4505..ea09f59706 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt @@ -17,13 +17,12 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue -import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.Inject import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient import kotlinx.coroutines.launch -@ContributesBinding(SessionScope::class) +@Inject class UserStatusPresenter( private val matrixClient: MatrixClient, ) : Presenter { diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt index 7cfa03fa81..fa61089144 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt @@ -9,6 +9,7 @@ package io.element.android.features.preferences.impl.userstatus import androidx.annotation.StringRes import androidx.compose.foundation.text.input.TextFieldState +import androidx.compose.runtime.Immutable import io.element.android.features.preferences.impl.R import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.api.user.UserStatus @@ -20,6 +21,7 @@ data class UserStatusState( val eventSink: (UserStatusEvent) -> Unit, ) +@Immutable sealed interface UserStatusPickerState { data object Hidden : UserStatusPickerState data object ShowingPicker : UserStatusPickerState @@ -29,7 +31,7 @@ sealed interface UserStatusPickerState { ) : UserStatusPickerState } -enum class PredefinedUserStatus(val emoji: String, @param:StringRes val labelRes: Int) { +enum class PredefinedUserStatus(val emoji: String, @StringRes val labelRes: Int) { IN_A_MEETING("💬", R.string.common_user_status_in_a_meeting), FOCUS_TIME("💡", R.string.common_user_status_focus_time), ON_THE_ROAD("🚙", R.string.common_user_status_on_the_road), diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index f7d37f0adf..245052120c 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -61,7 +61,7 @@ import io.element.android.libraries.matrix.api.user.UserStatus import io.element.android.libraries.ui.strings.CommonStrings @Composable -fun UserStatusRow( +fun UserStatusView( state: UserStatusState, modifier: Modifier = Modifier, ) { @@ -85,8 +85,8 @@ fun UserStatusRow( UserStatusPickerBottomSheet( currentRawStatus = state.rawStatus, onDismiss = { state.eventSink(UserStatusEvent.DismissPicker) }, - onSelectPredefined = { status -> state.eventSink(UserStatusEvent.SetStatus(status)) }, - onSelectCustom = { state.eventSink(UserStatusEvent.OpenCustomInput) }, + onSelectPredefinedStatus = { status -> state.eventSink(UserStatusEvent.SetStatus(status)) }, + onSelectCustomStatus = { state.eventSink(UserStatusEvent.OpenCustomInput) }, ) } } @@ -95,7 +95,6 @@ fun UserStatusRow( emoji = pickerState.emoji, textFieldState = pickerState.textFieldState, rawStatus = state.rawStatus, - onEmojiChange = { state.eventSink(UserStatusEvent.UpdateCustomEmoji(it)) }, onConfirm = { state.eventSink( UserStatusEvent.SetStatus(UserStatus(pickerState.emoji, pickerState.textFieldState.text.toString())) @@ -159,8 +158,8 @@ private fun CurrentStatusRow( private fun UserStatusPickerBottomSheet( currentRawStatus: UserStatus?, onDismiss: () -> Unit, - onSelectPredefined: (UserStatus) -> Unit, - onSelectCustom: () -> Unit, + onSelectPredefinedStatus: (UserStatus) -> Unit, + onSelectCustomStatus: () -> Unit, modifier: Modifier = Modifier, ) { val sheetState = rememberModalBottomSheetState() @@ -191,7 +190,7 @@ private fun UserStatusPickerBottomSheet( }, onClick = { sheetState.hide(coroutineScope) { - onSelectPredefined(predefinedUserStatus) + onSelectPredefinedStatus(predefinedUserStatus) } }, ) @@ -203,7 +202,7 @@ private fun UserStatusPickerBottomSheet( leadingContent = ListItemContent.Text(text = "✏️"), onClick = { sheetState.hide(coroutineScope) { - onSelectCustom() + onSelectCustomStatus() } }, ) @@ -217,7 +216,6 @@ private fun CustomStatusInputRow( emoji: String, textFieldState: TextFieldState, rawStatus: UserStatus?, - onEmojiChange: (String) -> Unit, onConfirm: () -> Unit, onCancel: () -> Unit, modifier: Modifier = Modifier, @@ -299,6 +297,6 @@ private fun CustomStatusInputRow( @PreviewsDayNight @Composable -internal fun UserStatusRowPreview(@PreviewParameter(UserStatusStateProvider::class) state: UserStatusState) = ElementPreview { - UserStatusRow(state = state) +internal fun UserStatusViewPreview(@PreviewParameter(UserStatusStateProvider::class) state: UserStatusState) = ElementPreview { + UserStatusView(state = state) } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt index 046191d7cf..581658ff28 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt @@ -8,8 +8,10 @@ package io.element.android.libraries.matrix.api.user import android.os.Parcelable +import androidx.compose.runtime.Immutable import kotlinx.parcelize.Parcelize +@Immutable sealed interface DisplayedStatus : Parcelable { /** Status set manually by the user via m.status. */ @Parcelize 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 92107f3ac2..4d40fa2123 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 @@ -138,6 +138,7 @@ import org.matrix.rustcomponents.sdk.CreateRoomParameters as RustCreateRoomParam import org.matrix.rustcomponents.sdk.RoomPreset as RustRoomPreset import org.matrix.rustcomponents.sdk.SyncService as ClientSyncService +@Suppress("LargeClass") class RustMatrixClient( override val sessionPaths: SessionPaths, private val innerClient: Client, From f9a8acf4a55c1bd7f467b1a3f2dc438a609b2498 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 25 Jun 2026 10:50:51 +0000 Subject: [PATCH 042/383] Update screenshots --- ...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 | 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 ++-- ...res.preferences.impl.root_PreferencesRootViewDark_6_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 | 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 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_6_en.png | 3 +++ ...es.preferences.impl.userstatus_UserStatusView_Day_0_en.png | 3 +++ ...es.preferences.impl.userstatus_UserStatusView_Day_1_en.png | 3 +++ ...es.preferences.impl.userstatus_UserStatusView_Day_2_en.png | 3 +++ ...es.preferences.impl.userstatus_UserStatusView_Day_3_en.png | 3 +++ ...es.preferences.impl.userstatus_UserStatusView_Day_4_en.png | 3 +++ ...es.preferences.impl.userstatus_UserStatusView_Day_5_en.png | 3 +++ ...es.preferences.impl.userstatus_UserStatusView_Day_6_en.png | 3 +++ ....preferences.impl.userstatus_UserStatusView_Night_0_en.png | 3 +++ ....preferences.impl.userstatus_UserStatusView_Night_1_en.png | 3 +++ ....preferences.impl.userstatus_UserStatusView_Night_2_en.png | 3 +++ ....preferences.impl.userstatus_UserStatusView_Night_3_en.png | 3 +++ ....preferences.impl.userstatus_UserStatusView_Night_4_en.png | 3 +++ ....preferences.impl.userstatus_UserStatusView_Night_5_en.png | 3 +++ ....preferences.impl.userstatus_UserStatusView_Night_6_en.png | 3 +++ 28 files changed, 72 insertions(+), 24 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_6_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_6_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png 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 6e46211c3e..4e4f3b0fd3 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:cff89dace11868ae57ad7c701303ab19096be52bbc21f7b43f91097fe8a612f1 -size 40300 +oid sha256:4b3d5527423e0bb16a65fc9981db06b7e5eaef2736e68833dd91aae5825b9126 +size 40439 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 053b0cf1f6..312a9bad45 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:92420711d5445edf625ff3125ecabbfbd4317dda6d7e29b4484a3b38d8d3193d -size 24297 +oid sha256:941f79f738e902fcca7e3ec2f71acc4c230532bdb2c9136a2e7420ac88106ba4 +size 27372 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 2c9cc8de20..32610f27d2 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:f36ead42cf5f79023ca960698b25864e44a098b71d4de8a4fbff6e2cb0a86b99 -size 35546 +oid sha256:dc80aa470630ec356274dec6abd0f05149506f4bb1c1b495a4ad8ee4efc8ac69 +size 38510 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 2d0012240f..08dc4d97cc 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:83085cec3cd4e3a8eb9c8b112d54d9aa1eaa6ca3206b5f526b6e0edc7392ce92 -size 26743 +oid sha256:a89c8eeebf6cba350daa4940ea8248148286341bf19a4b36f63330ab508bfa20 +size 29985 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 a89b3d05f5..9c32e85b15 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:6a9739c8908859f2401d118e32f4354a2132d6d08173c4e5683eaa1b8dee8cc5 -size 26897 +oid sha256:b5743d92c92425093ddeff2af31d8c3a803a029711aed1712c7cbc50890b0d77 +size 29992 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 d5f5b7f6ca..423bca1a33 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:c0d9335e3b6900a366d4770849736b7bc866bb205c9b6f004a3521d6a058916b -size 20020 +oid sha256:cfa5e8a6baef9873454a43857cfa7983ef64dc65a0ff8649ccc96ac1dac7f999 +size 32775 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_6_en.png new file mode 100644 index 0000000000..273cf6c781 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:837ebeb30aebfb154e98b1b4603156cf0ac877b58efae17d534aaf269ce8ba10 +size 20037 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 d527233adc..a1906506ce 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:a911c0f75b2146fffb24d3bddac02ae096eac871285ef15c4d1477629a5b2d49 -size 41390 +oid sha256:50da5b2b2851c4b13daadc44e81beaf19294985fb4c6e37caf2105f0bddc6bb6 +size 41628 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 77170a40ca..8b41f74ad9 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:dee0eff6123dca9f9b3ba544d2db16b1e2ab982d20a5d8a0013b0e08e37afddd -size 25094 +oid sha256:17fc2a4024aec430ca302e915f951c231d6f8c66de9030bc8acf64954cbd8d8b +size 28424 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 7be86a8757..09a752bb66 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:6fef2b0dd09457de0079e3c00ea6e07a81bfb7d0f500d228d38c9054b446708f -size 36271 +oid sha256:b766642d069f44c06f7a2bf74dba24070fc3260cb77cc9658d163d971b9573d4 +size 39408 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 046163551a..a95a91b731 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:9a8ef73ae13ff39f1612dde7582225a18656015c2608fa45510bef3d8a52a705 -size 27701 +oid sha256:db069c64c97811f2b311bb63c8dbb9f78f534bdb3475d7b433412350445ec894 +size 30937 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 1c8583ea33..ffa813f1ac 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:691bdc37a68ad14bf1ac08ff242861412915c597017b7980850fb2a82070c228 -size 27646 +oid sha256:66f3f2d1f043603f36187c2ea1e86f40628b23f0aed69f90e2452dbbae558133 +size 30888 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 5c6556e3b3..83b748ebff 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:41c88c94e910f524567d7054d7914eeddccff2b0249e331582ea1ab130d40d6a -size 20454 +oid sha256:0b82b065f1ea1dda8a159b5688c803ba2f7c7e1d60a31e51a9353a8ec1928321 +size 34166 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_6_en.png new file mode 100644 index 0000000000..d77f3adbf9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07ad7e092d6b8e41064bcbce131ef53d70a552dd6f9292dd286dd7c10948cf9a +size 20459 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_0_en.png new file mode 100644 index 0000000000..d98e3fd475 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c14e7ad5b7c320873dab0b97a6261b2b62a7405d133e9c53fe2184e9757becac +size 9203 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png new file mode 100644 index 0000000000..33a7b53d6d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:82cf75a0887b9482cd80e04b3c60b588930a0076571b4f5f7ea8247dc525a912 +size 7114 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png new file mode 100644 index 0000000000..58c1aa1c27 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c1b2766c7c6c3a27484944d772da87cd2b7acc42f25fd21f19bae6dffea204c +size 7232 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png new file mode 100644 index 0000000000..7f8cabb58b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c04a8ab290295a792e3b78d7155be66618aa3d054eb1009431f3d7ae9746f053 +size 28895 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png new file mode 100644 index 0000000000..6d8d5388c4 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6de59d47eeefb8c03c9ed0694c67b1666eb35cb7f178c57a52041a19b0398fde +size 27426 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png new file mode 100644 index 0000000000..f96db19f31 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:232de960e0b5aa52d824dabdd33b544847d940054b1f90197d48cb3160a7d818 +size 12079 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png new file mode 100644 index 0000000000..0fd9e3adb4 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5b44a0abf28f2b88bfc8d57e4b3c7ab248840f41190a389ac3c7b31e58202235 +size 11995 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_0_en.png new file mode 100644 index 0000000000..00a43265e2 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:343ddb8692135fb051766c340a4ac6143a5dc57917f0cc16fe11678f2b9bae6e +size 8774 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png new file mode 100644 index 0000000000..687070419e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4311673b25a516c05ca019b72604deb2115a36195d987c116b47f94d9220d82 +size 6736 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png new file mode 100644 index 0000000000..ea9751bafc --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8e4c37ef03cdf83319be9ad61a8ff6c91a6a33404680e66d81736563c2a2ec9 +size 6872 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png new file mode 100644 index 0000000000..0b5876ab7e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ec521e4dcc594b59eb159aee39141f1dd94ba10fcacfaa33159c4280b8e22ea +size 27739 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png new file mode 100644 index 0000000000..696fea1cf9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:168aef1da5c35f252d49f77866608a010c0ce42c1c1f6daa2ca0f115a5b5e3cf +size 26228 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png new file mode 100644 index 0000000000..15ea618fb7 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:260a44e1132a30150bd94b4232750b768cd1e74b1b149dc1e2d2261061ebf08d +size 11721 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png new file mode 100644 index 0000000000..0dbf6deb0d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27297084473b61e5dc49ab399785433e73caaada5c29684d346e982a2476077d +size 11428 From 4efc82fa74ef7abe36417605c55f04ee2c8787e6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 1 Jul 2026 17:29:09 +0200 Subject: [PATCH 043/383] A11y: Add programmatic label and keyboard focus indicator to PIN entry field Fixes: https://github.com/element-hq/element-x-android/issues/6391 Fixes: https://github.com/element-hq/element-x-android/issues/6401 Co-Authored-By: Claude Sonnet 4.6 --- .../impl/components/PinEntryTextField.kt | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt index 439c6aeaa7..dbbabb390c 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt @@ -22,8 +22,18 @@ import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.Text 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.focus.onFocusChanged +import androidx.compose.ui.res.pluralStringResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -32,6 +42,8 @@ import io.element.android.features.lockscreen.impl.pin.model.PinEntry import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.pinDigitBg +import io.element.android.libraries.ui.strings.CommonPlurals +import io.element.android.libraries.ui.strings.CommonStrings @Composable fun PinEntryTextField( @@ -40,15 +52,21 @@ fun PinEntryTextField( onValueChange: (String) -> Unit, modifier: Modifier = Modifier, ) { + var isFocused by remember { mutableStateOf(false) } + val filledCount = pinEntry.digits.count { it is PinDigit.Filled } + val pinFieldLabel = stringResource(CommonStrings.a11y_pin_field) + val digitsEnteredLabel = pluralStringResource(CommonPlurals.a11y_digits_entered, filledCount, filledCount) BasicTextField( - modifier = modifier, + modifier = modifier + .onFocusChanged { isFocused = it.isFocused } + .semantics { contentDescription = "$pinFieldLabel, $digitsEnteredLabel" }, value = pinEntry.toText(), onValueChange = { onValueChange(it) }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.NumberPassword), decorationBox = { - PinEntryRow(pinEntry = pinEntry, isSecured = isSecured) + PinEntryRow(pinEntry = pinEntry, isSecured = isSecured, isFocused = isFocused) } ) } @@ -58,8 +76,14 @@ fun PinEntryTextField( private fun PinEntryRow( pinEntry: PinEntry, isSecured: Boolean, + isFocused: Boolean = false, ) { FlowRow( + modifier = Modifier.border( + width = 2.dp, + color = if (isFocused) ElementTheme.colors.borderInteractiveHovered else Color.Transparent, + shape = RoundedCornerShape(8.dp), + ), horizontalArrangement = Arrangement.spacedBy(8.dp, alignment = Alignment.CenterHorizontally), verticalArrangement = Arrangement.spacedBy(8.dp), ) { From 26e4e895a9cd1dbfa09a75dee70b321ffc642e16 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 1 Jul 2026 17:51:12 +0200 Subject: [PATCH 044/383] Fix accessibility: announce checked/unchecked state for invite user rows (#6407) Replace clickable(role = Role.Checkbox) with toggleable(value = checked, role = Role.Checkbox) so TalkBack can announce the current state and state changes. Set the inner Checkbox.onCheckedChange = null to make it a purely visual indicator, avoiding duplicate accessibility focus on the same control. Co-Authored-By: Claude Sonnet 4.6 --- .../libraries/matrix/ui/components/CheckableUserRow.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableUserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableUserRow.kt index 917b03f309..dfcc154da4 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableUserRow.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableUserRow.kt @@ -8,12 +8,12 @@ package io.element.android.libraries.matrix.ui.components -import androidx.compose.foundation.clickable 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.width +import androidx.compose.foundation.selection.toggleable import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.ui.Alignment @@ -39,8 +39,8 @@ fun CheckableUserRow( Row( modifier = modifier .fillMaxWidth() - .clickable(role = Role.Checkbox, enabled = enabled) { - onCheckedChange(!checked) + .toggleable(value = checked, role = Role.Checkbox, enabled = enabled) { + onCheckedChange(it) }, verticalAlignment = Alignment.CenterVertically, ) { @@ -65,7 +65,7 @@ fun CheckableUserRow( } } Checkbox( - onCheckedChange = onCheckedChange, + onCheckedChange = null, checked = checked, enabled = enabled, ) From 416da32c4066715fd8f34801c4a9d39405c30447 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 2 Jul 2026 13:38:25 +0200 Subject: [PATCH 045/383] Set focused state only on the digit. --- .../impl/components/PinEntryTextField.kt | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt index dbbabb390c..8014504950 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt @@ -28,12 +28,11 @@ 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.focus.onFocusChanged 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.semantics import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -59,7 +58,9 @@ fun PinEntryTextField( BasicTextField( modifier = modifier .onFocusChanged { isFocused = it.isFocused } - .semantics { contentDescription = "$pinFieldLabel, $digitsEnteredLabel" }, + .clearAndSetSemantics { + contentDescription = "$pinFieldLabel, $digitsEnteredLabel" + }, value = pinEntry.toText(), onValueChange = { onValueChange(it) @@ -76,19 +77,18 @@ fun PinEntryTextField( private fun PinEntryRow( pinEntry: PinEntry, isSecured: Boolean, - isFocused: Boolean = false, + isFocused: Boolean, ) { FlowRow( - modifier = Modifier.border( - width = 2.dp, - color = if (isFocused) ElementTheme.colors.borderInteractiveHovered else Color.Transparent, - shape = RoundedCornerShape(8.dp), - ), horizontalArrangement = Arrangement.spacedBy(8.dp, alignment = Alignment.CenterHorizontally), verticalArrangement = Arrangement.spacedBy(8.dp), ) { - for (digit in pinEntry.digits) { - PinDigitView(digit = digit, isSecured = isSecured) + pinEntry.digits.forEachIndexed { index, digit -> + PinDigitView( + digit = digit, + isSecured = isSecured, + isFocused = isFocused && index == pinEntry.digits.indexOfFirst { it is PinDigit.Empty } + ) } } } @@ -97,11 +97,16 @@ private fun PinEntryRow( private fun PinDigitView( digit: PinDigit, isSecured: Boolean, + isFocused: Boolean, ) { val shape = RoundedCornerShape(8.dp) val appearanceModifier = when (digit) { PinDigit.Empty -> { - Modifier.border(1.dp, ElementTheme.colors.iconPrimary, shape) + if (isFocused) { + Modifier.border(2.dp, ElementTheme.colors.borderFocused, shape) + } else { + Modifier.border(1.dp, ElementTheme.colors.iconSecondary, shape) + } } is PinDigit.Filled -> { Modifier.background(ElementTheme.colors.pinDigitBg, shape) From 25716f6f3a257aa3058cab97b0da705b9028b211 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 2 Jul 2026 15:33:20 +0200 Subject: [PATCH 046/383] Fix regression --- .../features/lockscreen/impl/components/PinEntryTextField.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt index 8014504950..2feaf5f01e 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt @@ -105,7 +105,7 @@ private fun PinDigitView( if (isFocused) { Modifier.border(2.dp, ElementTheme.colors.borderFocused, shape) } else { - Modifier.border(1.dp, ElementTheme.colors.iconSecondary, shape) + Modifier.border(1.dp, ElementTheme.colors.iconPrimary, shape) } } is PinDigit.Filled -> { From bf1ace48f2ea062391cd78175abdacaf53ce83d0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 2 Jul 2026 15:38:53 +0200 Subject: [PATCH 047/383] Improve preview. --- .../impl/components/PinEntryTextField.kt | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt index 2feaf5f01e..bbdd5ce038 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt @@ -15,7 +15,6 @@ import androidx.compose.foundation.layout.Box 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.size import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicTextField @@ -50,8 +49,9 @@ fun PinEntryTextField( isSecured: Boolean, onValueChange: (String) -> Unit, modifier: Modifier = Modifier, + initialIsFocus: Boolean = false, ) { - var isFocused by remember { mutableStateOf(false) } + var isFocused by remember { mutableStateOf(initialIsFocus) } val filledCount = pinEntry.digits.count { it is PinDigit.Filled } val pinFieldLabel = stringResource(CommonStrings.a11y_pin_field) val digitsEnteredLabel = pluralStringResource(CommonPlurals.a11y_digits_entered, filledCount, filledCount) @@ -137,18 +137,19 @@ private fun PinDigitView( internal fun PinEntryTextFieldPreview() { ElementPreview { val pinEntry = PinEntry.createEmpty(4).fillWith("12") - Column { - PinEntryTextField( - pinEntry = pinEntry, - isSecured = true, - onValueChange = {}, - ) - Spacer(modifier = Modifier.size(16.dp)) - PinEntryTextField( - pinEntry = pinEntry, - isSecured = false, - onValueChange = {}, - ) + Column( + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { + listOf(true, false).forEach { isSecured -> + listOf(true, false).forEach { initialIsFocus -> + PinEntryTextField( + pinEntry = pinEntry, + isSecured = isSecured, + initialIsFocus = initialIsFocus, + onValueChange = {}, + ) + } + } } } } From bfe21698f21e3a927478861f31c497ae3fd4f819 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 2 Jul 2026 18:04:43 +0200 Subject: [PATCH 048/383] Tweak some UserStatusView ui --- .../impl/userstatus/UserStatusView.kt | 59 +++++++++++-------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index 245052120c..dfc68ff446 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -10,8 +10,10 @@ package io.element.android.features.preferences.impl.userstatus import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.sizeIn import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.input.InputTransformation @@ -34,11 +36,11 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.layout.Layout +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons @@ -140,12 +142,17 @@ private fun CurrentStatusRow( } ListItem( headlineContent = { Text(text = text, modifier = Modifier.padding(vertical = 16.dp)) }, - leadingContent = ListItemContent.Custom({ - Text(text = emoji, modifier = Modifier.size(24.dp), textAlign = TextAlign.Center) - }), + leadingContent = ListItemContent.Custom { EmojiText(emoji) }, trailingContent = ListItemContent.Custom({ - IconButton(onClick = onClear) { - Icon(imageVector = CompoundIcons.Close(), contentDescription = null) + IconButton( + onClick = onClear, + // Remove the extra padding caused by IconButton + modifier = Modifier.offset(x = 12.dp) + ) { + Icon( + imageVector = CompoundIcons.Close(), + contentDescription = stringResource(CommonStrings.action_clear), + ) } }), onClick = onClick, @@ -153,6 +160,18 @@ private fun CurrentStatusRow( ) } +@Composable +private fun EmojiText(emoji: String) { + // Ensure the emoji doesn't scale with fontSize to match icons size + val fontSize = with(LocalDensity.current) { 16.dp.toSp() } + Text( + modifier = Modifier.sizeIn(minWidth = 24.dp, minHeight = 24.dp), + text = emoji, + textAlign = TextAlign.Center, + style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSize), + ) +} + @OptIn(ExperimentalMaterial3Api::class) @Composable private fun UserStatusPickerBottomSheet( @@ -176,15 +195,9 @@ private fun UserStatusPickerBottomSheet( val isSelected = currentRawStatus == predefinedUserStatus ListItem( headlineContent = { Text(text = label) }, - leadingContent = ListItemContent.Text(text = predefined.emoji), + leadingContent = ListItemContent.Custom { EmojiText(predefined.emoji) }, trailingContent = if (isSelected) { - ListItemContent.Custom({ - Icon( - imageVector = CompoundIcons.Check(), - contentDescription = null, - tint = ElementTheme.colors.iconAccentPrimary, - ) - }) + ListItemContent.Icon(IconSource.Vector(CompoundIcons.Check()), tintColor = ElementTheme.colors.iconAccentPrimary) } else { null }, @@ -199,7 +212,7 @@ private fun UserStatusPickerBottomSheet( headlineContent = { Text(text = stringResource(R.string.common_user_status_custom)) }, - leadingContent = ListItemContent.Text(text = "✏️"), + leadingContent = ListItemContent.Custom { EmojiText("✏️") }, onClick = { sheetState.hide(coroutineScope) { onSelectCustomStatus() @@ -258,22 +271,22 @@ private fun CustomStatusInputRow( }, trailingContent = ListItemContent.Custom({ // Layout measures both buttons to determine the max natural width, - // then places only the active one — no hardcoded padding values needed. + // then places only the active one. Layout( content = { TextButton(onClick = onConfirm, text = saveLabel) TextButton(onClick = onCancel, text = cancelLabel) } ) { measurables, constraints -> - val placeables = measurables.map { it.measure(Constraints()) } + val placeables = measurables.map { it.measure(constraints) } val maxWidth = placeables.maxOf { it.width } val maxHeight = placeables.maxOf { it.height } layout(maxWidth, maxHeight) { - if (hasChanges) { - placeables[0].placeRelative(0, 0) - } else { - placeables[1].placeRelative(0, 0) - } + val active = if (hasChanges) placeables[0] else placeables[1] + active.placeRelative( + x = (maxWidth - active.width) / 2, + y = (maxHeight - active.height) / 2, + ) } } }), @@ -287,7 +300,7 @@ private fun CustomStatusInputRow( .clickable { }, ) { Box(contentAlignment = Alignment.Center) { - Text(text = emoji, style = ElementTheme.typography.fontBodyLgRegular) + EmojiText(emoji) } } }), From 301f930bcc55e053c7a208bd347db32eb0ea3bb4 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 2 Jul 2026 17:55:54 +0000 Subject: [PATCH 049/383] Update screenshots --- ...res.preferences.impl.root_PreferencesRootViewDark_5_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_5_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_1_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_2_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_3_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_4_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_5_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_6_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_1_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_2_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_3_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_4_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_5_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_6_en.png | 4 ++-- 14 files changed, 28 insertions(+), 28 deletions(-) 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 423bca1a33..f6b76e38e7 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:cfa5e8a6baef9873454a43857cfa7983ef64dc65a0ff8649ccc96ac1dac7f999 -size 32775 +oid sha256:7c75ad887209b88e700c6ad53090ed4c2d7e5a3f49836608999e9a3124a63fc0 +size 32869 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 83b748ebff..13957a0450 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:0b82b065f1ea1dda8a159b5688c803ba2f7c7e1d60a31e51a9353a8ec1928321 -size 34166 +oid sha256:f12abebdcc42404c0a5719c490f5da4d3d5a1986d469884773bf9ed8071dd27b +size 34154 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png index 33a7b53d6d..0607484ce0 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82cf75a0887b9482cd80e04b3c60b588930a0076571b4f5f7ea8247dc525a912 -size 7114 +oid sha256:35f0fb99a74477ebfa53a019ded68043035de9ba0f86a6a71b032137a125d107 +size 7168 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png index 58c1aa1c27..9f77167b6e 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c1b2766c7c6c3a27484944d772da87cd2b7acc42f25fd21f19bae6dffea204c -size 7232 +oid sha256:6432133a87271013cab796baa7d48ab8e96f65f049b92a9074ec03f540e11545 +size 7269 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png index 7f8cabb58b..470324716e 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c04a8ab290295a792e3b78d7155be66618aa3d054eb1009431f3d7ae9746f053 -size 28895 +oid sha256:ebc88a04da18e07b5f94cc52f75ad033fa01917de6c32ac77a1b400fd27c62cd +size 28944 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png index 6d8d5388c4..56c7646b1b 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6de59d47eeefb8c03c9ed0694c67b1666eb35cb7f178c57a52041a19b0398fde -size 27426 +oid sha256:3cff5ee1c0cc217b20c68bb4f4d2335ab03e9dd8d16045550358e748002c538b +size 27460 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png index f96db19f31..1f73455d54 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:232de960e0b5aa52d824dabdd33b544847d940054b1f90197d48cb3160a7d818 -size 12079 +oid sha256:b5dc5c492ed3fd552e77c0be85b639d55bc7e976f15b761f927b0b80ecca601d +size 12115 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png index 0fd9e3adb4..0ca6f66438 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5b44a0abf28f2b88bfc8d57e4b3c7ab248840f41190a389ac3c7b31e58202235 -size 11995 +oid sha256:5896eb5df6f5398bdb94e74280d0d5c04b6a5a53c2378b7377c60fa58eef544b +size 12013 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png index 687070419e..b6c2706180 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4311673b25a516c05ca019b72604deb2115a36195d987c116b47f94d9220d82 -size 6736 +oid sha256:b4b5eb36080cc5750c4cd36ae66ba618c033e794fdf0a4fb5afbae5e1fa10824 +size 6789 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png index ea9751bafc..0b65cb998b 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d8e4c37ef03cdf83319be9ad61a8ff6c91a6a33404680e66d81736563c2a2ec9 -size 6872 +oid sha256:bf614dc03afdb990baae40b020bd3f3d6396226b45fc4eee18f2d55100df5bff +size 6918 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png index 0b5876ab7e..2aca39dc8d 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ec521e4dcc594b59eb159aee39141f1dd94ba10fcacfaa33159c4280b8e22ea -size 27739 +oid sha256:fff529404e3219d00ded2f701066c48506b96512b08b1750665d3c2c0a75ed97 +size 27700 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png index 696fea1cf9..5ff2f9b93d 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:168aef1da5c35f252d49f77866608a010c0ce42c1c1f6daa2ca0f115a5b5e3cf -size 26228 +oid sha256:1017de34abdb57805946efdd6d486ab76adecdc458d17eb9b1128be0dbe8ff00 +size 26227 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index 15ea618fb7..a687241151 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:260a44e1132a30150bd94b4232750b768cd1e74b1b149dc1e2d2261061ebf08d -size 11721 +oid sha256:e7ce8a8c6b4d1692e4b127b7f17f507552666c631893025082c385b93d835a73 +size 11726 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png index 0dbf6deb0d..a1d1c5ec8e 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:27297084473b61e5dc49ab399785433e73caaada5c29684d346e982a2476077d -size 11428 +oid sha256:8b93c08531efbeacb55f84b17ac793a7b226e5a2db7bc5072e94bc040cd1e9bc +size 11386 From 06d778859c7187e372a71f5027d3ca4f7945d8e9 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 3 Jul 2026 07:58:47 +0000 Subject: [PATCH 050/383] Update screenshots --- ....lockscreen.impl.components_PinEntryTextField_Day_0_en.png | 4 ++-- ...ockscreen.impl.components_PinEntryTextField_Night_0_en.png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Day_0_en.png index 3ab1c052d2..3a22d6959f 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:76bb68d4ee420ec14a8c9372225c91407ab452479e0897c374721eb834dc6ba0 -size 9920 +oid sha256:2046f1225b2f58812502196f4b7d1c7a4d87f740b32e40dd82762fade1c42ea2 +size 16167 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Night_0_en.png index 18a2ab9466..10223f5bf6 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d72cda6587357da35dd5a22ff595dd0f9500dac14cf731a348e209bb17ed7b56 -size 9979 +oid sha256:62384687c273cb57dbd25bfaa558d83e3efc527fc4dfff4aca8bf85ab1ce9e4b +size 16446 From bad39d62e998170920943bb2c0a6ed58febfc81a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 3 Jul 2026 09:59:54 +0200 Subject: [PATCH 051/383] Optimize code --- .../features/lockscreen/impl/components/PinEntryTextField.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt index bbdd5ce038..28e005fd1d 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/components/PinEntryTextField.kt @@ -83,11 +83,12 @@ private fun PinEntryRow( horizontalArrangement = Arrangement.spacedBy(8.dp, alignment = Alignment.CenterHorizontally), verticalArrangement = Arrangement.spacedBy(8.dp), ) { + val focusedIndex = pinEntry.digits.indexOfFirst { it is PinDigit.Empty } pinEntry.digits.forEachIndexed { index, digit -> PinDigitView( digit = digit, isSecured = isSecured, - isFocused = isFocused && index == pinEntry.digits.indexOfFirst { it is PinDigit.Empty } + isFocused = isFocused && index == focusedIndex ) } } From 387022a9af91290525489ed3295035c681a98b54 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 7 Jul 2026 14:24:52 +0200 Subject: [PATCH 052/383] Use color from theme and improve preview of EmojiItem --- .../components/customreaction/EmojiItem.kt | 38 ++++++++++++------- .../customreaction/picker/SkinTonePicker.kt | 16 ++++---- 2 files changed, 33 insertions(+), 21 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 d934f53bfb..db5967e9a4 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 @@ -18,6 +18,7 @@ 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.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.sizeIn import androidx.compose.foundation.shape.CircleShape @@ -56,6 +57,7 @@ import io.element.android.features.messages.impl.timeline.components.customreact 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.features.messages.impl.timeline.components.customreaction.picker.aSkinList 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 @@ -219,6 +221,7 @@ fun EmojiItem( style = LocalTextStyle.current.copy(fontSize = emojiSize), ) if (hasSkinTones) { + val pickerIndicatorColor = ElementTheme.colors.borderInteractivePrimary Canvas( modifier = Modifier .align(Alignment.BottomEnd) @@ -230,7 +233,7 @@ fun EmojiItem( lineTo(0f, size.height) close() } - drawPath(path, color = Color.Gray.copy(alpha = 0.5f), style = Fill) + drawPath(path, color = pickerIndicatorColor, style = Fill) } } @@ -260,21 +263,28 @@ fun EmojiItem( @Composable internal fun EmojiItemPreview() = ElementPreview { Row( + modifier = Modifier.padding(4.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), ) { - for (isSelected in listOf(true, false)) { - EmojiItem( - item = Emoji( - hexcode = "", - label = "", - tags = null, - shortcodes = persistentListOf(), - unicode = "👍", - skins = null - ), - isSelected = isSelected, - onSelectEmoji = {}, - ) + for (isSelected in listOf(false, true)) { + for (skinList in listOf(persistentListOf(), aSkinList())) { + val hasSelectedSkinValues = if (skinList.isNotEmpty()) listOf(false, true) else listOf(false) + for (hasSelectedSkin in hasSelectedSkinValues) { + EmojiItem( + item = Emoji( + hexcode = "", + label = "", + tags = null, + shortcodes = persistentListOf(), + unicode = "👍", + skins = skinList, + ), + isSelected = isSelected, + onSelectEmoji = {}, + hasSelectedSkin = hasSelectedSkin, + ) + } + } } } } 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 c49b07023f..56540e8251 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 @@ -120,14 +120,16 @@ internal fun SkinTonePickerPreview() = ElementPreview { 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", "👍🏿"), - ), + skins = aSkinList(), ), onSelect = {}, ) } + +internal fun aSkinList() = 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", "👍🏿"), +) From 3ec7aa2a551650826bfc11563a20bfeeaf7503fe Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 7 Jul 2026 14:34:14 +0200 Subject: [PATCH 053/383] Remove default parameter values and make them not nullable. --- .../components/customreaction/EmojiItem.kt | 32 ++++++++++--------- .../customreaction/picker/EmojiPicker.kt | 8 ++--- .../customreaction/picker/SkinTonePicker.kt | 6 ++-- 3 files changed, 25 insertions(+), 21 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 db5967e9a4..a191de7202 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 @@ -70,13 +70,13 @@ fun EmojiItem( item: Emoji, isSelected: Boolean, onSelectEmoji: (Emoji) -> Unit, + onLongPress: (Emoji) -> Unit, + onDismissSkinPicker: () -> Unit, + skinPickerEmoji: Emoji?, + selectedSkinUnicodes: ImmutableSet, + hasSelectedSkin: Boolean, modifier: Modifier = Modifier, emojiSize: TextUnit = 20.sp, - onLongPress: ((Emoji) -> Unit)? = null, - skinPickerEmoji: Emoji? = null, - onDismissSkinPicker: (() -> Unit)? = null, - selectedSkinUnicodes: ImmutableSet = persistentSetOf(), - hasSelectedSkin: Boolean = false, ) { val backgroundColor = when { isSelected -> ElementTheme.colors.bgActionPrimaryRest @@ -139,12 +139,10 @@ fun EmojiItem( var startOffset = Offset.Zero detectDragGesturesAfterLongPress( onDragStart = { position -> - if (onLongPress != null) { - startOffset = position - dismissed = false - onLongPress(item) - hoveredIndex = -1 - } + startOffset = position + dismissed = false + onLongPress(item) + hoveredIndex = -1 }, onDrag = { change, _ -> if (!dismissed) { @@ -159,7 +157,7 @@ fun EmojiItem( if (!isValidDrag) { dismissed = true hoveredIndex = -1 - onDismissSkinPicker?.invoke() + onDismissSkinPicker() } else { val skinItemsCount = item.skins!!.size // Original + variants @@ -199,7 +197,7 @@ fun EmojiItem( } dismissed = false hoveredIndex = -1 - onDismissSkinPicker?.invoke() + onDismissSkinPicker() }, onDragCancel = { dismissed = false @@ -241,7 +239,7 @@ fun EmojiItem( val pickerHeight = SkinTonePadding * 2 + SkinToneSlotSize val popupOffsetPx = with(density) { -pickerHeight.roundToPx() } Popup( - onDismissRequest = { onDismissSkinPicker?.invoke() }, + onDismissRequest = { onDismissSkinPicker() }, alignment = Alignment.BottomCenter, offset = IntOffset(0, popupOffsetPx), ) { @@ -249,7 +247,7 @@ fun EmojiItem( emoji = item, onSelect = { selectedEmoji -> onSelectEmoji(selectedEmoji) - onDismissSkinPicker?.invoke() + onDismissSkinPicker() }, hoveredIndex = hoveredIndex, selectedUnicodes = selectedSkinUnicodes, @@ -282,6 +280,10 @@ internal fun EmojiItemPreview() = ElementPreview { isSelected = isSelected, onSelectEmoji = {}, hasSelectedSkin = hasSelectedSkin, + onLongPress = {}, + onDismissSkinPicker = {}, + skinPickerEmoji = null, + selectedSkinUnicodes = persistentSetOf(), ) } } 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 05fb849ce9..ce65a435f4 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 @@ -131,10 +131,10 @@ private fun EmojiResults( emojis: ImmutableList, isEmojiSelected: (Emoji) -> Boolean, onSelectEmoji: (Emoji) -> Unit, - onLongPress: ((Emoji) -> Unit)? = null, - skinPickerEmoji: Emoji? = null, - onDismissSkinPicker: (() -> Unit)? = null, - selectedEmojis: ImmutableSet = persistentSetOf(), + onLongPress: (Emoji) -> Unit, + skinPickerEmoji: Emoji?, + onDismissSkinPicker: () -> Unit, + selectedEmojis: ImmutableSet, ) { LazyVerticalGrid( modifier = Modifier.fillMaxSize(), 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 56540e8251..1ac66b5378 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 @@ -43,10 +43,10 @@ val SkinTonePadding = 4.dp @Composable fun SkinTonePicker( emoji: Emoji, + hoveredIndex: Int, + selectedUnicodes: ImmutableSet, onSelect: (Emoji) -> Unit, modifier: Modifier = Modifier, - hoveredIndex: Int = -1, - selectedUnicodes: ImmutableSet = persistentSetOf(), ) { val skins = emoji.skins.orEmpty() val emojiSize = 32.dp.toSp() @@ -122,6 +122,8 @@ internal fun SkinTonePickerPreview() = ElementPreview { unicode = "👍", skins = aSkinList(), ), + hoveredIndex = -1, + selectedUnicodes = persistentSetOf(), onSelect = {}, ) } From 243acf1ee05f9711484c53c1bc1e16397c85784b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 7 Jul 2026 15:19:18 +0200 Subject: [PATCH 054/383] Add more screenshots --- .../components/customreaction/EmojiItem.kt | 29 +++++++++++++++++++ .../tests/konsist/KonsistPreviewTest.kt | 1 + 2 files changed, 30 insertions(+) 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 a191de7202..db3a70715d 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 @@ -290,3 +290,32 @@ internal fun EmojiItemPreview() = ElementPreview { } } } + +@PreviewsDayNight +@Composable +internal fun EmojiItemWithPopupPreview() = ElementPreview { + Row( + modifier = Modifier + .padding(top = 100.dp, bottom = 4.dp, start = 200.dp, end = 200.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + val item = Emoji( + hexcode = "", + label = "", + tags = null, + shortcodes = persistentListOf(), + unicode = "👍", + skins = aSkinList(), + ) + EmojiItem( + item = item, + isSelected = false, + onSelectEmoji = {}, + hasSelectedSkin = false, + onLongPress = {}, + onDismissSkinPicker = {}, + skinPickerEmoji = item, + selectedSkinUnicodes = persistentSetOf("👍🏾"), + ) + } +} 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..ddd1082ace 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 @@ -87,6 +87,7 @@ class KonsistPreviewTest { "BackgroundVerticalGradientDisabledPreview", "BackgroundVerticalGradientPreview", "ColorAliasesPreview", + "EmojiItemWithPopupPreview", "FocusedEventPreview", "GradientFloatingActionButtonCircleShapePreview", "HeaderFooterPageScrollablePreview", From 4190939ff8d624b82161aa535387057035f935e9 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 7 Jul 2026 14:54:55 +0000 Subject: [PATCH 055/383] Update screenshots --- ....components.customreaction_EmojiItemWithPopup_Day_0_en.png | 3 +++ ...omponents.customreaction_EmojiItemWithPopup_Night_0_en.png | 3 +++ ....timeline.components.customreaction_EmojiItem_Day_0_en.png | 4 ++-- ...imeline.components.customreaction_EmojiItem_Night_0_en.png | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png new file mode 100644 index 0000000000..912b90b537 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4746d11c30648f7c517b0880021e5a1dc6ed2819af6c800b081b0d842ac2c384 +size 5325 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png new file mode 100644 index 0000000000..45011fea4d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eede6f990a7a1dbddee1cd9e722b30600160d475ad2ae72faebcb773f52aaa7b +size 20793 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en.png index 9ccf324c94..3971eb1c25 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f11b581b1b7b5b0098390067f1f227537a0d30687002e429937797e3cad57392 -size 7457 +oid sha256:d5d9248a5372da8d93013991d8487946f5a133987f75ae1aeccba9346b05d9ee +size 15280 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en.png index 1a1e717c8c..de8d641791 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c90af9a0afef94b7a960f5fc6b399412b05d6814d5da9ac920ff191f29ed05e3 -size 7477 +oid sha256:b415e40a4169a1b4d321daba926b3f90871109ecf49db1e1be9ed929580c21c7 +size 14963 From 4fd0be1fe5020ade909ecdea666058999509c697 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Tue, 7 Jul 2026 16:46:42 +0000 Subject: [PATCH 056/383] Review --- .../mediaupload/impl/AndroidMediaPreProcessor.kt | 6 +++--- .../mediaupload/impl/SvgDimensionExtractor.kt | 15 +++++++-------- 2 files changed, 10 insertions(+), 11 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 406f4e89bf..b374e530f4 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 @@ -223,10 +223,10 @@ class AndroidMediaPreProcessor( private suspend fun processSvgImage(uri: Uri, mimeType: String): MediaUploadInfo { Timber.d("Processing SVG image ${uri.path.orEmpty().hash()}") val file = copyToTmpFile(uri) - val (width, height) = svgDimensionExtractor.extractDimensions(file) + val size = svgDimensionExtractor.extractDimensions(file) val imageInfo = ImageInfo( - width = width, - height = height, + width = size.width.toLong(), + height = size.height.toLong(), mimetype = mimeType, size = file.length(), thumbnailInfo = null, diff --git a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/SvgDimensionExtractor.kt b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/SvgDimensionExtractor.kt index 5ef756a904..f32b596df1 100644 --- a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/SvgDimensionExtractor.kt +++ b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/SvgDimensionExtractor.kt @@ -1,6 +1,5 @@ /* - * 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. @@ -16,7 +15,7 @@ class SvgDimensionExtractor( private val defaultWidth: Long = 640L, private val defaultHeight: Long = 480L, ) { - fun extractDimensions(file: File): Pair { + fun extractDimensions(file: File): android.util.Size { return file.inputStream().use { inputStream -> try { val parser = Xml.newPullParser() @@ -32,7 +31,7 @@ class SvgDimensionExtractor( val parsedHeight = height?.let { parseLength(it) } if (parsedWidth != null && parsedHeight != null) { - return parsedWidth to parsedHeight + return android.util.Size(parsedWidth.toInt(), parsedHeight.toInt()) } if (viewBox != null) { @@ -40,17 +39,17 @@ class SvgDimensionExtractor( if (parts.size == 4 && parts[2] != null && parts[3] != null) { val vbWidth = parts[2]!!.toLong().coerceAtLeast(1) val vbHeight = parts[3]!!.toLong().coerceAtLeast(1) - return vbWidth to vbHeight + return android.util.Size(vbWidth.toInt(), vbHeight.toInt()) } } - return (parsedWidth ?: defaultWidth) to (parsedHeight ?: defaultHeight) + return android.util.Size((parsedWidth ?: defaultWidth).toInt(), (parsedHeight ?: defaultHeight).toInt()) } eventType = parser.next() } - defaultWidth to defaultHeight + android.util.Size(defaultWidth.toInt(), defaultHeight.toInt()) } catch (_: Exception) { - defaultWidth to defaultHeight + android.util.Size(defaultWidth.toInt(), defaultHeight.toInt()) } } } From 885e042c12f5210b66a27e3edef1a681a2862710 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 8 Jul 2026 09:50:22 +0200 Subject: [PATCH 057/383] Initial content scanner integration (#7139) * Create a `ContentScanner` component: - Add `:features:contentscanner:api` module with the interface. - Implement the concrete component using the Rust SDK in `:libraries:matrix:impl`. This can be used to both set up the content scanner media fetching in the SDK Client and manually scanning media sources from the Android side * Create `ContentScannerUrlProvider` in a new `:features:contentscaner:api` module as a noop implementation Use it as a placeholder for the code to instantiate a `RustContentScanner` with the fetched URL and set it as part of the SDK client. * Expose the optional `ContentScanner` in the `@SessionScope` * Split the storage part of the Element well-known retriever so it can be reused for the non-session bound retriever. Also add the new `content_scanner_url` field to it. This will be used by the enterprise code to fetch the actual content scanner url. * Bump enterprise commit to have access to the actual content scanner url provider implementation * Fix tests and lint issues * Use the right namespace for `:features:contentscanner:api`, also use the right namespace for `impl` --------- Co-authored-by: Benoit Marty --- enterprise | 2 +- features/contentscanner/api/build.gradle.kts | 23 ++ features/contentscanner/impl/build.gradle.kts | 35 +++ .../libraries/matrix/api/MatrixClient.kt | 2 + .../matrix/api/scanner/ContentScanner.kt | 27 ++ .../api/scanner/ContentScannerUrlProvider.kt | 18 ++ .../libraries/matrix/impl/RustMatrixClient.kt | 2 + .../matrix/impl/RustMatrixClientFactory.kt | 23 ++ .../matrix/impl/di/SessionMatrixModule.kt | 6 + .../DefaultContentScannerUrlProvider.kt | 20 ++ .../matrix/impl/scanner/RustContentScanner.kt | 42 +++ .../impl/RustMatrixClientFactoryTest.kt | 3 + .../matrix/impl/RustMatrixClientTest.kt | 2 + .../impl/scanner/FakeFfiContentScanner.kt | 24 ++ .../impl/scanner/RustContentScannerTest.kt | 56 ++++ .../libraries/matrix/test/FakeMatrixClient.kt | 2 + .../matrix/test/scanner/FakeContentScanner.kt | 19 ++ .../libraries/network/NetworkModule.kt | 4 + .../libraries/network/RetrofitFactory.kt | 6 +- .../wellknown/api/ElementWellKnown.kt | 1 + .../wellknown/api/ElementWellknownStore.kt | 14 + .../wellknown/api/WellknownRetrieverResult.kt | 6 + .../impl/DefaultSessionWellknownRetriever.kt | 70 +++-- .../wellknown/impl/DefaultWellKnownStore.kt | 63 ++++ .../impl/DefaultWellknownRetriever.kt | 12 +- .../impl/InternalElementWellKnown.kt | 2 + .../libraries/wellknown/impl/Mapper.kt | 3 +- .../DefaultSessionWellknownRetrieverTest.kt | 68 ++-- .../impl/DefaultWellKnownStoreTest.kt | 158 ++++++++++ .../impl/DefaultWellknownRetrieverTest.kt | 291 ++++++++++++++++++ libraries/wellknown/test/build.gradle.kts | 3 + .../test/FakeElementWellknownStore.kt | 53 ++++ .../features/wellknown/test/Fixtures.kt | 2 + 33 files changed, 988 insertions(+), 74 deletions(-) create mode 100644 features/contentscanner/api/build.gradle.kts create mode 100644 features/contentscanner/impl/build.gradle.kts create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/scanner/ContentScanner.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/scanner/ContentScannerUrlProvider.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/scanner/DefaultContentScannerUrlProvider.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/scanner/RustContentScanner.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/scanner/FakeFfiContentScanner.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/scanner/RustContentScannerTest.kt create mode 100644 libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/scanner/FakeContentScanner.kt create mode 100644 libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellknownStore.kt create mode 100644 libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStore.kt create mode 100644 libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStoreTest.kt create mode 100644 libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt create mode 100644 libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/FakeElementWellknownStore.kt diff --git a/enterprise b/enterprise index efdf9d9a15..bc38a11f95 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit efdf9d9a15a5b600c55f674d64794e7737ad906e +Subproject commit bc38a11f95988cc1bbc209decb998f21c465ded0 diff --git a/features/contentscanner/api/build.gradle.kts b/features/contentscanner/api/build.gradle.kts new file mode 100644 index 0000000000..0e3d592878 --- /dev/null +++ b/features/contentscanner/api/build.gradle.kts @@ -0,0 +1,23 @@ +plugins { + id("io.element.android-compose-library") + id("kotlin-parcelize") +} + +android { + namespace = "io.element.android.features.contentscanner.api" +} + +dependencies { + implementation(projects.libraries.core) + implementation(projects.libraries.architecture) + implementation(projects.libraries.matrix.api) + implementation(projects.libraries.matrixui) + implementation(projects.libraries.designsystem) + + testImplementation(libs.test.junit) + testImplementation(libs.coroutines.test) + testImplementation(libs.molecule.runtime) + testImplementation(libs.test.truth) + testImplementation(libs.test.turbine) + testImplementation(projects.libraries.matrix.test) +} diff --git a/features/contentscanner/impl/build.gradle.kts b/features/contentscanner/impl/build.gradle.kts new file mode 100644 index 0000000000..53e8843b1d --- /dev/null +++ b/features/contentscanner/impl/build.gradle.kts @@ -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. + */ + +import extension.setupDependencyInjection + +plugins { + id("io.element.android-compose-library") + id("kotlin-parcelize") +} + +android { + namespace = "io.element.android.features.contentscanner.impl" +} + +setupDependencyInjection() + +dependencies { + api(projects.features.contentscanner.api) + implementation(projects.libraries.core) + implementation(projects.libraries.architecture) + implementation(projects.libraries.matrix.api) + implementation(projects.libraries.matrixui) + implementation(projects.libraries.designsystem) + + testImplementation(libs.test.junit) + testImplementation(libs.coroutines.test) + testImplementation(libs.molecule.runtime) + testImplementation(libs.test.truth) + testImplementation(libs.test.turbine) + testImplementation(projects.libraries.matrix.test) +} 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 6546e4c41a..8f9c6601ca 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 @@ -38,6 +38,7 @@ 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.scanner.ContentScanner import io.element.android.libraries.matrix.api.spaces.SpaceService import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion import io.element.android.libraries.matrix.api.sync.SyncService @@ -71,6 +72,7 @@ interface MatrixClient { val ignoredUsersFlow: StateFlow> val roomMembershipObserver: RoomMembershipObserver val ownBeaconInfoUpdates: Flow + val contentScanner: ContentScanner? 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/scanner/ContentScanner.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/scanner/ContentScanner.kt new file mode 100644 index 0000000000..e2c4839c4d --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/scanner/ContentScanner.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.matrix.api.scanner + +import io.element.android.libraries.matrix.api.media.MediaSource + +/** + * Component used to manually scan media content for potential security risks. + * + * While the Matrix SDK automatically scans media content we load if a content scanner instance is provided, this interface allows for scanning + * some media sources in advance without actually loading their contents, which can be useful for pre-fetching scenarios. + */ +interface ContentScanner { + /** + * Manually scans the given [mediaSource] for potential security risks. + * + * @param mediaSource The media source to scan. + * @return A [Result] containing a [Boolean] indicating whether the content is safe (true) or potentially unsafe (false). + * If the scan fails, the [Result] will contain an exception. + */ + suspend fun scan(mediaSource: MediaSource): Result +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/scanner/ContentScannerUrlProvider.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/scanner/ContentScannerUrlProvider.kt new file mode 100644 index 0000000000..600866f586 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/scanner/ContentScannerUrlProvider.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.scanner + +/** + * Provides the URL of the content scanner service for a given homeserver, if any is set up. + */ +fun interface ContentScannerUrlProvider { + /** + * Returns the URL of the content scanner service for the given [homeserver], or `null` if no content scanner is set up. + */ + suspend fun getContentScannerUrl(homeserver: String): Result +} 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 2cfbbbdc73..5c81a3f085 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 @@ -45,6 +45,7 @@ import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibilit import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility import io.element.android.libraries.matrix.api.roomlist.RoomListService +import io.element.android.libraries.matrix.api.scanner.ContentScanner import io.element.android.libraries.matrix.api.spaces.SpaceService import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion import io.element.android.libraries.matrix.api.sync.SyncState @@ -150,6 +151,7 @@ class RustMatrixClient( private val featureFlagService: FeatureFlagService, private val analyticsService: AnalyticsService, private val workManagerScheduler: WorkManagerScheduler, + override val contentScanner: ContentScanner?, ) : MatrixClient { override val sessionId: UserId = UserId(innerClient.userId()) override val deviceId: DeviceId = DeviceId(innerClient.deviceId()) 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 fae99b75c8..b4a9272166 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 @@ -17,11 +17,14 @@ import io.element.android.libraries.di.CacheDirectory 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.UserId import io.element.android.libraries.matrix.api.paths.SessionPaths +import io.element.android.libraries.matrix.api.scanner.ContentScannerUrlProvider import io.element.android.libraries.matrix.impl.analytics.UtdTracker import io.element.android.libraries.matrix.impl.paths.getSessionPaths import io.element.android.libraries.matrix.impl.proxy.ProxyProvider import io.element.android.libraries.matrix.impl.room.TimelineEventFilterFactory +import io.element.android.libraries.matrix.impl.scanner.RustContentScanner import io.element.android.libraries.matrix.impl.storage.SqliteStoreBuilderProvider import io.element.android.libraries.matrix.impl.util.anonymizedTokens import io.element.android.libraries.network.useragent.UserAgentProvider @@ -34,6 +37,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.Client import org.matrix.rustcomponents.sdk.ClientBuilder +import org.matrix.rustcomponents.sdk.ContentScanner import org.matrix.rustcomponents.sdk.CrossProcessLockConfig import org.matrix.rustcomponents.sdk.RequestConfig import org.matrix.rustcomponents.sdk.Session @@ -66,6 +70,7 @@ class RustMatrixClientFactory( private val clientBuilderProvider: ClientBuilderProvider, private val sqliteStoreBuilderProvider: SqliteStoreBuilderProvider, private val workManagerScheduler: WorkManagerScheduler, + private val contentScannerUrlProvider: ContentScannerUrlProvider, ) { private val sessionDelegate = RustClientSessionDelegate( sessionStore = sessionStore, @@ -113,6 +118,23 @@ class RustMatrixClientFactory( client.setUtdDelegate(UtdTracker(analyticsService)) + val domainName = UserId(client.userId()).domainName + // If a content scanner URL is available for the homeserver, create a RustContentScanner and set it on the client. + // This allows the SDK to use the content scanner for automatic media scanning. + // If no content scanner URL is available, the contentScanner will be null. + val contentScanner = domainName?.let { + contentScannerUrlProvider.getContentScannerUrl(domainName) + .getOrNull() + ?.let { contentScannerUrl -> + val contentScanner = ContentScanner(contentScannerUrl) + client.setContentScanner(contentScanner) + RustContentScanner( + client = client, + rustScanner = contentScanner, + ) + } + } + val syncService = client.syncService() .withSharePos(true) .withOfflineMode() @@ -132,6 +154,7 @@ class RustMatrixClientFactory( featureFlagService = featureFlagService, analyticsService = analyticsService, workManagerScheduler = workManagerScheduler, + contentScanner = contentScanner, ).also { 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/di/SessionMatrixModule.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/di/SessionMatrixModule.kt index bef24003b9..d4f49af416 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 @@ -23,6 +23,7 @@ import io.element.android.libraries.matrix.api.notificationsettings.Notification import io.element.android.libraries.matrix.api.room.RoomMembershipObserver 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.scanner.ContentScanner import io.element.android.libraries.matrix.api.spaces.SpaceService import io.element.android.libraries.matrix.api.sync.SyncService import io.element.android.libraries.matrix.api.verification.SessionVerificationService @@ -96,4 +97,9 @@ object SessionMatrixModule { fun providesHomeserverCapabilitiesProvider(matrixClient: MatrixClient): HomeserverCapabilitiesProvider { return matrixClient.homeserverCapabilities() } + + @Provides + fun providesContentScanner(matrixClient: MatrixClient): ContentScanner? { + return matrixClient.contentScanner + } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/scanner/DefaultContentScannerUrlProvider.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/scanner/DefaultContentScannerUrlProvider.kt new file mode 100644 index 0000000000..b43dcfb3e8 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/scanner/DefaultContentScannerUrlProvider.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.impl.scanner + +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.matrix.api.scanner.ContentScannerUrlProvider + +/** + * Default FOSS implementation of [ContentScannerUrlProvider] that returns `null` for the content scanner URL. + */ +@ContributesBinding(AppScope::class) +class DefaultContentScannerUrlProvider : ContentScannerUrlProvider { + override suspend fun getContentScannerUrl(homeserver: String): Result = Result.success(null) +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/scanner/RustContentScanner.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/scanner/RustContentScanner.kt new file mode 100644 index 0000000000..ecfa4f0bcd --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/scanner/RustContentScanner.kt @@ -0,0 +1,42 @@ +/* + * 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.scanner + +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.matrix.api.media.MediaSource +import io.element.android.libraries.matrix.api.scanner.ContentScanner +import org.matrix.rustcomponents.sdk.Client +import org.matrix.rustcomponents.sdk.NoHandle +import org.matrix.rustcomponents.sdk.ContentScanner as RustScanner +import org.matrix.rustcomponents.sdk.MediaSource as RustMediaSource + +class RustContentScanner( + private val client: Client, + private val rustScanner: RustScanner, +) : ContentScanner { + override suspend fun scan(mediaSource: MediaSource): Result { + return runCatchingExceptions { + rustScanner.scan(client, mediaSource.toRustMediaSource()).clean + } + } +} + +private fun MediaSource.toRustMediaSource(): RustMediaSource { + val json = this.json + return try { + if (json != null) { + RustMediaSource.fromJson(json) + } else { + RustMediaSource.fromUrl(safeUrl) + } + } catch (e: LinkageError) { + // Used for tests, since we can't instantiate an actual `RustMediaSource` because the native library can't be loaded + val isTest = runCatchingExceptions { Class.forName("org.junit.Test") }.isSuccess + if (isTest) RustMediaSource(NoHandle) else throw e + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt index 1c25acf088..d1536d949e 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt @@ -11,6 +11,7 @@ package io.element.android.libraries.matrix.impl import com.google.common.truth.Truth.assertThat import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.scanner.ContentScannerUrlProvider import io.element.android.libraries.matrix.impl.auth.FakeProxyProvider import io.element.android.libraries.matrix.impl.room.FakeTimelineEventFilterFactory import io.element.android.libraries.matrix.impl.storage.FakeSqliteStoreBuilderProvider @@ -51,6 +52,7 @@ fun TestScope.createRustMatrixClientFactory( ), clientBuilderProvider: ClientBuilderProvider = FakeClientBuilderProvider(), workManagerScheduler: FakeWorkManagerScheduler = FakeWorkManagerScheduler(), + contentScannerUrlProvider: ContentScannerUrlProvider = { Result.success(null) }, ) = RustMatrixClientFactory( cacheDirectory = cacheDirectory, appCoroutineScope = backgroundScope, @@ -65,4 +67,5 @@ fun TestScope.createRustMatrixClientFactory( clientBuilderProvider = clientBuilderProvider, sqliteStoreBuilderProvider = FakeSqliteStoreBuilderProvider(), workManagerScheduler = workManagerScheduler, + contentScannerUrlProvider = contentScannerUrlProvider, ) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt index a8e812d031..745fbf02d5 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt @@ -22,6 +22,7 @@ import io.element.android.libraries.matrix.test.A_DEVICE_ID 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_NAME +import io.element.android.libraries.matrix.test.scanner.FakeContentScanner import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.test.InMemorySessionStore import io.element.android.libraries.sessionstorage.test.aSessionData @@ -156,5 +157,6 @@ class RustMatrixClientTest { featureFlagService = FakeFeatureFlagService(), analyticsService = FakeAnalyticsService(), workManagerScheduler = FakeWorkManagerScheduler(submitLambda = {}), + contentScanner = FakeContentScanner(), ) } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/scanner/FakeFfiContentScanner.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/scanner/FakeFfiContentScanner.kt new file mode 100644 index 0000000000..a359747198 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/scanner/FakeFfiContentScanner.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.matrix.impl.scanner + +import org.matrix.rustcomponents.sdk.Client +import org.matrix.rustcomponents.sdk.ContentScanner +import org.matrix.rustcomponents.sdk.MediaSource +import org.matrix.rustcomponents.sdk.NoHandle +import uniffi.matrix_sdk_contentscanner.MediaScanResponse + +class FakeFfiContentScanner( + private val scan: suspend (client: Client, mediaSource: MediaSource) -> MediaScanResponse = { _, _ -> + MediaScanResponse(clean = true, info = "Just peachy") + }, +) : ContentScanner(NoHandle) { + override suspend fun scan(client: Client, mediaSource: MediaSource): MediaScanResponse { + return scan.invoke(client, mediaSource) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/scanner/RustContentScannerTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/scanner/RustContentScannerTest.kt new file mode 100644 index 0000000000..8a1522c2f2 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/scanner/RustContentScannerTest.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.scanner + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClient +import io.element.android.libraries.matrix.test.media.aMediaSource +import kotlinx.coroutines.test.runTest +import org.junit.Test +import uniffi.matrix_sdk_contentscanner.MediaScanResponse + +class RustContentScannerTest { + @Test + fun `test successful valid scan`() = runTest { + val scanner = RustContentScanner( + client = FakeFfiClient(), + rustScanner = FakeFfiContentScanner(), + ) + + scanner.scan(aMediaSource()).run { + assertThat(isSuccess).isTrue() + assertThat(getOrNull()).isTrue() + } + } + + @Test + fun `test successful invalid scan`() = runTest { + val scanner = RustContentScanner( + client = FakeFfiClient(), + rustScanner = FakeFfiContentScanner(scan = { _, _ -> MediaScanResponse(clean = false, info = "Not clean") }) + ) + + scanner.scan(aMediaSource()).run { + assertThat(isSuccess).isTrue() + assertThat(getOrNull()).isFalse() + } + } + + @Test + fun `test failed scan`() = runTest { + val scanner = RustContentScanner( + client = FakeFfiClient(), + rustScanner = FakeFfiContentScanner(scan = { _, _ -> throw IllegalStateException("BOOM") }) + ) + + scanner.scan(aMediaSource()).run { + assertThat(isFailure).isTrue() + assertThat(getOrNull()).isNull() + } + } +} 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 2397f12443..98fe01553c 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 @@ -38,6 +38,7 @@ 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.scanner.ContentScanner import io.element.android.libraries.matrix.api.spaces.SpaceService import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion import io.element.android.libraries.matrix.api.sync.SyncService @@ -122,6 +123,7 @@ class FakeMatrixClient( private val getMapStyleUrlResult: () -> Result = { lambdaError() }, private val getDatabaseSizesLambda: () -> Result = { lambdaError() }, private val resetWellKnownConfigLambda: () -> Result = { lambdaError() }, + override val contentScanner: ContentScanner? = null ) : MatrixClient { var setDisplayNameCalled: Boolean = false private set diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/scanner/FakeContentScanner.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/scanner/FakeContentScanner.kt new file mode 100644 index 0000000000..a4d9ce72e7 --- /dev/null +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/scanner/FakeContentScanner.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.test.scanner + +import io.element.android.libraries.matrix.api.media.MediaSource +import io.element.android.libraries.matrix.api.scanner.ContentScanner + +class FakeContentScanner( + private val scan: suspend (mediaSource: MediaSource) -> Result = { Result.success(true) }, +) : ContentScanner { + override suspend fun scan(mediaSource: MediaSource): Result { + return scan.invoke(mediaSource) + } +} diff --git a/libraries/network/src/main/kotlin/io/element/android/libraries/network/NetworkModule.kt b/libraries/network/src/main/kotlin/io/element/android/libraries/network/NetworkModule.kt index d8809e042c..90e78d860e 100644 --- a/libraries/network/src/main/kotlin/io/element/android/libraries/network/NetworkModule.kt +++ b/libraries/network/src/main/kotlin/io/element/android/libraries/network/NetworkModule.kt @@ -16,6 +16,7 @@ import dev.zacsweers.metro.SingleIn import io.element.android.libraries.network.interceptors.DynamicHttpLoggingInterceptor import io.element.android.libraries.network.interceptors.FormattedJsonHttpLogger import io.element.android.libraries.network.interceptors.UserAgentInterceptor +import okhttp3.Call import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import java.util.concurrent.TimeUnit @@ -36,6 +37,9 @@ object NetworkModule { addInterceptor(dynamicHttpLoggingInterceptor) }.build() + @Provides + fun providesCallFactory(okHttpClient: OkHttpClient): Call.Factory = Call.Factory { request -> okHttpClient.newCall(request) } + @Provides @SingleIn(AppScope::class) fun providesHttpLoggingInterceptor(): HttpLoggingInterceptor { 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 39a54dca61..ecb1004b90 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 @@ -11,19 +11,19 @@ package io.element.android.libraries.network import dev.zacsweers.metro.Inject import io.element.android.libraries.androidutils.json.JsonProvider import io.element.android.libraries.core.uri.ensureTrailingSlash +import okhttp3.Call import okhttp3.MediaType.Companion.toMediaType -import okhttp3.OkHttpClient import retrofit2.Retrofit import retrofit2.converter.kotlinx.serialization.asConverterFactory @Inject class RetrofitFactory( - private val okHttpClient: () -> OkHttpClient, + private val callFactory: () -> Call.Factory, private val json: () -> JsonProvider, ) { fun create(baseUrl: String): Retrofit = Retrofit.Builder() .baseUrl(baseUrl.ensureTrailingSlash()) .addConverterFactory(json()().asConverterFactory("application/json".toMediaType())) - .callFactory { request -> okHttpClient().newCall(request) } + .callFactory(callFactory()) .build() } 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 8f2c07ab68..45448f66c2 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 @@ -16,4 +16,5 @@ data class ElementWellKnown( val notificationSound: String?, val identityProviderAppScheme: String?, val customRecoveryPassphrase: CustomRecoveryPassphrase?, + val contentScannerUrl: String?, ) diff --git a/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellknownStore.kt b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellknownStore.kt new file mode 100644 index 0000000000..80b2ab4c5e --- /dev/null +++ b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellknownStore.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.wellknown.api + +interface ElementWellknownStore { + suspend fun get(domain: String): WellknownRetrieverResult + suspend fun update(domain: String, wellknown: String): Result + suspend fun delete(domain: String): Result +} diff --git a/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/WellknownRetrieverResult.kt b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/WellknownRetrieverResult.kt index 3236f18660..fcc54df0b5 100644 --- a/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/WellknownRetrieverResult.kt +++ b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/WellknownRetrieverResult.kt @@ -14,6 +14,11 @@ sealed interface WellknownRetrieverResult { */ data class Success(val data: T) : WellknownRetrieverResult + /** + * Well-known data has been retrieved from the local cache but is outdated and a manual refresh has been launched. + */ + data class Outdated(val data: T) : WellknownRetrieverResult + /** * Well-known data is not found (file does not exist server side, we got a 404). */ @@ -26,6 +31,7 @@ sealed interface WellknownRetrieverResult { fun dataOrNull(): T? = when (this) { is Success -> data + is Outdated -> data is Error -> null NotFound -> null } 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 a0223e93cc..3446cdcb65 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,17 +10,15 @@ 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.ElementWellknownStore 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 @@ -29,34 +27,41 @@ import timber.log.Timber class DefaultSessionWellknownRetriever( private val matrixClient: MatrixClient, private val json: JsonProvider, - private val cacheStore: CacheStore, - private val systemClock: SystemClock, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, + private val elementWellknownStore: ElementWellknownStore, ) : 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) { + val cacheData = elementWellknownStore.get(domain) + return when (cacheData) { + is WellknownRetrieverResult.Success -> { + Timber.d("Using cached well-known for domain $domain") + cacheData + } + is WellknownRetrieverResult.Outdated -> { + // Return the outdated data but refresh in the background + // If the cache is missing or outdated, trigger a refresh in background but still return the cached value + Timber.d("Outdated cached well-known for domain $domain, returning existing value and fetching new one from network") sessionCoroutineScope.launch { + val url = "https://$domain/.well-known/element/element.json" fetchElementWellKnown(url) } + cacheData } - 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) + is WellknownRetrieverResult.NotFound -> { + // Try to fetch from the server + Timber.d("No cached well-known for domain $domain, fetching from network") + val url = "https://$domain/.well-known/element/element.json" + fetchElementWellKnown(url) + } + is WellknownRetrieverResult.Error -> { + // Return the error + Timber.e(cacheData.exception, "Error retrieving well-known for domain $domain") + cacheData.exception.toWellknownRetrieverResult() } } - - return fetchElementWellKnown(url) } private suspend fun fetchElementWellKnown(url: String): WellknownRetrieverResult { @@ -66,13 +71,11 @@ class DefaultSessionWellknownRetriever( val data = String(it) val parsed = json().decodeFromString(data).map() // Also store in cache, if valid - cacheStore.storeData( - key = url, - data = CacheData( - value = data, - updatedAt = systemClock.epochMillis(), - ) - ) + elementWellknownStore.update(domain, data) + .onFailure { exception -> + Timber.e(exception, "Failed to parse cached Element .well-known data for $domain, deleting cache") + elementWellknownStore.delete(domain) + } parsed } .toWellknownRetrieverResult() @@ -85,16 +88,15 @@ class DefaultSessionWellknownRetriever( onFailure = { Timber.e(it, "Failed to retrieve Element .well-known from $domain") // This check on message value is not ideal but this is what we got from the SDK. - if ((it as? ClientException.Generic)?.message?.contains("404") == true) { - WellknownRetrieverResult.NotFound - } else { - WellknownRetrieverResult.Error(it as Exception) - } + it.toWellknownRetrieverResult() } ) - companion object { - // 1 day - private const val CACHE_VALIDITY_MILLIS = 1 * 24 * 60 * 60 * 1000L + private fun Throwable.toWellknownRetrieverResult(): WellknownRetrieverResult { + return if ((this as? ClientException.Generic)?.message?.contains("404") == true) { + WellknownRetrieverResult.NotFound + } else { + WellknownRetrieverResult.Error(this as Exception) + } } } diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStore.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStore.kt new file mode 100644 index 0000000000..c3cfcc5019 --- /dev/null +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStore.kt @@ -0,0 +1,63 @@ +/* + * 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.impl + +import dev.zacsweers.metro.AppScope +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.runCatchingExceptions +import io.element.android.libraries.wellknown.api.ElementWellKnown +import io.element.android.libraries.wellknown.api.ElementWellknownStore +import io.element.android.libraries.wellknown.api.WellknownRetrieverResult +import io.element.android.services.toolbox.api.systemclock.SystemClock + +@ContributesBinding(AppScope::class) +class DefaultWellKnownStore( + private val cacheStore: CacheStore, + private val json: JsonProvider, + private val systemClock: SystemClock, +) : ElementWellknownStore { + override suspend fun get(domain: String): WellknownRetrieverResult { + return runCatchingExceptions { + val cachedData = cacheStore.getData(key(domain)) + if (cachedData != null) { + val data = json().decodeFromString(cachedData.value).map() + if (systemClock.epochMillis() > cachedData.updatedAt + CACHE_VALIDITY_MILLIS) { + WellknownRetrieverResult.Outdated(data) + } else { + WellknownRetrieverResult.Success(data) + } + } else { + WellknownRetrieverResult.NotFound + } + }.recover { + WellknownRetrieverResult.Error(it as Exception) + }.getOrThrow() + } + + override suspend fun update(domain: String, wellknown: String): Result { + return runCatchingExceptions { + cacheStore.storeData(key(domain), CacheData(wellknown, systemClock.epochMillis())) + } + } + + override suspend fun delete(domain: String): Result { + return runCatchingExceptions { + cacheStore.deleteData(key(domain)) + } + } + + private fun key(domain: String): String = "https://$domain/.well-known/element/element.json" + + companion object { + // 1 day + private const val CACHE_VALIDITY_MILLIS = 1 * 24 * 60 * 60 * 1000L + } +} diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt index 02dae72a43..a43584d542 100644 --- a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt @@ -10,26 +10,34 @@ package io.element.android.libraries.wellknown.impl import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.androidutils.json.JsonProvider import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.core.uri.ensureProtocol import io.element.android.libraries.network.RetrofitFactory import io.element.android.libraries.wellknown.api.ElementWellKnown +import io.element.android.libraries.wellknown.api.ElementWellknownStore import io.element.android.libraries.wellknown.api.WellknownRetriever import io.element.android.libraries.wellknown.api.WellknownRetrieverResult import retrofit2.HttpException import timber.log.Timber import java.net.HttpURLConnection +import java.net.URL @ContributesBinding(AppScope::class) class DefaultWellknownRetriever( private val retrofitFactory: RetrofitFactory, + private val elementWellknownStore: ElementWellknownStore, + private val jsonProvider: JsonProvider, ) : WellknownRetriever { override suspend fun getElementWellKnown(baseUrl: String): WellknownRetrieverResult { + val domain = URL(baseUrl).host return buildWellknownApi(baseUrl) .map { wellknownApi -> try { - val result = wellknownApi.getElementWellKnown().map() - WellknownRetrieverResult.Success(result) + val json = jsonProvider() + val result = wellknownApi.getElementWellKnown() + elementWellknownStore.update(domain, json.encodeToString(result)) + WellknownRetrieverResult.Success(result.map()) } catch (e: Exception) { // Is it a 404? Timber.e(e, "Failed to retrieve Element well-known data for $baseUrl") 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 cd0f39c77f..ad60caefa5 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 @@ -44,6 +44,8 @@ data class InternalElementWellKnown( val identityProviderAppScheme: String? = null, @SerialName("custom_recovery_passphrase") val customRecoveryPassphrase: InternalCustomRecoveryPassphrase? = null, + @SerialName("content_scanner_url") + val contentScannerUrl: String? = null, ) @Serializable 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 c8760881d4..420dea2bae 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 @@ -22,7 +22,7 @@ private val loggerTag = LoggerTag("Wellknown") */ private const val MINIMUM_PASSPHRASE_CHARACTER_COUNT = 1 -internal fun InternalElementWellKnown.map() = ElementWellKnown( +fun InternalElementWellKnown.map() = ElementWellKnown( registrationHelperUrl = registrationHelperUrl, enforceElementPro = enforceElementPro, rageshakeUrl = rageshakeUrl, @@ -30,6 +30,7 @@ internal fun InternalElementWellKnown.map() = ElementWellKnown( notificationSound = notificationSound, identityProviderAppScheme = identityProviderAppScheme, customRecoveryPassphrase = customRecoveryPassphrase?.toPublic(), + contentScannerUrl = contentScannerUrl, ) private fun InternalCustomRecoveryPassphrase.toPublic(): CustomRecoveryPassphrase { 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 a64d156f6e..ec939b9988 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 @@ -11,20 +11,16 @@ package io.element.android.libraries.wellknown.impl import com.google.common.truth.Truth.assertThat +import io.element.android.features.wellknown.test.FakeElementWellknownStore 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.api.exception.ClientException 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.CustomRecoveryPassphrase 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 @@ -53,6 +49,7 @@ class DefaultSessionWellknownRetrieverTest { notificationSound = null, identityProviderAppScheme = null, customRecoveryPassphrase = null, + contentScannerUrl = null, ) ) ) @@ -79,6 +76,7 @@ class DefaultSessionWellknownRetrieverTest { notificationSound = "a_notification_sound.flac", identityProviderAppScheme = "an_app_scheme", customRecoveryPassphrase = null, + contentScannerUrl = "https://content-scanner.example.com", ) ) ) @@ -108,6 +106,7 @@ class DefaultSessionWellknownRetrieverTest { brandColor = null, notificationSound = null, identityProviderAppScheme = null, + contentScannerUrl = null, customRecoveryPassphrase = null, ) ) @@ -225,16 +224,23 @@ class DefaultSessionWellknownRetrieverTest { assertThat(sut.getElementWellKnown()).isInstanceOf(WellknownRetrieverResult.Error::class.java) } + @Test + fun `get element wellknown 404 http error counts as not found`() = runTest { + val sut = createDefaultSessionWellknownRetriever( + getUrlLambda = { + Result.failure(ClientException.Generic("Not Found: 404 status code", "The file could not be found")) + } + ) + assertThat(sut.getElementWellKnown()).isInstanceOf(WellknownRetrieverResult.NotFound::class.java) + } + @Test fun `get element wellknown hitting cache`() = runTest { val sut = createDefaultSessionWellknownRetriever( getUrlLambda = { lambdaError() }, - cacheStore = InMemoryCacheStore( + cacheStore = FakeElementWellknownStore( initialData = mapOf( - WELLKNOWN_URL to CacheData( - value = WELLKNOWN_CONTENT, - updatedAt = A_FAKE_TIMESTAMP, - ) + WELLKNOWN_URL to WellknownRetrieverResult.Success(parsedWellKnownContent()) ) ) ) @@ -248,6 +254,7 @@ class DefaultSessionWellknownRetrieverTest { notificationSound = "a_notification_sound.flac", identityProviderAppScheme = "an_app_scheme", customRecoveryPassphrase = null, + contentScannerUrl = "https://content-scanner.example.com", ) ) ) @@ -255,12 +262,9 @@ class DefaultSessionWellknownRetrieverTest { @Test fun `get element wellknown hitting cache containing invalid json`() = runTest { - val cacheStore = InMemoryCacheStore( + val cacheStore = FakeElementWellknownStore( initialData = mapOf( - WELLKNOWN_URL to CacheData( - value = WELLKNOWN_CONTENT, - updatedAt = A_FAKE_TIMESTAMP, - ) + WELLKNOWN_URL to WellknownRetrieverResult.Error(IllegalStateException("Invalid JSON")) ) ) val sut = createDefaultSessionWellknownRetriever( @@ -272,28 +276,24 @@ class DefaultSessionWellknownRetrieverTest { ) assertThat(sut.getElementWellKnown()).isInstanceOf(WellknownRetrieverResult.Error::class.java) // Ensure that the cache is deleted after the failure to parse it - assertThat(cacheStore.dataMap).isEmpty() + assertThat(cacheStore.get(WELLKNOWN_URL)).isEqualTo(WellknownRetrieverResult.NotFound) } @Test fun `get element wellknown hitting outdated cache`() = runTest { + val cacheStore = FakeElementWellknownStore( + initialData = mapOf( + WELLKNOWN_URL to WellknownRetrieverResult.Outdated(parsedWellKnownContent()), + ) + ) 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) + cacheStore = cacheStore, ) assertThat(sut.getElementWellKnown()).isEqualTo( - WellknownRetrieverResult.Success( + WellknownRetrieverResult.Outdated( ElementWellKnown( registrationHelperUrl = "a_registration_url", enforceElementPro = true, @@ -302,6 +302,7 @@ class DefaultSessionWellknownRetrieverTest { notificationSound = "a_notification_sound.flac", identityProviderAppScheme = "an_app_scheme", customRecoveryPassphrase = null, + contentScannerUrl = "https://content-scanner.example.com", ) ) ) @@ -314,20 +315,20 @@ class DefaultSessionWellknownRetrieverTest { ) } + private fun parsedWellKnownContent() = DefaultJsonProvider().invoke().decodeFromString(WELLKNOWN_CONTENT).map() + private fun TestScope.createDefaultSessionWellknownRetriever( + cacheStore: FakeElementWellknownStore = FakeElementWellknownStore(), getUrlLambda: (String) -> Result, jsonProvider: JsonProvider = DefaultJsonProvider(), - cacheStore: CacheStore = InMemoryCacheStore(), - systemClock: SystemClock = FakeSystemClock(), ) = DefaultSessionWellknownRetriever( matrixClient = FakeMatrixClient( userIdServerNameLambda = { "user.domain.org" }, getUrlLambda = getUrlLambda, ), json = jsonProvider, - cacheStore = cacheStore, - systemClock = systemClock, sessionCoroutineScope = backgroundScope, + elementWellknownStore = cacheStore, ) companion object { @@ -338,7 +339,8 @@ class DefaultSessionWellknownRetrieverTest { "rageshake_url": "a_rageshake_url", "brand_color": "#FF0000", "notification_sound": "a_notification_sound.flac", - "idp_app_scheme": "an_app_scheme" + "idp_app_scheme": "an_app_scheme", + "content_scanner_url": "https://content-scanner.example.com" }""" } } diff --git a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStoreTest.kt b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStoreTest.kt new file mode 100644 index 0000000000..11ec521fed --- /dev/null +++ b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStoreTest.kt @@ -0,0 +1,158 @@ +/* + * 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.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.cachestore.api.CacheData +import io.element.android.libraries.sessionstorage.test.InMemoryCacheStore +import io.element.android.libraries.wellknown.api.CustomRecoveryPassphrase +import io.element.android.libraries.wellknown.api.WellknownRetrieverResult +import io.element.android.services.toolbox.test.systemclock.A_FAKE_TIMESTAMP +import io.element.android.services.toolbox.test.systemclock.FakeSystemClock +import kotlinx.coroutines.test.runTest +import org.junit.Test + +private const val A_DOMAIN = "matrix.example.com" +private const val A_CACHE_KEY = "https://$A_DOMAIN/.well-known/element/element.json" + +// 1 day in millis +private const val CACHE_VALIDITY_MILLIS = 1 * 24 * 60 * 60 * 1000L + +class DefaultWellKnownStoreTest { + private val jsonProvider = DefaultJsonProvider() + + @Test + fun `get returns NotFound when cache is empty`() = runTest { + val sut = createDefaultWellKnownStore() + assertThat(sut.get(A_DOMAIN)).isEqualTo(WellknownRetrieverResult.NotFound) + } + + @Test + fun `get returns Success when cache has fresh data`() = runTest { + val wellKnown = InternalElementWellKnown(rageshakeUrl = "https://rageshake.example.com") + val jsonString = jsonProvider().encodeToString(wellKnown) + val clock = FakeSystemClock(epochMillisResult = A_FAKE_TIMESTAMP) + val cacheStore = InMemoryCacheStore( + initialData = mapOf(A_CACHE_KEY to CacheData(jsonString, A_FAKE_TIMESTAMP)) + ) + val sut = createDefaultWellKnownStore(cacheStore = cacheStore, systemClock = clock) + + val result = sut.get(A_DOMAIN) + + assertThat(result).isEqualTo(WellknownRetrieverResult.Success(wellKnown.map())) + } + + @Test + fun `get returns Outdated when cached data has expired`() = runTest { + val wellKnown = InternalElementWellKnown(rageshakeUrl = "https://rageshake.example.com") + val jsonString = jsonProvider().encodeToString(wellKnown) + // Store data at timestamp 0, but clock is past the validity window + val expiredTimestamp = 0L + val nowTimestamp = expiredTimestamp + CACHE_VALIDITY_MILLIS + 1 + val clock = FakeSystemClock(epochMillisResult = nowTimestamp) + val cacheStore = InMemoryCacheStore( + initialData = mapOf(A_CACHE_KEY to CacheData(jsonString, expiredTimestamp)) + ) + val sut = createDefaultWellKnownStore(cacheStore = cacheStore, systemClock = clock) + + val result = sut.get(A_DOMAIN) + + assertThat(result).isEqualTo(WellknownRetrieverResult.Outdated(wellKnown.map())) + } + + @Test + fun `get returns Error when cached data is invalid JSON`() = runTest { + val cacheStore = InMemoryCacheStore( + initialData = mapOf(A_CACHE_KEY to CacheData("not valid json at all", A_FAKE_TIMESTAMP)) + ) + val sut = createDefaultWellKnownStore(cacheStore = cacheStore) + + val result = sut.get(A_DOMAIN) + + assertThat(result).isInstanceOf(WellknownRetrieverResult.Error::class.java) + } + + @Test + fun `update stores data and get returns Success`() = runTest { + val wellKnown = """ + { + "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": { + "min_character_count": 8 + } + } + """.trimIndent() + val clock = FakeSystemClock(epochMillisResult = A_FAKE_TIMESTAMP) + val cacheStore = InMemoryCacheStore() + val sut = createDefaultWellKnownStore(cacheStore = cacheStore, systemClock = clock) + + val updateResult = sut.update(A_DOMAIN, wellKnown) + assertThat(updateResult.isSuccess).isTrue() + + val result = sut.get(A_DOMAIN) + assertThat(result).isEqualTo(WellknownRetrieverResult.Success(anElementWellKnown( + registrationHelperUrl = "https://element.io", + enforceElementPro = true, + rageshakeUrl = "https://example.org/rageshake", + brandColor = "#FF0000", + notificationSound = "ring.flac", + identityProviderAppScheme = "io.element.app", + customRecoveryPassphrase = CustomRecoveryPassphrase(8), + ))) + } + + @Test + fun `delete removes data and get returns NotFound`() = runTest { + val wellKnown = InternalElementWellKnown(rageshakeUrl = "https://rageshake.example.com") + val jsonString = jsonProvider().encodeToString(wellKnown) + val clock = FakeSystemClock(epochMillisResult = A_FAKE_TIMESTAMP) + val cacheStore = InMemoryCacheStore( + initialData = mapOf(A_CACHE_KEY to CacheData(jsonString, A_FAKE_TIMESTAMP)) + ) + val sut = createDefaultWellKnownStore(cacheStore = cacheStore, systemClock = clock) + + val deleteResult = sut.delete(A_DOMAIN) + assertThat(deleteResult.isSuccess).isTrue() + + assertThat(sut.get(A_DOMAIN)).isEqualTo(WellknownRetrieverResult.NotFound) + } + + @Test + fun `get returns data at the exact cache validity boundary as Success`() = runTest { + val wellKnown = InternalElementWellKnown(notificationSound = "ping.flac") + val jsonString = jsonProvider().encodeToString(wellKnown) + // Exactly at the boundary: epochMillis == updatedAt + CACHE_VALIDITY_MILLIS → not expired + val storedAt = 1000L + val nowAtBoundary = storedAt + CACHE_VALIDITY_MILLIS + val clock = FakeSystemClock(epochMillisResult = nowAtBoundary) + val cacheStore = InMemoryCacheStore( + initialData = mapOf(A_CACHE_KEY to CacheData(jsonString, storedAt)) + ) + val sut = createDefaultWellKnownStore(cacheStore = cacheStore, systemClock = clock) + + val result = sut.get(A_DOMAIN) + + assertThat(result).isEqualTo(WellknownRetrieverResult.Success(wellKnown.map())) + } + + private fun createDefaultWellKnownStore( + cacheStore: InMemoryCacheStore = InMemoryCacheStore(), + systemClock: FakeSystemClock = FakeSystemClock(), + ) = DefaultWellKnownStore( + cacheStore = cacheStore, + json = jsonProvider, + systemClock = systemClock, + ) +} diff --git a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt new file mode 100644 index 0000000000..0e9288f658 --- /dev/null +++ b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt @@ -0,0 +1,291 @@ +/* + * 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. + */ + +@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.FakeElementWellknownStore +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.network.RetrofitFactory +import io.element.android.libraries.wellknown.api.CustomRecoveryPassphrase +import io.element.android.libraries.wellknown.api.ElementWellKnown +import io.element.android.libraries.wellknown.api.WellknownRetrieverResult +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import okhttp3.Call +import okhttp3.Request +import okhttp3.Response +import okhttp3.ResponseBody.Companion.toResponseBody +import okio.IOException +import org.junit.Test +import java.net.PortUnreachableException + +class DefaultWellknownRetrieverTest { + @Test + fun `get empty element wellknown`() = runTest { + val mockCall = mockCall(defaultResponse(body = "{}")) + val sut = createDefaultWellknownRetriever( + callFactory = { mockCall }, + ) + assertThat(sut.getElementWellKnown(WELLKNOWN_URL)).isEqualTo( + WellknownRetrieverResult.Success( + ElementWellKnown( + registrationHelperUrl = null, + enforceElementPro = null, + rageshakeUrl = null, + brandColor = null, + notificationSound = null, + identityProviderAppScheme = null, + customRecoveryPassphrase = null, + contentScannerUrl = null, + ) + ) + ) + verify(exactly = 1) { mockCall.enqueue(any()) } + } + + @Test + fun `get element wellknown with full content`() = runTest { + val sut = createDefaultWellknownRetriever( + callFactory = { mockCall(defaultResponse()) } + ) + assertThat(sut.getElementWellKnown(WELLKNOWN_URL)).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", + customRecoveryPassphrase = null, + contentScannerUrl = "https://content-scanner.example.com", + ) + ) + ) + } + + @Test + fun `get element wellknown with unknown key`() = runTest { + val sut = createDefaultWellknownRetriever( + callFactory = { + mockCall(defaultResponse(body = """{ + "registration_helper_url": "a_registration_url", + "enforce_element_pro": true, + "rageshake_url": "a_rageshake_url", + // Note the trailing comma, and the comment! + "other": true, + }""".trimIndent())) + } + ) + assertThat(sut.getElementWellKnown(WELLKNOWN_URL)).isEqualTo( + WellknownRetrieverResult.Success( + ElementWellKnown( + registrationHelperUrl = "a_registration_url", + enforceElementPro = true, + rageshakeUrl = "a_rageshake_url", + brandColor = null, + notificationSound = null, + identityProviderAppScheme = null, + contentScannerUrl = null, + customRecoveryPassphrase = null, + ) + ) + ) + } + + @Test + fun `get element wellknown with custom recovery passphrase settings`() = runTest { + val sut = createDefaultWellknownRetriever( + callFactory = { + mockCall(defaultResponse(body = """{ + "custom_recovery_passphrase": { + "min_character_count": 8 + } + }""".trimIndent())) + } + ) + assertThat(sut.getElementWellKnown(WELLKNOWN_URL)).isEqualTo( + WellknownRetrieverResult.Success( + anElementWellKnown( + customRecoveryPassphrase = CustomRecoveryPassphrase(minCharacterCount = 8) + ) + ) + ) + } + + @Test + fun `get element wellknown with custom recovery passphrase settings missing min character count floors to 1`() = runTest { + val sut = createDefaultWellknownRetriever( + callFactory = { + mockCall(defaultResponse(body = """{ + "custom_recovery_passphrase": {} + }""".trimIndent())) + } + ) + assertThat(sut.getElementWellKnown(WELLKNOWN_URL)).isEqualTo( + WellknownRetrieverResult.Success( + anElementWellKnown( + customRecoveryPassphrase = CustomRecoveryPassphrase(minCharacterCount = 1) + ) + ) + ) + } + + @Test + fun `get element wellknown with zero min character count floors to 1`() = runTest { + val sut = createDefaultWellknownRetriever( + callFactory = { + mockCall( + defaultResponse( + body = """{ + "custom_recovery_passphrase": { + "min_character_count": 0 + } + }""".trimIndent() + ) + ) + } + ) + assertThat(sut.getElementWellKnown(WELLKNOWN_URL)).isEqualTo( + WellknownRetrieverResult.Success( + anElementWellKnown( + customRecoveryPassphrase = CustomRecoveryPassphrase(minCharacterCount = 1) + ) + ) + ) + } + + @Test + fun `get element wellknown with negative min character count floors to 1`() = runTest { + val sut = createDefaultWellknownRetriever( + callFactory = { + mockCall( + defaultResponse( + body = """{ + "custom_recovery_passphrase": { + "min_character_count": -5 + } + }""".trimIndent() + ) + ) + } + ) + assertThat(sut.getElementWellKnown(WELLKNOWN_URL)).isEqualTo( + WellknownRetrieverResult.Success( + anElementWellKnown( + customRecoveryPassphrase = CustomRecoveryPassphrase(minCharacterCount = 1) + ) + ) + ) + } + + @Test + fun `get element wellknown json error`() = runTest { + val sut = createDefaultWellknownRetriever( + callFactory = { mockCall(defaultResponse(status = 500)) } + ) + assertThat(sut.getElementWellKnown(WELLKNOWN_URL)).isInstanceOf(WellknownRetrieverResult.Error::class.java) + } + + @Test + fun `get element wellknown network error`() = runTest { + val sut = createDefaultWellknownRetriever( + callFactory = { mockCall(error = PortUnreachableException()) } + ) + assertThat(sut.getElementWellKnown(WELLKNOWN_URL)).isInstanceOf(WellknownRetrieverResult.Error::class.java) + } + + @Test + fun `get element wellknown 404 http error counts as not found`() = runTest { + val sut = createDefaultWellknownRetriever( + callFactory = { mockCall(defaultResponse(status = 404)) } + ) + assertThat(sut.getElementWellKnown(WELLKNOWN_URL)).isInstanceOf(WellknownRetrieverResult.NotFound::class.java) + } + + @Test + fun `get element wellknown hitting cache containing invalid json`() = runTest { + val cacheStore = FakeElementWellknownStore( + initialData = mapOf( + WELLKNOWN_URL to WellknownRetrieverResult.Error(IllegalStateException("Invalid JSON")) + ) + ) + val sut = createDefaultWellknownRetriever( + callFactory = { mockCall(defaultResponse(body = "invalid json")) }, + cacheStore = cacheStore, + jsonProvider = JsonProvider { error("Failed to parse JSON") } + ) + assertThat(sut.getElementWellKnown(WELLKNOWN_URL)).isInstanceOf(WellknownRetrieverResult.Error::class.java) + // Ensure that the cache is deleted after the failure to parse it + assertThat(cacheStore.get(WELLKNOWN_URL)).isEqualTo(WellknownRetrieverResult.NotFound) + } + + private fun defaultResponse( + body: String = WELLKNOWN_CONTENT, + status: Int = 200, + ) = Response.Builder() + .code(status) + .message("OK") + .protocol(okhttp3.Protocol.HTTP_1_1) + .request(Request.Builder().url(WELLKNOWN_URL).build()) + .body(body.toByteArray().toResponseBody()) + .build() + + private fun createDefaultWellknownRetriever( + callFactory: Call.Factory = Call.Factory { _: Request -> mockCall(defaultResponse()) }, + cacheStore: FakeElementWellknownStore = FakeElementWellknownStore(), + jsonProvider: JsonProvider = DefaultJsonProvider(), + ) = DefaultWellknownRetriever( + retrofitFactory = RetrofitFactory( + callFactory = { callFactory }, + json = { jsonProvider } + ), + jsonProvider = jsonProvider, + elementWellknownStore = cacheStore, + ) + + 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", + "content_scanner_url": "https://content-scanner.example.com" + }""" + } +} + +private fun mockCall( + response: Response? = null, + error: IOException? = null, +): Call = mockk { + if (error != null) { + every { enqueue(any()) } answers { + val callback = firstArg() + callback.onFailure(this@mockk, error) + } + } else if (response != null) { + every { enqueue(any()) } answers { + val callback = firstArg() + callback.onResponse(this@mockk, response) + } + } else { + error("Either response or error must be provided") + } +} diff --git a/libraries/wellknown/test/build.gradle.kts b/libraries/wellknown/test/build.gradle.kts index 0ce22348b3..8eb47ef5ca 100644 --- a/libraries/wellknown/test/build.gradle.kts +++ b/libraries/wellknown/test/build.gradle.kts @@ -15,6 +15,9 @@ android { } dependencies { + implementation(libs.serialization.json) + implementation(projects.libraries.androidutils) implementation(projects.libraries.wellknown.api) + implementation(projects.libraries.wellknown.impl) implementation(projects.tests.testutils) } diff --git a/libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/FakeElementWellknownStore.kt b/libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/FakeElementWellknownStore.kt new file mode 100644 index 0000000000..c5e2d2ae5b --- /dev/null +++ b/libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/FakeElementWellknownStore.kt @@ -0,0 +1,53 @@ +/* + * 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.wellknown.test + +import io.element.android.libraries.androidutils.json.DefaultJsonProvider +import io.element.android.libraries.androidutils.json.JsonProvider +import io.element.android.libraries.wellknown.api.ElementWellKnown +import io.element.android.libraries.wellknown.api.ElementWellknownStore +import io.element.android.libraries.wellknown.api.WellknownRetrieverResult +import io.element.android.libraries.wellknown.impl.InternalElementWellKnown +import io.element.android.libraries.wellknown.impl.map +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.JsonDecodingException +import java.net.URL + +class FakeElementWellknownStore( + initialData: Map> = emptyMap(), + private val jsonProvider: JsonProvider = DefaultJsonProvider(), +) : ElementWellknownStore { + private val cachedData = mutableMapOf>() + + init { + initialData.forEach { (url, result) -> + cachedData[URL(url).host] = result + } + } + + override suspend fun get(domain: String): WellknownRetrieverResult { + return cachedData[domain] ?: WellknownRetrieverResult.NotFound + } + + @OptIn(ExperimentalSerializationApi::class) + override suspend fun update(domain: String, wellknown: String): Result { + val json = jsonProvider() + val mapped = try { + json.decodeFromString(wellknown).map() + } catch (e: JsonDecodingException) { + return Result.failure(e) + } + cachedData[domain] = WellknownRetrieverResult.Success(mapped) + return Result.success(Unit) + } + + override suspend fun delete(domain: String): Result { + cachedData.remove(domain) + return Result.success(Unit) + } +} 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 51b06f7226..8ec8874ad9 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 @@ -19,6 +19,7 @@ fun anElementWellKnown( notificationSound: String? = null, identityProviderAppScheme: String? = null, customRecoveryPassphrase: CustomRecoveryPassphrase? = null, + contentScannerUrl: String? = null, ) = ElementWellKnown( registrationHelperUrl = registrationHelperUrl, enforceElementPro = enforceElementPro, @@ -27,6 +28,7 @@ fun anElementWellKnown( notificationSound = notificationSound, identityProviderAppScheme = identityProviderAppScheme, customRecoveryPassphrase = customRecoveryPassphrase, + contentScannerUrl = contentScannerUrl, ) fun aCustomRecoveryPassphrase( From 25479480c4f8040eca118ea93577250704f3fb18 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Jul 2026 09:55:08 +0200 Subject: [PATCH 058/383] Update enhancement template so that global feature request are opened on element-meta --- .github/ISSUE_TEMPLATE/enhancement.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml index 114bc2bc65..e43022edab 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.yml +++ b/.github/ISSUE_TEMPLATE/enhancement.yml @@ -1,11 +1,11 @@ name: Enhancement request -description: Do you have a suggestion or feature request? +description: Do you have a suggestion or feature request? Please open issue on the repo element-hq/element-meta the request is global to all Element clients. labels: [T-Enhancement] body: - type: markdown attributes: value: | - Thank you for taking the time to propose an enhancement to an existing feature. If you would like to propose a new feature or a major cross-platform change, please [start a discussion here](https://github.com/element-hq/element-meta/discussions/new?category=ideas). + Thank you for taking the time to propose an enhancement to an existing feature. If you would like to propose a new feature or a major cross-platform change, please open an issue on the [element-meta repository](https://github.com/element-hq/element-meta/issues/new?template=enhancement.yml) instead. - type: textarea id: usecase attributes: From 15149af6b7be0f469db65be8d1e97d81b2657507 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Jul 2026 09:59:16 +0200 Subject: [PATCH 059/383] Update bug template question as many users do not understand the question. Also change the default answer to `No`. --- .github/ISSUE_TEMPLATE/bug.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 73f8c96ebc..71370e3296 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -69,18 +69,18 @@ body: description: | Trigger the defect, then click on the menu from the room list then "Report a bug". Describe the issue, mentioning that you have also filed a bug (it's helpful if you can include a link to the bug). Send the report to submit anonymous logs to the developers. options: - - 'Yes' - 'No' + - 'Yes' validations: required: true - type: dropdown id: pr attributes: - label: Are you willing to provide a PR? + label: Will you submit a Pull Request? description: | - Providing a PR can drastically speed up the process of fixing this bug. Don't worry, it's still OK to answer 'No' :). + Submitting a Pull Request can drastically speed up the process of fixing this bug. Don't worry, it's still OK to answer 'No' :). options: - - 'Yes' - 'No' + - 'Yes' validations: required: true From e0161e5b250a8cb362e5b26b1cd37ce838f6b871 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Jul 2026 10:02:04 +0200 Subject: [PATCH 060/383] Fix typo --- .github/ISSUE_TEMPLATE/enhancement.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml index e43022edab..d2715e6e8b 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.yml +++ b/.github/ISSUE_TEMPLATE/enhancement.yml @@ -1,5 +1,5 @@ name: Enhancement request -description: Do you have a suggestion or feature request? Please open issue on the repo element-hq/element-meta the request is global to all Element clients. +description: Do you have a suggestion or feature request? Please open issue on the repo element-hq/element-meta if the request is global to all Element clients. labels: [T-Enhancement] body: - type: markdown From 28abf3049e5f25d1ae4433dbc6a9aae37fa94529 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Jul 2026 11:55:50 +0200 Subject: [PATCH 061/383] Cleanup AndroidManifest.xml files. --- app/src/main/AndroidManifest.xml | 3 --- features/call/impl/src/main/AndroidManifest.xml | 1 + libraries/androidutils/src/main/AndroidManifest.xml | 1 - .../api => mediaviewer/impl}/src/main/AndroidManifest.xml | 6 +++--- .../voicerecorder}/impl/src/main/AndroidManifest.xml | 0 5 files changed, 4 insertions(+), 7 deletions(-) rename libraries/{matrix/api => mediaviewer/impl}/src/main/AndroidManifest.xml (60%) rename {features/messages => libraries/voicerecorder}/impl/src/main/AndroidManifest.xml (100%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d63e18ec1a..f6a3225cb8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,9 +8,6 @@ - - - + diff --git a/libraries/androidutils/src/main/AndroidManifest.xml b/libraries/androidutils/src/main/AndroidManifest.xml index 446c4606d7..941f4ef1a8 100644 --- a/libraries/androidutils/src/main/AndroidManifest.xml +++ b/libraries/androidutils/src/main/AndroidManifest.xml @@ -7,5 +7,4 @@ --> - diff --git a/libraries/matrix/api/src/main/AndroidManifest.xml b/libraries/mediaviewer/impl/src/main/AndroidManifest.xml similarity index 60% rename from libraries/matrix/api/src/main/AndroidManifest.xml rename to libraries/mediaviewer/impl/src/main/AndroidManifest.xml index 608f16cc36..3e5f3ecc7e 100644 --- a/libraries/matrix/api/src/main/AndroidManifest.xml +++ b/libraries/mediaviewer/impl/src/main/AndroidManifest.xml @@ -1,12 +1,12 @@ - + + diff --git a/features/messages/impl/src/main/AndroidManifest.xml b/libraries/voicerecorder/impl/src/main/AndroidManifest.xml similarity index 100% rename from features/messages/impl/src/main/AndroidManifest.xml rename to libraries/voicerecorder/impl/src/main/AndroidManifest.xml From 20a55f48409421ba53ebe4af154b5eff23acd47b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 22 Jun 2026 18:47:06 +0200 Subject: [PATCH 062/383] aapt dump --- tools/manifest/aaptDump.sh | 13 +++ tools/manifest/gplay/release/aaptDump.txt | 96 +++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100755 tools/manifest/aaptDump.sh create mode 100644 tools/manifest/gplay/release/aaptDump.txt diff --git a/tools/manifest/aaptDump.sh b/tools/manifest/aaptDump.sh new file mode 100755 index 0000000000..440cf441bc --- /dev/null +++ b/tools/manifest/aaptDump.sh @@ -0,0 +1,13 @@ +#! /bin/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. + +# Assemble Gplay Release +./gradlew assembleGplayRelease + +# Dump information +$ANDROID_HOME/build-tools/37.0.0/aapt dump badging ./app/build/outputs/apk/gplay/release/app-gplay-universal-release.apk | + > ./tools/manifest/gplay/release/aaptDump.txt diff --git a/tools/manifest/gplay/release/aaptDump.txt b/tools/manifest/gplay/release/aaptDump.txt new file mode 100644 index 0000000000..918080f5c1 --- /dev/null +++ b/tools/manifest/gplay/release/aaptDump.txt @@ -0,0 +1,96 @@ +package: name='io.element.android.x' versionCode='202606040' versionName='26.06.4' platformBuildVersionName='17' platformBuildVersionCode='37' compileSdkVersion='37' compileSdkVersionCodename='17' +sdkVersion:'24' +targetSdkVersion:'37' +uses-permission: name='android.permission.REQUEST_INSTALL_PACKAGES' +uses-permission: name='android.permission.POST_NOTIFICATIONS' +uses-permission: name='android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS' +uses-permission: name='android.permission.RECORD_AUDIO' +uses-permission: name='android.permission.ACCESS_COARSE_LOCATION' +uses-permission: name='android.permission.ACCESS_FINE_LOCATION' +uses-permission: name='android.permission.FOREGROUND_SERVICE' +uses-permission: name='android.permission.FOREGROUND_SERVICE_LOCATION' +uses-permission: name='android.permission.CAMERA' +uses-permission: name='android.permission.MODIFY_AUDIO_SETTINGS' +uses-permission: name='android.permission.WAKE_LOCK' +uses-permission: name='android.permission.FOREGROUND_SERVICE_MICROPHONE' +uses-permission: name='android.permission.USE_FULL_SCREEN_INTENT' +uses-permission: name='android.permission.ACCESS_NETWORK_STATE' +uses-permission: name='android.permission.INTERNET' +uses-permission: name='android.permission.VIBRATE' +uses-permission: name='android.permission.ACCESS_WIFI_STATE' +uses-permission: name='android.permission.USE_BIOMETRIC' +uses-permission: name='android.permission.USE_FINGERPRINT' +uses-permission: name='com.google.android.c2dm.permission.RECEIVE' +uses-permission: name='android.permission.RECEIVE_BOOT_COMPLETED' +uses-permission: name='io.element.android.x.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION' +application-label:'Element X' +application-label-be:'Element X' +application-label-bg:'Element X' +application-label-ca:'Element X' +application-label-cs:'Element X' +application-label-cy:'Element X' +application-label-da:'Element X' +application-label-de:'Element X' +application-label-el:'Element X' +application-label-en-US:'Element X' +application-label-es:'Element X' +application-label-et:'Element X' +application-label-eu:'Element X' +application-label-fa:'Element X' +application-label-fi:'Element X' +application-label-fr:'Element X' +application-label-hr:'Element X' +application-label-hu:'Element X' +application-label-in:'Element X' +application-label-it:'Element X' +application-label-ja:'Element X' +application-label-ka:'Element X' +application-label-ko:'Element X' +application-label-lt:'Element X' +application-label-nb:'Element X' +application-label-nl:'Element X' +application-label-pl:'Element X' +application-label-pt:'Element X' +application-label-pt-BR:'Element X' +application-label-ro:'Element X' +application-label-ru:'Element X' +application-label-sk:'Element X' +application-label-sv:'Element X' +application-label-tr:'Element X' +application-label-uk:'Element X' +application-label-ur:'Element X' +application-label-uz:'Element X' +application-label-vi:'Element X' +application-label-zh:'Element X' +application-label-zh-CN:'Element X' +application-label-zh-TW:'Element X' +application-icon-120:'res/BW.xml' +application-icon-160:'res/BW.xml' +application-icon-240:'res/BW.xml' +application-icon-320:'res/BW.xml' +application-icon-480:'res/BW.xml' +application-icon-640:'res/BW.xml' +application-icon-65534:'res/BW.xml' +application-icon-65535:'res/BW.xml' +application: label='Element X' icon='res/BW.xml' +launchable-activity: name='io.element.android.x.MainActivity' label='' icon='' +uses-library-not-required:'androidx.window.extensions' +uses-library-not-required:'androidx.window.sidecar' +feature-group: label='' + uses-feature-not-required: name='android.hardware.camera' + uses-feature-not-required: name='android.hardware.microphone' + uses-feature-not-required: name='android.hardware.vulkan.version' version='4194307' + uses-feature-not-required: name='android.hardware.wifi' + uses-feature: name='android.hardware.faketouch' + uses-implied-feature: name='android.hardware.faketouch' reason='default feature for all apps' + uses-feature: name='android.hardware.location' + uses-implied-feature: name='android.hardware.location' reason='requested android.permission.ACCESS_COARSE_LOCATION permission, and requested android.permission.ACCESS_FINE_LOCATION permission' +main +other-activities +other-receivers +other-services +supports-screens: 'small' 'normal' 'large' 'xlarge' +supports-any-density: 'true' +locales: '--_--' 'be' 'bg' 'ca' 'cs' 'cy' 'da' 'de' 'el' 'en-US' 'es' 'et' 'eu' 'fa' 'fi' 'fr' 'hr' 'hu' 'in' 'it' 'ja' 'ka' 'ko' 'lt' 'nb' 'nl' 'pl' 'pt' 'pt-BR' 'ro' 'ru' 'sk' 'sv' 'tr' 'uk' 'ur' 'uz' 'vi' 'zh' 'zh-CN' 'zh-TW' +densities: '120' '160' '240' '320' '480' '640' '65534' '65535' +native-code: 'arm64-v8a' 'armeabi-v7a' 'x86' 'x86_64' From 8731e2243a76ab5a899f8b30880b0180f0ca14e4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Jul 2026 13:29:50 +0200 Subject: [PATCH 063/383] Fix script issue --- tools/manifest/aaptDump.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/manifest/aaptDump.sh b/tools/manifest/aaptDump.sh index 440cf441bc..ac66b92593 100755 --- a/tools/manifest/aaptDump.sh +++ b/tools/manifest/aaptDump.sh @@ -9,5 +9,5 @@ ./gradlew assembleGplayRelease # Dump information -$ANDROID_HOME/build-tools/37.0.0/aapt dump badging ./app/build/outputs/apk/gplay/release/app-gplay-universal-release.apk | +$ANDROID_HOME/build-tools/37.0.0/aapt dump badging ./app/build/outputs/apk/gplay/release/app-gplay-universal-release.apk \ > ./tools/manifest/gplay/release/aaptDump.txt From 06c9c9b77c8c18271c7cefc8c0dd77417223ba83 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Jul 2026 13:30:44 +0200 Subject: [PATCH 064/383] Ensure that Manifest content (aapt dump) is unchanged. --- .github/workflows/build.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7d1f7d8ea3..35620c2f92 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -104,7 +104,16 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Compile release sources if: ${{ matrix.variant == 'release' }} - run: ./gradlew bundleGplayRelease -PallWarningsAsErrors=true $CI_GRADLE_ARG_PROPERTIES + run: ./gradlew assembleGplayRelease bundleGplayRelease -PallWarningsAsErrors=true $CI_GRADLE_ARG_PROPERTIES + - name: Run aapt dump + if: ${{ matrix.variant == 'release' }} + run: | + $ANDROID_HOME/build-tools/37.0.0/aapt dump badging \ + ./app/build/outputs/apk/gplay/release/app-gplay-universal-release.apk \ + > /tmp/currentAaptDump.txt + - name: Check manifest has not changed + if: ${{ matrix.variant == 'release' }} + run: diff /tmp/currentAaptDump.txt ./tools/manifest/gplay/release/aaptDump.txt - name: Compile nightly sources if: ${{ matrix.variant == 'nightly' }} run: ./gradlew compileGplayNightlySources -PallWarningsAsErrors=true $CI_GRADLE_ARG_PROPERTIES From ac822544f28dc9e92686d2529e08207ea2de9ac4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Jul 2026 14:12:32 +0200 Subject: [PATCH 065/383] Split gradle invocation, else universal build is not generated. --- .github/workflows/build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 35620c2f92..521eafb3d3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -104,7 +104,9 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Compile release sources if: ${{ matrix.variant == 'release' }} - run: ./gradlew assembleGplayRelease bundleGplayRelease -PallWarningsAsErrors=true $CI_GRADLE_ARG_PROPERTIES + run: | + ./gradlew assembleGplayRelease -PallWarningsAsErrors=true $CI_GRADLE_ARG_PROPERTIES + ./gradlew bundleGplayRelease -PallWarningsAsErrors=true $CI_GRADLE_ARG_PROPERTIES - name: Run aapt dump if: ${{ matrix.variant == 'release' }} run: | From a7f4418555515f657be955305fb7528541bb0b21 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Jul 2026 14:13:12 +0200 Subject: [PATCH 066/383] Update dump. --- tools/manifest/gplay/release/aaptDump.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/manifest/gplay/release/aaptDump.txt b/tools/manifest/gplay/release/aaptDump.txt index 918080f5c1..7764f0d76b 100644 --- a/tools/manifest/gplay/release/aaptDump.txt +++ b/tools/manifest/gplay/release/aaptDump.txt @@ -1,4 +1,4 @@ -package: name='io.element.android.x' versionCode='202606040' versionName='26.06.4' platformBuildVersionName='17' platformBuildVersionCode='37' compileSdkVersion='37' compileSdkVersionCodename='17' +package: name='io.element.android.x' versionCode='202607000' versionName='26.07.0' platformBuildVersionName='17' platformBuildVersionCode='37' compileSdkVersion='37' compileSdkVersionCodename='17' sdkVersion:'24' targetSdkVersion:'37' uses-permission: name='android.permission.REQUEST_INSTALL_PACKAGES' From 55f3a1acfbfcffee27f7db303ea8e3a3720ad4e4 Mon Sep 17 00:00:00 2001 From: manfrommedan Date: Wed, 8 Jul 2026 15:32:01 +0300 Subject: [PATCH 067/383] Keep the in-progress edit when attaching media Picking an attachment reset the composer to Normal, which dropped an in-progress edit: the attachment went out as a new message and the leftover edit text then created another one instead of editing the original. Route every attach path through a single resetComposerModeAfterAttaching() helper that clears Reply/Normal but keeps an edit pending, so the typed text still edits the original on the next send. This also covers the multi-item gallery picker added in #6519, which reset the mode unconditionally. Reply is still cleared (the attachment becomes the reply). Fixes #7083. --- .../MessageComposerPresenter.kt | 16 ++-- .../MessageComposerPresenterTest.kt | 74 +++++++++++++++++++ .../mediapickers/test/FakePickerProvider.kt | 9 ++- 3 files changed, 92 insertions(+), 7 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 858e872365..eaa00f427e 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 @@ -288,8 +288,7 @@ class MessageComposerPresenter( inReplyToEventId = inReplyToEventId, ) - // Reset composer since the attachment has been sent - messageComposerContext.composerMode = MessageComposerMode.Normal + resetComposerModeAfterAttaching() } is MessageComposerEvent.SetMode -> { localCoroutineScope.setMode(event.composerMode, markdownTextEditorState, richTextEditorState) @@ -638,8 +637,7 @@ class MessageComposerPresenter( val inReplyToEventId = (messageComposerContext.composerMode as? MessageComposerMode.Reply)?.eventId navigator.navigateToPreviewAttachments(persistentListOf(mediaAttachment), inReplyToEventId) - // Reset composer since the attachment will be sent in a separate flow - messageComposerContext.composerMode = MessageComposerMode.Normal + resetComposerModeAfterAttaching() } private fun handlePickedMediaList( @@ -663,7 +661,15 @@ class MessageComposerPresenter( val inReplyToEventId = (messageComposerContext.composerMode as? MessageComposerMode.Reply)?.eventId navigator.navigateToPreviewAttachments(attachments, inReplyToEventId) - messageComposerContext.composerMode = MessageComposerMode.Normal + resetComposerModeAfterAttaching() + } + + private fun resetComposerModeAfterAttaching() { + // An attachment is sent as its own message, so a Reply/Normal mode is consumed and reset. + // An in-progress edit must survive: the typed text still edits the original on the next send. + if (!messageComposerContext.composerMode.isEditing) { + messageComposerContext.composerMode = MessageComposerMode.Normal + } } private suspend fun sendMedia( 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 7c6f47058e..499e4bf91a 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 @@ -34,6 +34,7 @@ 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.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 @@ -758,6 +759,79 @@ class MessageComposerPresenterTest : RobolectricTest() { } } + @Test + fun `present - Pick media from gallery while editing keeps the edit pending`() = runTest { + val onPreviewAttachmentLambda = lambdaRecorder { _: ImmutableList, _: EventId? -> } + val navigator = FakeMessagesNavigator( + onPreviewAttachmentLambda = onPreviewAttachmentLambda + ) + val presenter = createPresenter(navigator = navigator) + pickerProvider.givenMimeType(MimeTypes.Images) + presenter.test { + var state = awaitFirstItem() + val editMode = anEditMode() + state.eventSink(MessageComposerEvent.SetMode(editMode)) + state = awaitItem() + assertThat(state.mode).isEqualTo(editMode) + // The media is sent as a new message while the edit stays active. If the mode reset, + // a Normal-mode state would be emitted and expectNoEvents() below would fail. + state.eventSink(MessageComposerEvent.PickAttachmentSource.FromGallery) + onPreviewAttachmentLambda.assertions().isCalledOnce() + expectNoEvents() + assertThat(state.mode).isEqualTo(editMode) + } + } + + @Test + fun `present - Pick media from gallery while replying clears the reply mode`() = runTest { + val onPreviewAttachmentLambda = lambdaRecorder { _: ImmutableList, _: EventId? -> } + val navigator = FakeMessagesNavigator( + onPreviewAttachmentLambda = onPreviewAttachmentLambda + ) + val presenter = createPresenter(navigator = navigator) + pickerProvider.givenMimeType(MimeTypes.Images) + presenter.test { + var state = awaitFirstItem() + state.eventSink(MessageComposerEvent.SetMode(aReplyMode())) + state = awaitItem() + assertThat(state.mode).isInstanceOf(MessageComposerMode.Reply::class.java) + // The media becomes the reply, so the reply intent is consumed and the composer resets. + state.eventSink(MessageComposerEvent.PickAttachmentSource.FromGallery) + onPreviewAttachmentLambda.assertions().isCalledOnce() + state = awaitItem() + assertThat(state.mode).isEqualTo(MessageComposerMode.Normal) + } + } + + @Test + fun `present - Pick multiple media from gallery while editing keeps the edit pending`() = runTest { + val onPreviewAttachmentLambda = lambdaRecorder { _: ImmutableList, _: EventId? -> } + val navigator = FakeMessagesNavigator( + onPreviewAttachmentLambda = onPreviewAttachmentLambda + ) + val presenter = createPresenter( + navigator = navigator, + featureFlagService = FakeFeatureFlagService( + initialState = mapOf(FeatureFlags.SendGalleryMessages.key to true) + ), + ) + pickerProvider.givenMimeType(MimeTypes.Images) + // Two Uris take the multi-item branch (handlePickedMediaList) instead of delegating to the + // single-item path, so the edit is preserved for gallery messages too. + pickerProvider.givenMultipleResults(listOf(mockk(), mockk())) + presenter.test { + var state = awaitFirstItem() + val editMode = anEditMode() + state.eventSink(MessageComposerEvent.SetMode(editMode)) + state = awaitItem() + assertThat(state.mode).isEqualTo(editMode) + state.eventSink(MessageComposerEvent.PickAttachmentSource.FromGallery) + onPreviewAttachmentLambda.assertions().isCalledOnce() + expectNoEvents() + assertThat(state.mode).isEqualTo(editMode) + } + } + @Test fun `present - Pick media from gallery & cancel does nothing`() = runTest { val presenter = createPresenter() diff --git a/libraries/mediapickers/test/src/main/kotlin/io/element/android/libraries/mediapickers/test/FakePickerProvider.kt b/libraries/mediapickers/test/src/main/kotlin/io/element/android/libraries/mediapickers/test/FakePickerProvider.kt index 5d3be8acd1..022ad05da2 100644 --- a/libraries/mediapickers/test/src/main/kotlin/io/element/android/libraries/mediapickers/test/FakePickerProvider.kt +++ b/libraries/mediapickers/test/src/main/kotlin/io/element/android/libraries/mediapickers/test/FakePickerProvider.kt @@ -19,6 +19,7 @@ import io.element.android.libraries.mediapickers.api.PickerProvider class FakePickerProvider : PickerProvider { private var mimeType = MimeTypes.Any private var result: Uri? = null + private var multipleResults: List? = null @Composable override fun registerGalleryPicker(onResult: (uri: Uri?, mimeType: String?) -> Unit): PickerLauncher { @@ -32,7 +33,7 @@ class FakePickerProvider : PickerProvider { @Composable override fun registerGalleryMultiPicker(onResult: (uris: List) -> Unit): PickerLauncher> { - return NoOpPickerLauncher { onResult(result?.let { listOf(it) } ?: emptyList()) } + return NoOpPickerLauncher { onResult(multipleResults ?: result?.let { listOf(it) } ?: emptyList()) } } @Composable @@ -42,7 +43,7 @@ class FakePickerProvider : PickerProvider { @Composable override fun registerFileMultiPicker(mimeType: String, onResult: (uris: List) -> Unit): PickerLauncher, List> { - return NoOpPickerLauncher { onResult(result?.let { listOf(it) } ?: emptyList()) } + return NoOpPickerLauncher { onResult(multipleResults ?: result?.let { listOf(it) } ?: emptyList()) } } @Composable @@ -59,6 +60,10 @@ class FakePickerProvider : PickerProvider { this.result = value } + fun givenMultipleResults(uris: List) { + this.multipleResults = uris + } + fun givenMimeType(mimeType: String) { this.mimeType = mimeType } From ebc16bb3e1d899283037d41e7b7897a0cff98e60 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Jul 2026 14:39:04 +0200 Subject: [PATCH 068/383] Update version in ./tools/manifest/gplay/release/aaptDump.txt during the release. --- tools/release/release.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/release/release.sh b/tools/release/release.sh index 0934e6c714..83ccc6d258 100755 --- a/tools/release/release.sh +++ b/tools/release/release.sh @@ -151,12 +151,20 @@ sed "s/private const val versionMonth = .*/private const val versionMonth = ${ve sed "s/private const val versionReleaseNumber = .*/private const val versionReleaseNumber = ${versionReleaseNumber}/" ${versionsFileBak} > ${versionsFile} rm ${versionsFileBak} +printf -v versionReleaseNumber2Digits "%02d" "${versionReleaseNumber}" +versionCode="20${versionYear}${versionMonth}${versionReleaseNumber2Digits}0" + +# Update the file aaptDump.txt with the new version +aaptDumpFile="./tools/manifest/gplay/release/aaptDump.txt" +sed "s/versionCode='[0-9]*'/versionCode='${versionCode}'/" ${aaptDumpFile} > ${aaptDumpFile}.bak +sed "s/versionName='[0-9]*\.[0-9]*\.[0-9]*'/versionName='${version}'/" ${aaptDumpFile}.bak > ${aaptDumpFile} +rm ${aaptDumpFile}.bak + git commit -a -m "Setting version for the release ${version}" printf "\n================================================================================\n" printf "Creating fastlane file...\n" -printf -v versionReleaseNumber2Digits "%02d" "${versionReleaseNumber}" -fastlaneFile="20${versionYear}${versionMonth}${versionReleaseNumber2Digits}0.txt" +fastlaneFile="${versionCode}.txt" fastlanePathFile="./fastlane/metadata/android/en-US/changelogs/${fastlaneFile}" printf "Main changes in this version: bug fixes and improvements.\nFull changelog: https://github.com/element-hq/element-x-android/releases" > "${fastlanePathFile}" From 2e161914a9f70b7587ab547ebde85c581665f0fd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Jul 2026 14:42:13 +0200 Subject: [PATCH 069/383] Update aaptDump.txt when syncing strings from Localazy New locales added via Localazy would change the locales line in aaptDump.txt and break the manifest CI check if the reference file is not kept in sync. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/sync-localazy.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml index d52100ad9f..6bd5c84283 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -39,6 +39,7 @@ jobs: ./tools/localazy/downloadStrings.sh --all ./tools/localazy/importSupportedLocalesFromLocalazy.py ./tools/test/generateAllScreenshots.py + ./tools/manifest/aaptDump.sh - name: Create Pull Request for Strings uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 with: From 74bc2c0f5d062099a90d278a299b00ad18b29cf8 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 7 Jul 2026 21:37:32 +0200 Subject: [PATCH 070/383] Add local network address classifier and permission advisor --- .../androidutils/src/main/AndroidManifest.xml | 1 + .../androidutils/network/DnsResolver.kt | 25 ++++ .../network/LocalNetworkAddressClassifier.kt | 75 +++++++++++ .../androidutils/network/FakeDnsResolver.kt | 33 +++++ .../LocalNetworkAddressClassifierTest.kt | 124 ++++++++++++++++++ .../api/LocalNetworkPermissionAdvisor.kt | 16 +++ .../DefaultLocalNetworkPermissionAdvisor.kt | 36 +++++ ...efaultLocalNetworkPermissionAdvisorTest.kt | 79 +++++++++++ .../test/FakeLocalNetworkPermissionAdvisor.kt | 16 +++ 9 files changed, 405 insertions(+) create mode 100644 libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/network/DnsResolver.kt create mode 100644 libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/network/LocalNetworkAddressClassifier.kt create mode 100644 libraries/androidutils/src/test/kotlin/io/element/android/libraries/androidutils/network/FakeDnsResolver.kt create mode 100644 libraries/androidutils/src/test/kotlin/io/element/android/libraries/androidutils/network/LocalNetworkAddressClassifierTest.kt create mode 100644 libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/LocalNetworkPermissionAdvisor.kt create mode 100644 libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultLocalNetworkPermissionAdvisor.kt create mode 100644 libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultLocalNetworkPermissionAdvisorTest.kt create mode 100644 libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakeLocalNetworkPermissionAdvisor.kt diff --git a/libraries/androidutils/src/main/AndroidManifest.xml b/libraries/androidutils/src/main/AndroidManifest.xml index 446c4606d7..c27910aee3 100644 --- a/libraries/androidutils/src/main/AndroidManifest.xml +++ b/libraries/androidutils/src/main/AndroidManifest.xml @@ -8,4 +8,5 @@ + diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/network/DnsResolver.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/network/DnsResolver.kt new file mode 100644 index 0000000000..da84a99a17 --- /dev/null +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/network/DnsResolver.kt @@ -0,0 +1,25 @@ +/* + * 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.network + +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import java.net.InetAddress + +interface DnsResolver { + suspend fun resolve(host: String): List +} + +@ContributesBinding(AppScope::class) +class DefaultDnsResolver : DnsResolver { + override suspend fun resolve(host: String): List = withContext(Dispatchers.IO) { + InetAddress.getAllByName(host).toList() + } +} diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/network/LocalNetworkAddressClassifier.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/network/LocalNetworkAddressClassifier.kt new file mode 100644 index 0000000000..b26ef49ac0 --- /dev/null +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/network/LocalNetworkAddressClassifier.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.androidutils.network + +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.core.data.tryOrNull +import java.net.Inet4Address +import java.net.Inet6Address +import java.net.InetAddress +import java.net.URI + +sealed interface LocalNetworkClassification { + data object PublicIp : LocalNetworkClassification + data object LocalIp : LocalNetworkClassification + data object Unresolvable : LocalNetworkClassification +} + +interface LocalNetworkAddressClassifier { + /** + * Classify [url] as pointing to a local network, a public host, or unresolvable. + */ + suspend fun classify(url: String): LocalNetworkClassification +} + +@ContributesBinding(AppScope::class) +class DefaultLocalNetworkAddressClassifier( + private val dnsResolver: DnsResolver, +) : LocalNetworkAddressClassifier { + override suspend fun classify(url: String): LocalNetworkClassification { + val host = extractHost(url) ?: return LocalNetworkClassification.Unresolvable + // `.local` domains are always link-local by definition + if (host.endsWith(".local", ignoreCase = true)) return LocalNetworkClassification.LocalIp + + val resolved = tryOrNull { dnsResolver.resolve(host) } + + if (resolved.isNullOrEmpty()) return LocalNetworkClassification.Unresolvable + + return if (resolved.any { it.isLocalRange() }) { + LocalNetworkClassification.LocalIp + } else { + LocalNetworkClassification.PublicIp + } + } + + private fun extractHost(url: String): String? { + return tryOrNull { + val uri = URI(url) + uri.host?.takeIf { it.isNotBlank() } + } + } + + private fun InetAddress.isLocalRange(): Boolean { + if (isLoopbackAddress || isLinkLocalAddress || isSiteLocalAddress) return true + // Cases not covered by jvm + // 1. IPV4 100.64.0.0/10 + if (this is Inet4Address) { + val bytes = address + val b0 = bytes[0].toInt() and 0xff + val b1 = bytes[1].toInt() and 0xff + if (b0 == 100 && b1 in 64..127) return true + } + // 2. IPV6 fc00::/7 + if (this is Inet6Address) { + val firstByte = address[0].toInt() and 0xff + if (firstByte and 0xfe == 0xfc) return true + } + return false + } +} diff --git a/libraries/androidutils/src/test/kotlin/io/element/android/libraries/androidutils/network/FakeDnsResolver.kt b/libraries/androidutils/src/test/kotlin/io/element/android/libraries/androidutils/network/FakeDnsResolver.kt new file mode 100644 index 0000000000..5015abc307 --- /dev/null +++ b/libraries/androidutils/src/test/kotlin/io/element/android/libraries/androidutils/network/FakeDnsResolver.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.network + +import io.element.android.libraries.core.data.tryOrNull +import java.net.InetAddress +import java.net.UnknownHostException + +class FakeDnsResolver( + private val results: Map> = emptyMap(), + private val throwOnUnknown: Boolean = true, +) : DnsResolver { + override suspend fun resolve(host: String): List { + // Mimic production DefaultDnsResolver: InetAddress resolves IP literals synchronously + // (no DNS lookup), so tests can pass literals through without registering them in [results]. + if (looksLikeIpLiteral(host)) { + tryOrNull { InetAddress.getAllByName(host).toList() }?.let { return it } + } + return results[host] + ?: if (throwOnUnknown) throw UnknownHostException(host) else emptyList() + } + + private fun looksLikeIpLiteral(host: String): Boolean { + if (':' in host) return true + val parts = host.split('.') + return parts.size == 4 && parts.all { it.toIntOrNull() != null } + } +} diff --git a/libraries/androidutils/src/test/kotlin/io/element/android/libraries/androidutils/network/LocalNetworkAddressClassifierTest.kt b/libraries/androidutils/src/test/kotlin/io/element/android/libraries/androidutils/network/LocalNetworkAddressClassifierTest.kt new file mode 100644 index 0000000000..4c567822b2 --- /dev/null +++ b/libraries/androidutils/src/test/kotlin/io/element/android/libraries/androidutils/network/LocalNetworkAddressClassifierTest.kt @@ -0,0 +1,124 @@ +/* + * 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.network + +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.runTest +import org.junit.Test +import java.net.InetAddress + +class LocalNetworkAddressClassifierTest { + private fun classifier( + resolver: DnsResolver = FakeDnsResolver(), + ) = DefaultLocalNetworkAddressClassifier(resolver) + + @Test + fun `IPv4 loopback literal is LocalIp`() = runTest { + assertThat(classifier().classify("https://127.0.0.1:8008")).isEqualTo(LocalNetworkClassification.LocalIp) + } + + @Test + fun `IPv4 RFC1918 10 literal is LocalIp`() = runTest { + assertThat(classifier().classify("https://10.0.0.5")).isEqualTo(LocalNetworkClassification.LocalIp) + } + + @Test + fun `IPv4 RFC1918 172_16 literal is LocalIp`() = runTest { + assertThat(classifier().classify("https://172.20.1.2")).isEqualTo(LocalNetworkClassification.LocalIp) + } + + @Test + fun `IPv4 RFC1918 192_168 literal is LocalIp`() = runTest { + assertThat(classifier().classify("https://192.168.1.10")).isEqualTo(LocalNetworkClassification.LocalIp) + } + + @Test + fun `IPv4 link local literal is LocalIp`() = runTest { + assertThat(classifier().classify("https://169.254.10.20")).isEqualTo(LocalNetworkClassification.LocalIp) + } + + @Test + fun `IPv4 CGNAT 100_64_0_0_10 literal is LocalIp`() = runTest { + assertThat(classifier().classify("https://100.100.0.1")).isEqualTo(LocalNetworkClassification.LocalIp) + } + + @Test + fun `IPv4 public literal is PublicIp`() = runTest { + assertThat(classifier().classify("https://8.8.8.8")).isEqualTo(LocalNetworkClassification.PublicIp) + } + + @Test + fun `IPv6 loopback literal is LocalIp`() = runTest { + assertThat(classifier().classify("https://[::1]")).isEqualTo(LocalNetworkClassification.LocalIp) + } + + @Test + fun `IPv6 link local literal is LocalIp`() = runTest { + assertThat(classifier().classify("https://[fe80::1]")).isEqualTo(LocalNetworkClassification.LocalIp) + } + + @Test + fun `IPv6 unique local literal is LocalIp`() = runTest { + assertThat(classifier().classify("https://[fc00::1]")).isEqualTo(LocalNetworkClassification.LocalIp) + } + + @Test + fun `IPv6 public literal is PublicIp`() = runTest { + assertThat(classifier().classify("https://[2606:4700:4700::1111]")).isEqualTo(LocalNetworkClassification.PublicIp) + } + + @Test + fun `dot local mDNS name is LocalIp without DNS`() = runTest { + assertThat(classifier().classify("https://matrix.local")) + .isEqualTo(LocalNetworkClassification.LocalIp) + } + + @Test + fun `hostname resolving to public IP is PublicIp`() = runTest { + val resolver = FakeDnsResolver( + results = mapOf("matrix.org" to listOf(InetAddress.getByName("8.8.8.8"))) + ) + assertThat(classifier(resolver).classify("https://matrix.org")) + .isEqualTo(LocalNetworkClassification.PublicIp) + } + + @Test + fun `hostname resolving to private IP is LocalIp`() = runTest { + val resolver = FakeDnsResolver( + results = mapOf("matrix.corp.internal" to listOf(InetAddress.getByName("10.0.0.5"))) + ) + assertThat(classifier(resolver).classify("https://matrix.corp.internal")) + .isEqualTo(LocalNetworkClassification.LocalIp) + } + + @Test + fun `hostname with mixed public and private addresses is LocalIp`() = runTest { + val resolver = FakeDnsResolver( + results = mapOf( + "matrix.example" to listOf( + InetAddress.getByName("8.8.8.8"), + InetAddress.getByName("10.0.0.5"), + ) + ) + ) + assertThat(classifier(resolver).classify("https://matrix.example")) + .isEqualTo(LocalNetworkClassification.LocalIp) + } + + @Test + fun `unresolvable hostname is Unresolvable`() = runTest { + val resolver = FakeDnsResolver(throwOnUnknown = true) + assertThat(classifier(resolver).classify("https://nonexistent.example")) + .isEqualTo(LocalNetworkClassification.Unresolvable) + } + + @Test + fun `malformed URL is Unresolvable`() = runTest { + assertThat(classifier().classify("not a url")).isEqualTo(LocalNetworkClassification.Unresolvable) + } +} diff --git a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/LocalNetworkPermissionAdvisor.kt b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/LocalNetworkPermissionAdvisor.kt new file mode 100644 index 0000000000..7ed46a63e1 --- /dev/null +++ b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/LocalNetworkPermissionAdvisor.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.permissions.api + +interface LocalNetworkPermissionAdvisor { + /** + * Returns true when the app should request the ACCESS_LOCAL_NETWORK permission before making + * network requests to [homeserverUrl]. + */ + suspend fun shouldRequestPermissionFor(homeserverUrl: String): Boolean +} diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultLocalNetworkPermissionAdvisor.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultLocalNetworkPermissionAdvisor.kt new file mode 100644 index 0000000000..a34ece0859 --- /dev/null +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultLocalNetworkPermissionAdvisor.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.permissions.impl + +import android.Manifest.permission.ACCESS_LOCAL_NETWORK +import android.os.Build +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.androidutils.network.LocalNetworkAddressClassifier +import io.element.android.libraries.androidutils.network.LocalNetworkClassification +import io.element.android.libraries.permissions.api.LocalNetworkPermissionAdvisor +import io.element.android.libraries.permissions.api.PermissionStateProvider +import io.element.android.services.toolbox.api.sdk.BuildVersionSdkIntProvider + +@ContributesBinding(AppScope::class) +class DefaultLocalNetworkPermissionAdvisor( + private val classifier: LocalNetworkAddressClassifier, + private val permissionStateProvider: PermissionStateProvider, + private val buildVersionSdkIntProvider: BuildVersionSdkIntProvider, +) : LocalNetworkPermissionAdvisor { + override suspend fun shouldRequestPermissionFor(homeserverUrl: String): Boolean { + if (!buildVersionSdkIntProvider.isAtLeast(Build.VERSION_CODES.CINNAMON_BUN)) return false + if (permissionStateProvider.isPermissionGranted(ACCESS_LOCAL_NETWORK)) return false + return when (classifier.classify(homeserverUrl)) { + LocalNetworkClassification.LocalIp -> true + LocalNetworkClassification.PublicIp, + // Unresolvable: we can't confirm the host is local, so we don't prompt, acceptable trade-off vs. over-prompting. + LocalNetworkClassification.Unresolvable -> false + } + } +} diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultLocalNetworkPermissionAdvisorTest.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultLocalNetworkPermissionAdvisorTest.kt new file mode 100644 index 0000000000..2ed1dd7548 --- /dev/null +++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultLocalNetworkPermissionAdvisorTest.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.permissions.impl + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.androidutils.network.LocalNetworkAddressClassifier +import io.element.android.libraries.androidutils.network.LocalNetworkClassification +import io.element.android.libraries.permissions.test.FakePermissionStateProvider +import io.element.android.services.toolbox.test.sdk.FakeBuildVersionSdkIntProvider +import kotlinx.coroutines.test.runTest +import org.junit.Test + +private const val LOCAL_URL = "https://matrix.corp.internal" +private const val PUBLIC_URL = "https://matrix.org" + +class DefaultLocalNetworkPermissionAdvisorTest { + private fun advisor( + sdkInt: Int, + permissionGranted: Boolean, + classification: LocalNetworkClassification, + ) = DefaultLocalNetworkPermissionAdvisor( + classifier = FakeLocalNetworkAddressClassifier(classification), + permissionStateProvider = FakePermissionStateProvider(permissionGranted = permissionGranted), + buildVersionSdkIntProvider = FakeBuildVersionSdkIntProvider(sdkInt), + ) + + @Test + fun `returns false when SDK below 37`() = runTest { + val result = advisor(sdkInt = 36, permissionGranted = false, classification = LocalNetworkClassification.LocalIp) + .shouldRequestPermissionFor(LOCAL_URL) + assertThat(result).isFalse() + } + + @Test + fun `returns false when permission already granted`() = runTest { + val result = advisor(sdkInt = 37, permissionGranted = true, classification = LocalNetworkClassification.LocalIp) + .shouldRequestPermissionFor(LOCAL_URL) + assertThat(result).isFalse() + } + + @Test + fun `returns false when URL classified as public IP`() = runTest { + val result = advisor(sdkInt = 37, permissionGranted = false, classification = LocalNetworkClassification.PublicIp) + .shouldRequestPermissionFor(PUBLIC_URL) + assertThat(result).isFalse() + } + + @Test + fun `returns true when SDK 37, permission missing, URL is local`() = runTest { + val result = advisor(sdkInt = 37, permissionGranted = false, classification = LocalNetworkClassification.LocalIp) + .shouldRequestPermissionFor(LOCAL_URL) + assertThat(result).isTrue() + } + + @Test + fun `returns false when SDK 37, permission missing, URL unresolvable`() = runTest { + val result = advisor(sdkInt = 37, permissionGranted = false, classification = LocalNetworkClassification.Unresolvable) + .shouldRequestPermissionFor(LOCAL_URL) + assertThat(result).isFalse() + } + + @Test + fun `returns true when SDK above 37, permission missing, URL is local`() = runTest { + val result = advisor(sdkInt = 38, permissionGranted = false, classification = LocalNetworkClassification.LocalIp) + .shouldRequestPermissionFor(LOCAL_URL) + assertThat(result).isTrue() + } +} + +private class FakeLocalNetworkAddressClassifier( + private val classification: LocalNetworkClassification, +) : LocalNetworkAddressClassifier { + override suspend fun classify(url: String): LocalNetworkClassification = classification +} diff --git a/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakeLocalNetworkPermissionAdvisor.kt b/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakeLocalNetworkPermissionAdvisor.kt new file mode 100644 index 0000000000..1a3363d6dc --- /dev/null +++ b/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakeLocalNetworkPermissionAdvisor.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.permissions.test + +import io.element.android.libraries.permissions.api.LocalNetworkPermissionAdvisor + +class FakeLocalNetworkPermissionAdvisor( + private val shouldPrompt: Boolean = false, +) : LocalNetworkPermissionAdvisor { + override suspend fun shouldRequestPermissionFor(homeserverUrl: String): Boolean = shouldPrompt +} From 7f4d264ee040210d7e43a5599eb0fa99f61b1ef0 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 7 Jul 2026 21:37:37 +0200 Subject: [PATCH 071/383] Add ForceRequestPermissions event to bypass soft-denial intercept --- .../permissions/api/PermissionsEvent.kt | 16 ++++++++++++++++ .../impl/DefaultPermissionsPresenter.kt | 3 +++ .../permissions/test/FakePermissionsPresenter.kt | 1 + 3 files changed, 20 insertions(+) diff --git a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsEvent.kt b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsEvent.kt index fd01e12134..8604959068 100644 --- a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsEvent.kt +++ b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/PermissionsEvent.kt @@ -9,7 +9,23 @@ package io.element.android.libraries.permissions.api sealed interface PermissionsEvent { + /** + * Request the runtime permission. If the app has already recorded a soft denial for this + * permission, this event is intercepted to raise [PermissionsState.showDialog] instead of + * hitting the OS — the intent is for the caller to render `PermissionsView` to prompt the + * user to open system settings. + * + * If the caller renders its own "already denied" UI and wants the OS prompt regardless, + * use [ForceRequestPermissions]. + */ data object RequestPermissions : PermissionsEvent + + /** + * Same as [RequestPermissions] but bypasses the soft-denial intercept — always launches + * the OS permission dialog. The OS may still auto-deny for permanently-denied permissions. + */ + data object ForceRequestPermissions : PermissionsEvent + data object CloseDialog : PermissionsEvent data object OpenSystemSettingAndCloseDialog : PermissionsEvent } diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt index 42331e001a..e3979e5ed2 100644 --- a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultPermissionsPresenter.kt @@ -112,6 +112,9 @@ class DefaultPermissionsPresenter( permissionState.launchPermissionRequest() } } + PermissionsEvent.ForceRequestPermissions -> { + permissionState.launchPermissionRequest() + } PermissionsEvent.OpenSystemSettingAndCloseDialog -> { permissionActions.openSettings(permission) showDialog.value = false diff --git a/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionsPresenter.kt b/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionsPresenter.kt index efd584585f..4c04a919da 100644 --- a/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionsPresenter.kt +++ b/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakePermissionsPresenter.kt @@ -21,6 +21,7 @@ class FakePermissionsPresenter( private fun handleEvent(event: PermissionsEvent) { when (event) { PermissionsEvent.RequestPermissions -> state.value = state.value.copy(showDialog = true, permissionAlreadyAsked = true) + PermissionsEvent.ForceRequestPermissions -> state.value = state.value.copy(permissionAlreadyAsked = true) PermissionsEvent.CloseDialog -> state.value = state.value.copy(showDialog = false) PermissionsEvent.OpenSystemSettingAndCloseDialog -> state.value = state.value.copy(showDialog = false) } From e9abed9178c0430f93224bf2ae04a85f1929a73e Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 7 Jul 2026 21:37:43 +0200 Subject: [PATCH 072/383] Expose homeserverUrl on MatrixClient --- .../io/element/android/libraries/matrix/api/MatrixClient.kt | 3 +++ .../element/android/libraries/matrix/impl/RustMatrixClient.kt | 1 + .../libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt | 3 +++ .../element/android/libraries/matrix/test/FakeMatrixClient.kt | 1 + 4 files changed, 8 insertions(+) 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 6546e4c41a..a360dd04ed 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 @@ -54,6 +54,9 @@ import java.util.Optional interface MatrixClient { val sessionId: SessionId val deviceId: DeviceId + + /** Base URL of the homeserver this client is connected to. */ + val homeserverUrl: String val sessionPaths: SessionPaths val userProfile: StateFlow val roomListService: RoomListService 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 2cfbbbdc73..19d8d7fec9 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 @@ -153,6 +153,7 @@ class RustMatrixClient( ) : MatrixClient { override val sessionId: UserId = UserId(innerClient.userId()) override val deviceId: DeviceId = DeviceId(innerClient.deviceId()) + override val homeserverUrl: String = innerClient.homeserver() override val sessionCoroutineScope = appCoroutineScope.childScope(dispatchers.main, "Session-$sessionId") private val sessionDispatcher = dispatchers.io.limitedParallelism(64) 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 43c36f7bfb..4c23744d53 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 @@ -10,6 +10,7 @@ package io.element.android.libraries.matrix.impl.fixtures.fakes import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSession import io.element.android.libraries.matrix.test.A_DEVICE_ID +import io.element.android.libraries.matrix.test.A_HOMESERVER_URL import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.simulateLongTask @@ -41,6 +42,7 @@ import uniffi.matrix_sdk_base.MediaRetentionPolicy class FakeFfiClient( private val userId: String = A_USER_ID.value, private val deviceId: String = A_DEVICE_ID.value, + private val homeserver: String = A_HOMESERVER_URL, private val notificationClient: NotificationClient = FakeFfiNotificationClient(), private val notificationSettings: NotificationSettings = FakeFfiNotificationSettings(), private val encryption: Encryption = FakeFfiEncryption(), @@ -56,6 +58,7 @@ class FakeFfiClient( ) : Client(NoHandle) { override fun userId(): String = userId override fun deviceId(): String = deviceId + override fun homeserver(): String = homeserver override suspend fun notificationClient(processSetup: NotificationProcessSetup) = notificationClient override suspend fun getNotificationSettings(): NotificationSettings = notificationSettings override fun encryption(): Encryption = encryption 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 2397f12443..8f69b621c8 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 @@ -74,6 +74,7 @@ class FakeMatrixClient( override val sessionId: SessionId = A_SESSION_ID, override val sessionPaths: SessionPaths = SessionPaths(fileDirectory = File("files"), cacheDirectory = File("cache")), override val deviceId: DeviceId = A_DEVICE_ID, + override val homeserverUrl: String = A_HOMESERVER_URL, override val sessionCoroutineScope: CoroutineScope = TestScope(), private val userDisplayName: String? = A_USER_NAME, private val userAvatarUrl: String? = AN_AVATAR_URL, From c2e8912fe209753c59647b044c35787edff5b154 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 7 Jul 2026 21:37:48 +0200 Subject: [PATCH 073/383] Add LocalNetworkPermissionGate with rationale dialog --- .../LocalNetworkPermissionDialogView.kt | 44 +++++++++ .../LocalNetworkPermissionGate.kt | 95 +++++++++++++++++++ .../LocalNetworkPermissionGateState.kt | 27 ++++++ .../src/main/res/values/temporary.xml | 2 + 4 files changed, 168 insertions(+) create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionDialogView.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGate.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGateState.kt diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionDialogView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionDialogView.kt new file mode 100644 index 0000000000..216b84fb11 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionDialogView.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.login.impl.localnetwork + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun LocalNetworkPermissionDialogView( + dialog: LocalNetworkPermissionDialog, + onSubmit: () -> Unit, + onDismiss: () -> Unit, + modifier: Modifier = Modifier, +) { + when (dialog) { + LocalNetworkPermissionDialog.None -> Unit + LocalNetworkPermissionDialog.Rationale -> ConfirmationDialog( + title = stringResource(CommonStrings.screen_local_network_opt_in_title), + content = stringResource(CommonStrings.screen_local_network_opt_in_subtitle), + submitText = stringResource(CommonStrings.dialog_allow_access), + cancelText = stringResource(CommonStrings.action_not_now), + onSubmitClick = onSubmit, + onDismiss = onDismiss, + modifier = modifier, + ) + LocalNetworkPermissionDialog.Settings -> ConfirmationDialog( + title = stringResource(CommonStrings.screen_local_network_opt_in_title), + content = stringResource(CommonStrings.screen_local_network_opt_in_subtitle), + submitText = stringResource(CommonStrings.action_open_settings), + cancelText = stringResource(CommonStrings.action_not_now), + onSubmitClick = onSubmit, + onDismiss = onDismiss, + modifier = modifier, + ) + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGate.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGate.kt new file mode 100644 index 0000000000..857a8f9287 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGate.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.features.login.impl.localnetwork + +import android.Manifest +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.rememberUpdatedState +import androidx.compose.runtime.setValue +import dev.zacsweers.metro.Inject +import io.element.android.libraries.permissions.api.LocalNetworkPermissionAdvisor +import io.element.android.libraries.permissions.api.PermissionsEvent +import io.element.android.libraries.permissions.api.PermissionsPresenter +import kotlinx.coroutines.launch + +@Inject +class LocalNetworkPermissionGate( + private val advisor: LocalNetworkPermissionAdvisor, + permissionsPresenterFactory: PermissionsPresenter.Factory, +) { + private val permissionsPresenter: PermissionsPresenter = + permissionsPresenterFactory.create(Manifest.permission.ACCESS_LOCAL_NETWORK) + + @Composable + fun present( + urlOf: (T) -> String, + onProceed: suspend (T) -> Unit, + ): LocalNetworkPermissionGateState { + val coroutineScope = rememberCoroutineScope() + val permissionsState = permissionsPresenter.present() + var pendingSubmit by remember { mutableStateOf(null) } + + val urlOf by rememberUpdatedState(urlOf) + val onProceed by rememberUpdatedState(onProceed) + + LaunchedEffect(permissionsState.permissionGranted, pendingSubmit) { + val pending = pendingSubmit + if (pending != null && permissionsState.permissionGranted) { + coroutineScope.launch { onProceed(pending) } + pendingSubmit = null + } + } + + val dialog by rememberUpdatedState( + when { + pendingSubmit == null -> LocalNetworkPermissionDialog.None + permissionsState.permissionGranted -> LocalNetworkPermissionDialog.None + permissionsState.shouldShowRationale || !permissionsState.permissionAlreadyAsked -> LocalNetworkPermissionDialog.Rationale + else -> LocalNetworkPermissionDialog.Settings + } + ) + + fun submit(value: T) { + coroutineScope.launch { + if (advisor.shouldRequestPermissionFor(urlOf(value))) { + pendingSubmit = value + } else { + onProceed(value) + } + } + } + + fun requestPermission() { + when (dialog) { + LocalNetworkPermissionDialog.Settings -> { + permissionsState.eventSink(PermissionsEvent.OpenSystemSettingAndCloseDialog) + } + LocalNetworkPermissionDialog.Rationale -> { + permissionsState.eventSink(PermissionsEvent.ForceRequestPermissions) + } + else -> Unit + } + } + + fun abort() { + pendingSubmit = null + } + + return LocalNetworkPermissionGateState( + dialog = dialog, + submit = ::submit, + requestPermission = ::requestPermission, + abort = ::abort, + ) + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGateState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGateState.kt new file mode 100644 index 0000000000..3213a96cd8 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGateState.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.login.impl.localnetwork + +data class LocalNetworkPermissionGateState( + val dialog: LocalNetworkPermissionDialog, + val submit: (T) -> Unit, + val requestPermission: () -> Unit, + val abort: () -> Unit, +) + +/** + * Which rationale dialog (if any) should be rendered on top of the caller's UI. + * + * [Rationale] is shown before the runtime prompt so the user knows why the permission is needed. + * [Settings] is shown when the OS says a rationale can no longer be shown (permanently denied). + */ +enum class LocalNetworkPermissionDialog { + None, + Rationale, + Settings, +} diff --git a/libraries/ui-strings/src/main/res/values/temporary.xml b/libraries/ui-strings/src/main/res/values/temporary.xml index fd1edb0759..a192e2c9df 100644 --- a/libraries/ui-strings/src/main/res/values/temporary.xml +++ b/libraries/ui-strings/src/main/res/values/temporary.xml @@ -8,4 +8,6 @@ "Mark as read" "Jump to first unread message" + Allow access to local network + Your homeserver is on your local network. To connect, Element needs permission to reach other devices on this network. From e92923a77d86bf85bb08345df76ba562a70ac0e4 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 7 Jul 2026 21:37:52 +0200 Subject: [PATCH 074/383] Prompt for local network permission on logged-in home --- appnav/build.gradle.kts | 2 + .../android/appnav/loggedin/LoggedInEvents.kt | 3 ++ .../appnav/loggedin/LoggedInPresenter.kt | 37 +++++++++++++++++++ .../android/appnav/loggedin/LoggedInState.kt | 7 ++++ .../appnav/loggedin/LoggedInStateProvider.kt | 4 ++ .../android/appnav/loggedin/LoggedInView.kt | 34 +++++++++++++++++ .../appnav/loggedin/LoggedInPresenterTest.kt | 6 +++ 7 files changed, 93 insertions(+) diff --git a/appnav/build.gradle.kts b/appnav/build.gradle.kts index 7440ecd2bf..ce9764360b 100644 --- a/appnav/build.gradle.kts +++ b/appnav/build.gradle.kts @@ -34,6 +34,7 @@ dependencies { implementation(projects.libraries.featureflag.api) implementation(projects.libraries.matrix.api) implementation(projects.libraries.oauth.api) + implementation(projects.libraries.permissions.api) implementation(projects.libraries.preferences.api) implementation(projects.libraries.push.api) implementation(projects.libraries.pushproviders.api) @@ -61,6 +62,7 @@ dependencies { testImplementation(projects.features.share.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.oauth.test) + testImplementation(projects.libraries.permissions.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/loggedin/LoggedInEvents.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInEvents.kt index d2a9c9298e..66fffce9e8 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInEvents.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInEvents.kt @@ -12,4 +12,7 @@ sealed interface LoggedInEvents { data class CloseErrorDialog(val doNotShowAgain: Boolean) : LoggedInEvents data object CheckSlidingSyncProxyAvailability : LoggedInEvents data object LogoutAndMigrateToNativeSlidingSync : LoggedInEvents + data object DismissLocalNetworkPermissionPrompt : LoggedInEvents + + data object RequestLocationNetworkPermission : LoggedInEvents } 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 752d10e7a9..fab9797c76 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 @@ -8,6 +8,7 @@ package io.element.android.appnav.loggedin +import android.Manifest import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState @@ -15,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.setValue @@ -36,6 +38,9 @@ import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion import io.element.android.libraries.matrix.api.sync.SyncService import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus +import io.element.android.libraries.permissions.api.LocalNetworkPermissionAdvisor +import io.element.android.libraries.permissions.api.PermissionsEvent +import io.element.android.libraries.permissions.api.PermissionsPresenter import io.element.android.libraries.push.api.PushService import io.element.android.libraries.push.api.PusherRegistrationFailure import io.element.android.services.analytics.api.AnalyticsService @@ -58,7 +63,12 @@ class LoggedInPresenter( private val encryptionService: EncryptionService, private val buildMeta: BuildMeta, private val networkMonitor: NetworkMonitor, + private val localNetworkPermissionAdvisor: LocalNetworkPermissionAdvisor, + permissionsPresenterFactory: PermissionsPresenter.Factory, ) : Presenter { + private val localNetworkPermissionsPresenter: PermissionsPresenter = + permissionsPresenterFactory.create(Manifest.permission.ACCESS_LOCAL_NETWORK) + @Composable override fun present(): LoggedInState { val coroutineScope = rememberCoroutineScope() @@ -117,6 +127,21 @@ class LoggedInPresenter( } } + val localNetworkPermissionState = localNetworkPermissionsPresenter.present() + var localNetworkPromptDismissedThisSession by remember { mutableStateOf(false) } + val advisorRequestsPrompt by produceState(initialValue = false, localNetworkPermissionState.permissionGranted) { + value = localNetworkPermissionAdvisor.shouldRequestPermissionFor(matrixClient.homeserverUrl) + } + LaunchedEffect(localNetworkPermissionState.permissionGranted) { + if (localNetworkPermissionState.permissionGranted) localNetworkPromptDismissedThisSession = false + } + val localNetworkPermissionDialog = when { + !advisorRequestsPrompt -> LocalNetworkPermissionDialog.None + localNetworkPromptDismissedThisSession -> LocalNetworkPermissionDialog.None + localNetworkPermissionState.shouldShowRationale -> LocalNetworkPermissionDialog.Rationale + else -> LocalNetworkPermissionDialog.Settings + } + fun handleEvent(event: LoggedInEvents) { when (event) { is LoggedInEvents.CloseErrorDialog -> { @@ -134,6 +159,17 @@ class LoggedInPresenter( // Force the logout since Native Sliding Sync is already enforced by the SDK matrixClient.logout(userInitiated = true, ignoreSdkError = true) } + LoggedInEvents.DismissLocalNetworkPermissionPrompt -> { + localNetworkPromptDismissedThisSession = true + } + LoggedInEvents.RequestLocationNetworkPermission -> { + if (localNetworkPermissionDialog == LocalNetworkPermissionDialog.Settings) { + localNetworkPermissionState.eventSink(PermissionsEvent.OpenSystemSettingAndCloseDialog) + } else { + localNetworkPermissionState.eventSink(PermissionsEvent.RequestPermissions) + } + localNetworkPromptDismissedThisSession = true + } } } @@ -143,6 +179,7 @@ class LoggedInPresenter( ignoreRegistrationError = ignoreRegistrationError, forceNativeSlidingSyncMigration = forceNativeSlidingSyncMigration, appName = buildMeta.applicationName, + localNetworkPermissionDialog = localNetworkPermissionDialog, eventSink = ::handleEvent, ) } diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt index b066f9f867..fdfff9bf75 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt @@ -16,5 +16,12 @@ data class LoggedInState( val ignoreRegistrationError: Boolean, val forceNativeSlidingSyncMigration: Boolean, val appName: String, + val localNetworkPermissionDialog: LocalNetworkPermissionDialog, val eventSink: (LoggedInEvents) -> Unit, ) + +enum class LocalNetworkPermissionDialog { + None, + Rationale, + Settings, +} diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt index b2f5407519..afe09ec78b 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt @@ -19,6 +19,8 @@ open class LoggedInStateProvider : PreviewParameterProvider { aLoggedInState(showSyncSpinner = true), aLoggedInState(pusherRegistrationState = AsyncData.Failure(PusherRegistrationFailure.NoDistributorsAvailable())), aLoggedInState(forceNativeSlidingSyncMigration = true), + aLoggedInState(localNetworkPermissionDialog = LocalNetworkPermissionDialog.Rationale), + aLoggedInState(localNetworkPermissionDialog = LocalNetworkPermissionDialog.Settings), ) } @@ -27,11 +29,13 @@ fun aLoggedInState( pusherRegistrationState: AsyncData = AsyncData.Uninitialized, forceNativeSlidingSyncMigration: Boolean = false, appName: String = "Element X", + localNetworkPermissionDialog: LocalNetworkPermissionDialog = LocalNetworkPermissionDialog.None, ) = LoggedInState( showSyncSpinner = showSyncSpinner, pusherRegistrationState = pusherRegistrationState, ignoreRegistrationError = false, forceNativeSlidingSyncMigration = forceNativeSlidingSyncMigration, appName = appName, + localNetworkPermissionDialog = localNetworkPermissionDialog, eventSink = {}, ) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt index 62d8de8c29..198a731e49 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.lifecycle.Lifecycle import io.element.android.appnav.R import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialogWithDoNotShowAgain import io.element.android.libraries.designsystem.preview.ElementPreview @@ -82,6 +83,39 @@ fun LoggedInView( } ) } + + LocalNetworkPermissionDialog(state = state) +} + +@Composable +private fun LocalNetworkPermissionDialog(state: LoggedInState) { + when (state.localNetworkPermissionDialog) { + LocalNetworkPermissionDialog.None -> Unit + LocalNetworkPermissionDialog.Rationale -> ConfirmationDialog( + title = stringResource(CommonStrings.screen_local_network_opt_in_title), + content = stringResource(CommonStrings.screen_local_network_opt_in_subtitle), + submitText = stringResource(CommonStrings.dialog_allow_access), + cancelText = stringResource(CommonStrings.action_not_now), + onSubmitClick = { + state.eventSink(LoggedInEvents.RequestLocationNetworkPermission) + }, + onDismiss = { + state.eventSink(LoggedInEvents.DismissLocalNetworkPermissionPrompt) + }, + ) + LocalNetworkPermissionDialog.Settings -> ConfirmationDialog( + title = stringResource(CommonStrings.screen_local_network_opt_in_title), + content = stringResource(CommonStrings.screen_local_network_opt_in_subtitle), + submitText = stringResource(CommonStrings.action_open_settings), + cancelText = stringResource(CommonStrings.action_not_now), + onSubmitClick = { + state.eventSink(LoggedInEvents.RequestLocationNetworkPermission) + }, + onDismiss = { + state.eventSink(LoggedInEvents.DismissLocalNetworkPermissionPrompt) + }, + ) + } } private fun Throwable.getReason(): String? { 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 18c8cfd7b9..faa19d9e61 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 @@ -36,6 +36,8 @@ import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService import io.element.android.libraries.matrix.test.sync.FakeSyncService import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService +import io.element.android.libraries.permissions.test.FakeLocalNetworkPermissionAdvisor +import io.element.android.libraries.permissions.test.FakePermissionsPresenterFactory import io.element.android.libraries.push.api.PushService import io.element.android.libraries.push.api.PusherRegistrationFailure import io.element.android.libraries.push.test.FakePushService @@ -124,6 +126,8 @@ class LoggedInPresenterTest { encryptionService = encryptionService, buildMeta = buildMeta, networkMonitor = networkMonitor, + localNetworkPermissionAdvisor = FakeLocalNetworkPermissionAdvisor(), + permissionsPresenterFactory = FakePermissionsPresenterFactory(), ).test { encryptionService.emitRecoveryState(RecoveryState.UNKNOWN) encryptionService.emitRecoveryState(RecoveryState.INCOMPLETE) @@ -368,6 +372,8 @@ class LoggedInPresenterTest { encryptionService = encryptionService, buildMeta = buildMeta, networkMonitor = networkMonitor, + localNetworkPermissionAdvisor = FakeLocalNetworkPermissionAdvisor(), + permissionsPresenterFactory = FakePermissionsPresenterFactory(), ) } } From 6f0788fd3410344ba4a998716a1e265eb97f1b6f Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 7 Jul 2026 21:37:58 +0200 Subject: [PATCH 075/383] Introduce LoginModePresenter with local network permission gate --- .../features/login/impl/di/LoginModule.kt | 5 + .../features/login/impl/login/LoginHelper.kt | 128 ------------------ .../login/impl/login/LoginModeEvent.kt | 23 ++++ .../login/impl/login/LoginModePresenter.kt | 117 ++++++++++++++++ .../login/{LoginMode.kt => LoginModeState.kt} | 11 +- .../impl/login/LoginModeStateProvider.kt | 21 +++ .../login/impl/resolver/HomeserverResolver.kt | 13 ++ .../ChooseAccountProviderPresenter.kt | 35 +++-- .../ChooseAccountProviderState.kt | 7 +- .../ChooseAccountProviderStateProvider.kt | 9 +- .../ChooseAccountProviderView.kt | 17 ++- .../LoginWithClassicPresenter.kt | 23 ++-- .../loginwithclassic/LoginWithClassicState.kt | 5 +- .../LoginWithClassicStateProvider.kt | 8 +- .../loginwithclassic/LoginWithClassicView.kt | 17 ++- .../ConfirmAccountProviderPresenter.kt | 21 ++- .../ConfirmAccountProviderState.kt | 8 +- .../ConfirmAccountProviderStateProvider.kt | 9 +- .../ConfirmAccountProviderView.kt | 18 ++- .../screens/onboarding/OnBoardingPresenter.kt | 23 ++-- .../screens/onboarding/OnBoardingState.kt | 7 +- .../onboarding/OnBoardingStateProvider.kt | 8 +- .../impl/screens/onboarding/OnBoardingView.kt | 17 ++- .../ChooseAccountProviderPresenterTest.kt | 20 +-- .../ChooseAccountProviderStateTest.kt | 5 +- .../ChooseAccountProviderViewTest.kt | 3 +- .../LoginWithClassicPresenterTest.kt | 18 +-- .../ConfirmAccountProviderPresenterTest.kt | 76 +++++------ .../onboarding/OnBoardingPresenterTest.kt | 25 ++-- .../screens/onboarding/OnboardingViewTest.kt | 9 +- .../SearchAccountProviderPresenterTest.kt | 11 +- 31 files changed, 420 insertions(+), 297 deletions(-) delete mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginHelper.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeEvent.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModePresenter.kt rename features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/{LoginMode.kt => LoginModeState.kt} (55%) create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeStateProvider.kt 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 4523e6f45e..037acf859b 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,6 +14,8 @@ 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.login.LoginModePresenter +import io.element.android.features.login.impl.login.LoginModeState import io.element.android.libraries.architecture.Presenter @ContributesTo(AppScope::class) @@ -21,4 +23,7 @@ import io.element.android.libraries.architecture.Presenter interface LoginModule { @Binds fun bindChangeServerPresenter(presenter: ChangeServerPresenter): Presenter + + @Binds + fun bindLoginModePresenter(presenter: LoginModePresenter): 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 deleted file mode 100644 index 3c871a8a1d..0000000000 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginHelper.kt +++ /dev/null @@ -1,128 +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.login.impl.login - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.State -import androidx.compose.runtime.mutableStateOf -import dev.zacsweers.metro.Inject -import io.element.android.features.login.impl.error.ChangeServerError -import io.element.android.features.login.impl.screens.chooseaccountprovider.ChooseAccountProviderPresenter -import io.element.android.features.login.impl.screens.confirmaccountprovider.ConfirmAccountProviderPresenter -import io.element.android.features.login.impl.screens.createaccount.AccountCreationNotSupported -import io.element.android.features.login.impl.screens.onboarding.OnBoardingPresenter -import io.element.android.features.login.impl.web.WebClientUrlForAuthenticationRetriever -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.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 - * submitting login requests. - * It's a helper to avoid code duplication. It is used by [OnBoardingPresenter], [ConfirmAccountProviderPresenter] - * and [ChooseAccountProviderPresenter]. - */ -@Inject -class LoginHelper( - private val oAuthActionFlow: OAuthActionFlow, - private val authenticationService: MatrixAuthenticationService, - private val webClientUrlForAuthenticationRetriever: WebClientUrlForAuthenticationRetriever, -) { - private val loginModeState: MutableState> = mutableStateOf(AsyncData.Uninitialized) - - @Composable - fun collectLoginMode(): State> { - LaunchedEffect(Unit) { - oAuthActionFlow.collect { oAuthAction -> - if (oAuthAction != null) { - onOAuthAction(oAuthAction) - } - } - } - return loginModeState - } - - fun clearError() { - loginModeState.value = AsyncData.Uninitialized - } - - suspend fun submit( - isAccountCreation: Boolean, - homeserverUrl: String, - resolvedHomeserverUrl: String?, - loginHint: String?, - ) { - suspend { - 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.supportsOAuthLogin) { - // Retrieve the details right now - 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) - LoginMode.AccountCreation(url) - } else if (matrixHomeServerDetails.supportsPasswordLogin) { - LoginMode.PasswordLogin - } else { - error("Unsupported login flow") - } - }.getOrThrow() - }.runCatchingUpdatingState( - state = loginModeState, - errorTransform = { - when (it) { - is AccountCreationNotSupported -> it - else -> ChangeServerError.from(it) - } - } - ) - } - - 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 (oAuthAction) { - is OAuthAction.GoBack -> { - authenticationService.cancelOAuthLogin() - .onSuccess { - loginModeState.value = AsyncData.Uninitialized - } - .onFailure { failure -> - loginModeState.value = AsyncData.Failure(failure) - } - } - is OAuthAction.Success -> { - authenticationService.loginWithOAuth(oAuthAction.url) - .onFailure { failure -> - loginModeState.value = AsyncData.Failure(failure) - } - } - } - oAuthActionFlow.reset() - } -} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeEvent.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeEvent.kt new file mode 100644 index 0000000000..73400890d5 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeEvent.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.login.impl.login + +sealed interface LoginModeEvent { + data class Submit( + val isAccountCreation: Boolean, + val homeserverUrl: String, + val resolvedHomeserverUrl: String?, + val loginHint: String?, + ) : LoginModeEvent + + data object ClearError : LoginModeEvent + + data object RequestLocalNetworkPermission : LoginModeEvent + + data object DismissLocalNetworkPermission : LoginModeEvent +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModePresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModePresenter.kt new file mode 100644 index 0000000000..43c03bfbe3 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModePresenter.kt @@ -0,0 +1,117 @@ +/* + * 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.login + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import dev.zacsweers.metro.Inject +import io.element.android.features.login.impl.error.ChangeServerError +import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionGate +import io.element.android.features.login.impl.screens.createaccount.AccountCreationNotSupported +import io.element.android.features.login.impl.web.WebClientUrlForAuthenticationRetriever +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.matrix.api.auth.MatrixAuthenticationService +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 + +@Inject +class LoginModePresenter( + private val oAuthActionFlow: OAuthActionFlow, + private val authenticationService: MatrixAuthenticationService, + private val webClientUrlForAuthenticationRetriever: WebClientUrlForAuthenticationRetriever, + private val localNetworkPermissionGate: LocalNetworkPermissionGate, +) : Presenter { + @Composable + override fun present(): LoginModeState { + val loginMode: MutableState> = remember { mutableStateOf(AsyncData.Uninitialized) } + + val gateState = localNetworkPermissionGate.present( + urlOf = { it.homeserverUrl }, + onProceed = { request -> performSubmit(request, loginMode) }, + ) + + // Forward OAuth navigation events to the presenter's own loginMode state. + LaunchedEffect(Unit) { + oAuthActionFlow.collect { action -> + if (action != null) handleOAuthAction(action, loginMode) + } + } + + fun handleEvent(event: LoginModeEvent) { + when (event) { + LoginModeEvent.ClearError -> loginMode.value = AsyncData.Uninitialized + is LoginModeEvent.Submit -> gateState.submit(event) + LoginModeEvent.DismissLocalNetworkPermission -> gateState.abort() + LoginModeEvent.RequestLocalNetworkPermission -> gateState.requestPermission() + } + } + return LoginModeState( + loginMode = loginMode.value, + localNetworkPermissionDialog = gateState.dialog, + eventSink = ::handleEvent, + ) + } + + private suspend fun performSubmit(request: LoginModeEvent.Submit, loginMode: MutableState>) { + suspend { + authenticationService.setHomeserver(request.homeserverUrl).recoverCatching { + // Fallback to the well-known-resolved URL if the primary URL failed and the caller supplied one. + if (request.resolvedHomeserverUrl != null && request.resolvedHomeserverUrl != request.homeserverUrl) { + authenticationService.setHomeserver(request.resolvedHomeserverUrl).getOrThrow() + } else { + throw it + } + }.map { matrixHomeServerDetails -> + when { + matrixHomeServerDetails.supportsOAuthLogin -> { + val oAuthPrompt = if (request.isAccountCreation) OAuthPrompt.Create else OAuthPrompt.Login + LoginMode.OAuth( + authenticationService.getOAuthUrl(prompt = oAuthPrompt, loginHint = request.loginHint).getOrThrow() + ) + } + request.isAccountCreation -> LoginMode.AccountCreation( + webClientUrlForAuthenticationRetriever.retrieve(request.homeserverUrl) + ) + matrixHomeServerDetails.supportsPasswordLogin -> LoginMode.PasswordLogin + else -> error("Unsupported login flow") + } + }.getOrThrow() + }.runCatchingUpdatingState( + state = loginMode, + errorTransform = { + when (it) { + is AccountCreationNotSupported -> it + else -> ChangeServerError.from(it) + } + } + ) + } + + private suspend fun handleOAuthAction(action: OAuthAction, loginMode: MutableState>) { + if (action is OAuthAction.GoBack && action.toUnblock && loginMode.value !is AsyncData.Loading) { + // Ignore GoBack that isn't tied to an in-flight login — it comes from LoginFlowNode + // when the user backs out after a completed login attempt. + return + } + loginMode.value = AsyncData.Loading() + when (action) { + is OAuthAction.GoBack -> authenticationService.cancelOAuthLogin() + .onSuccess { loginMode.value = AsyncData.Uninitialized } + .onFailure { loginMode.value = AsyncData.Failure(it) } + is OAuthAction.Success -> authenticationService.loginWithOAuth(action.url) + .onFailure { loginMode.value = AsyncData.Failure(it) } + } + 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/LoginModeState.kt similarity index 55% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginMode.kt rename to features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeState.kt index 5ea52e0ebd..3ca3a42a5d 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/LoginModeState.kt @@ -1,6 +1,5 @@ /* - * 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. @@ -8,8 +7,16 @@ package io.element.android.features.login.impl.login +import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialog +import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.auth.OAuthDetails +data class LoginModeState( + val loginMode: AsyncData, + val localNetworkPermissionDialog: LocalNetworkPermissionDialog, + val eventSink: (LoginModeEvent) -> Unit, +) + sealed interface LoginMode { data object PasswordLogin : LoginMode data class OAuth(val oAuthDetails: OAuthDetails) : LoginMode diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeStateProvider.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeStateProvider.kt new file mode 100644 index 0000000000..a0adc327fe --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeStateProvider.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.features.login.impl.login + +import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialog +import io.element.android.libraries.architecture.AsyncData + +fun aLoginModeState( + loginMode: AsyncData = AsyncData.Uninitialized, + localNetworkPermissionDialog: LocalNetworkPermissionDialog = LocalNetworkPermissionDialog.None, + eventSink: (LoginModeEvent) -> Unit = {}, +) = LoginModeState( + loginMode = loginMode, + localNetworkPermissionDialog = localNetworkPermissionDialog, + eventSink = eventSink, +) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/HomeserverResolver.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/HomeserverResolver.kt index 1c4ef8cd09..b6eb26c87f 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/HomeserverResolver.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/HomeserverResolver.kt @@ -14,6 +14,7 @@ import io.element.android.libraries.core.coroutine.parallelMap import io.element.android.libraries.core.uri.ensureProtocol import io.element.android.libraries.core.uri.isValidUrl import io.element.android.libraries.matrix.api.auth.HomeServerLoginCompatibilityChecker +import io.element.android.libraries.permissions.api.LocalNetworkPermissionAdvisor import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow @@ -28,6 +29,7 @@ import java.util.Collections class HomeserverResolver( private val dispatchers: CoroutineDispatchers, private val homeServerLoginCompatibilityChecker: HomeServerLoginCompatibilityChecker, + private val localNetworkPermissionAdvisor: LocalNetworkPermissionAdvisor, ) { fun resolve(userInput: String): Flow> = flow { val flowContext = currentCoroutineContext() @@ -39,6 +41,17 @@ class HomeserverResolver( // Run all the requests in parallel withContext(dispatchers.io) { list.parallelMap { url -> + // Skip the compatibility probe if we'd need ACCESS_LOCAL_NETWORK first — + // otherwise the probe hangs on the TCP timeout for ~30s. Emit the URL as a + // candidate directly; the actual sign-in flow triggers the permission prompt. + if (localNetworkPermissionAdvisor.shouldRequestPermissionFor(url)) { + currentList.add(HomeserverData(homeserverUrl = url)) + withContext(flowContext) { + emit(currentList.toList()) + } + return@parallelMap + } + val isValid = homeServerLoginCompatibilityChecker.check(url) .onFailure { Timber.w(it, "Failed to check compatibility with homeserver $url") } .getOrNull() 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 c6d6d76486..a9983a19d1 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 @@ -12,50 +12,49 @@ 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 dev.zacsweers.metro.Inject import io.element.android.appconfig.AuthenticationConfig import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.features.login.impl.accountprovider.AccountProvider -import io.element.android.features.login.impl.login.LoginHelper +import io.element.android.features.login.impl.login.LoginModeEvent +import io.element.android.features.login.impl.login.LoginModeState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.uri.ensureProtocol import kotlinx.collections.immutable.toImmutableList -import kotlinx.coroutines.launch @Inject class ChooseAccountProviderPresenter( private val enterpriseService: EnterpriseService, - private val loginHelper: LoginHelper, + private val loginModePresenter: Presenter, ) : Presenter { @Composable override fun present(): ChooseAccountProviderState { - val localCoroutineScope = rememberCoroutineScope() - val loginMode by loginHelper.collectLoginMode() - + val loginModeState = loginModePresenter.present() var selectedAccountProvider: AccountProvider? by remember { mutableStateOf(null) } fun handleEvent(event: ChooseAccountProviderEvents) { when (event) { - ChooseAccountProviderEvents.Continue -> localCoroutineScope.launch { - selectedAccountProvider?.let { - loginHelper.submit( - isAccountCreation = false, - homeserverUrl = it.url, - resolvedHomeserverUrl = null, - loginHint = null, + ChooseAccountProviderEvents.Continue -> { + selectedAccountProvider?.let { provider -> + loginModeState.eventSink( + LoginModeEvent.Submit( + isAccountCreation = false, + homeserverUrl = provider.url, + resolvedHomeserverUrl = null, + loginHint = null, + ) ) } } is ChooseAccountProviderEvents.SelectAccountProvider -> { - // Ensure that the user do not change the server during processing - if (loginMode is AsyncData.Uninitialized) { + // Ensure that the user does not change the server during processing. + if (loginModeState.loginMode is AsyncData.Uninitialized) { selectedAccountProvider = event.accountProvider } } - ChooseAccountProviderEvents.ClearError -> loginHelper.clearError() + ChooseAccountProviderEvents.ClearError -> loginModeState.eventSink(LoginModeEvent.ClearError) } } @@ -77,7 +76,7 @@ class ChooseAccountProviderPresenter( return ChooseAccountProviderState( accountProviders = staticAccountProviderList, selectedAccountProvider = selectedAccountProvider, - loginMode = loginMode, + loginModeState = loginModeState, eventSink = ::handleEvent, ) } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderState.kt index e34fbccb41..a31e5c464f 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderState.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderState.kt @@ -9,16 +9,17 @@ package io.element.android.features.login.impl.screens.chooseaccountprovider import io.element.android.features.login.impl.accountprovider.AccountProvider -import io.element.android.features.login.impl.login.LoginMode +import io.element.android.features.login.impl.login.LoginModeState import io.element.android.libraries.architecture.AsyncData import kotlinx.collections.immutable.ImmutableList data class ChooseAccountProviderState( val accountProviders: ImmutableList, val selectedAccountProvider: AccountProvider?, - val loginMode: AsyncData, + val loginModeState: LoginModeState, val eventSink: (ChooseAccountProviderEvents) -> Unit, ) { val submitEnabled: Boolean - get() = selectedAccountProvider != null && (loginMode is AsyncData.Uninitialized || loginMode is AsyncData.Loading) + get() = selectedAccountProvider != null && + (loginModeState.loginMode is AsyncData.Uninitialized || loginModeState.loginMode is AsyncData.Loading) } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderStateProvider.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderStateProvider.kt index 93bd665011..3fea548fca 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderStateProvider.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderStateProvider.kt @@ -11,7 +11,8 @@ package io.element.android.features.login.impl.screens.chooseaccountprovider import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.login.impl.accountprovider.AccountProvider import io.element.android.features.login.impl.accountprovider.anAccountProvider -import io.element.android.features.login.impl.login.LoginMode +import io.element.android.features.login.impl.login.LoginModeState +import io.element.android.features.login.impl.login.aLoginModeState import io.element.android.libraries.architecture.AsyncData import kotlinx.collections.immutable.toImmutableList @@ -58,7 +59,7 @@ open class ChooseAccountProviderStateProvider : PreviewParameterProvider = AsyncData.Uninitialized, + loginModeState: LoginModeState = aLoginModeState(), eventSink: (ChooseAccountProviderEvents) -> Unit = {}, ) = ChooseAccountProviderState( accountProviders = accountProviders.toImmutableList(), selectedAccountProvider = selectedAccountProvider, - loginMode = loginMode, + loginModeState = loginModeState, eventSink = eventSink, ) 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 f05606dbc3..be37775965 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 @@ -33,6 +33,8 @@ import androidx.compose.ui.unit.dp import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.login.impl.R import io.element.android.features.login.impl.accountprovider.AccountProviderView +import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialogView +import io.element.android.features.login.impl.login.LoginModeEvent import io.element.android.features.login.impl.login.LoginModeView import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule @@ -56,9 +58,9 @@ fun ChooseAccountProviderView( onCreateAccountContinue: (url: String) -> Unit, modifier: Modifier = Modifier, ) { - val isLoading by remember(state.loginMode) { + val isLoading by remember(state.loginModeState.loginMode) { derivedStateOf { - state.loginMode is AsyncData.Loading + state.loginModeState.loginMode is AsyncData.Loading } } @@ -124,7 +126,7 @@ fun ChooseAccountProviderView( Spacer(modifier = Modifier.height(48.dp)) } LoginModeView( - loginMode = state.loginMode, + loginMode = state.loginModeState.loginMode, onClearError = { state.eventSink(ChooseAccountProviderEvents.ClearError) }, @@ -135,6 +137,15 @@ fun ChooseAccountProviderView( ) } } + LocalNetworkPermissionDialogView( + dialog = state.loginModeState.localNetworkPermissionDialog, + onSubmit = { + state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission) + }, + onDismiss = { + state.loginModeState.eventSink(LoginModeEvent.DismissLocalNetworkPermission) + } + ) } @PreviewsDayNight 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 90a528c3ae..765dfaadd1 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 @@ -20,7 +20,8 @@ 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.features.login.impl.login.LoginModeEvent +import io.element.android.features.login.impl.login.LoginModeState import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.meta.BuildMeta @@ -32,7 +33,7 @@ import kotlinx.coroutines.launch class LoginWithClassicPresenter( @Assisted private val userId: UserId, @Assisted private val navigator: LoginWithClassicNavigator, - private val loginHelper: LoginHelper, + private val loginModePresenter: Presenter, private val elementClassicConnection: ElementClassicConnection, private val accountProviderDataSource: AccountProviderDataSource, private val buildMeta: BuildMeta, @@ -51,7 +52,7 @@ class LoginWithClassicPresenter( var loginWithClassicAction by remember { mutableStateOf>(AsyncAction.Uninitialized) } - val loginMode by loginHelper.collectLoginMode() + val loginModeState = loginModePresenter.present() val elementClassicConnectionState by elementClassicConnection.stateFlow.collectAsState() fun handleEvent(event: LoginWithClassicEvent) { @@ -69,11 +70,13 @@ class LoginWithClassicPresenter( 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, + loginModeState.eventSink( + LoginModeEvent.Submit( + isAccountCreation = false, + homeserverUrl = accountProvider, + resolvedHomeserverUrl = currentState.elementClassicSession.homeserverUrl, + loginHint = "mxid:" + elementClassicUserId.value, + ) ) } } @@ -83,7 +86,7 @@ class LoginWithClassicPresenter( } LoginWithClassicEvent.ClearError -> { loginWithClassicAction = AsyncAction.Uninitialized - loginHelper.clearError() + loginModeState.eventSink(LoginModeEvent.ClearError) } } } @@ -94,7 +97,7 @@ class LoginWithClassicPresenter( userId = userId, displayName = elementClassicReady?.displayName, avatar = elementClassicReady?.avatar, - loginMode = loginMode, + loginModeState = loginModeState, 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 index 275a444768..8e93298e76 100644 --- 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 @@ -9,9 +9,8 @@ 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.features.login.impl.login.LoginModeState import io.element.android.libraries.architecture.AsyncAction -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.core.UserId @Stable @@ -21,6 +20,6 @@ data class LoginWithClassicState( val displayName: String?, val avatar: Bitmap?, val loginWithClassicAction: AsyncAction, - val loginMode: AsyncData, + val loginModeState: LoginModeState, 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 index 31b1770f63..6dfc292f6f 100644 --- 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 @@ -9,9 +9,9 @@ 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.features.login.impl.login.LoginModeState +import io.element.android.features.login.impl.login.aLoginModeState import io.element.android.libraries.architecture.AsyncAction -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE import io.element.android.libraries.matrix.api.core.UserId @@ -29,7 +29,7 @@ fun aLoginWithClassicState( displayName: String? = null, avatar: Bitmap? = null, loginWithClassicAction: AsyncAction = AsyncAction.Uninitialized, - loginMode: AsyncData = AsyncData.Uninitialized, + loginModeState: LoginModeState = aLoginModeState(), eventSink: (LoginWithClassicEvent) -> Unit = {}, ) = LoginWithClassicState( isElementPro = isElementPro, @@ -37,6 +37,6 @@ fun aLoginWithClassicState( displayName = displayName, avatar = avatar, loginWithClassicAction = loginWithClassicAction, - loginMode = loginMode, + loginModeState = loginModeState, 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 index b1ca50fe61..389d07ea1a 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 @@ -35,6 +35,8 @@ 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.login.impl.R +import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialogView +import io.element.android.features.login.impl.login.LoginModeEvent 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 @@ -65,9 +67,9 @@ fun LoginWithClassicView( onCreateAccountContinue: (url: String) -> Unit, modifier: Modifier = Modifier, ) { - val isLoading by remember(state.loginMode) { + val isLoading by remember(state.loginModeState.loginMode) { derivedStateOf { - state.loginMode is AsyncData.Loading + state.loginModeState.loginMode is AsyncData.Loading } } @@ -195,7 +197,7 @@ fun LoginWithClassicView( } ) LoginModeView( - loginMode = state.loginMode, + loginMode = state.loginModeState.loginMode, onClearError = { state.eventSink(LoginWithClassicEvent.ClearError) }, @@ -204,6 +206,15 @@ fun LoginWithClassicView( onNeedLoginPassword = onNeedLoginPassword, onCreateAccountContinue = onCreateAccountContinue, ) + LocalNetworkPermissionDialogView( + dialog = state.loginModeState.localNetworkPermissionDialog, + onSubmit = { + state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission) + }, + onDismiss = { + state.loginModeState.eventSink(LoginModeEvent.DismissLocalNetworkPermission) + } + ) } @PreviewsDayNight 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 bf06613830..0111b1e7d7 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 @@ -11,20 +11,19 @@ package io.element.android.features.login.impl.screens.confirmaccountprovider import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.rememberCoroutineScope 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.login.LoginHelper +import io.element.android.features.login.impl.login.LoginModeEvent +import io.element.android.features.login.impl.login.LoginModeState import io.element.android.libraries.architecture.Presenter -import kotlinx.coroutines.launch @AssistedInject class ConfirmAccountProviderPresenter( @Assisted private val params: Params, private val accountProviderDataSource: AccountProviderDataSource, - private val loginHelper: LoginHelper, + private val loginModePresenter: Presenter, ) : Presenter { data class Params( val isAccountCreation: Boolean, @@ -38,28 +37,26 @@ class ConfirmAccountProviderPresenter( @Composable override fun present(): ConfirmAccountProviderState { val accountProvider by accountProviderDataSource.flow.collectAsState() - val localCoroutineScope = rememberCoroutineScope() - - val loginMode by loginHelper.collectLoginMode() + val loginModeState = loginModePresenter.present() fun handleEvent(event: ConfirmAccountProviderEvents) { when (event) { - ConfirmAccountProviderEvents.Continue -> localCoroutineScope.launch { - loginHelper.submit( + ConfirmAccountProviderEvents.Continue -> loginModeState.eventSink( + LoginModeEvent.Submit( isAccountCreation = params.isAccountCreation, homeserverUrl = accountProvider.url, resolvedHomeserverUrl = null, loginHint = null, ) - } - ConfirmAccountProviderEvents.ClearError -> loginHelper.clearError() + ) + ConfirmAccountProviderEvents.ClearError -> loginModeState.eventSink(LoginModeEvent.ClearError) } } return ConfirmAccountProviderState( accountProvider = accountProvider, isAccountCreation = params.isAccountCreation, - loginMode = loginMode, + loginModeState = loginModeState, eventSink = ::handleEvent, ) } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderState.kt index b29b610b3e..6e6deb8c2c 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderState.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderState.kt @@ -9,14 +9,16 @@ package io.element.android.features.login.impl.screens.confirmaccountprovider import io.element.android.features.login.impl.accountprovider.AccountProvider -import io.element.android.features.login.impl.login.LoginMode +import io.element.android.features.login.impl.login.LoginModeState import io.element.android.libraries.architecture.AsyncData data class ConfirmAccountProviderState( val accountProvider: AccountProvider, val isAccountCreation: Boolean, - val loginMode: AsyncData, + val loginModeState: LoginModeState, val eventSink: (ConfirmAccountProviderEvents) -> Unit ) { - val submitEnabled: Boolean get() = accountProvider.url.isNotEmpty() && (loginMode is AsyncData.Uninitialized || loginMode is AsyncData.Loading) + val submitEnabled: Boolean + get() = accountProvider.url.isNotEmpty() && + (loginModeState.loginMode is AsyncData.Uninitialized || loginModeState.loginMode is AsyncData.Loading) } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderStateProvider.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderStateProvider.kt index f3a48a86b4..f597ad6b54 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderStateProvider.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderStateProvider.kt @@ -11,7 +11,8 @@ package io.element.android.features.login.impl.screens.confirmaccountprovider import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.login.impl.accountprovider.AccountProvider import io.element.android.features.login.impl.accountprovider.anAccountProvider -import io.element.android.features.login.impl.login.LoginMode +import io.element.android.features.login.impl.login.LoginModeState +import io.element.android.features.login.impl.login.aLoginModeState import io.element.android.features.login.impl.screens.createaccount.AccountCreationNotSupported import io.element.android.libraries.architecture.AsyncData @@ -24,7 +25,7 @@ open class ConfirmAccountProviderStateProvider : PreviewParameterProvider = AsyncData.Uninitialized, + loginModeState: LoginModeState = aLoginModeState(), eventSink: (ConfirmAccountProviderEvents) -> Unit = {}, ) = ConfirmAccountProviderState( accountProvider = accountProvider, isAccountCreation = isAccountCreation, - loginMode = loginMode, + loginModeState = loginModeState, eventSink = eventSink ) 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 c2525f3756..3db0748a04 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 @@ -20,6 +20,8 @@ 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.login.impl.R +import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialogView +import io.element.android.features.login.impl.login.LoginModeEvent 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 @@ -45,9 +47,9 @@ fun ConfirmAccountProviderView( onChange: () -> Unit, modifier: Modifier = Modifier, ) { - val isLoading by remember(state.loginMode) { + val isLoading by remember(state.loginModeState.loginMode) { derivedStateOf { - state.loginMode is AsyncData.Loading + state.loginModeState.loginMode is AsyncData.Loading } } val eventSink = state.eventSink @@ -98,7 +100,7 @@ fun ConfirmAccountProviderView( } ) { LoginModeView( - loginMode = state.loginMode, + loginMode = state.loginModeState.loginMode, onClearError = { eventSink(ConfirmAccountProviderEvents.ClearError) }, @@ -108,6 +110,16 @@ fun ConfirmAccountProviderView( onCreateAccountContinue = onCreateAccountContinue, ) } + + LocalNetworkPermissionDialogView( + dialog = state.loginModeState.localNetworkPermissionDialog, + onSubmit = { + state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission) + }, + onDismiss = { + state.loginModeState.eventSink(LoginModeEvent.DismissLocalNetworkPermission) + } + ) } @PreviewsDayNight 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 306549d11b..29e4b1afe5 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 @@ -25,7 +25,8 @@ import io.element.android.features.enterprise.api.EnterpriseService 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.login.LoginModeEvent +import io.element.android.features.login.impl.login.LoginModeState import io.element.android.features.rageshake.api.RageshakeFeatureAvailability import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.meta.BuildMeta @@ -41,7 +42,7 @@ class OnBoardingPresenter( private val enterpriseService: EnterpriseService, private val defaultAccountProviderAccessControl: DefaultAccountProviderAccessControl, private val rageshakeFeatureAvailability: RageshakeFeatureAvailability, - private val loginHelper: LoginHelper, + private val loginModePresenter: Presenter, private val onBoardingLogoResIdProvider: OnBoardingLogoResIdProvider, private val sessionStore: SessionStore, private val accountProviderDataSource: AccountProviderDataSource, @@ -98,21 +99,23 @@ class OnBoardingPresenter( value = sessionStore.numberOfSessions() > 0 } - val loginMode by loginHelper.collectLoginMode() + val loginModeState = loginModePresenter.present() fun handleEvent(event: OnBoardingEvents) { when (event) { is OnBoardingEvents.OnSignIn -> localCoroutineScope.launch { // Ensure that the current account provider is set accountProviderDataSource.setUrl(event.defaultAccountProvider) - loginHelper.submit( - isAccountCreation = false, - homeserverUrl = event.defaultAccountProvider, - resolvedHomeserverUrl = null, - loginHint = params.loginHint?.takeIf { forcedAccountProvider == null }, + loginModeState.eventSink( + LoginModeEvent.Submit( + isAccountCreation = false, + homeserverUrl = event.defaultAccountProvider, + resolvedHomeserverUrl = null, + loginHint = params.loginHint?.takeIf { forcedAccountProvider == null }, + ) ) } - OnBoardingEvents.ClearError -> loginHelper.clearError() + OnBoardingEvents.ClearError -> loginModeState.eventSink(LoginModeEvent.ClearError) OnBoardingEvents.OnVersionClick -> { if (canReportBug) { if (multipleTapToUnlock.unlock(localCoroutineScope)) { @@ -133,7 +136,7 @@ class OnBoardingPresenter( canLoginWithQrCode = canLoginWithQrCode, canCreateAccount = defaultAccountProvider == null && canConnectToAnyHomeserver && OnBoardingConfig.CAN_CREATE_ACCOUNT, canReportBug = canReportBug && showReportBug, - loginMode = loginMode, + loginModeState = loginModeState, version = buildMeta.versionName, onBoardingLogoResId = onBoardingLogoResId, 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 316efb03ef..4fb4b8090e 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 @@ -9,7 +9,7 @@ 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.login.LoginModeState import io.element.android.libraries.architecture.AsyncData data class OnBoardingState( @@ -25,9 +25,10 @@ data class OnBoardingState( val version: String, @DrawableRes val onBoardingLogoResId: Int?, - val loginMode: AsyncData, + val loginModeState: LoginModeState, val eventSink: (OnBoardingEvents) -> Unit, ) { val submitEnabled: Boolean - get() = defaultAccountProvider != null && (loginMode is AsyncData.Uninitialized || loginMode is AsyncData.Loading) + get() = defaultAccountProvider != null && + (loginModeState.loginMode is AsyncData.Uninitialized || loginModeState.loginMode is AsyncData.Loading) } 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 249a904dc3..41e4a81818 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 @@ -10,8 +10,8 @@ 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.libraries.architecture.AsyncData +import io.element.android.features.login.impl.login.LoginModeState +import io.element.android.features.login.impl.login.aLoginModeState import io.element.android.libraries.designsystem.R open class OnBoardingStateProvider : PreviewParameterProvider { @@ -49,7 +49,7 @@ fun anOnBoardingState( version: String = "1.0.0", @DrawableRes customLogoResId: Int? = null, - loginMode: AsyncData = AsyncData.Uninitialized, + loginModeState: LoginModeState = aLoginModeState(), eventSink: (OnBoardingEvents) -> Unit = {}, ) = OnBoardingState( isAddingAccount = isAddingAccount, @@ -62,7 +62,7 @@ fun anOnBoardingState( canCreateAccount = canCreateAccount, canReportBug = canReportBug, version = version, - loginMode = loginMode, + loginModeState = loginModeState, onBoardingLogoResId = customLogoResId, 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 420bb61475..74fdbffab1 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 @@ -33,6 +33,8 @@ 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.login.impl.R +import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialogView +import io.element.android.features.login.impl.login.LoginModeEvent import io.element.android.features.login.impl.login.LoginModeView import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.atomic.atoms.ElementLogoAtom @@ -74,7 +76,7 @@ fun OnBoardingView( ) { val loginView = @Composable { LoginModeView( - loginMode = state.loginMode, + loginMode = state.loginModeState.loginMode, onClearError = { state.eventSink(OnBoardingEvents.ClearError) }, @@ -83,6 +85,15 @@ fun OnBoardingView( onNeedLoginPassword = onNeedLoginPassword, onCreateAccountContinue = onCreateAccountContinue, ) + LocalNetworkPermissionDialogView( + dialog = state.loginModeState.localNetworkPermissionDialog, + onSubmit = { + state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission) + }, + onDismiss = { + state.loginModeState.eventSink(LoginModeEvent.DismissLocalNetworkPermission) + } + ) } val buttons = @Composable { OnBoardingButtons( @@ -260,9 +271,9 @@ private fun OnBoardingButtons( onCreateAccount: () -> Unit, onReportProblem: () -> Unit, ) { - val isLoading by remember(state.loginMode) { + val isLoading by remember(state.loginModeState.loginMode) { derivedStateOf { - state.loginMode is AsyncData.Loading + state.loginModeState.loginMode is AsyncData.Loading } } diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderPresenterTest.kt index 7461a7db55..4f00bb002b 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderPresenterTest.kt @@ -12,8 +12,8 @@ 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.login.impl.accountprovider.AccountProvider -import io.element.android.features.login.impl.login.LoginHelper -import io.element.android.features.login.impl.screens.onboarding.createLoginHelper +import io.element.android.features.login.impl.login.LoginModePresenter +import io.element.android.features.login.impl.screens.onboarding.createLoginModePresenter import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.core.uri.ensureProtocol import io.element.android.libraries.matrix.test.AN_ACCOUNT_PROVIDER_2 @@ -81,7 +81,7 @@ class ChooseAccountProviderPresenterTest { enterpriseService = FakeEnterpriseService( defaultHomeserverListResult = { listOf(ACCOUNT_PROVIDER_FROM_CONFIG_1, ACCOUNT_PROVIDER_FROM_CONFIG_2) }, ), - loginHelper = createLoginHelper( + loginModePresenter = createLoginModePresenter( authenticationService = authenticationService, ), ) @@ -105,7 +105,7 @@ class ChooseAccountProviderPresenterTest { enterpriseService = FakeEnterpriseService( defaultHomeserverListResult = { listOf(ACCOUNT_PROVIDER_FROM_CONFIG_1, ACCOUNT_PROVIDER_FROM_CONFIG_2) }, ), - loginHelper = createLoginHelper( + loginModePresenter = createLoginModePresenter( authenticationService = authenticationService, ), ) @@ -121,12 +121,12 @@ class ChooseAccountProviderPresenterTest { // Check an error was returned val submittedState = awaitItem() - assertThat(submittedState.loginMode).isInstanceOf(AsyncData.Failure::class.java) + assertThat(submittedState.loginModeState.loginMode).isInstanceOf(AsyncData.Failure::class.java) // Assert the error is then cleared submittedState.eventSink(ChooseAccountProviderEvents.ClearError) val clearedState = awaitItem() - assertThat(clearedState.loginMode).isEqualTo(AsyncData.Uninitialized) + assertThat(clearedState.loginModeState.loginMode).isEqualTo(AsyncData.Uninitialized) } } } @@ -138,7 +138,7 @@ class ChooseAccountProviderPresenterTest { enterpriseService = FakeEnterpriseService( defaultHomeserverListResult = { listOf(ACCOUNT_PROVIDER_FROM_CONFIG_1, ACCOUNT_PROVIDER_FROM_CONFIG_2) }, ), - loginHelper = createLoginHelper( + loginModePresenter = createLoginModePresenter( authenticationService = authenticationService, ), ) @@ -152,7 +152,7 @@ class ChooseAccountProviderPresenterTest { it.eventSink(ChooseAccountProviderEvents.Continue) } awaitItem().also { - assertThat(it.loginMode.isLoading()).isTrue() + assertThat(it.loginModeState.loginMode.isLoading()).isTrue() it.eventSink(ChooseAccountProviderEvents.SelectAccountProvider(accountProvider2)) } expectNoEvents() @@ -162,8 +162,8 @@ class ChooseAccountProviderPresenterTest { private fun createPresenter( enterpriseService: EnterpriseService = FakeEnterpriseService(), - loginHelper: LoginHelper = createLoginHelper(), + loginModePresenter: LoginModePresenter = createLoginModePresenter(), ) = ChooseAccountProviderPresenter( enterpriseService = enterpriseService, - loginHelper = loginHelper, + loginModePresenter = loginModePresenter, ) diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderStateTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderStateTest.kt index ba1eff39e8..a5cb54e7e1 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderStateTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/chooseaccountprovider/ChooseAccountProviderStateTest.kt @@ -11,6 +11,7 @@ package io.element.android.features.login.impl.screens.chooseaccountprovider import com.google.common.truth.Truth.assertThat import io.element.android.features.login.impl.accountprovider.anAccountProvider import io.element.android.features.login.impl.login.LoginMode +import io.element.android.features.login.impl.login.aLoginModeState import io.element.android.libraries.architecture.AsyncData import org.junit.Test @@ -35,7 +36,7 @@ class ChooseAccountProviderStateTest { fun `submitEnabled returns false when there is a selectedAccountProvider but there is an error`() { val sut = aChooseAccountProviderState( selectedAccountProvider = anAccountProvider(), - loginMode = AsyncData.Failure(Throwable("Error")), + loginModeState = aLoginModeState(loginMode = AsyncData.Failure(Throwable("Error"))), ) assertThat(sut.submitEnabled).isFalse() } @@ -44,7 +45,7 @@ class ChooseAccountProviderStateTest { fun `submitEnabled returns false when there is a selectedAccountProvider but the result is successful`() { val sut = aChooseAccountProviderState( selectedAccountProvider = anAccountProvider(), - loginMode = AsyncData.Success(LoginMode.PasswordLogin), + loginModeState = aLoginModeState(loginMode = AsyncData.Success(LoginMode.PasswordLogin)), ) assertThat(sut.submitEnabled).isFalse() } 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 b036e07e92..f1ce703d1c 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 @@ -17,6 +17,7 @@ import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.v2.runAndroidComposeUiTest import io.element.android.features.login.impl.accountprovider.anAccountProvider +import io.element.android.features.login.impl.login.aLoginModeState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.auth.OAuthDetails import io.element.android.libraries.matrix.test.AN_EXCEPTION @@ -69,7 +70,7 @@ class ChooseAccountProviderViewTest : RobolectricTest() { val eventSink = EventsRecorder() setChooseAccountProviderView( state = aChooseAccountProviderState( - loginMode = AsyncData.Failure(AN_EXCEPTION), + loginModeState = aLoginModeState(loginMode = AsyncData.Failure(AN_EXCEPTION)), eventSink = eventSink, ), ) 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 6b2a4fb0e1..8d56386fa4 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 @@ -16,8 +16,8 @@ import io.element.android.features.login.impl.classic.FakeElementClassicConnecti 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.features.login.impl.login.LoginModePresenter +import io.element.android.features.login.impl.screens.onboarding.createLoginModePresenter 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 @@ -42,7 +42,7 @@ class LoginWithClassicPresenterTest { assertThat(initialState.displayName).isNull() assertThat(initialState.avatar).isNull() assertThat(initialState.loginWithClassicAction.isUninitialized()).isTrue() - assertThat(initialState.loginMode.isUninitialized()).isTrue() + assertThat(initialState.loginModeState.loginMode.isUninitialized()).isTrue() } } @@ -69,7 +69,7 @@ class LoginWithClassicPresenterTest { ) val presenter = createPresenter( elementClassicConnection = elementClassicConnection, - loginHelper = createLoginHelper( + loginModePresenter = createLoginModePresenter( authenticationService = authenticationService, ), ) @@ -108,7 +108,7 @@ class LoginWithClassicPresenterTest { ) val presenter = createPresenter( elementClassicConnection = elementClassicConnection, - loginHelper = createLoginHelper( + loginModePresenter = createLoginModePresenter( authenticationService = authenticationService, ), ) @@ -147,7 +147,7 @@ class LoginWithClassicPresenterTest { val navigateToMissingKeyBackupResult = lambdaRecorder { } val presenter = createPresenter( elementClassicConnection = elementClassicConnection, - loginHelper = createLoginHelper( + loginModePresenter = createLoginModePresenter( authenticationService = authenticationService, ), navigator = FakeLoginWithClassicNavigator( @@ -188,7 +188,7 @@ class LoginWithClassicPresenterTest { val navigateToMissingKeyBackupResult = lambdaRecorder { } val presenter = createPresenter( elementClassicConnection = elementClassicConnection, - loginHelper = createLoginHelper( + loginModePresenter = createLoginModePresenter( authenticationService = authenticationService, ), navigator = FakeLoginWithClassicNavigator( @@ -247,14 +247,14 @@ class LoginWithClassicPresenterTest { private fun createPresenter( userId: UserId = A_USER_ID, navigator: LoginWithClassicNavigator = FakeLoginWithClassicNavigator(), - loginHelper: LoginHelper = createLoginHelper(), + loginModePresenter: LoginModePresenter = createLoginModePresenter(), elementClassicConnection: ElementClassicConnection = FakeElementClassicConnection(), accountProviderDataSource: AccountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), isEnterpriseBuild: Boolean = false, ) = LoginWithClassicPresenter( userId = userId, navigator = navigator, - loginHelper = loginHelper, + loginModePresenter = loginModePresenter, elementClassicConnection = elementClassicConnection, accountProviderDataSource = accountProviderDataSource, buildMeta = aBuildMeta( 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 a9045ab152..c20896870b 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 @@ -14,7 +14,7 @@ import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.features.login.impl.login.LoginMode import io.element.android.features.login.impl.screens.createaccount.AccountCreationNotSupported -import io.element.android.features.login.impl.screens.onboarding.createLoginHelper +import io.element.android.features.login.impl.screens.onboarding.createLoginModePresenter import io.element.android.features.login.impl.web.FakeWebClientUrlForAuthenticationRetriever import io.element.android.features.login.impl.web.WebClientUrlForAuthenticationRetriever import io.element.android.libraries.architecture.AsyncData @@ -43,7 +43,7 @@ class ConfirmAccountProviderPresenterTest { assertThat(initialState.isAccountCreation).isFalse() assertThat(initialState.submitEnabled).isTrue() assertThat(initialState.accountProvider.url).isEqualTo(AuthenticationConfig.MATRIX_ORG_URL) - assertThat(initialState.loginMode).isEqualTo(AsyncData.Uninitialized) + assertThat(initialState.loginModeState.loginMode).isEqualTo(AsyncData.Uninitialized) } } @@ -62,11 +62,11 @@ class ConfirmAccountProviderPresenterTest { initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue) val loadingState = awaitItem() assertThat(loadingState.submitEnabled).isTrue() - assertThat(loadingState.loginMode).isInstanceOf(AsyncData.Loading::class.java) + assertThat(loadingState.loginModeState.loginMode).isInstanceOf(AsyncData.Loading::class.java) val successState = awaitItem() assertThat(successState.submitEnabled).isFalse() - assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) - assertThat(successState.loginMode.dataOrNull()).isEqualTo(LoginMode.PasswordLogin) + assertThat(successState.loginModeState.loginMode).isInstanceOf(AsyncData.Success::class.java) + assertThat(successState.loginModeState.loginMode.dataOrNull()).isEqualTo(LoginMode.PasswordLogin) } } @@ -85,11 +85,11 @@ class ConfirmAccountProviderPresenterTest { initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue) val loadingState = awaitItem() assertThat(loadingState.submitEnabled).isTrue() - assertThat(loadingState.loginMode).isInstanceOf(AsyncData.Loading::class.java) + assertThat(loadingState.loginModeState.loginMode).isInstanceOf(AsyncData.Loading::class.java) val successState = awaitItem() assertThat(successState.submitEnabled).isFalse() - assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) - assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) + assertThat(successState.loginModeState.loginMode).isInstanceOf(AsyncData.Success::class.java) + assertThat(successState.loginModeState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) } } @@ -110,15 +110,15 @@ class ConfirmAccountProviderPresenterTest { initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue) val loadingState = awaitItem() assertThat(loadingState.submitEnabled).isTrue() - assertThat(loadingState.loginMode).isInstanceOf(AsyncData.Loading::class.java) + assertThat(loadingState.loginModeState.loginMode).isInstanceOf(AsyncData.Loading::class.java) val successState = awaitItem() assertThat(successState.submitEnabled).isFalse() - assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) - assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) + assertThat(successState.loginModeState.loginMode).isInstanceOf(AsyncData.Success::class.java) + assertThat(successState.loginModeState.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) + assertThat(cancelFailureState.loginModeState.loginMode).isInstanceOf(AsyncData.Failure::class.java) } } @@ -139,14 +139,14 @@ class ConfirmAccountProviderPresenterTest { initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue) val loadingState = awaitItem() assertThat(loadingState.submitEnabled).isTrue() - assertThat(loadingState.loginMode).isInstanceOf(AsyncData.Loading::class.java) + assertThat(loadingState.loginModeState.loginMode).isInstanceOf(AsyncData.Loading::class.java) val successState = awaitItem() assertThat(successState.submitEnabled).isFalse() - assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) - assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) + assertThat(successState.loginModeState.loginMode).isInstanceOf(AsyncData.Success::class.java) + assertThat(successState.loginModeState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) defaultOAuthActionFlow.post(OAuthAction.GoBack()) val cancelFinalState = awaitItem() - assertThat(cancelFinalState.loginMode).isInstanceOf(AsyncData.Uninitialized::class.java) + assertThat(cancelFinalState.loginModeState.loginMode).isInstanceOf(AsyncData.Uninitialized::class.java) } } @@ -167,10 +167,10 @@ class ConfirmAccountProviderPresenterTest { initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue) val loadingState = awaitItem() assertThat(loadingState.submitEnabled).isTrue() - assertThat(loadingState.loginMode).isInstanceOf(AsyncData.Loading::class.java) + assertThat(loadingState.loginModeState.loginMode).isInstanceOf(AsyncData.Loading::class.java) defaultOAuthActionFlow.post(OAuthAction.GoBack(toUnblock = true)) val cancelFinalState = awaitItem() - assertThat(cancelFinalState.loginMode).isInstanceOf(AsyncData.Uninitialized::class.java) + assertThat(cancelFinalState.loginModeState.loginMode).isInstanceOf(AsyncData.Uninitialized::class.java) } } @@ -191,17 +191,17 @@ class ConfirmAccountProviderPresenterTest { initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue) val loadingState = awaitItem() assertThat(loadingState.submitEnabled).isTrue() - assertThat(loadingState.loginMode).isInstanceOf(AsyncData.Loading::class.java) + assertThat(loadingState.loginModeState.loginMode).isInstanceOf(AsyncData.Loading::class.java) val successState = awaitItem() assertThat(successState.submitEnabled).isFalse() - assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) - assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) + assertThat(successState.loginModeState.loginMode).isInstanceOf(AsyncData.Success::class.java) + assertThat(successState.loginModeState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) authenticationService.givenLoginError(AN_EXCEPTION) defaultOAuthActionFlow.post(OAuthAction.Success("aUrl")) val cancelLoadingState = awaitItem() - assertThat(cancelLoadingState.loginMode).isInstanceOf(AsyncData.Loading::class.java) + assertThat(cancelLoadingState.loginModeState.loginMode).isInstanceOf(AsyncData.Loading::class.java) val cancelFailureState = awaitItem() - assertThat(cancelFailureState.loginMode).isInstanceOf(AsyncData.Failure::class.java) + assertThat(cancelFailureState.loginModeState.loginMode).isInstanceOf(AsyncData.Failure::class.java) } } @@ -222,14 +222,14 @@ class ConfirmAccountProviderPresenterTest { initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue) val loadingState = awaitItem() assertThat(loadingState.submitEnabled).isTrue() - assertThat(loadingState.loginMode).isInstanceOf(AsyncData.Loading::class.java) + assertThat(loadingState.loginModeState.loginMode).isInstanceOf(AsyncData.Loading::class.java) val successState = awaitItem() assertThat(successState.submitEnabled).isFalse() - assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java) - assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) + assertThat(successState.loginModeState.loginMode).isInstanceOf(AsyncData.Success::class.java) + assertThat(successState.loginModeState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) defaultOidcActionFlow.post(OAuthAction.Success("aUrl")) val successSuccessState = awaitItem() - assertThat(successSuccessState.loginMode).isInstanceOf(AsyncData.Loading::class.java) + assertThat(successSuccessState.loginModeState.loginMode).isInstanceOf(AsyncData.Loading::class.java) } } @@ -249,7 +249,7 @@ class ConfirmAccountProviderPresenterTest { skipItems(1) // Loading val failureState = awaitItem() assertThat(failureState.submitEnabled).isFalse() - assertThat(failureState.loginMode).isInstanceOf(AsyncData.Failure::class.java) + assertThat(failureState.loginModeState.loginMode).isInstanceOf(AsyncData.Failure::class.java) } } @@ -273,12 +273,12 @@ class ConfirmAccountProviderPresenterTest { // Check an error was returned val submittedState = awaitItem() - assertThat(submittedState.loginMode).isInstanceOf(AsyncData.Failure::class.java) + assertThat(submittedState.loginModeState.loginMode).isInstanceOf(AsyncData.Failure::class.java) // Assert the error is then cleared submittedState.eventSink(ConfirmAccountProviderEvents.ClearError) val clearedState = awaitItem() - assertThat(clearedState.loginMode).isEqualTo(AsyncData.Uninitialized) + assertThat(clearedState.loginModeState.loginMode).isEqualTo(AsyncData.Uninitialized) } } @@ -302,11 +302,11 @@ class ConfirmAccountProviderPresenterTest { skipItems(1) // Loading // Check an error was returned val submittedState = awaitItem() - assertThat(submittedState.loginMode.errorOrNull()).isInstanceOf(AccountCreationNotSupported::class.java) + assertThat(submittedState.loginModeState.loginMode.errorOrNull()).isInstanceOf(AccountCreationNotSupported::class.java) // Assert the error is then cleared submittedState.eventSink(ConfirmAccountProviderEvents.ClearError) val clearedState = awaitItem() - assertThat(clearedState.loginMode).isEqualTo(AsyncData.Uninitialized) + assertThat(clearedState.loginModeState.loginMode).isEqualTo(AsyncData.Uninitialized) } } @@ -326,8 +326,8 @@ class ConfirmAccountProviderPresenterTest { initialState.eventSink(ConfirmAccountProviderEvents.Continue) skipItems(1) // Loading val submittedState = awaitItem() - assertThat(submittedState.loginMode).isInstanceOf(AsyncData.Success::class.java) - assertThat(submittedState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) + assertThat(submittedState.loginModeState.loginMode).isInstanceOf(AsyncData.Success::class.java) + assertThat(submittedState.loginModeState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) } } @@ -349,8 +349,8 @@ class ConfirmAccountProviderPresenterTest { initialState.eventSink(ConfirmAccountProviderEvents.Continue) skipItems(1) // Loading val submittedState = awaitItem() - assertThat(submittedState.loginMode).isInstanceOf(AsyncData.Success::class.java) - assertThat(submittedState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) + assertThat(submittedState.loginModeState.loginMode).isInstanceOf(AsyncData.Success::class.java) + assertThat(submittedState.loginModeState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) } } @@ -372,7 +372,7 @@ class ConfirmAccountProviderPresenterTest { initialState.eventSink(ConfirmAccountProviderEvents.Continue) skipItems(1) // Loading val submittedState = awaitItem() - assertThat(submittedState.loginMode.dataOrNull()).isEqualTo(LoginMode.AccountCreation(aUrl)) + assertThat(submittedState.loginModeState.loginMode.dataOrNull()).isEqualTo(LoginMode.AccountCreation(aUrl)) } } @@ -385,7 +385,7 @@ class ConfirmAccountProviderPresenterTest { ) = ConfirmAccountProviderPresenter( params = params, accountProviderDataSource = accountProviderDataSource, - loginHelper = createLoginHelper( + loginModePresenter = createLoginModePresenter( authenticationService = matrixAuthenticationService, 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 8249694278..56ccc230b0 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 @@ -15,7 +15,8 @@ import io.element.android.features.enterprise.api.EnterpriseService 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.localnetwork.LocalNetworkPermissionGate +import io.element.android.features.login.impl.login.LoginModePresenter 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 @@ -255,7 +256,7 @@ class OnBoardingPresenterTest { enterpriseService = FakeEnterpriseService( isAllowedToConnectToHomeserverResult = { true }, ), - loginHelper = createLoginHelper( + loginModePresenter = createLoginModePresenter( authenticationService = authenticationService, ), accountProviderDataSource = accountProviderDataSource, @@ -271,12 +272,12 @@ class OnBoardingPresenterTest { assertThat(accountProviderDataSource.flow.first().url).isEqualTo(A_HOMESERVER_URL_2) // Check an error was returned val submittedState = awaitItem() - assertThat(submittedState.loginMode).isInstanceOf(AsyncData.Failure::class.java) + assertThat(submittedState.loginModeState.loginMode).isInstanceOf(AsyncData.Failure::class.java) // Assert the error is then cleared submittedState.eventSink(OnBoardingEvents.ClearError) val clearedState = awaitItem() - assertThat(clearedState.loginMode).isEqualTo(AsyncData.Uninitialized) + assertThat(clearedState.loginModeState.loginMode).isEqualTo(AsyncData.Uninitialized) } } } @@ -292,7 +293,7 @@ private fun createPresenter( enterpriseService: EnterpriseService = FakeEnterpriseService(), wellknownRetriever: WellknownRetriever = FakeWellknownRetriever(), rageshakeFeatureAvailability: () -> Flow = { flowOf(true) }, - loginHelper: LoginHelper = createLoginHelper(), + loginModePresenter: LoginModePresenter = createLoginModePresenter(), onBoardingLogoResIdProvider: OnBoardingLogoResIdProvider = OnBoardingLogoResIdProvider { null }, sessionStore: SessionStore = InMemorySessionStore(), accountProviderDataSource: AccountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), @@ -305,18 +306,26 @@ private fun createPresenter( wellknownRetriever = wellknownRetriever, ), rageshakeFeatureAvailability = rageshakeFeatureAvailability, - loginHelper = loginHelper, + loginModePresenter = loginModePresenter, onBoardingLogoResIdProvider = onBoardingLogoResIdProvider, sessionStore = sessionStore, accountProviderDataSource = accountProviderDataSource, ) -fun createLoginHelper( +fun createLoginModePresenter( oAuthActionFlow: OAuthActionFlow = FakeOAuthActionFlow(), authenticationService: MatrixAuthenticationService = FakeMatrixAuthenticationService(), webClientUrlForAuthenticationRetriever: WebClientUrlForAuthenticationRetriever = FakeWebClientUrlForAuthenticationRetriever(), -): LoginHelper = LoginHelper( + localNetworkPermissionAdvisor: io.element.android.libraries.permissions.api.LocalNetworkPermissionAdvisor = + io.element.android.libraries.permissions.test.FakeLocalNetworkPermissionAdvisor(), + permissionsPresenterFactory: io.element.android.libraries.permissions.api.PermissionsPresenter.Factory = + io.element.android.libraries.permissions.test.FakePermissionsPresenterFactory(), +): LoginModePresenter = LoginModePresenter( oAuthActionFlow = oAuthActionFlow, authenticationService = authenticationService, webClientUrlForAuthenticationRetriever = webClientUrlForAuthenticationRetriever, + localNetworkPermissionGate = LocalNetworkPermissionGate( + advisor = localNetworkPermissionAdvisor, + permissionsPresenterFactory = permissionsPresenterFactory, + ), ) 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 52d1667687..1bdcb9bda1 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 @@ -21,6 +21,7 @@ import com.google.testing.junit.testparameterinjector.KotlinTestParameters.named 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.features.login.impl.login.aLoginModeState import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.auth.OAuthDetails import io.element.android.libraries.matrix.test.AN_EXCEPTION @@ -148,7 +149,7 @@ class OnboardingViewTest : RobolectricTestParameter() { setOnboardingView( state = anOnBoardingState( defaultAccountProvider = "element.io", - loginMode = AsyncData.Failure(AN_EXCEPTION), + loginModeState = aLoginModeState(loginMode = AsyncData.Failure(AN_EXCEPTION)), eventSink = eventSink, ), ) @@ -208,7 +209,7 @@ class OnboardingViewTest : RobolectricTestParameter() { ensureCalledOnce { callback -> setOnboardingView( state = anOnBoardingState( - loginMode = AsyncData.Success(LoginMode.PasswordLogin), + loginModeState = aLoginModeState(loginMode = AsyncData.Success(LoginMode.PasswordLogin)), eventSink = eventSink, ), onNeedLoginPassword = callback, @@ -224,7 +225,7 @@ class OnboardingViewTest : RobolectricTestParameter() { ensureCalledOnceWithParam(oAuthDetails) { callback -> setOnboardingView( state = anOnBoardingState( - loginMode = AsyncData.Success(LoginMode.OAuth(oAuthDetails)), + loginModeState = aLoginModeState(loginMode = AsyncData.Success(LoginMode.OAuth(oAuthDetails))), eventSink = eventSink, ), onOAuthDetails = callback, @@ -240,7 +241,7 @@ class OnboardingViewTest : RobolectricTestParameter() { ensureCalledOnceWithParam(oAuthDetails.url) { callback -> setOnboardingView( state = anOnBoardingState( - loginMode = AsyncData.Success(LoginMode.AccountCreation("aUrl")), + loginModeState = aLoginModeState(loginMode = AsyncData.Success(LoginMode.AccountCreation("aUrl"))), eventSink = eventSink, ), onCreateAccountContinue = callback, diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt index 87afb77474..29c5d4a86c 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderPresenterTest.kt @@ -13,6 +13,7 @@ import io.element.android.features.login.impl.changeserver.aChangeServerState import io.element.android.features.login.impl.resolver.HomeserverResolver import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.test.auth.FakeHomeServerLoginCompatibilityChecker +import io.element.android.libraries.permissions.test.FakeLocalNetworkPermissionAdvisor import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value @@ -30,7 +31,7 @@ class SearchAccountProviderPresenterTest { fun `present - initial state`() = runTest { val fakeLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker(checkResult = { Result.success(true) }) val presenter = SearchAccountProviderPresenter( - homeserverResolver = HomeserverResolver(testCoroutineDispatchers(), fakeLoginCompatibilityChecker), + homeserverResolver = HomeserverResolver(testCoroutineDispatchers(), fakeLoginCompatibilityChecker, FakeLocalNetworkPermissionAdvisor()), changeServerPresenter = { aChangeServerState() } ) presenter.test { @@ -44,7 +45,7 @@ class SearchAccountProviderPresenterTest { fun `present - error while checking login compatibility`() = runTest { val fakeLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker(checkResult = { Result.failure(IllegalStateException("Oops")) }) val presenter = SearchAccountProviderPresenter( - homeserverResolver = HomeserverResolver(testCoroutineDispatchers(), fakeLoginCompatibilityChecker), + homeserverResolver = HomeserverResolver(testCoroutineDispatchers(), fakeLoginCompatibilityChecker, FakeLocalNetworkPermissionAdvisor()), changeServerPresenter = { aChangeServerState() } ) presenter.test { @@ -68,7 +69,7 @@ class SearchAccountProviderPresenterTest { fun `present - enter text no result`() = runTest { val fakeWellknownRetriever = FakeHomeServerLoginCompatibilityChecker(checkResult = { Result.success(false) }) val presenter = SearchAccountProviderPresenter( - homeserverResolver = HomeserverResolver(testCoroutineDispatchers(), fakeWellknownRetriever), + homeserverResolver = HomeserverResolver(testCoroutineDispatchers(), fakeWellknownRetriever, FakeLocalNetworkPermissionAdvisor()), changeServerPresenter = { aChangeServerState() } ) presenter.test { @@ -101,7 +102,7 @@ class SearchAccountProviderPresenterTest { } val fakeLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker(checkResult = checkResult) val presenter = SearchAccountProviderPresenter( - homeserverResolver = HomeserverResolver(testCoroutineDispatchers(), fakeLoginCompatibilityChecker), + homeserverResolver = HomeserverResolver(testCoroutineDispatchers(), fakeLoginCompatibilityChecker, FakeLocalNetworkPermissionAdvisor()), changeServerPresenter = { aChangeServerState() } ) presenter.test { @@ -141,7 +142,7 @@ class SearchAccountProviderPresenterTest { } val fakeLoginCompatibilityChecker = FakeHomeServerLoginCompatibilityChecker(checkResult = checkResult) val presenter = SearchAccountProviderPresenter( - homeserverResolver = HomeserverResolver(testCoroutineDispatchers(), fakeLoginCompatibilityChecker), + homeserverResolver = HomeserverResolver(testCoroutineDispatchers(), fakeLoginCompatibilityChecker, FakeLocalNetworkPermissionAdvisor()), changeServerPresenter = { aChangeServerState() } ) presenter.test { From a8b3db4621bc98ce6a95493b4b3c21b61d69c4df Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 7 Jul 2026 21:38:03 +0200 Subject: [PATCH 076/383] Prompt for local network permission when changing server --- .../impl/changeserver/ChangeServerEvents.kt | 2 + .../changeserver/ChangeServerPresenter.kt | 21 +++-- .../impl/changeserver/ChangeServerState.kt | 2 + .../changeserver/ChangeServerStateProvider.kt | 4 + .../impl/changeserver/ChangeServerView.kt | 10 +++ .../changeserver/ChangeServerPresenterTest.kt | 80 +++++++++++++++++++ 6 files changed, 111 insertions(+), 8 deletions(-) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerEvents.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerEvents.kt index 27e6128dd0..4f0d228dd2 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerEvents.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerEvents.kt @@ -13,4 +13,6 @@ import io.element.android.features.login.impl.accountprovider.AccountProvider sealed interface ChangeServerEvents { data class ChangeServer(val accountProvider: AccountProvider) : ChangeServerEvents data object ClearError : ChangeServerEvents + data object RequestLocalNetworkPermission : ChangeServerEvents + data object DismissLocalNetworkPermission : ChangeServerEvents } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenter.kt index 4a4fb3ca41..79f76d5fb5 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenter.kt @@ -12,50 +12,55 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import dev.zacsweers.metro.Inject import io.element.android.features.login.impl.accesscontrol.DefaultAccountProviderAccessControl import io.element.android.features.login.impl.accountprovider.AccountProvider import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.features.login.impl.error.ChangeServerError +import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionGate 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.matrix.api.auth.MatrixAuthenticationService -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch @Inject class ChangeServerPresenter( private val authenticationService: MatrixAuthenticationService, private val accountProviderDataSource: AccountProviderDataSource, private val defaultAccountProviderAccessControl: DefaultAccountProviderAccessControl, + private val localNetworkPermissionGate: LocalNetworkPermissionGate, ) : Presenter { @Composable override fun present(): ChangeServerState { - val localCoroutineScope = rememberCoroutineScope() - val changeServerAction: MutableState> = remember { mutableStateOf(AsyncData.Uninitialized) } + val gateState = localNetworkPermissionGate.present( + urlOf = { provider -> provider.url }, + onProceed = { provider -> changeServer(provider, changeServerAction) }, + ) + fun handleEvent(event: ChangeServerEvents) { when (event) { - is ChangeServerEvents.ChangeServer -> localCoroutineScope.changeServer(event.accountProvider, changeServerAction) ChangeServerEvents.ClearError -> changeServerAction.value = AsyncData.Uninitialized + is ChangeServerEvents.ChangeServer -> gateState.submit(event.accountProvider) + ChangeServerEvents.DismissLocalNetworkPermission -> gateState.abort() + ChangeServerEvents.RequestLocalNetworkPermission -> gateState.requestPermission() } } return ChangeServerState( changeServerAction = changeServerAction.value, + localNetworkPermissionDialog = gateState.dialog, eventSink = ::handleEvent, ) } - private fun CoroutineScope.changeServer( + private suspend fun changeServer( data: AccountProvider, changeServerAction: MutableState>, - ) = launch { + ) { suspend { defaultAccountProviderAccessControl.assertIsAllowedToConnectToAccountProvider( title = data.title, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerState.kt index eea3ad78cd..a3467b21ba 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerState.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerState.kt @@ -8,9 +8,11 @@ package io.element.android.features.login.impl.changeserver +import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialog import io.element.android.libraries.architecture.AsyncData data class ChangeServerState( val changeServerAction: AsyncData, + val localNetworkPermissionDialog: LocalNetworkPermissionDialog, val eventSink: (ChangeServerEvents) -> Unit ) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerStateProvider.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerStateProvider.kt index 1a94bb5631..693bca34bd 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerStateProvider.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerStateProvider.kt @@ -10,6 +10,7 @@ package io.element.android.features.login.impl.changeserver import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.login.impl.error.ChangeServerError +import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialog import io.element.android.libraries.architecture.AsyncData open class ChangeServerStateProvider : PreviewParameterProvider { @@ -39,12 +40,15 @@ open class ChangeServerStateProvider : PreviewParameterProvider = AsyncData.Uninitialized, + localNetworkPermissionDialog: LocalNetworkPermissionDialog = LocalNetworkPermissionDialog.None, ) = ChangeServerState( changeServerAction = changeServerAction, + localNetworkPermissionDialog = localNetworkPermissionDialog, eventSink = {} ) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt index d6b9c1709b..15b987ce16 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import io.element.android.features.login.impl.R import io.element.android.features.login.impl.dialogs.SlidingSyncNotSupportedDialog import io.element.android.features.login.impl.error.ChangeServerError +import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialogView import io.element.android.libraries.androidutils.system.openGooglePlay import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.ProgressDialog @@ -121,6 +122,15 @@ fun ChangeServerView( } AsyncData.Uninitialized -> Unit } + LocalNetworkPermissionDialogView( + dialog = state.localNetworkPermissionDialog, + onSubmit = { + eventSink.invoke(ChangeServerEvents.RequestLocalNetworkPermission) + }, + onDismiss = { + eventSink.invoke(ChangeServerEvents.DismissLocalNetworkPermission) + } + ) } @PreviewsDayNight 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 274b58ee49..02ee9d5042 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 @@ -15,6 +15,8 @@ import io.element.android.features.login.impl.accesscontrol.DefaultAccountProvid import io.element.android.features.login.impl.accountprovider.AccountProvider import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.features.login.impl.error.ChangeServerError +import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialog +import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionGate import io.element.android.features.wellknown.test.FakeWellknownRetriever import io.element.android.features.wellknown.test.anElementWellKnown import io.element.android.libraries.architecture.AsyncData @@ -23,6 +25,9 @@ import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.A_HOMESERVER_URL import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService import io.element.android.libraries.matrix.test.auth.aMatrixHomeServerDetails +import io.element.android.libraries.permissions.test.FakeLocalNetworkPermissionAdvisor +import io.element.android.libraries.permissions.test.FakePermissionsPresenter +import io.element.android.libraries.permissions.test.FakePermissionsPresenterFactory import io.element.android.libraries.wellknown.api.ElementWellKnown import io.element.android.libraries.wellknown.api.WellknownRetriever import io.element.android.libraries.wellknown.api.WellknownRetrieverResult @@ -43,6 +48,7 @@ class ChangeServerPresenterTest { createPresenter().test { val initialState = awaitItem() assertThat(initialState.changeServerAction).isEqualTo(AsyncData.Uninitialized) + assertThat(initialState.localNetworkPermissionDialog).isEqualTo(LocalNetworkPermissionDialog.None) } } @@ -183,11 +189,81 @@ class ChangeServerPresenterTest { } } + @Test + fun `present - advisor advises prompt, dialog shown before setHomeserver runs`() = runTest { + val authenticationService = FakeMatrixAuthenticationService( + setHomeserverResult = { Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true)) }, + ) + createPresenter( + authenticationService = authenticationService, + enterpriseService = FakeEnterpriseService(isAllowedToConnectToHomeserverResult = { true }), + localNetworkPermissionAdvisor = FakeLocalNetworkPermissionAdvisor(shouldPrompt = true), + permissionsPresenter = FakePermissionsPresenter(), + ).test { + val initialState = awaitItem() + assertThat(initialState.localNetworkPermissionDialog).isEqualTo(LocalNetworkPermissionDialog.None) + initialState.eventSink.invoke(ChangeServerEvents.ChangeServer(AccountProvider(url = A_HOMESERVER_URL))) + val promptState = expectMostRecentItem() + // Dialog is shown, permission has not been requested yet, setHomeserver has not been called. + assertThat(promptState.localNetworkPermissionDialog).isNotEqualTo(LocalNetworkPermissionDialog.None) + assertThat(promptState.changeServerAction).isEqualTo(AsyncData.Uninitialized) + } + } + + @Test + fun `present - dismissing the dialog aborts the submit`() = runTest { + createPresenter( + authenticationService = FakeMatrixAuthenticationService( + setHomeserverResult = { Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true)) }, + ), + enterpriseService = FakeEnterpriseService(isAllowedToConnectToHomeserverResult = { true }), + localNetworkPermissionAdvisor = FakeLocalNetworkPermissionAdvisor(shouldPrompt = true), + permissionsPresenter = FakePermissionsPresenter(), + ).test { + val initialState = awaitItem() + initialState.eventSink.invoke(ChangeServerEvents.ChangeServer(AccountProvider(url = A_HOMESERVER_URL))) + val promptState = expectMostRecentItem() + assertThat(promptState.localNetworkPermissionDialog).isNotEqualTo(LocalNetworkPermissionDialog.None) + promptState.eventSink.invoke(ChangeServerEvents.DismissLocalNetworkPermission) + val dismissedState = expectMostRecentItem() + assertThat(dismissedState.localNetworkPermissionDialog).isEqualTo(LocalNetworkPermissionDialog.None) + assertThat(dismissedState.changeServerAction).isEqualTo(AsyncData.Uninitialized) + } + } + + @Test + fun `present - advisor advises prompt, permission granted resumes setHomeserver`() = runTest { + val authenticationService = FakeMatrixAuthenticationService( + setHomeserverResult = { Result.success(aMatrixHomeServerDetails(supportsOAuthLogin = true)) }, + ) + val permissionsPresenter = FakePermissionsPresenter() + createPresenter( + authenticationService = authenticationService, + enterpriseService = FakeEnterpriseService(isAllowedToConnectToHomeserverResult = { true }), + localNetworkPermissionAdvisor = FakeLocalNetworkPermissionAdvisor(shouldPrompt = true), + permissionsPresenter = permissionsPresenter, + ).test { + val initialState = awaitItem() + initialState.eventSink.invoke(ChangeServerEvents.ChangeServer(AccountProvider(url = A_HOMESERVER_URL))) + val promptState = expectMostRecentItem() + assertThat(promptState.localNetworkPermissionDialog).isNotEqualTo(LocalNetworkPermissionDialog.None) + permissionsPresenter.setPermissionGranted() + // Await recompositions until the deferred setHomeserver completes. + var finalState = awaitItem() + while (finalState.changeServerAction !is AsyncData.Success) { + finalState = awaitItem() + } + assertThat(finalState.changeServerAction).isEqualTo(AsyncData.Success(Unit)) + } + } + private fun createPresenter( authenticationService: FakeMatrixAuthenticationService = FakeMatrixAuthenticationService(), accountProviderDataSource: AccountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), enterpriseService: EnterpriseService = FakeEnterpriseService(), wellknownRetriever: WellknownRetriever = FakeWellknownRetriever(), + localNetworkPermissionAdvisor: FakeLocalNetworkPermissionAdvisor = FakeLocalNetworkPermissionAdvisor(), + permissionsPresenter: FakePermissionsPresenter = FakePermissionsPresenter(), ) = ChangeServerPresenter( authenticationService = authenticationService, accountProviderDataSource = accountProviderDataSource, @@ -195,5 +271,9 @@ class ChangeServerPresenterTest { enterpriseService = enterpriseService, wellknownRetriever = wellknownRetriever, ), + localNetworkPermissionGate = LocalNetworkPermissionGate( + advisor = localNetworkPermissionAdvisor, + permissionsPresenterFactory = FakePermissionsPresenterFactory(permissionsPresenter), + ), ) } From f25ca5b96318b23a29a75110f4feaaf102261eed Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 7 Jul 2026 20:18:30 +0000 Subject: [PATCH 077/383] Update screenshots --- .../images/appnav.loggedin_LoggedInView_Day_4_en.png | 3 +++ .../images/appnav.loggedin_LoggedInView_Day_5_en.png | 3 +++ .../images/appnav.loggedin_LoggedInView_Night_4_en.png | 3 +++ .../images/appnav.loggedin_LoggedInView_Night_5_en.png | 3 +++ ...ures.login.impl.changeserver_ChangeServerView_Day_6_en.png | 3 +++ ...es.login.impl.changeserver_ChangeServerView_Night_6_en.png | 3 +++ ...nts.preview.imageeditor_AttachmentImageEditorView_2_en.png | 4 ++-- ...nts.preview.imageeditor_AttachmentImageEditorView_5_en.png | 4 ++-- ...rypto.identity_MessagesViewWithIdentityChange_Day_0_en.png | 4 ++-- ...rypto.identity_MessagesViewWithIdentityChange_Day_1_en.png | 4 ++-- ...rypto.identity_MessagesViewWithIdentityChange_Day_2_en.png | 4 ++-- ...pto.identity_MessagesViewWithIdentityChange_Night_0_en.png | 4 ++-- ...pto.identity_MessagesViewWithIdentityChange_Night_1_en.png | 4 ++-- ...pto.identity_MessagesViewWithIdentityChange_Night_2_en.png | 4 ++-- ...re.resolve_ResolveVerifiedUserSendFailureView_Day_1_en.png | 4 ++-- ...re.resolve_ResolveVerifiedUserSendFailureView_Day_2_en.png | 4 ++-- ....resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png | 4 ++-- ....resolve_ResolveVerifiedUserSendFailureView_Night_2_en.png | 4 ++-- ...meline.components.event_ATimelineItemEventRow_Day_0_en.png | 4 ++-- ...line.components.event_ATimelineItemEventRow_Night_0_en.png | 4 ++-- ....components.event_TimelineImageWithCaptionRow_Day_0_en.png | 4 ++-- ...omponents.event_TimelineImageWithCaptionRow_Night_0_en.png | 4 ++-- ....components.event_TimelineVideoWithCaptionRow_Day_0_en.png | 4 ++-- ...omponents.event_TimelineVideoWithCaptionRow_Night_0_en.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 ++-- .../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_1_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_1_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 ++-- ...references.impl.blockedusers_BlockedUsersView_Day_4_en.png | 4 ++-- ...references.impl.blockedusers_BlockedUsersView_Day_5_en.png | 4 ++-- ...ferences.impl.blockedusers_BlockedUsersView_Night_4_en.png | 4 ++-- ...ferences.impl.blockedusers_BlockedUsersView_Night_5_en.png | 4 ++-- ...embermoderation.impl_RoomMemberModerationView_Day_5_en.png | 4 ++-- ...embermoderation.impl_RoomMemberModerationView_Day_7_en.png | 4 ++-- ...bermoderation.impl_RoomMemberModerationView_Night_5_en.png | 4 ++-- ...bermoderation.impl_RoomMemberModerationView_Night_7_en.png | 4 ++-- ...eme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png | 4 ++-- ...e.components_HorizontalFloatingToolbarNoFab_Night_0_en.png | 4 ++-- ...em.theme.components_HorizontalFloatingToolbar_Day_0_en.png | 4 ++-- ....theme.components_HorizontalFloatingToolbar_Night_0_en.png | 4 ++-- 94 files changed, 194 insertions(+), 176 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png create mode 100644 tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_6_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_6_en.png diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png new file mode 100644 index 0000000000..5cfd616c0e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:924b97967296d3f50e1f911a14bd63b9d5d0d3d5d171053c1a0e6a5048c4d336 +size 34048 diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png new file mode 100644 index 0000000000..ea86b6f571 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f98480a126f3cd955fc10e42404d8aa812e2f7fb59a9655593bbebb1c8fa972 +size 33249 diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png new file mode 100644 index 0000000000..348422394b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c89fc51cf4c9a8b623bb7582aa1490109220cec3b0bfc9ce58e150c5a7702029 +size 32158 diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png new file mode 100644 index 0000000000..d66f1ab4f2 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:794613b9e61283cab807a35b23875b4ea9c1198789c844958c755699279fa3b7 +size 31413 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_6_en.png new file mode 100644 index 0000000000..7ff27996e2 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ee3174b63b166511e6c51725a8b6fe00b31eafff011f9059f2f728b77823b465 +size 33670 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_6_en.png new file mode 100644 index 0000000000..2c304a2695 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7910112f7ab526dbf0e5326213e03c3f3fe109dc8cc1bd3a8bf5fb05ddb5b0a7 +size 32054 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 8edee63bc1..3192cf2a5e 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:de82970da241172b94f822f8792e6fc721dcfc7f0f67e3523962e253e9750884 -size 255933 +oid sha256:1885bbe8b0ea497ac20d7bcdd0c6a93ba0533e898378d35e1cafdc8c9924fd56 +size 279984 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 ccfdd7d9ed..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:fe6cb72de5079be2ac02ec39f74bac0d20492cd6f5509b71ad9cfc4cc52955d3 -size 326468 +oid sha256:1ca032575e4ebd75a2ebc5a4cb9f966e48cdfa56f4ff42d6d9309fa3577a1adb +size 310609 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en.png index 5f51b27f5e..693a36b7dd 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3274314ab9e39c23a6b9d66adf80ac8bb7b364ce60a300f96582374a18bc821f -size 54590 +oid sha256:3dbb8ef39b6a7a0c2f576d8bd101aa97c89da696f23e6d5836846494471c01a1 +size 55799 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en.png index e1f6ee6430..b1850a50a5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e27c7c51fe07cca51b92a601aa9c58deab609bfa5e82f8f6f88eaab6ae59ec3 -size 64307 +oid sha256:f1dd0da147212e13a6c0ad5ad8f85ce55666c444076c238ea27eba5605cfab1f +size 56909 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png index 5289eaca63..4185f46b51 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:65f9ee083a73669a0d3f9d88141a610ea53f3c39e89d8f706d414b04555b4764 -size 59321 +oid sha256:085963fcb425147d35a9ad947a7a3e4ba4712bd3d2f32e93099ff15cffe83b88 +size 64761 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en.png index d3f7da6320..2e70435fa5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a94a4cc176b5d52ef9b21339749324adeef9857b6cdaa2ae973903e2408662a -size 55904 +oid sha256:7a3667390d9d88894bbdd5d72b0b714b29c9ff160653e310e97b0da87b6ba8b0 +size 54724 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en.png index bd3b0196d6..0f6de1b844 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f7f7415abbe51858f938e16ad03c6aab983fb3d5e2a53a028bae3c031446646 -size 67848 +oid sha256:28512b0fda0b71b98eab03cee15c9d3163825b1a3545670cfa277ddd5434c87a +size 58417 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en.png index f4d51ccc61..6c774d4cec 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a8f5aaaa7ebb0e61b07867590d99a8791c5d04cad1ce0f334d23dce6f26c6e6 -size 67276 +oid sha256:6ed6a5f1a2055e19a6b8fb0af4738845bd2184f755c323022c52154cdfa07e05 +size 60909 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en.png index bd73e322ab..02d0fc8eeb 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12020ba97720f2374f9ace172693f08be01522e4ca30d3970efa91d802581e81 -size 3657 +oid sha256:f77d8243c23d3f37dff86dec53671cbde9fafe1314f6e6b445abdfe47d751ad6 +size 56187 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en.png index 93622cedfe..bd73e322ab 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:87193a7c9eb9d40234970e5f5be02e80f2b3ffe91e2c9ca6afd58b8bccdd5911 -size 55075 +oid sha256:12020ba97720f2374f9ace172693f08be01522e4ca30d3970efa91d802581e81 +size 3657 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png index bd73e322ab..0cf6c10c4e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12020ba97720f2374f9ace172693f08be01522e4ca30d3970efa91d802581e81 -size 3657 +oid sha256:49f0bb16d3d57b59242e704e3dd4e8885c59721a42129837ff6a4f0d7d02de11 +size 54433 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en.png index bd73e322ab..adec213a8c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12020ba97720f2374f9ace172693f08be01522e4ca30d3970efa91d802581e81 -size 3657 +oid sha256:8ebee4aec3dbab6e1bb05fda7c5e423f0e931560743d0f0ccbac6b70fa9ad808 +size 52921 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 index 08169845d5..38a81d10b8 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86eac241e9084cc830ff13d231908da2eb0dff246aa5cac64dddaac68a5d5f13 -size 295298 +oid sha256:4420dfe9f6f95411093eb1c17825a389a31d7a5d5ef146129e5872cdd5d87aff +size 295295 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 index 3f12875a5b..06dd93b269 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7076c9a44a433cd9eeca536365ae262d39b4ad99a8f854faadec272cb1b82031 -size 294992 +oid sha256:578a3707102c7754f607c3a14f94f32cafa30ee570db174386533c484cb4773c +size 295031 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en.png index 29e7582971..fc985de87d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d6441c572f64d99bc119d649e5e6422fe516b9d097f310ccbd99a9ddded9609f -size 612494 +oid sha256:3f358da2b9b0521c14e525bcb2bd41c29c96aacaf5f007546e6d362bde2ee3fb +size 612526 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en.png index 176ebfa36b..90bee6c117 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a867dda82242d2b13bd4bc84a9f1c9b8b7b99c030e19a6cce39b2f828b517f3 -size 611488 +oid sha256:a709de55bc68cf12064ebdbde92c0a99bef3252958d7966540458d253e8c12c2 +size 611422 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en.png index f792a1663a..80857358e7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3bb005a88e9a4d2bb850478ee8ac2c4f31d32625bd6d2abf455fade461cd399 -size 607806 +oid sha256:54e71f45db31e8664c42f8c05feb91ae839589e00cb89d12088c15c85fb9f25f +size 607824 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en.png index 18319e718f..8733429e34 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4a2a57f5547f98b9ac2d8bf7195a1e4b49e03834e8866c6cc76660a6a3b16e74 -size 606823 +oid sha256:8bb505fe6d67669339c9366f8ee5bc75974e223837d95e76e637455a51c18711 +size 606787 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 0435f55de6..ab6392a424 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:ff839731834d7d0c94fa9a2c412014ddbaeaa053c5af1c8cbd00a3f3a583f364 -size 379511 +oid sha256:94f89a37549a3f198442db467bc7d8539f0b5649d97927bfe731f090d6dfb03d +size 379505 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 f0b5506b89..9cbd5c1d95 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:04ea6c2947a21d3d4a3d43e9c4750c4f2a49056536a4da3f34c95df8353e9de3 -size 377990 +oid sha256:d0e170b4bea262de612bf3374d475fcd25470ff91b7554d20809c51857a78cec +size 377963 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 1f0fdabe6d..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:b8bb5a6de6601da8d7fe59f110a054577e2e25dae4bb449f60c04e7d7a1b9551 -size 365073 +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 195aa04fe2..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:76e5ae44362792d570cd82f3910c8bd0acde509b8418c5892e0385e7d636f042 -size 370223 +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 058a3992c3..29771235f0 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:00fe1e676086766a3eac3e4457eff52c989789fc5d8d0df2624c019ed25ce9af -size 363322 +oid sha256:60b9f2b920cd2a2a414805d1f0f77925232d9ae60bd607fa18d4395cda2dd73d +size 363291 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 db4ea8296a..c6d4541184 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:2f0d24b8011564ee7a8b2f8c2e6a24eda668ee42d451d862f884acb7926aa06c -size 368529 +oid sha256:c00e504593d8eb61b598f05f46ee4d591757975a80c0b4227b240847d2cd4868 +size 368510 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 84d9d4e5c3..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:7c609a633ab23eae5729ecb57a17a385bac65e81cbf0180c01e0847f1028039e -size 347890 +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 73b7e674e2..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:991deacdfb7bc371a2df960a2364ae3b2187e588aa5afe7f39409e367040dd9c -size 363893 +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 bac23aab98..22ff4965d1 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:e30686c7c037ef102717e0316543faf4d3ed2671c21eca96a667150daab380d6 -size 346614 +oid sha256:787151f8f242a8794a804bf14831f6ca680814d617e85feb3652103e8a0f20cd +size 346565 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 b6e4650d9d..4e17de6908 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:2cd357a1fbaa425eca95587bff2f768a45e773f983f75664875653ba1900e534 -size 361625 +oid sha256:c1e15400fa2c5ee6087316501445c551a3932b65e16de31e68acc5efbd16a559 +size 361603 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 01d4dca84b..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:ef2bf449671b652cb152b3baab92ab100eab77a54229ab49daeab156f2f484d0 -size 369724 +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 f0dfbc3321..1600afff71 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:f7a6302320bd1e4258e03487539bf46b0b12781dfc8a22b3f9f267017a6146fa -size 354751 +oid sha256:273351cc9c533b2424859a0de00a8a3786628abc3a88175705c4205dedf7e9aa +size 354737 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 c4943b892c..e38cf03ad6 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:4c410e853089cc2c4a2c48a00dd9a8babc8095aed72bb4625057444710559c6c -size 368129 +oid sha256:41a0e404dea7f52359b24b3ec3926b1405429b165cfed44c63b3922ea6d3cb46 +size 368114 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 b5dac8434c..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:1a92f8af94682facac66d4aacb6e49f345561c15be2f8b689041b78aeaaae831 -size 345062 +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 8aa2cca147..1b99468924 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:02ecb903124273e24151ea2088f6b99144f7dcadba00a582b6210dd23835b5c9 -size 357743 +oid sha256:3a9509411777f342261cab58b92a022b3c9f8f0f7a9e4d0527120a91976575f0 +size 357733 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 cececc229a..b5032c29b3 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:f0c6dafaa41849af00d5097a85bd88e3a054a0a9e41c0466a08e6ff8dd6102b2 -size 356857 +oid sha256:dce23463c335d01eb67293cfcede5d85e96ab2ba035cc9a188d42e8e6866bc63 +size 356831 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 a332744358..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:588967869cbd25ed8b82aff5618175660a8a9e45a5a861b1c7867cf1913f575b -size 364646 +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 d7b969fd5b..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:2528df873713755f542f61cd794080929586c1bd5f316c0378ce9e837c21d50b -size 397145 +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 0041a870b9..63bd9c3f6d 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:a2bd77c08be705c66225f16c29fd6826decd92b41922d0f8ffc0d1a63d8c59d2 -size 356193 +oid sha256:a6cd94664f89bdad2a9761ea8b20acb83fed3ed7cb5be41af8fe4852643c0bfc +size 356175 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 9fcf389708..f67906a37c 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:9daeee1aaa04247da3c8bb5aaae9947aab1ed2d2057995e53d6ebdb63e5cd356 -size 355848 +oid sha256:ffa68c8398d789444151855496e5df4ffa03218a383db6ea46fd4f979829b823 +size 355831 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 6e83d6491d..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:34152c742abc486a48234e22101833bc163cf11979890d06aac41e68e3c404d0 -size 364846 +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 0021619c44..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:7b23d3a37774283067a8919b8c332b1bb5a79e90dceb7216b484b985491282e5 -size 355389 +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 77abe20982..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:5c3d87862c6d7fc88d0f23cd54c5b9f77028992fdd7c282a195b964dd17e85ac -size 367855 +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 1d34761a9b..448bcec677 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:f7d9b5fc0ff5d7828ad6f4dc0c9bd9520b4920553da97ed7b4e030ee844c0208 -size 353054 +oid sha256:fe0daf9161bc2da194992a2fc9505bf2009c5dbed78cdb35d2eb7ed1380a7df5 +size 353037 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 c081fa16a5..5243218ae3 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:6a92bcf5885322e11a706071969fb674b1f6e60e021af153aaa125baa4a602ae -size 366285 +oid sha256:9a85db2f5958db867578663533f204b2e803372d470da890fd8056ffed0cf46c +size 366254 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 47a9a6b630..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:54372845e922d047408dd960d048b9b5eae2263d589117d8e7d197741aa34f32 -size 342827 +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 ceca184bd7..5560c21967 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:8e82011a72f36889c53ab61ed2b9947c7fb5f868c9b7010904fc10f4ca587082 -size 356082 +oid sha256:af4a48ee80535f2c0a226c4ffa4344054fb63b7b0a88ea2c030a4eb8dd5e9644 +size 356078 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 5cc5cfe4fc..5cdad1df92 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:6524cc87257cc9d3f135904f4e14594b56df695e71fe576418d2319c472d710b -size 355285 +oid sha256:9e2d8caf5aaae7d3406c703288e491f328552f0acd18e56afd5265b4ceaf1cd1 +size 355272 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 a431a9429a..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:93c2df04d65f6078ce3f7067fbae8a7317ec42ed0fc013dee962a3953269f3b7 -size 362813 +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 b51a89586b..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:e642229c58169775fe702769a306bbef22698516ae6f7ac75a761213c3f195fa -size 395446 +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 ae8495618a..aa322fc2e4 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:08057fdc1e1184720b438ddd2a8753f00791baf2456cc30b45de8e6bdeb57e8e -size 354404 +oid sha256:5fae87094ea13b14e2dc7c16ca96e4f8096ff39e962799468fb4ead4c666620f +size 354381 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 40105c1498..9d617f6688 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:5ed24d190f10c079f8cf176404372d40eb25cc78ce595a22febc540315057b86 -size 354075 +oid sha256:dabad9dcd5b8f0d4bb964a0187ad7c94b023b04552dacd29a077daddfd48d550 +size 354052 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 1a8ea3e4e9..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:66aba7b4271a990fac85b0bbc7cbdc371fa1e38a4da5bb4e2f62a80b21cb3a8f -size 363012 +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 c9227ebf94..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:e614f4a8657637c584a283d69124236d00fe1251c2b8d739c5688a57a6fd152e -size 353693 +oid sha256:756f0cff90ddd61adce2f467c0384d74d430f6d51c091e4980e45bcc9ee6f0fd +size 353705 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 7a5e5e1512..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:0e3467a7606a5a7beaafb510faf008ed567b1e3a9915ede6e2ec09c491af0bb9 -size 56552 +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 843adcdff0..52e023ec49 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:446ae29cbb211665f6d91129a7dee0f718b407fcb2a64d3f2c0e962e1cb47af7 -size 50168 +oid sha256:c8420417cf8ba717747dead34b9646515f35eb94e1f71aa952b77c3ff433043e +size 49684 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 ee23a7111d..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:38ae233a128e887efc48da73be3d6ce50a7095601315ed49a3c9cb209ffdda26 -size 58352 +oid sha256:9b071ba6e99b68dcc75f5aaed3a879f2e30614c954b88c6dc05e1dfec57f1079 +size 65771 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 9685e6cbc9..875fb85bda 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:d1a28720d554bc4698eb52e27e7c6228ac9c14b3703a8c139c3113f8b8fa284e -size 40355 +oid sha256:f966bd2eade0180013c2c019963ad9f89c04f16cadcc04954bf3a4427c854635 +size 40002 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 7ce91f4684..a1dc68a3d5 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:7b749e1260d6ba2b7fef5ae9efd58612f6d67d1788f6c1e5cebc22d58d0fd7b7 -size 58563 +oid sha256:871d92a7565dd233ea87d53658be4e5202775def8e17fea8d386b8975c3b065e +size 53868 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 f6456f0ec1..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:22153168f6f3e84ab789faea29c94fffbc1a5e4c1b9a98deccb0460192fdde23 -size 57213 +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 6a3ffb84b6..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:48b91e52306daa750b4b5792535e1f1865ae3b74a36215376a51dafdd0dcd506 -size 54837 +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 abf8eb7086..6c0a7b4edc 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:1e79e1cc59ba62ca8eb99300eb520b05d7ac6d52c077e3010c03b474865b15f4 -size 58374 +oid sha256:f5aa22c3d79a392625ae231abc046f07f7cdabd91613d5e6f07aede5382aba9b +size 60410 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 5d4f5bdaeb..ac1d94a4dd 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:08fb14008b08d86755c3473e7194ef0a39bb73c3f0d48122ca80c6a019ec98eb -size 48676 +oid sha256:be5b086ab6934bae88b39987bc51e709c5adb81bdd04fa028e97832c725fd68a +size 50219 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 b3af9d831a..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:ce795c4e32a1be3d57f6b1c87588d8c7ed0442996ab9d8a96f1ec5a07627e598 -size 59663 +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 2c88d322d4..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:963fcec9647d0e5e57bd3fbe3edd389c17be7558c1da7e93fa44f34db34307ee -size 57726 +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 281aad62a7..135d84dd90 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:85f6f4c64f67faa99b9af65307a0cd3b46a68db52503c9c929375408597995d9 -size 62094 +oid sha256:4ff538a81d013fdc90dd7be466f710088eea93e081d23448b0731d301a4a3bb2 +size 60702 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 cfa6e4dbc3..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:7a3281f35461edb900ea434c68543dc684a5fad7dab7c9aabac510bc59d442b3 -size 56479 +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 5f3a619097..17df34a50a 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:19d14e3d779b163053c28e66d3381f0cabe3b540744606e955cd733f9e044089 -size 51713 +oid sha256:6548f5bf1906e1dddcbcc03bb8f76b42e604075751ea8efbc3ead826bf4cfad7 +size 51258 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 6e8468054f..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:262e8d4b8daa2d25593834fd0ab5d7019b0a3dd13707aa96e0701bf9240c6525 -size 59809 +oid sha256:10bce6df962a5198f019f509b1cdb55e28195587de4b74742ddc29833f1333a4 +size 69216 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 d7eb027558..5b842a7e61 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:5789d10db607ad77acd5d9391b970b2e0a0f962c205b3bf40db5c78d0dcea48b -size 38821 +oid sha256:529c7a98771dbdef837f3aea963871aca1ec086de9d9f8b86c5f6758d21468a8 +size 38724 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 f4ab74029b..f425dd2c4c 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:51a5b682243b969bc2d7d609decb823b0509d240f3ff14ee78319260af76a47f -size 58740 +oid sha256:bd6dc088e16f722b36c2198d6a8611af87dec2451f94ca3c2b6880b97f709b98 +size 54095 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 3974618f39..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:718d5c9f24c114f3bf88e000b637ea19598d7bb9b97001ba137fc12a6a1285e4 -size 52608 +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 0ad1e67deb..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:82e6e38576a507b19e58fce9dda0734ec00bcedcb0baf8f4c7919dbaaf7d2b85 -size 55046 +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 a009d0f584..5a877a59e1 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:478851e9e2e8c80095aa552b98a5d574749200ff49899c9472c913b07459c4b5 -size 53758 +oid sha256:5a582219d3143acb08563193bf7106e1ee8f6612e359d0a192e9a2f67c6799e3 +size 55375 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 f82a7a8219..0383bb8f95 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:22ea7fe121a63b35a2c2bb47609e692f8bf2b913871a6baf3d420c04334c6c4a -size 44344 +oid sha256:7c88b3ed8cc69dee59d4d0a726a9e383d00f2815b6525315f7dcd96f9c25ec2a +size 45618 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 7261c9b671..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:7cf3d727da78b39ecf24d4df7db0884af9008db67cc92274849c1b0978f87726 -size 59252 +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 cfa62a6626..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:bfe848e4c365cf4b4d663145f74e5f8b3f47a4c8994961c530603f0248400316 -size 57117 +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 89065e6bf0..4d6afdbbb1 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:a966c9a1fa4fdd933f4ef9239592e90458a2819ff4a45c857714d2e38c0df5b2 -size 64405 +oid sha256:35069d4fae829d9afe479308dd72ad025fa011290d23133a231f4e70f601ee75 +size 62987 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png index 7cca911c45..074820e157 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26e14b77fa3c3aeaea58782309e6de8b9047e07945009322990ebf5f4c283309 -size 52770 +oid sha256:7caacb336793b8ae4b83e9a10a82325e25e8b3c036f881898ed28688250eb6e0 +size 55744 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png index 7cca911c45..2af459c158 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26e14b77fa3c3aeaea58782309e6de8b9047e07945009322990ebf5f4c283309 -size 52770 +oid sha256:28a95d4b7ebca92c4e0467f3ecd9acdaf7f6257604d190f5d088a9a25e87d637 +size 55305 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png index a68f886f73..616c06bf46 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5a2e306087a967849f61872b56a83f194d1a76df5723f0bbae6e6e2f4a98c63 -size 55725 +oid sha256:0ce2519906f1aaf34700ca9ba4bdeaa72030f1f5aff3f7e24352a1435ac67d98 +size 53966 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png index 616c06bf46..36d19c6b72 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ce2519906f1aaf34700ca9ba4bdeaa72030f1f5aff3f7e24352a1435ac67d98 -size 53966 +oid sha256:7dfa2767c55a81d3f121b8fa55443b7b05f9369e91639b80e0be349863799ad7 +size 55438 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png index 5c597300e4..73b8b8e50c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 -size 3853 +oid sha256:e8a3ad99763929d2783147814e44fa9ec7e7efb7b99949e3580f23c38fb5d971 +size 9398 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png index f8a1f24b34..5c597300e4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1342b6427f5b2e3075ae3ccee60bf1d3b11afaccf3e152643d6ef2d65c21b54e -size 9108 +oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 +size 3853 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png index 4ae7279fe7..d47bf90664 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:410a8596d4c70b9a3856d959d6d71ade8e831e8581ff410c9900957a93b3eb50 -size 8114 +oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c +size 3664 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png index d47bf90664..a87d89c701 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c -size 3664 +oid sha256:0f3a0cb5d9bae6725a1c527f3d9575aabf85d3edf63a28d9faa23f4f0b65e2d0 +size 7624 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png index 58546b8522..ee5c582240 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30357bf18792db5ab20085010251170a724ffe8c00313facd04ee704e806af64 -size 10982 +oid sha256:75de341f705bb22955f9399180519b65ad59c2e1917317d56e50ea4db78f35bc +size 12102 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png index 52fd9b9693..fedead0fa8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58b9491aaa5554b89d86c62a5c9c44975367538c6baa5562f8dc5768f76d8264 -size 8705 +oid sha256:4811667dec0f32accc5e2c8a5dd5c0b34017fcff8d1e0376ee7a4708426bca0f +size 9838 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png index 83302d6ba4..38ad0e4b56 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:16dee1dfe746cd40dac9fe8f0af3ecb42cd14bab5cc490917b589beed065ed1b -size 14686 +oid sha256:326d59cf768b2dbd96eb7964d54c8eda509a5cd57c6e62087625e3314da0bb4d +size 13658 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png index 687e0d436a..4da2a98aca 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d57df7110371c9224e232b707d6a1b10ce14afcb56c803a78220792f2a0d4cf2 -size 11354 +oid sha256:ef0dc4d53daeb986f378b6e4d85928b4b6729336c89cf21e642c88c53688a3ab +size 10292 From 3dabece5f8fe04abc907fa1ef295db39befd2c27 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 8 Jul 2026 17:29:51 +0200 Subject: [PATCH 078/383] Restore AndroidManifest.xml to fix lint warning. --- features/messages/impl/src/main/AndroidManifest.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 features/messages/impl/src/main/AndroidManifest.xml diff --git a/features/messages/impl/src/main/AndroidManifest.xml b/features/messages/impl/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..ed135aef7a --- /dev/null +++ b/features/messages/impl/src/main/AndroidManifest.xml @@ -0,0 +1,10 @@ + + + + From 17bcf8c55c4c650e4f6d9f192041a3db2f03ab50 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 8 Jul 2026 17:58:06 +0200 Subject: [PATCH 079/383] Reflect new design updates --- .../components/ActiveCallTimelineItemView.kt | 31 +++++++------------ .../src/main/res/values/localazy.xml | 8 ++--- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt index 8a5fc925d2..e034f4ad4d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt @@ -251,18 +251,7 @@ private fun GroupCallBody(event: TimelineItem.Event, state: RtcNotificationState ) } } else { - val membersToShowCount = 4 - // Keep the one with avatar first but maintain - // the first user as it might be the call creator - val sortedMembers = remember(state.joinedMembers) { - if (state.joinedMembers.isEmpty()) return@remember emptyList() - val first = state.joinedMembers.first() - val rest = state.joinedMembers.drop(1).sortedByDescending { it.avatarUrl != null } - listOf(first) + rest - } - val displayMembers = sortedMembers.take(membersToShowCount) - val extraCount = state.joinedMembers.size - membersToShowCount - + val displayMembers = state.joinedMembers.take(3) AvatarRow( avatarDataList = displayMembers .map { user -> @@ -277,13 +266,15 @@ private fun GroupCallBody(event: TimelineItem.Event, state: RtcNotificationState overlapRatio = 0.5f, lastOnTop = true, ) - if (extraCount > 0) { - Text( - text = pluralStringResource(CommonPlurals.screen_timeline_active_call_extra_joined_count, count = state.joinedMembers.size, extraCount), - style = ElementTheme.typography.fontBodySmRegular, - color = ElementTheme.colors.textSecondary, - ) - } + Text( + text = pluralStringResource( + CommonPlurals.screen_timeline_active_call_joined_count, + count = state.joinedMembers.size, + state.joinedMembers.size + ), + style = ElementTheme.typography.fontBodySmRegular, + color = ElementTheme.colors.textSecondary, + ) } } } @@ -327,7 +318,7 @@ internal fun ActiveCallTimelineItemViewPreview() = ElementPreview( aMatrixUser(displayName = USER_NAME_CHARLIE), aMatrixUser(displayName = USER_NAME_JOHN_DOE, avatarUrl = "anUrlC"), ), - isJoined = true, + isJoined = false, callStartTsMillis = System.currentTimeMillis(), callIntent = callIntent ) to false, diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 27e6cd40eb..daf7753e4f 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -479,6 +479,10 @@ Are you sure you want to continue?" "Location sharing in progress" "%1$s Live Location" "%1$s Android" + + "%1$d joined" + "%1$d joined" + "Rageshake to report bug" "Screenshot" "%1$s: %2$s" @@ -537,10 +541,6 @@ Are you sure you want to continue?" "Spaces" "Shared %1$s" "On the map" - - "+ %1$d joined" - "+ %1$d joined" - "Message not sent because %1$s’s verified digital identity was reset." "Message not sent because %1$s has not verified all devices." "Message not sent because you have not verified one or more of your devices." From fad8dce1667589b8ff4295990df0a5f5ef0113f1 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 8 Jul 2026 18:16:13 +0200 Subject: [PATCH 080/383] Address PR review comments --- .../impl/userstatus/UserStatusView.kt | 4 -- .../userstatus/UserStatusPresenterTest.kt | 40 +++++-------------- .../libraries/matrix/impl/RustMatrixClient.kt | 1 + 3 files changed, 11 insertions(+), 34 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index dfc68ff446..7169aaec66 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -22,7 +22,6 @@ import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.foundation.text.input.clearText import androidx.compose.foundation.text.input.maxLength import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.minimumInteractiveComponentSize import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -121,9 +120,6 @@ private fun EmptyStatusRow( modifier = Modifier.padding(vertical = 16.dp), ) }, - trailingContent = ListItemContent.Custom({ - Box(modifier = Modifier.minimumInteractiveComponentSize()) - }), leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Reaction())), modifier = modifier.clickable(onClick = onClick), ) diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt index 4a03a22607..3f78843b74 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt @@ -7,13 +7,11 @@ package io.element.android.features.preferences.impl.userstatus -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.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.api.user.UserStatus import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.tests.testutils.test import kotlinx.coroutines.test.runTest import org.junit.Test @@ -23,9 +21,7 @@ class UserStatusPresenterTest { @Test fun `initial state - no status set`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - createPresenter().present() - }.test { + createPresenter().test { val state = awaitItem() assertThat(state.displayedStatus).isNull() assertThat(state.pickerState).isEqualTo(UserStatusPickerState.Hidden) @@ -34,9 +30,7 @@ class UserStatusPresenterTest { @Test fun `Open event transitions to ShowingPicker`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - createPresenter().present() - }.test { + createPresenter().test { val state = awaitItem() state.eventSink(UserStatusEvent.OpenPicker) assertThat(awaitItem().pickerState).isEqualTo(UserStatusPickerState.ShowingPicker) @@ -45,9 +39,7 @@ class UserStatusPresenterTest { @Test fun `Dismiss event from ShowingPicker goes back to Hidden`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - createPresenter().present() - }.test { + createPresenter().test { val state = awaitItem() state.eventSink(UserStatusEvent.OpenPicker) awaitItem() // ShowingPicker @@ -59,9 +51,7 @@ class UserStatusPresenterTest { @Test fun `Set event calls setUserStatus and transitions to Hidden with updated status`() = runTest { val client = FakeMatrixClient() - moleculeFlow(RecompositionMode.Immediate) { - createPresenter(client).present() - }.test { + createPresenter(client).test { val status = UserStatus(emoji = "💬", text = "In a meeting") awaitItem().eventSink(UserStatusEvent.SetStatus(status)) val newState = awaitItem() @@ -73,9 +63,7 @@ class UserStatusPresenterTest { @Test fun `OpenCustomInput with no existing status uses defaults`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - createPresenter().present() - }.test { + createPresenter().test { awaitItem().eventSink(UserStatusEvent.OpenCustomInput) val state = awaitItem() val pickerState = state.pickerState as UserStatusPickerState.CustomInput @@ -87,9 +75,7 @@ class UserStatusPresenterTest { @Test fun `OpenCustomInput with existing rawStatus pre-fills values`() = runTest { val client = FakeMatrixClient() - moleculeFlow(RecompositionMode.Immediate) { - createPresenter(client).present() - }.test { + createPresenter(client).test { val status = UserStatus(emoji = "🌴", text = "Away") awaitItem().eventSink(UserStatusEvent.SetStatus(status)) // Single emission: pickerState=Hidden and displayedStatus both set in one recomposition @@ -103,9 +89,7 @@ class UserStatusPresenterTest { @Test fun `UpdateCustomEmoji updates emoji in CustomInput state`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - createPresenter().present() - }.test { + createPresenter().test { awaitItem().eventSink(UserStatusEvent.OpenCustomInput) awaitItem().eventSink(UserStatusEvent.UpdateCustomEmoji("🚀")) val state = awaitItem() @@ -115,9 +99,7 @@ class UserStatusPresenterTest { @Test fun `CancelCustomInput goes back to Hidden`() = runTest { - moleculeFlow(RecompositionMode.Immediate) { - createPresenter().present() - }.test { + createPresenter().test { awaitItem().eventSink(UserStatusEvent.OpenCustomInput) awaitItem().eventSink(UserStatusEvent.CancelCustomInput) // CustomInput state, fire Cancel assertThat(awaitItem().pickerState).isEqualTo(UserStatusPickerState.Hidden) @@ -127,9 +109,7 @@ class UserStatusPresenterTest { @Test fun `Clear event calls clearUserStatus and clears displayed status`() = runTest { val client = FakeMatrixClient() - moleculeFlow(RecompositionMode.Immediate) { - createPresenter(client).present() - }.test { + createPresenter(client).test { val status = UserStatus(emoji = "☕", text = "Be right back") awaitItem().eventSink(UserStatusEvent.SetStatus(status)) // Single emission: pickerState=Hidden and displayedStatus both set in one recomposition 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 af6762d421..6ddca47bff 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 @@ -456,6 +456,7 @@ class RustMatrixClient( displayedStatus = localUserStatus?.let { DisplayedStatus.UserSet(it) }, ) ) + // Also update our session storage sessionStore.updateUserProfile( sessionId = sessionId.value, displayName = matrixUser.displayName, From 101e23da38d0bddd89bc5be2a92e3285bc030e46 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 17:20:43 +0000 Subject: [PATCH 081/383] Update dependency androidx.compose:compose-bom to v2026.06.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 ef95884507..8da586af6b 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.06.00" +compose_bom = "2026.06.01" # Coroutines coroutines = "1.11.0" From 566b0c6f86fabde8e62536e0088fceaeda1393dc Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Wed, 8 Jul 2026 20:01:21 +0000 Subject: [PATCH 082/383] Add item count text as the placeholder for in reply to box for galleries --- .../ui/messages/reply/InReplyToMetadata.kt | 42 ++++ .../messages/reply/InReplyToMetadataKtTest.kt | 222 ++++++++++++++++++ .../src/main/res/values/temporary.xml | 6 + 3 files changed, 270 insertions(+) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadata.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadata.kt index 9e5e468cd9..2da5184389 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadata.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadata.kt @@ -10,12 +10,15 @@ package io.element.android.libraries.matrix.ui.messages.reply import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.GalleryItemType +import io.element.android.libraries.matrix.api.timeline.item.event.GalleryMessageType import io.element.android.libraries.matrix.api.timeline.item.event.ImageMessageType import io.element.android.libraries.matrix.api.timeline.item.event.LegacyCallInviteContent import io.element.android.libraries.matrix.api.timeline.item.event.LiveLocationContent @@ -35,6 +38,7 @@ import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType import io.element.android.libraries.matrix.ui.messages.reply.InReplyToMetadata.Text import io.element.android.libraries.matrix.ui.messages.reply.InReplyToMetadata.Thumbnail +import io.element.android.libraries.ui.strings.CommonPlurals import io.element.android.libraries.ui.strings.CommonStrings @Immutable @@ -104,6 +108,44 @@ internal fun InReplyToDetails.Ready.metadata(hideImage: Boolean): InReplyToMetad type = AttachmentThumbnailType.Voice, ) ) + is GalleryMessageType -> { + val caption = textContent?.takeIf { it.isNotBlank() } + val isMediaGallery = type.items.all { it is GalleryItemType.Image || it is GalleryItemType.Video } + val countPlural = if (isMediaGallery) { + CommonPlurals.common_gallery_reply_media_items + } else { + CommonPlurals.common_gallery_reply_attachments + } + val text = caption ?: pluralStringResource(countPlural, type.items.size, type.items.size) + if (isMediaGallery) { + val firstMediaItem = type.items.firstOrNull { it is GalleryItemType.Image || it is GalleryItemType.Video } + val thumbnailSource = when (firstMediaItem) { + is GalleryItemType.Image -> (firstMediaItem.content.info?.thumbnailSource ?: firstMediaItem.content.source).takeUnless { hideImage } + is GalleryItemType.Video -> firstMediaItem.content.info?.thumbnailSource?.takeUnless { hideImage } + else -> null + } + val blurHash = when (firstMediaItem) { + is GalleryItemType.Image -> firstMediaItem.content.info?.blurhash + is GalleryItemType.Video -> firstMediaItem.content.info?.blurhash + else -> null + } + Thumbnail( + AttachmentThumbnailInfo( + thumbnailSource = thumbnailSource, + textContent = text, + type = AttachmentThumbnailType.Image, + blurHash = blurHash, + ) + ) + } else { + Thumbnail( + AttachmentThumbnailInfo( + textContent = text, + type = AttachmentThumbnailType.File, + ) + ) + } + } else -> Text(textContent ?: eventContent.body) } is StickerContent -> Thumbnail( diff --git a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadataKtTest.kt b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadataKtTest.kt index 0847315867..5b6df661f3 100644 --- a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadataKtTest.kt +++ b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadataKtTest.kt @@ -24,6 +24,8 @@ import io.element.android.libraries.matrix.api.timeline.item.event.EventContent import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType +import io.element.android.libraries.matrix.api.timeline.item.event.GalleryItemType +import io.element.android.libraries.matrix.api.timeline.item.event.GalleryMessageType import io.element.android.libraries.matrix.api.timeline.item.event.ImageMessageType import io.element.android.libraries.matrix.api.timeline.item.event.LocationMessageType import io.element.android.libraries.matrix.api.timeline.item.event.OtherState @@ -407,6 +409,226 @@ class InReplyToMetadataKtTest : RobolectricTest() { } } + @Test + fun `a gallery message with all media items shows media count`() = runTest { + moleculeFlow(RecompositionMode.Immediate) { + withConfigurationAndContext { + anInReplyToDetailsReady( + eventContent = aMessageContent( + messageType = GalleryMessageType( + body = "", + formatted = null, + items = listOf( + GalleryItemType.Image( + ImageMessageType( + filename = "image1.jpg", + caption = null, + formattedCaption = null, + source = aMediaSource(), + info = anImageInfo(), + ) + ), + GalleryItemType.Image( + ImageMessageType( + filename = "image2.jpg", + caption = null, + formattedCaption = null, + source = aMediaSource(), + info = anImageInfo(), + ) + ), + ), + ) + ), + textContent = "", + ).metadata(hideImage = false) + } + }.test { + awaitItem().let { + assertThat(it).isEqualTo( + InReplyToMetadata.Thumbnail( + attachmentThumbnailInfo = AttachmentThumbnailInfo( + thumbnailSource = aMediaSource(), + textContent = "2 media items…", + type = AttachmentThumbnailType.Image, + blurHash = A_BLUR_HASH, + ) + ) + ) + } + } + } + + @Test + fun `a gallery message with attachment items shows attachment count`() = runTest { + moleculeFlow(RecompositionMode.Immediate) { + withConfigurationAndContext { + anInReplyToDetailsReady( + eventContent = aMessageContent( + messageType = GalleryMessageType( + body = "", + formatted = null, + items = listOf( + GalleryItemType.File( + FileMessageType( + filename = "doc1.pdf", + caption = null, + formattedCaption = null, + source = aMediaSource(), + info = FileInfo( + mimetype = null, + size = null, + thumbnailInfo = null, + thumbnailSource = null, + ), + ) + ), + GalleryItemType.File( + FileMessageType( + filename = "doc2.pdf", + caption = null, + formattedCaption = null, + source = aMediaSource(), + info = FileInfo( + mimetype = null, + size = null, + thumbnailInfo = null, + thumbnailSource = null, + ), + ) + ), + ), + ) + ), + textContent = "", + ).metadata(hideImage = false) + } + }.test { + awaitItem().let { + assertThat(it).isEqualTo( + InReplyToMetadata.Thumbnail( + attachmentThumbnailInfo = AttachmentThumbnailInfo( + thumbnailSource = null, + textContent = "2 attachments…", + type = AttachmentThumbnailType.File, + blurHash = null, + ) + ) + ) + } + } + } + + @Test + fun `a gallery message with caption shows caption instead of count`() = runTest { + moleculeFlow(RecompositionMode.Immediate) { + withConfigurationAndContext { + anInReplyToDetailsReady( + eventContent = aMessageContent( + messageType = GalleryMessageType( + body = "My vacation photos", + formatted = null, + items = listOf( + GalleryItemType.Image( + ImageMessageType( + filename = "image1.jpg", + caption = null, + formattedCaption = null, + source = aMediaSource(), + info = anImageInfo(), + ) + ), + GalleryItemType.Image( + ImageMessageType( + filename = "image2.jpg", + caption = null, + formattedCaption = null, + source = aMediaSource(), + info = anImageInfo(), + ) + ), + ), + ) + ), + textContent = "My vacation photos", + ).metadata(hideImage = false) + } + }.test { + awaitItem().let { + assertThat(it).isEqualTo( + InReplyToMetadata.Thumbnail( + attachmentThumbnailInfo = AttachmentThumbnailInfo( + thumbnailSource = aMediaSource(), + textContent = "My vacation photos", + type = AttachmentThumbnailType.Image, + blurHash = A_BLUR_HASH, + ) + ) + ) + } + } + } + + @Test + fun `a gallery message with attachment items and caption shows caption instead of count`() = runTest { + moleculeFlow(RecompositionMode.Immediate) { + withConfigurationAndContext { + anInReplyToDetailsReady( + eventContent = aMessageContent( + messageType = GalleryMessageType( + body = "My documents", + formatted = null, + items = listOf( + GalleryItemType.File( + FileMessageType( + filename = "doc1.pdf", + caption = null, + formattedCaption = null, + source = aMediaSource(), + info = FileInfo( + mimetype = null, + size = null, + thumbnailInfo = null, + thumbnailSource = null, + ), + ) + ), + GalleryItemType.File( + FileMessageType( + filename = "doc2.pdf", + caption = null, + formattedCaption = null, + source = aMediaSource(), + info = FileInfo( + mimetype = null, + size = null, + thumbnailInfo = null, + thumbnailSource = null, + ), + ) + ), + ), + ) + ), + textContent = "My documents", + ).metadata(hideImage = false) + } + }.test { + awaitItem().let { + assertThat(it).isEqualTo( + InReplyToMetadata.Thumbnail( + attachmentThumbnailInfo = AttachmentThumbnailInfo( + thumbnailSource = null, + textContent = "My documents", + type = AttachmentThumbnailType.File, + blurHash = null, + ) + ) + ) + } + } + } + @Test fun `a poll content`() = runTest { moleculeFlow(RecompositionMode.Immediate) { diff --git a/libraries/ui-strings/src/main/res/values/temporary.xml b/libraries/ui-strings/src/main/res/values/temporary.xml index fd1edb0759..47d2007517 100644 --- a/libraries/ui-strings/src/main/res/values/temporary.xml +++ b/libraries/ui-strings/src/main/res/values/temporary.xml @@ -8,4 +8,10 @@ "Mark as read" "Jump to first unread message" + + "%1$d media items…" + + + "%1$d attachments…" + From c7f4c96f70791a3e04d2d77a8cd0ffd4208e9c79 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 22:04:39 +0000 Subject: [PATCH 083/383] Update dependency androidx.sqlite:sqlite-ktx to v2.7.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 ef95884507..d3cb11cdc5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -209,7 +209,7 @@ sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", ver 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.16.0" -sqlite = "androidx.sqlite:sqlite-ktx:2.6.2" +sqlite = "androidx.sqlite:sqlite-ktx:2.7.0" 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" } From 6296a538ebc251a6d1dc6de8b6f72227336e8e43 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 10:52:45 +0200 Subject: [PATCH 084/383] Update metro to v1.3.0 (#7168) 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 ef95884507..4db11a279e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -54,7 +54,7 @@ haze = "1.7.2" dependencyAnalysis = "3.16.0" # DI -metro = "1.2.1" +metro = "1.3.0" # Auto service autoservice = "1.1.1" From 9e160e027dcf874e71105d8183c7d41c477ce7ea Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 10:51:24 +0000 Subject: [PATCH 085/383] Update dependency io.sentry:sentry-android to v8.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 4db11a279e..0d23a6e37b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -230,7 +230,7 @@ color_picker = "io.mhssn:colorpicker:1.0.0" # Analytics posthog = "com.posthog:posthog-android:3.51.1" -sentry = "io.sentry:sentry-android:8.46.0" +sentry = "io.sentry:sentry-android:8.47.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.37.0" From 96d443e443e0b2ce06b4b3e85669312dce69c1b6 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 9 Jul 2026 13:51:37 +0200 Subject: [PATCH 086/383] Fix compilation warning --- .../preferences/impl/userstatus/UserStatusView.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index 7169aaec66..acd2b0676d 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -22,7 +22,8 @@ import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.foundation.text.input.clearText import androidx.compose.foundation.text.input.maxLength import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.material3.SheetValue +import androidx.compose.material3.rememberBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf @@ -177,7 +178,10 @@ private fun UserStatusPickerBottomSheet( onSelectCustomStatus: () -> Unit, modifier: Modifier = Modifier, ) { - val sheetState = rememberModalBottomSheetState() + val sheetState = rememberBottomSheetState( + initialValue = SheetValue.Hidden, + enabledValues = setOf(SheetValue.Hidden, SheetValue.Expanded) + ) val coroutineScope = rememberCoroutineScope() ModalBottomSheet( onDismissRequest = onDismiss, From 5f4bb30b18a3f0f45bfe001e3bf9caba37bdb097 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 9 Jul 2026 17:22:15 +0200 Subject: [PATCH 087/383] Address PR review comments --- .../appnav/loggedin/LoggedInPresenter.kt | 3 +- .../android/appnav/loggedin/LoggedInState.kt | 7 +-- .../appnav/loggedin/LoggedInStateProvider.kt | 1 + .../android/appnav/loggedin/LoggedInView.kt | 39 +++------------- .../impl/changeserver/ChangeServerState.kt | 2 +- .../changeserver/ChangeServerStateProvider.kt | 2 +- .../impl/changeserver/ChangeServerView.kt | 2 +- .../LocalNetworkPermissionDialogView.kt | 44 ------------------- .../LocalNetworkPermissionGate.kt | 13 +++--- .../LocalNetworkPermissionGateState.kt | 14 +----- .../login/impl/login/LoginModePresenter.kt | 10 +++++ .../login/impl/login/LoginModeState.kt | 2 +- .../impl/login/LoginModeStateProvider.kt | 2 +- .../login/impl/resolver/HomeserverResolver.kt | 21 +++------ .../ChooseAccountProviderView.kt | 2 +- .../loginwithclassic/LoginWithClassicView.kt | 2 +- .../ConfirmAccountProviderView.kt | 2 +- .../impl/screens/onboarding/OnBoardingView.kt | 2 +- .../changeserver/ChangeServerPresenterTest.kt | 2 +- .../onboarding/OnBoardingPresenterTest.kt | 3 +- .../LocalNetworkPermissionAdvisor.kt | 2 +- .../LocalNetworkPermissionDialog.kt | 20 +++++++++ .../LocalNetworkPermissionDialogView.kt | 37 ++++++++++++++++ .../DefaultLocalNetworkPermissionAdvisor.kt | 8 ++-- ...efaultLocalNetworkPermissionAdvisorTest.kt | 2 +- .../test/FakeLocalNetworkPermissionAdvisor.kt | 2 +- 26 files changed, 112 insertions(+), 134 deletions(-) delete mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionDialogView.kt rename libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/{ => localnetwork}/LocalNetworkPermissionAdvisor.kt (87%) create mode 100644 libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialog.kt create mode 100644 libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialogView.kt rename libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/{ => localnetwork}/DefaultLocalNetworkPermissionAdvisor.kt (83%) rename libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/{ => localnetwork}/DefaultLocalNetworkPermissionAdvisorTest.kt (98%) 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 fab9797c76..0723ad4606 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 @@ -38,9 +38,10 @@ import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion import io.element.android.libraries.matrix.api.sync.SyncService import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus -import io.element.android.libraries.permissions.api.LocalNetworkPermissionAdvisor import io.element.android.libraries.permissions.api.PermissionsEvent import io.element.android.libraries.permissions.api.PermissionsPresenter +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionAdvisor +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialog import io.element.android.libraries.push.api.PushService import io.element.android.libraries.push.api.PusherRegistrationFailure import io.element.android.services.analytics.api.AnalyticsService diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt index fdfff9bf75..edc12383bf 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInState.kt @@ -9,6 +9,7 @@ package io.element.android.appnav.loggedin import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialog data class LoggedInState( val showSyncSpinner: Boolean, @@ -19,9 +20,3 @@ data class LoggedInState( val localNetworkPermissionDialog: LocalNetworkPermissionDialog, val eventSink: (LoggedInEvents) -> Unit, ) - -enum class LocalNetworkPermissionDialog { - None, - Rationale, - Settings, -} diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt index afe09ec78b..67fcb95c2c 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInStateProvider.kt @@ -10,6 +10,7 @@ package io.element.android.appnav.loggedin import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialog import io.element.android.libraries.push.api.PusherRegistrationFailure open class LoggedInStateProvider : PreviewParameterProvider { diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt index 198a731e49..e57d378da4 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt @@ -19,13 +19,13 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.lifecycle.Lifecycle import io.element.android.appnav.R import io.element.android.libraries.architecture.AsyncData -import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialogWithDoNotShowAgain import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.utils.OnLifecycleEvent import io.element.android.libraries.matrix.api.exception.isNetworkError +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialogView import io.element.android.libraries.push.api.PusherRegistrationFailure import io.element.android.libraries.ui.strings.CommonStrings @@ -84,38 +84,11 @@ fun LoggedInView( ) } - LocalNetworkPermissionDialog(state = state) -} - -@Composable -private fun LocalNetworkPermissionDialog(state: LoggedInState) { - when (state.localNetworkPermissionDialog) { - LocalNetworkPermissionDialog.None -> Unit - LocalNetworkPermissionDialog.Rationale -> ConfirmationDialog( - title = stringResource(CommonStrings.screen_local_network_opt_in_title), - content = stringResource(CommonStrings.screen_local_network_opt_in_subtitle), - submitText = stringResource(CommonStrings.dialog_allow_access), - cancelText = stringResource(CommonStrings.action_not_now), - onSubmitClick = { - state.eventSink(LoggedInEvents.RequestLocationNetworkPermission) - }, - onDismiss = { - state.eventSink(LoggedInEvents.DismissLocalNetworkPermissionPrompt) - }, - ) - LocalNetworkPermissionDialog.Settings -> ConfirmationDialog( - title = stringResource(CommonStrings.screen_local_network_opt_in_title), - content = stringResource(CommonStrings.screen_local_network_opt_in_subtitle), - submitText = stringResource(CommonStrings.action_open_settings), - cancelText = stringResource(CommonStrings.action_not_now), - onSubmitClick = { - state.eventSink(LoggedInEvents.RequestLocationNetworkPermission) - }, - onDismiss = { - state.eventSink(LoggedInEvents.DismissLocalNetworkPermissionPrompt) - }, - ) - } + LocalNetworkPermissionDialogView( + dialog = state.localNetworkPermissionDialog, + onSubmit = { state.eventSink(LoggedInEvents.RequestLocationNetworkPermission) }, + onDismiss = { state.eventSink(LoggedInEvents.DismissLocalNetworkPermissionPrompt) }, + ) } private fun Throwable.getReason(): String? { diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerState.kt index a3467b21ba..6d8ce25d75 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerState.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerState.kt @@ -8,8 +8,8 @@ package io.element.android.features.login.impl.changeserver -import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialog import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialog data class ChangeServerState( val changeServerAction: AsyncData, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerStateProvider.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerStateProvider.kt index 693bca34bd..183158bceb 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerStateProvider.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerStateProvider.kt @@ -10,8 +10,8 @@ package io.element.android.features.login.impl.changeserver import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.login.impl.error.ChangeServerError -import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialog import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialog open class ChangeServerStateProvider : PreviewParameterProvider { override val values: Sequence diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt index 15b987ce16..30ae644a70 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt @@ -19,7 +19,6 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import io.element.android.features.login.impl.R import io.element.android.features.login.impl.dialogs.SlidingSyncNotSupportedDialog import io.element.android.features.login.impl.error.ChangeServerError -import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialogView import io.element.android.libraries.androidutils.system.openGooglePlay import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.ProgressDialog @@ -28,6 +27,7 @@ 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.LocalBuildMeta +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialogView import io.element.android.libraries.ui.strings.CommonStrings @Composable diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionDialogView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionDialogView.kt deleted file mode 100644 index 216b84fb11..0000000000 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionDialogView.kt +++ /dev/null @@ -1,44 +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.localnetwork - -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog -import io.element.android.libraries.ui.strings.CommonStrings - -@Composable -fun LocalNetworkPermissionDialogView( - dialog: LocalNetworkPermissionDialog, - onSubmit: () -> Unit, - onDismiss: () -> Unit, - modifier: Modifier = Modifier, -) { - when (dialog) { - LocalNetworkPermissionDialog.None -> Unit - LocalNetworkPermissionDialog.Rationale -> ConfirmationDialog( - title = stringResource(CommonStrings.screen_local_network_opt_in_title), - content = stringResource(CommonStrings.screen_local_network_opt_in_subtitle), - submitText = stringResource(CommonStrings.dialog_allow_access), - cancelText = stringResource(CommonStrings.action_not_now), - onSubmitClick = onSubmit, - onDismiss = onDismiss, - modifier = modifier, - ) - LocalNetworkPermissionDialog.Settings -> ConfirmationDialog( - title = stringResource(CommonStrings.screen_local_network_opt_in_title), - content = stringResource(CommonStrings.screen_local_network_opt_in_subtitle), - submitText = stringResource(CommonStrings.action_open_settings), - cancelText = stringResource(CommonStrings.action_not_now), - onSubmitClick = onSubmit, - onDismiss = onDismiss, - modifier = modifier, - ) - } -} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGate.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGate.kt index 857a8f9287..37a97e71dd 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGate.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGate.kt @@ -17,9 +17,10 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue import dev.zacsweers.metro.Inject -import io.element.android.libraries.permissions.api.LocalNetworkPermissionAdvisor import io.element.android.libraries.permissions.api.PermissionsEvent import io.element.android.libraries.permissions.api.PermissionsPresenter +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionAdvisor +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialog import kotlinx.coroutines.launch @Inject @@ -39,13 +40,13 @@ class LocalNetworkPermissionGate( val permissionsState = permissionsPresenter.present() var pendingSubmit by remember { mutableStateOf(null) } - val urlOf by rememberUpdatedState(urlOf) - val onProceed by rememberUpdatedState(onProceed) + val latestUrlOf by rememberUpdatedState(urlOf) + val latestOnProceed by rememberUpdatedState(onProceed) LaunchedEffect(permissionsState.permissionGranted, pendingSubmit) { val pending = pendingSubmit if (pending != null && permissionsState.permissionGranted) { - coroutineScope.launch { onProceed(pending) } + coroutineScope.launch { latestOnProceed(pending) } pendingSubmit = null } } @@ -61,10 +62,10 @@ class LocalNetworkPermissionGate( fun submit(value: T) { coroutineScope.launch { - if (advisor.shouldRequestPermissionFor(urlOf(value))) { + if (advisor.shouldRequestPermissionFor(latestUrlOf(value))) { pendingSubmit = value } else { - onProceed(value) + latestOnProceed(value) } } } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGateState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGateState.kt index 3213a96cd8..f3ecee729e 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGateState.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/localnetwork/LocalNetworkPermissionGateState.kt @@ -7,21 +7,11 @@ package io.element.android.features.login.impl.localnetwork +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialog + data class LocalNetworkPermissionGateState( val dialog: LocalNetworkPermissionDialog, val submit: (T) -> Unit, val requestPermission: () -> Unit, val abort: () -> Unit, ) - -/** - * Which rationale dialog (if any) should be rendered on top of the caller's UI. - * - * [Rationale] is shown before the runtime prompt so the user knows why the permission is needed. - * [Settings] is shown when the OS says a rationale can no longer be shown (permanently denied). - */ -enum class LocalNetworkPermissionDialog { - None, - Rationale, - Settings, -} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModePresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModePresenter.kt index 43c03bfbe3..34188095b0 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModePresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModePresenter.kt @@ -15,7 +15,11 @@ import androidx.compose.runtime.remember import dev.zacsweers.metro.Inject import io.element.android.features.login.impl.error.ChangeServerError import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionGate +import io.element.android.features.login.impl.screens.chooseaccountprovider.ChooseAccountProviderPresenter +import io.element.android.features.login.impl.screens.classic.loginwithclassic.LoginWithClassicPresenter +import io.element.android.features.login.impl.screens.confirmaccountprovider.ConfirmAccountProviderPresenter import io.element.android.features.login.impl.screens.createaccount.AccountCreationNotSupported +import io.element.android.features.login.impl.screens.onboarding.OnBoardingPresenter import io.element.android.features.login.impl.web.WebClientUrlForAuthenticationRetriever import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter @@ -25,6 +29,12 @@ 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 +/** + * Presenter responsible for managing the login flow, including handling OAuth actions and + * submitting login requests. + * It's a helper to avoid code duplication. It is used by [OnBoardingPresenter], [ConfirmAccountProviderPresenter], + * [ChooseAccountProviderPresenter] and [LoginWithClassicPresenter]. + */ @Inject class LoginModePresenter( private val oAuthActionFlow: OAuthActionFlow, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeState.kt index 3ca3a42a5d..849ff31f85 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeState.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeState.kt @@ -7,9 +7,9 @@ package io.element.android.features.login.impl.login -import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialog import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.auth.OAuthDetails +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialog data class LoginModeState( val loginMode: AsyncData, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeStateProvider.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeStateProvider.kt index a0adc327fe..1d33a1c48a 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeStateProvider.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeStateProvider.kt @@ -7,8 +7,8 @@ package io.element.android.features.login.impl.login -import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialog import io.element.android.libraries.architecture.AsyncData +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialog fun aLoginModeState( loginMode: AsyncData = AsyncData.Uninitialized, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/HomeserverResolver.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/HomeserverResolver.kt index b6eb26c87f..8c6cab79ce 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/HomeserverResolver.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/HomeserverResolver.kt @@ -14,7 +14,7 @@ import io.element.android.libraries.core.coroutine.parallelMap import io.element.android.libraries.core.uri.ensureProtocol import io.element.android.libraries.core.uri.isValidUrl import io.element.android.libraries.matrix.api.auth.HomeServerLoginCompatibilityChecker -import io.element.android.libraries.permissions.api.LocalNetworkPermissionAdvisor +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionAdvisor import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow @@ -44,21 +44,14 @@ class HomeserverResolver( // Skip the compatibility probe if we'd need ACCESS_LOCAL_NETWORK first — // otherwise the probe hangs on the TCP timeout for ~30s. Emit the URL as a // candidate directly; the actual sign-in flow triggers the permission prompt. - if (localNetworkPermissionAdvisor.shouldRequestPermissionFor(url)) { - currentList.add(HomeserverData(homeserverUrl = url)) - withContext(flowContext) { - emit(currentList.toList()) - } - return@parallelMap - } - - val isValid = homeServerLoginCompatibilityChecker.check(url) - .onFailure { Timber.w(it, "Failed to check compatibility with homeserver $url") } - .getOrNull() - ?: return@parallelMap + val shouldRequestPermissionOrIsValid = localNetworkPermissionAdvisor.shouldRequestPermissionFor(url) || + homeServerLoginCompatibilityChecker.check(url) + .onFailure { Timber.w(it, "Failed to check compatibility with homeserver $url") } + .getOrNull() + ?: return@parallelMap // Emit the list as soon as possible - if (isValid) { + if (shouldRequestPermissionOrIsValid) { currentList.add(HomeserverData(homeserverUrl = url)) withContext(flowContext) { emit(currentList.toList()) 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 be37775965..17e7d10efb 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 @@ -33,7 +33,6 @@ import androidx.compose.ui.unit.dp import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.login.impl.R import io.element.android.features.login.impl.accountprovider.AccountProviderView -import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialogView import io.element.android.features.login.impl.login.LoginModeEvent import io.element.android.features.login.impl.login.LoginModeView import io.element.android.libraries.architecture.AsyncData @@ -46,6 +45,7 @@ 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.OAuthDetails +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialogView import io.element.android.libraries.ui.strings.CommonStrings @Composable 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 389d07ea1a..75181a068e 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 @@ -35,7 +35,6 @@ 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.login.impl.R -import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialogView import io.element.android.features.login.impl.login.LoginModeEvent import io.element.android.features.login.impl.login.LoginModeView import io.element.android.libraries.architecture.AsyncData @@ -52,6 +51,7 @@ 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.OAuthDetails +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialogView import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings 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 3db0748a04..95fbff25ab 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 @@ -20,7 +20,6 @@ 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.login.impl.R -import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialogView import io.element.android.features.login.impl.login.LoginModeEvent import io.element.android.features.login.impl.login.LoginModeView import io.element.android.libraries.architecture.AsyncData @@ -33,6 +32,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.TextButton import io.element.android.libraries.matrix.api.auth.OAuthDetails +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialogView import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings 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 74fdbffab1..be86bbee9c 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 @@ -33,7 +33,6 @@ 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.login.impl.R -import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialogView import io.element.android.features.login.impl.login.LoginModeEvent import io.element.android.features.login.impl.login.LoginModeView import io.element.android.libraries.architecture.AsyncData @@ -52,6 +51,7 @@ 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.OAuthDetails +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialogView import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings 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 02ee9d5042..5d9040adac 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 @@ -15,7 +15,6 @@ import io.element.android.features.login.impl.accesscontrol.DefaultAccountProvid import io.element.android.features.login.impl.accountprovider.AccountProvider import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.features.login.impl.error.ChangeServerError -import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionDialog import io.element.android.features.login.impl.localnetwork.LocalNetworkPermissionGate import io.element.android.features.wellknown.test.FakeWellknownRetriever import io.element.android.features.wellknown.test.anElementWellKnown @@ -25,6 +24,7 @@ import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.A_HOMESERVER_URL import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService import io.element.android.libraries.matrix.test.auth.aMatrixHomeServerDetails +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialog import io.element.android.libraries.permissions.test.FakeLocalNetworkPermissionAdvisor import io.element.android.libraries.permissions.test.FakePermissionsPresenter import io.element.android.libraries.permissions.test.FakePermissionsPresenterFactory 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 56ccc230b0..79268aa1e4 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 @@ -34,6 +34,7 @@ import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationSer import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.oauth.api.OAuthActionFlow import io.element.android.libraries.oauth.test.customtab.FakeOAuthActionFlow +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionAdvisor import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.test.InMemorySessionStore import io.element.android.libraries.sessionstorage.test.aSessionData @@ -316,7 +317,7 @@ fun createLoginModePresenter( oAuthActionFlow: OAuthActionFlow = FakeOAuthActionFlow(), authenticationService: MatrixAuthenticationService = FakeMatrixAuthenticationService(), webClientUrlForAuthenticationRetriever: WebClientUrlForAuthenticationRetriever = FakeWebClientUrlForAuthenticationRetriever(), - localNetworkPermissionAdvisor: io.element.android.libraries.permissions.api.LocalNetworkPermissionAdvisor = + localNetworkPermissionAdvisor: LocalNetworkPermissionAdvisor = io.element.android.libraries.permissions.test.FakeLocalNetworkPermissionAdvisor(), permissionsPresenterFactory: io.element.android.libraries.permissions.api.PermissionsPresenter.Factory = io.element.android.libraries.permissions.test.FakePermissionsPresenterFactory(), diff --git a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/LocalNetworkPermissionAdvisor.kt b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionAdvisor.kt similarity index 87% rename from libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/LocalNetworkPermissionAdvisor.kt rename to libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionAdvisor.kt index 7ed46a63e1..9863dbb751 100644 --- a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/LocalNetworkPermissionAdvisor.kt +++ b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionAdvisor.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.permissions.api +package io.element.android.libraries.permissions.api.localnetwork interface LocalNetworkPermissionAdvisor { /** diff --git a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialog.kt b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialog.kt new file mode 100644 index 0000000000..68a440680f --- /dev/null +++ b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialog.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.permissions.api.localnetwork + +/** + * Which rationale dialog (if any) should be rendered on top of the caller's UI. + * + * [Rationale] is shown before the runtime prompt so the user knows why the permission is needed. + * [Settings] is shown when the OS says a rationale can no longer be shown (permanently denied). + */ +enum class LocalNetworkPermissionDialog { + None, + Rationale, + Settings, +} diff --git a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialogView.kt b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialogView.kt new file mode 100644 index 0000000000..d2337fdf5b --- /dev/null +++ b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialogView.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.permissions.api.localnetwork + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun LocalNetworkPermissionDialogView( + dialog: LocalNetworkPermissionDialog, + onSubmit: () -> Unit, + onDismiss: () -> Unit, + modifier: Modifier = Modifier, +) { + val submitTextRes = when (dialog) { + LocalNetworkPermissionDialog.None -> return + LocalNetworkPermissionDialog.Rationale -> CommonStrings.dialog_allow_access + LocalNetworkPermissionDialog.Settings -> CommonStrings.action_open_settings + } + ConfirmationDialog( + title = stringResource(CommonStrings.screen_local_network_opt_in_title), + content = stringResource(CommonStrings.screen_local_network_opt_in_subtitle), + submitText = stringResource(submitTextRes), + cancelText = stringResource(CommonStrings.action_not_now), + onSubmitClick = onSubmit, + onDismiss = onDismiss, + modifier = modifier, + ) +} diff --git a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultLocalNetworkPermissionAdvisor.kt b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/localnetwork/DefaultLocalNetworkPermissionAdvisor.kt similarity index 83% rename from libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultLocalNetworkPermissionAdvisor.kt rename to libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/localnetwork/DefaultLocalNetworkPermissionAdvisor.kt index a34ece0859..a1f4022c3c 100644 --- a/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/DefaultLocalNetworkPermissionAdvisor.kt +++ b/libraries/permissions/impl/src/main/kotlin/io/element/android/libraries/permissions/impl/localnetwork/DefaultLocalNetworkPermissionAdvisor.kt @@ -5,16 +5,16 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.permissions.impl +package io.element.android.libraries.permissions.impl.localnetwork -import android.Manifest.permission.ACCESS_LOCAL_NETWORK +import android.Manifest import android.os.Build import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import io.element.android.libraries.androidutils.network.LocalNetworkAddressClassifier import io.element.android.libraries.androidutils.network.LocalNetworkClassification -import io.element.android.libraries.permissions.api.LocalNetworkPermissionAdvisor import io.element.android.libraries.permissions.api.PermissionStateProvider +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionAdvisor import io.element.android.services.toolbox.api.sdk.BuildVersionSdkIntProvider @ContributesBinding(AppScope::class) @@ -25,7 +25,7 @@ class DefaultLocalNetworkPermissionAdvisor( ) : LocalNetworkPermissionAdvisor { override suspend fun shouldRequestPermissionFor(homeserverUrl: String): Boolean { if (!buildVersionSdkIntProvider.isAtLeast(Build.VERSION_CODES.CINNAMON_BUN)) return false - if (permissionStateProvider.isPermissionGranted(ACCESS_LOCAL_NETWORK)) return false + if (permissionStateProvider.isPermissionGranted(Manifest.permission.ACCESS_LOCAL_NETWORK)) return false return when (classifier.classify(homeserverUrl)) { LocalNetworkClassification.LocalIp -> true LocalNetworkClassification.PublicIp, diff --git a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultLocalNetworkPermissionAdvisorTest.kt b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/localnetwork/DefaultLocalNetworkPermissionAdvisorTest.kt similarity index 98% rename from libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultLocalNetworkPermissionAdvisorTest.kt rename to libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/localnetwork/DefaultLocalNetworkPermissionAdvisorTest.kt index 2ed1dd7548..1609ee1f20 100644 --- a/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/DefaultLocalNetworkPermissionAdvisorTest.kt +++ b/libraries/permissions/impl/src/test/kotlin/io/element/android/libraries/permissions/impl/localnetwork/DefaultLocalNetworkPermissionAdvisorTest.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.permissions.impl +package io.element.android.libraries.permissions.impl.localnetwork import com.google.common.truth.Truth.assertThat import io.element.android.libraries.androidutils.network.LocalNetworkAddressClassifier diff --git a/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakeLocalNetworkPermissionAdvisor.kt b/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakeLocalNetworkPermissionAdvisor.kt index 1a3363d6dc..f16872441c 100644 --- a/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakeLocalNetworkPermissionAdvisor.kt +++ b/libraries/permissions/test/src/main/kotlin/io/element/android/libraries/permissions/test/FakeLocalNetworkPermissionAdvisor.kt @@ -7,7 +7,7 @@ package io.element.android.libraries.permissions.test -import io.element.android.libraries.permissions.api.LocalNetworkPermissionAdvisor +import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionAdvisor class FakeLocalNetworkPermissionAdvisor( private val shouldPrompt: Boolean = false, From 330dd243e2c5ff6e546a2bdbcb2dd55088f1853c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Jul 2026 15:52:03 +0000 Subject: [PATCH 088/383] Update dependency org.jetbrains.kotlinx:kotlinx-collections-immutable to v0.5.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 4db11a279e..d86e0e0fcf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -196,7 +196,7 @@ coil_svg = { module = "io.coil-kt.coil3:coil-svg", version.ref = "coil" } coil_test = { module = "io.coil-kt.coil3:coil-test", version.ref = "coil" } datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "datetime" } serialization_json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization_json" } -kotlinx_collections_immutable = "org.jetbrains.kotlinx:kotlinx-collections-immutable:0.5.0" +kotlinx_collections_immutable = "org.jetbrains.kotlinx:kotlinx-collections-immutable:0.5.1" 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.22.2" From 3ad0ca797412efa2b5f37b46ff56ba97eabce146 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 10 Jul 2026 07:46:06 +0000 Subject: [PATCH 089/383] Update screenshots --- ....components.customreaction_EmojiItemWithPopup_Day_0_en.png | 4 ++-- ...omponents.customreaction_EmojiItemWithPopup_Night_0_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_5_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_6_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_5_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_6_en.png | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png index 912b90b537..a2b35f18ca 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4746d11c30648f7c517b0880021e5a1dc6ed2819af6c800b081b0d842ac2c384 -size 5325 +oid sha256:c5572491b675a16724cd9e33ebb477c82edf285fa07d57ebef09c670fcaaddf1 +size 21285 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png index 45011fea4d..9c425cec6e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eede6f990a7a1dbddee1cd9e722b30600160d475ad2ae72faebcb773f52aaa7b -size 20793 +oid sha256:290a2be6838445739b0181006f9fea87337a85cfed3573c153e9f503c66624a6 +size 4994 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png index 1f73455d54..7ef9b7ae0a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5dc5c492ed3fd552e77c0be85b639d55bc7e976f15b761f927b0b80ecca601d -size 12115 +oid sha256:d19e7a09114e76294a0626e5d617cf55fe7c13a0188a7d5b364f57c0d9daedc1 +size 12123 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png index 0ca6f66438..3e18858873 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5896eb5df6f5398bdb94e74280d0d5c04b6a5a53c2378b7377c60fa58eef544b -size 12013 +oid sha256:42f03759fcffbb750181168256130b6a94a1fcf91ee028e69a19a6e3b68ed0e8 +size 11711 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index a687241151..1e04c3e7d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e7ce8a8c6b4d1692e4b127b7f17f507552666c631893025082c385b93d835a73 -size 11726 +oid sha256:6bbc8c05e6f6818d00282228f52424ebe93e6e3dca3431d742e8c652d56460d6 +size 11712 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png index a1d1c5ec8e..8e1b9c99d2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b93c08531efbeacb55f84b17ac793a7b226e5a2db7bc5072e94bc040cd1e9bc -size 11386 +oid sha256:66f6d0d6b03ee4c999cd4edc9c6ae567d31b8b537ca6f9cc8fbe436d06ce80ab +size 11643 From a2f1e9eeec91aaeb5626a43ef0bbd5b2a6f416ae Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 10 Jul 2026 11:53:52 +0200 Subject: [PATCH 090/383] Use better ButtonDefaults method. It should not change anything since we are providing the 4 parameters --- .../libraries/designsystem/theme/components/Button.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt index db0aa39002..000ad1e470 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt @@ -294,7 +294,7 @@ internal enum class ButtonStyle { @Composable fun getColors(destructive: Boolean): ButtonColors = when (this) { - Filled -> ButtonDefaults.buttonColors( + Filled -> ButtonDefaults.filledTonalButtonColors( containerColor = getPrimaryColor(destructive), contentColor = ElementTheme.materialColors.onPrimary, disabledContainerColor = if (destructive) { @@ -304,13 +304,13 @@ internal enum class ButtonStyle { }, disabledContentColor = ElementTheme.colors.textOnSolidPrimary ) - Outlined -> ButtonDefaults.buttonColors( + Outlined -> ButtonDefaults.outlinedButtonColors( containerColor = Color.Transparent, contentColor = getPrimaryColor(destructive), disabledContainerColor = Color.Transparent, disabledContentColor = getDisabledContentColor(destructive), ) - Text -> ButtonDefaults.buttonColors( + Text -> ButtonDefaults.textButtonColors( containerColor = Color.Transparent, contentColor = if (destructive) { ElementTheme.colors.textCriticalPrimary From 8c935d8682896a4237e9121fd7973b8d37356464 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 10 Jul 2026 12:14:55 +0200 Subject: [PATCH 091/383] Improve focus rendering: now display a blue inset ring around the focused component. Closes #6397 --- .../android/compound/theme/ElementTheme.kt | 24 ++++ .../designsystem/theme/components/Button.kt | 107 ++++++++++-------- .../theme/components/SearchField.kt | 2 +- .../theme/components/TextField.kt | 2 +- 4 files changed, 88 insertions(+), 47 deletions(-) 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 ac83365658..d927ba8836 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 @@ -16,7 +16,11 @@ import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.ColorScheme import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.LocalRippleConfiguration +import androidx.compose.material3.LocalRippleThemeConfiguration import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.RippleConfiguration +import androidx.compose.material3.RippleThemeConfiguration import androidx.compose.material3.Typography import androidx.compose.material3.dynamicDarkColorScheme import androidx.compose.material3.dynamicLightColorScheme @@ -28,6 +32,7 @@ import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp import io.element.android.compound.tokens.compoundTypography import io.element.android.compound.tokens.generated.SemanticColors import io.element.android.compound.tokens.generated.TypographyTokens @@ -159,6 +164,25 @@ fun ElementTheme( CompositionLocalProvider( LocalCompoundColors provides currentCompoundColor, LocalContentColor provides colorScheme.onSurface, + // Configure the keyboard focus style: Draw a blue inset ring around the focused component. + // By default, a semi-transparent black overlay is used + LocalRippleThemeConfiguration provides RippleThemeConfiguration( + RippleThemeConfiguration.Focus.InsetRing( + outerStrokeInset = 0.dp, + outerStrokeWidth = 2.dp, + innerStrokeInset = 0.dp, + innerStrokeWidth = 0.dp, + ) + ), + // Configure the keyboard focus color. + // By default, ColorScheme.secondaryColor is used + LocalRippleConfiguration provides + RippleConfiguration( + focus = RippleConfiguration.Focus.InsetRing( + outerStrokeColor = ElementTheme.colors.borderFocused, + innerStrokeColor = Color.Transparent, + ) + ), ) { MaterialTheme( colorScheme = colorScheme, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt index 000ad1e470..299744cebf 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt @@ -28,13 +28,15 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ButtonColors import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.LocalRippleThemeConfiguration +import androidx.compose.material3.RippleThemeConfiguration import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.Immutable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.isSpecified import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.vector.ImageVector @@ -181,11 +183,8 @@ private fun ButtonInternal( ButtonSize.LargeLowPadding -> PaddingValues(horizontal = lowHorizontalPaddingValue, vertical = 13.dp) } - val shape = when (style) { - ButtonStyle.Filled, - ButtonStyle.Outlined -> RoundedCornerShape(percent = 50) - ButtonStyle.Text -> RectangleShape - } + // Apply the same shape to all buttons, so that the focus ring is consistent across styles. + val shape = RoundedCornerShape(percent = 50) val border = when (style) { ButtonStyle.Filled -> null @@ -202,48 +201,66 @@ private fun ButtonInternal( ButtonStyle.Text -> null } - androidx.compose.material3.Button( - onClick = { - if (!showProgress) { - onClick() - } - }, - modifier = modifier.heightIn(min = minHeight), - enabled = enabled, - shape = shape, - colors = colors, - elevation = null, - border = border, - contentPadding = contentPadding, - interactionSource = remember { MutableInteractionSource() }, + // Reduce outerStrokeInset on Filled buttons so that it's displayed around the button + val outerStrokeInset = when (style) { + ButtonStyle.Filled -> (-4).dp + ButtonStyle.Outlined, + ButtonStyle.Text -> 0.dp + } + + CompositionLocalProvider( + LocalRippleThemeConfiguration provides RippleThemeConfiguration( + RippleThemeConfiguration.Focus.InsetRing( + outerStrokeInset = outerStrokeInset, + outerStrokeWidth = 2.dp, + innerStrokeInset = 0.dp, + innerStrokeWidth = 0.dp, + ) + ), ) { - when { - showProgress -> { - CircularProgressIndicator( - modifier = Modifier - .progressSemantics() - .size(20.dp), - color = LocalContentColor.current, - strokeWidth = 2.dp, - ) - Spacer(modifier = Modifier.width(8.dp)) - } - leadingIcon != null -> { - Icon( - painter = leadingIcon.getPainter(), - contentDescription = null, - tint = LocalContentColor.current, - modifier = Modifier.size(20.dp), - ) - Spacer(modifier = Modifier.width(8.dp)) + androidx.compose.material3.Button( + onClick = { + if (!showProgress) { + onClick() + } + }, + modifier = modifier.heightIn(min = minHeight), + enabled = enabled, + shape = shape, + colors = colors, + elevation = null, + border = border, + contentPadding = contentPadding, + interactionSource = remember { MutableInteractionSource() }, + ) { + when { + showProgress -> { + CircularProgressIndicator( + modifier = Modifier + .progressSemantics() + .size(20.dp), + color = LocalContentColor.current, + strokeWidth = 2.dp, + ) + Spacer(modifier = Modifier.width(8.dp)) + } + leadingIcon != null -> { + Icon( + painter = leadingIcon.getPainter(), + contentDescription = null, + tint = LocalContentColor.current, + modifier = Modifier.size(20.dp), + ) + Spacer(modifier = Modifier.width(8.dp)) + } } + Text( + text = text, + style = ElementTheme.typography.fontBodyLgMedium, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) } - Text( - text = text, - style = ElementTheme.typography.fontBodyLgMedium, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/SearchField.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/SearchField.kt index d677a89577..8b318ecf4a 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/SearchField.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/SearchField.kt @@ -139,7 +139,7 @@ private fun SearchFieldContainer( border = BorderStroke( width = 1.dp, color = if (isFocused) { - ElementTheme.colors.borderInteractiveHovered + ElementTheme.colors.borderFocused } else { ElementTheme.colors.borderInteractiveSecondary } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/TextField.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/TextField.kt index d4e08eacf1..36d0255b08 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/TextField.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/TextField.kt @@ -293,8 +293,8 @@ private fun TextFieldContainer( width = if (isFocused) 2.dp else 1.dp, color = when { !enabled -> ElementTheme.colors.borderDisabled + isFocused -> ElementTheme.colors.borderFocused isError -> ElementTheme.colors.borderCriticalPrimary - isFocused -> ElementTheme.colors.borderInteractiveHovered else -> ElementTheme.colors.borderInteractiveSecondary } ) From e41c806dd49bf27db3ed0002181d21b560f9cabf Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 10 Jul 2026 12:22:42 +0200 Subject: [PATCH 092/383] Add Figma link --- .../kotlin/io/element/android/compound/theme/ElementTheme.kt | 1 + 1 file changed, 1 insertion(+) 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 d927ba8836..e0dd0f8cdd 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 @@ -165,6 +165,7 @@ fun ElementTheme( LocalCompoundColors provides currentCompoundColor, LocalContentColor provides colorScheme.onSurface, // Configure the keyboard focus style: Draw a blue inset ring around the focused component. + // Ref: https://www.figma.com/design/hlbsmSekQorGRN1t2R9JEy/Accessibility-checks?node-id=271-42066 // By default, a semi-transparent black overlay is used LocalRippleThemeConfiguration provides RippleThemeConfiguration( RippleThemeConfiguration.Focus.InsetRing( From a8cbc7911e9236000e36e4f185c73bc0a9bab192 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 10 Jul 2026 12:24:45 +0200 Subject: [PATCH 093/383] Fix typo --- .../kotlin/io/element/android/compound/theme/ElementTheme.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e0dd0f8cdd..34cea4f856 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 @@ -176,7 +176,7 @@ fun ElementTheme( ) ), // Configure the keyboard focus color. - // By default, ColorScheme.secondaryColor is used + // By default, ColorScheme.secondary is used LocalRippleConfiguration provides RippleConfiguration( focus = RippleConfiguration.Focus.InsetRing( From ac0ad510c83cbf75010775febbde4830389c87d9 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 10 Jul 2026 12:44:51 +0200 Subject: [PATCH 094/383] Stop live location share on location tick when past expiry --- .../DefaultActiveLiveLocationShareManager.kt | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) 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 c24d3f9cc2..36744664cb 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 @@ -52,9 +52,11 @@ class DefaultActiveLiveLocationShareManager( private val clock: SystemClock, private val sessionObserver: SessionObserver, ) : ActiveLiveLocationShareManager, LiveLocationReceiver { + private data class Timeout(val expiresAt: Instant, val job: Job) + private val isSetup = AtomicBoolean(false) private val cachedRooms = ConcurrentHashMap() - private val timeoutJobs = ConcurrentHashMap() + private val timeouts = ConcurrentHashMap() private val syncedActiveShareIds = MutableStateFlow>(emptySet()) private val localSharingRoomIds = MutableStateFlow>(emptySet()) override val sharingRoomIds: StateFlow> = localSharingRoomIds @@ -139,9 +141,18 @@ class DefaultActiveLiveLocationShareManager( } override suspend fun onLocationUpdate(location: Location) { - val activeSharesCount = localSharingRoomIds.value.size + val nowMillis = clock.epochMillis() + val (expired, active) = localSharingRoomIds.value.partition { roomId -> + val timeout = timeouts[roomId] ?: return@partition false + timeout.expiresAt.toEpochMilliseconds() <= nowMillis + } + expired.forEach { roomId -> + Timber.d("ActiveLiveLocationShareManager location tick detected expired share for room $roomId, stopping") + stopShare(roomId) + } + val activeSharesCount = active.size Timber.d("ActiveLiveLocationShareManager received location update for $activeSharesCount active share(s)") - localSharingRoomIds.value.forEach { roomId -> + active.forEach { roomId -> Timber.d("ActiveLiveLocationShareManager sending location to room $roomId") sendLiveLocation(roomId, location) .onFailure { @@ -192,20 +203,21 @@ class DefaultActiveLiveLocationShareManager( } private fun scheduleTimeout(roomId: RoomId, expiresAt: Instant) { - timeoutJobs.remove(roomId)?.cancel() + timeouts.remove(roomId)?.job?.cancel() val delayMillis = expiresAt.toEpochMilliseconds() - clock.epochMillis() - timeoutJobs[roomId] = matrixClient.sessionCoroutineScope.launch { + val job = matrixClient.sessionCoroutineScope.launch { delay(delayMillis) stopShare(roomId) .onFailure { error -> Timber.e(error, "ActiveLiveLocationShareManager failed to stop timed out share for room $roomId") } } + timeouts[roomId] = Timeout(expiresAt = expiresAt, job = job) } private suspend fun stopLocalShare(roomId: RoomId) { Timber.d("ActiveLiveLocationShareManager stop local share in $roomId") - timeoutJobs.remove(roomId)?.cancel() + timeouts.remove(roomId)?.job?.cancel() val wasSharing = localSharingRoomIds.getAndUpdate { it - roomId }.isNotEmpty() cachedRooms.remove(roomId)?.close() liveLocationStore.removeLiveLocationExpiry(roomId) @@ -220,11 +232,11 @@ class DefaultActiveLiveLocationShareManager( sessionObserver.removeListener(sessionListener) coordinator.unregister(matrixClient.sessionId) liveLocationStore.clear() + timeouts.values.forEach { it.job.cancel() } + timeouts.clear() for (room in cachedRooms.values) { room.close() - timeoutJobs[room.roomId]?.cancel() } - timeoutJobs.clear() cachedRooms.clear() localSharingRoomIds.value = emptySet() syncedActiveShareIds.value = emptySet() From 9d76f0c9207873d5c197a3153260fea0ce835867 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 10 Jul 2026 12:46:26 +0200 Subject: [PATCH 095/383] Test location-tick stops live location share past expiry --- ...faultActiveLiveLocationShareManagerTest.kt | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) 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 index 85f0e1c33f..9c15424cad 100644 --- 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 @@ -373,6 +373,53 @@ class DefaultActiveLiveLocationShareManagerTest { } } + @Test + fun `location update after expiry stops the share and does not send location`() = runTest { + val liveLocationStore = createInMemoryLiveLocationStore() + val beaconInfoUpdates = MutableSharedFlow(replay = 1) + val stopLiveLocationShareResult = lambdaRecorder> { Result.success(Unit) } + val sendLiveLocationResult = lambdaRecorder> { _ -> Result.success(Unit) } + val clock = FakeSystemClock(epochMillisResult = 1_000L) + 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, + sendLiveLocationResult = sendLiveLocationResult, + ), + ) + }, + coordinator = createCoordinator(), + liveLocationStore = liveLocationStore, + clock = clock, + ) + 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() + + // Advance the clock past the expiry so the next location tick is beyond the deadline. + clock.epochMillisResult = 1_000L + 1.minutes.inWholeMilliseconds + 1_000L + + manager.sharingRoomIds.test { + assertThat(awaitItem()).containsExactly(A_ROOM_ID) + manager.onLocationUpdate(io.element.android.features.location.api.Location(lat = 0.0, lon = 0.0, accuracy = null)) + assertThat(awaitItem()).isEmpty() + advanceUntilIdle() + } + assertThat(liveLocationStore.getLiveLocationExpiries()).doesNotContainKey(A_ROOM_ID) + assert(sendLiveLocationResult).isNeverCalled() + // stopLiveLocationShare is called twice: once defensively in startShare, once from the tick-triggered stopShare. + assert(stopLiveLocationShareResult).isCalledExactly(2) + } + @Test fun `session deleted clears local state`() = runTest { val startServiceRecorder = lambdaRecorder { } From a7502a8fe19f70dbc9fe05d1ad243b92a91117f0 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 10 Jul 2026 12:23:53 +0000 Subject: [PATCH 096/383] Update screenshots --- ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png | 4 ++-- ...s.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png | 4 ++-- ...impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png | 4 ++-- ...impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_5_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_5_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_6_en.png | 4 ++-- .../images/features.space.impl.root_SpaceView_Day_4_en.png | 4 ++-- .../images/features.space.impl.root_SpaceView_Night_4_en.png | 4 ++-- ....theme.components_TextButtonLargeLowPadding_Buttons_en.png | 4 ++-- ...signsystem.theme.components_TextButtonLarge_Buttons_en.png | 4 ++-- ...theme.components_TextButtonMediumLowPadding_Buttons_en.png | 4 ++-- ...ignsystem.theme.components_TextButtonMedium_Buttons_en.png | 4 ++-- ...signsystem.theme.components_TextButtonSmall_Buttons_en.png | 4 ++-- ...raries.matrix.ui.components_SpaceRoomItemView_Day_1_en.png | 4 ++-- ...raries.matrix.ui.components_SpaceRoomItemView_Day_6_en.png | 4 ++-- ...ries.matrix.ui.components_SpaceRoomItemView_Night_1_en.png | 4 ++-- ...ries.matrix.ui.components_SpaceRoomItemView_Night_6_en.png | 2 +- 18 files changed, 35 insertions(+), 35 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png index 4f9bf2657a..08d14f0832 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:839c24d04f7008a3b33be3624c71f19f01554a78903cc5d8e5337ab90d0fc41b -size 8268 +oid sha256:76632bda4afa1bc900b1174fe68a09a3d757d6f3227b4f541e0198219875c90c +size 8275 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png index e34031a1df..85f179f48d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:032efe4da3ebda3dcc92a6027604822dabf6062073c4e556242e755adf38e717 -size 11803 +oid sha256:b40de4a02b67814007f201cea9383e8ab30f2b7b56fb1efcdd2348ee207f4815 +size 11814 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png index c0f07d1314..b3f7f2dcf8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a448f6810521acc7d85904ba71ee4a3153d2eeb2c40d132b889eda774e0a6fdf -size 7956 +oid sha256:04473b9423b916f25920837e07b2b22ba495daa5d4f2de4070b70d3dd571072c +size 7975 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png index b643773964..8f4a2e1437 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:effa92f7695f9643efeebf929db6fdac31bd608a449ab306511897e8b2197b82 -size 10939 +oid sha256:7cf8f0f420c2eb69bc6a56e9238fb720d6fada2c250ae7b2dbdb8f431dfd9668 +size 10944 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png index 1f73455d54..270dbe6d1e 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5dc5c492ed3fd552e77c0be85b639d55bc7e976f15b761f927b0b80ecca601d -size 12115 +oid sha256:195338046951366fd2345fdc8471e3e2b2786723c8bfffa9fa9057929c608afb +size 12113 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index a687241151..fb72cafe03 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e7ce8a8c6b4d1692e4b127b7f17f507552666c631893025082c385b93d835a73 -size 11726 +oid sha256:4ef1b643a16b5a94c75f8bb845c36d3cbc7f7ed96a0cac32fdb9f0b09d26b4d1 +size 11747 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png index a1d1c5ec8e..ce1258d2ac 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b93c08531efbeacb55f84b17ac793a7b226e5a2db7bc5072e94bc040cd1e9bc -size 11386 +oid sha256:ce754ce205fd864e01828659aff42ab19dccf7c921c1c733ed1757f1b2122309 +size 11403 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.root_SpaceView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.root_SpaceView_Day_4_en.png index 12d1c506ab..bc27628ac1 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.root_SpaceView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.root_SpaceView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:20742175a23c7116089cec7b9886ad567db50d899dd5dca4388534d6120d73ce -size 60252 +oid sha256:8f8ef2430abd11b31b3e90976f85bd4578e667bd0acc0851544ee4d16358479d +size 60237 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.root_SpaceView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.root_SpaceView_Night_4_en.png index 28ef695554..058f822302 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.root_SpaceView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.root_SpaceView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee1ee7ae5a0350ca808b1839d7f033cb83947d33305a5cb5ff9a9faa4a5dadbf -size 58345 +oid sha256:8265b9acc3932df6f0e1eee5e85c2b16d13060c4164c3fbb5b1b0b598745770c +size 58326 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonLargeLowPadding_Buttons_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonLargeLowPadding_Buttons_en.png index 2317914c61..f3f0242a24 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonLargeLowPadding_Buttons_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonLargeLowPadding_Buttons_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4b18fc1dffd0b62b81d9e9ec5de8588919e27b18af178bfba474771cafd9800 -size 42717 +oid sha256:37f8e05e435b8d531c72a180ff87183dcec2aa319473bc540e19c9fdd0e5346a +size 42673 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonLarge_Buttons_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonLarge_Buttons_en.png index c3d49d4149..fe4359f4bb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonLarge_Buttons_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonLarge_Buttons_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7813a6da740ee5a83c56ac4883b2905582482b6d5d17254b30b895a242f85b60 -size 42752 +oid sha256:ffe628766efb7b932c82749546d5c9a6dd271a4ffe2cf162dbc36796538fce12 +size 42723 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonMediumLowPadding_Buttons_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonMediumLowPadding_Buttons_en.png index 2317914c61..f3f0242a24 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonMediumLowPadding_Buttons_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonMediumLowPadding_Buttons_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4b18fc1dffd0b62b81d9e9ec5de8588919e27b18af178bfba474771cafd9800 -size 42717 +oid sha256:37f8e05e435b8d531c72a180ff87183dcec2aa319473bc540e19c9fdd0e5346a +size 42673 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonMedium_Buttons_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonMedium_Buttons_en.png index 9eacca6dce..c091d1d246 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonMedium_Buttons_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonMedium_Buttons_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c081116bbbb293635b599ae4d4d25505cf442a0feae7fbded69f7772fec7d96f -size 42850 +oid sha256:ff352e5d173cc05b74d4086e5412d467b378239fa7f75b3c17c11b7f024047c1 +size 42823 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonSmall_Buttons_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonSmall_Buttons_en.png index f42bc48690..75c2412758 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonSmall_Buttons_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_TextButtonSmall_Buttons_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fdfe5a8f3e42c503560f32835237ab0f340b0a82a9dea7945d6cf19ed1845c93 -size 42868 +oid sha256:8ce5baff8faa00bec873dd65a22415d9bdba0c69f68168fb893036684ce2b0dc +size 42882 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en.png index e132d78fea..12fc229a83 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:928165a963ba3dadd278c8fee183fb5d6398b28369f28f782c9f08dbc69df52c -size 14235 +oid sha256:ad303cbc4984982a5d3e6fe341c611483d76a3cd4bf15705864c5c20443f9b4d +size 14226 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en.png index e0fc1fbcd1..7983b2870c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5ca516e5f7bc8a2231b5fa7535a80b03eb6ff44b2d83e66163b010a1802fa7e -size 32464 +oid sha256:ccc9c9c95b9a56bb6c453aea4b13be812b64ad5b7352f169a32208166ff70b9f +size 32449 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en.png index 6241a64e5a..e427a47553 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97e41908816ae4f32eeb85f00125dcd7eb28810d9157441f535a228de3ff31bd -size 13774 +oid sha256:70193284306460b8f9c333849c8d5e1b5b1e95c3ce446307ccff482c90c2d09a +size 13775 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en.png index 9d3c84eb6a..90d6923e20 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5cd30c16ff85d4140d25b738916948bf4180b49341b650886a318080c8697fd6 +oid sha256:0284751ecc89b295784fab1eb4a85e4615015ef915c9492a59ad8671f2805806 size 31606 From 754eb3d0c17689b245d55f9f5311a07461d9b882 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 10 Jul 2026 15:13:36 +0200 Subject: [PATCH 097/383] Improve code and use type Video when necessary --- .../ui/messages/reply/InReplyToMetadata.kt | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadata.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadata.kt index 2da5184389..3e3f46ffb5 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadata.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadata.kt @@ -111,13 +111,12 @@ internal fun InReplyToDetails.Ready.metadata(hideImage: Boolean): InReplyToMetad is GalleryMessageType -> { val caption = textContent?.takeIf { it.isNotBlank() } val isMediaGallery = type.items.all { it is GalleryItemType.Image || it is GalleryItemType.Video } - val countPlural = if (isMediaGallery) { - CommonPlurals.common_gallery_reply_media_items - } else { - CommonPlurals.common_gallery_reply_attachments - } - val text = caption ?: pluralStringResource(countPlural, type.items.size, type.items.size) if (isMediaGallery) { + val text = caption ?: pluralStringResource( + CommonPlurals.common_gallery_reply_media_items, + type.items.size, + type.items.size, + ) val firstMediaItem = type.items.firstOrNull { it is GalleryItemType.Image || it is GalleryItemType.Video } val thumbnailSource = when (firstMediaItem) { is GalleryItemType.Image -> (firstMediaItem.content.info?.thumbnailSource ?: firstMediaItem.content.source).takeUnless { hideImage } @@ -129,15 +128,24 @@ internal fun InReplyToDetails.Ready.metadata(hideImage: Boolean): InReplyToMetad is GalleryItemType.Video -> firstMediaItem.content.info?.blurhash else -> null } + val type = when (firstMediaItem) { + is GalleryItemType.Video -> AttachmentThumbnailType.Video + else -> AttachmentThumbnailType.Image + } Thumbnail( AttachmentThumbnailInfo( thumbnailSource = thumbnailSource, textContent = text, - type = AttachmentThumbnailType.Image, + type = type, blurHash = blurHash, ) ) } else { + val text = caption ?: pluralStringResource( + CommonPlurals.common_gallery_reply_attachments, + type.items.size, + type.items.size, + ) Thumbnail( AttachmentThumbnailInfo( textContent = text, From 7f13bb95cc5227971049667748a8735ed339e8e3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 10 Jul 2026 15:16:38 +0200 Subject: [PATCH 098/383] Ignore large test class. --- .../matrix/ui/messages/reply/InReplyToMetadataKtTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadataKtTest.kt b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadataKtTest.kt index 5b6df661f3..3fcb2f8f18 100644 --- a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadataKtTest.kt +++ b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToMetadataKtTest.kt @@ -54,6 +54,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Test import kotlin.time.Duration.Companion.minutes +@Suppress("LargeClass") class InReplyToMetadataKtTest : RobolectricTest() { @Test fun `any message content`() = runTest { From 07ea371806e980eb3bbedf522f658f39a45b05bf Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 10 Jul 2026 15:24:14 +0200 Subject: [PATCH 099/383] Move strings to Localazy --- libraries/ui-strings/src/main/res/values/localazy.xml | 8 ++++++++ libraries/ui-strings/src/main/res/values/temporary.xml | 6 ------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 82acfd14b3..b032c41d4b 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -268,6 +268,14 @@ Reason: %1$s." "Forward message" "Frequently used" "Gallery" + + "%1$d attachment…" + "%1$d attachments…" + + + "%1$d media item…" + "%1$d media items…" + "GIF" "Group call in progress" "Image" diff --git a/libraries/ui-strings/src/main/res/values/temporary.xml b/libraries/ui-strings/src/main/res/values/temporary.xml index 47d2007517..fd1edb0759 100644 --- a/libraries/ui-strings/src/main/res/values/temporary.xml +++ b/libraries/ui-strings/src/main/res/values/temporary.xml @@ -8,10 +8,4 @@ "Mark as read" "Jump to first unread message" - - "%1$d media items…" - - - "%1$d attachments…" - From e42f974c00113cadf83361408a16ad8f48e1f14c Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 10 Jul 2026 14:43:36 +0000 Subject: [PATCH 100/383] Update screenshots --- ...es.preferences.impl.userstatus_UserStatusView_Day_5_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_6_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_5_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_6_en.png | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png index 270dbe6d1e..7ef9b7ae0a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:195338046951366fd2345fdc8471e3e2b2786723c8bfffa9fa9057929c608afb -size 12113 +oid sha256:d19e7a09114e76294a0626e5d617cf55fe7c13a0188a7d5b364f57c0d9daedc1 +size 12123 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png index 3e18858873..f831ed92a2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:42f03759fcffbb750181168256130b6a94a1fcf91ee028e69a19a6e3b68ed0e8 -size 11711 +oid sha256:7fe1f51d385bba8821dfc0f0da84990cf0d148e991d765484b343d8764abd47d +size 11724 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index fb72cafe03..1e04c3e7d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ef1b643a16b5a94c75f8bb845c36d3cbc7f7ed96a0cac32fdb9f0b09d26b4d1 -size 11747 +oid sha256:6bbc8c05e6f6818d00282228f52424ebe93e6e3dca3431d742e8c652d56460d6 +size 11712 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png index ce1258d2ac..8e1b9c99d2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce754ce205fd864e01828659aff42ab19dccf7c921c1c733ed1757f1b2122309 -size 11403 +oid sha256:66f6d0d6b03ee4c999cd4edc9c6ae567d31b8b537ca6f9cc8fbe436d06ce80ab +size 11643 From b0c9947a11baf3bfb41ec1fa1b8bd8d7132831d9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 08:06:26 +0000 Subject: [PATCH 101/383] Update dependency org.matrix.rustcomponents:sdk-android to v26.07.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 90dd5c39bc..edf63b0fb9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -185,7 +185,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.06.30" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.07.13" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From 3edf4a6a69f7e9cb8d4b32d0f286c338fd08f0d4 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 13 Jul 2026 10:26:49 +0200 Subject: [PATCH 102/383] Fix AAPT dump missing and reordering some permissions (#7193) --- tools/manifest/gplay/release/aaptDump.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/manifest/gplay/release/aaptDump.txt b/tools/manifest/gplay/release/aaptDump.txt index 7764f0d76b..2bac911ec3 100644 --- a/tools/manifest/gplay/release/aaptDump.txt +++ b/tools/manifest/gplay/release/aaptDump.txt @@ -1,22 +1,23 @@ package: name='io.element.android.x' versionCode='202607000' versionName='26.07.0' platformBuildVersionName='17' platformBuildVersionCode='37' compileSdkVersion='37' compileSdkVersionCodename='17' sdkVersion:'24' targetSdkVersion:'37' -uses-permission: name='android.permission.REQUEST_INSTALL_PACKAGES' uses-permission: name='android.permission.POST_NOTIFICATIONS' uses-permission: name='android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS' +uses-permission: name='android.permission.REQUEST_INSTALL_PACKAGES' uses-permission: name='android.permission.RECORD_AUDIO' uses-permission: name='android.permission.ACCESS_COARSE_LOCATION' uses-permission: name='android.permission.ACCESS_FINE_LOCATION' uses-permission: name='android.permission.FOREGROUND_SERVICE' uses-permission: name='android.permission.FOREGROUND_SERVICE_LOCATION' +uses-permission: name='android.permission.INTERNET' uses-permission: name='android.permission.CAMERA' uses-permission: name='android.permission.MODIFY_AUDIO_SETTINGS' uses-permission: name='android.permission.WAKE_LOCK' uses-permission: name='android.permission.FOREGROUND_SERVICE_MICROPHONE' uses-permission: name='android.permission.USE_FULL_SCREEN_INTENT' uses-permission: name='android.permission.ACCESS_NETWORK_STATE' -uses-permission: name='android.permission.INTERNET' uses-permission: name='android.permission.VIBRATE' +uses-permission: name='android.permission.ACCESS_LOCAL_NETWORK' uses-permission: name='android.permission.ACCESS_WIFI_STATE' uses-permission: name='android.permission.USE_BIOMETRIC' uses-permission: name='android.permission.USE_FINGERPRINT' From 03304b3ece6b19289d8572611be07db862f9e1b6 Mon Sep 17 00:00:00 2001 From: ElementBot <110224175+ElementBot@users.noreply.github.com> Date: Mon, 13 Jul 2026 05:21:55 -0500 Subject: [PATCH 103/383] Sync Strings (#7192) * Sync Strings from Localazy * Update screenshots --------- Co-authored-by: jmartinesp <480955+jmartinesp@users.noreply.github.com> --- .../src/main/res/values-in/translations.xml | 20 + .../src/main/res/values-ja/translations.xml | 2 +- .../src/main/res/values-nb/translations.xml | 6 +- .../src/main/res/values-uz/translations.xml | 2 +- .../src/main/res/values-fa/translations.xml | 4 +- .../src/main/res/values-nb/translations.xml | 2 +- .../src/main/res/values-in/translations.xml | 3 + .../src/main/res/values-nb/translations.xml | 4 +- .../src/main/res/values-in/translations.xml | 4 + .../src/main/res/values-uz/translations.xml | 4 + .../src/main/res/values-fa/translations.xml | 2 + .../src/main/res/values-in/translations.xml | 19 + .../src/main/res/values-hr/translations.xml | 1 + .../src/main/res/values-in/translations.xml | 6 + .../src/main/res/values-nb/translations.xml | 4 + .../src/main/res/values-uz/translations.xml | 1 + .../src/main/res/values-fa/translations.xml | 2 + .../src/main/res/values-in/translations.xml | 11 + .../src/main/res/values-nb/translations.xml | 2 +- .../src/main/res/values-vi/translations.xml | 2 +- .../src/main/res/values-nb/translations.xml | 6 +- .../src/main/res/values-hr/translations.xml | 13 + .../src/main/res/values-in/translations.xml | 6 + .../src/main/res/values-it/translations.xml | 13 + .../src/main/res/values-ja/translations.xml | 6 + .../src/main/res/values-uz/translations.xml | 13 + .../src/main/res/values-hr/translations.xml | 18 + .../src/main/res/values-in/translations.xml | 15 + .../src/main/res/values-it/translations.xml | 20 +- .../src/main/res/values-uz/translations.xml | 26 + .../impl/src/main/res/values/localazy.xml | 2 +- .../src/main/res/values-uz/translations.xml | 2 +- .../src/main/res/values-hr/translations.xml | 2 + .../src/main/res/values-in/translations.xml | 2 + .../src/main/res/values-it/translations.xml | 2 + .../src/main/res/values-uz/translations.xml | 4 +- .../src/main/res/values-fa/translations.xml | 3 +- .../src/main/res/values-hr/translations.xml | 1 + .../src/main/res/values-in/translations.xml | 16 + .../src/main/res/values-uz/translations.xml | 1 + .../src/main/res/values-fa/translations.xml | 4 + .../src/main/res/values-fa/translations.xml | 3 +- .../src/main/res/values-in/translations.xml | 24 + .../src/main/res/values-ja/translations.xml | 4 +- .../impl/src/main/res/values/localazy.xml | 2 +- .../src/main/res/values-in/translations.xml | 2 + .../src/main/res/values-fi/translations.xml | 21 + .../src/main/res/values-hr/translations.xml | 21 + .../src/main/res/values-in/translations.xml | 1 + .../src/main/res/values-it/translations.xml | 21 + .../src/main/res/values-ja/translations.xml | 20 + .../src/main/res/values-nb/translations.xml | 16 +- .../src/main/res/values-ru/translations.xml | 22 + .../src/main/res/values-in/translations.xml | 15 + .../src/main/res/values-in/translations.xml | 17 + .../src/main/res/values-fi/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-nb/translations.xml | 2 +- .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-fa/translations.xml | 4 +- .../src/main/res/values-nb/translations.xml | 4 +- .../src/main/res/values-ja/translations.xml | 2 +- .../src/main/res/values-in/translations.xml | 2 + .../src/main/res/values-in/translations.xml | 1 + .../src/main/res/values-uz/translations.xml | 1 + .../src/main/res/values-fa/translations.xml | 1 + .../src/main/res/values-fa/translations.xml | 15 + .../src/main/res/values-in/translations.xml | 15 + .../src/main/res/values-fa/translations.xml | 11 + .../src/main/res/values-fa/translations.xml | 6 + .../src/main/res/values-fa/translations.xml | 2 + .../src/main/res/values-be/translations.xml | 1 - .../src/main/res/values-ca/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 | 27 +- .../src/main/res/values-eu/translations.xml | 1 - .../src/main/res/values-fa/translations.xml | 9 +- .../src/main/res/values-fi/translations.xml | 41 +- .../src/main/res/values-fr/translations.xml | 2 +- .../src/main/res/values-hr/translations.xml | 45 +- .../src/main/res/values-hu/translations.xml | 31 +- .../src/main/res/values-in/translations.xml | 95 +- .../src/main/res/values-it/translations.xml | 38 +- .../src/main/res/values-ja/translations.xml | 19 +- .../src/main/res/values-ka/translations.xml | 1 - .../src/main/res/values-ko/translations.xml | 1 - .../src/main/res/values-nb/translations.xml | 37 +- .../src/main/res/values-nl/translations.xml | 1 - .../src/main/res/values-pl/translations.xml | 26 +- .../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 | 27 +- .../src/main/res/values-sk/translations.xml | 1 - .../src/main/res/values-sv/translations.xml | 1 - .../src/main/res/values-tr/translations.xml | 5 +- .../src/main/res/values-uk/translations.xml | 22 +- .../src/main/res/values-ur/translations.xml | 1 - .../src/main/res/values-uz/translations.xml | 28 +- .../src/main/res/values-vi/translations.xml | 1 - .../main/res/values-zh-rTW/translations.xml | 1 - .../src/main/res/values-zh/translations.xml | 26 +- .../src/main/res/values/localazy.xml | 13 +- .../appnav.loggedin_LoggedInView_Day_4_de.png | 3 + .../appnav.loggedin_LoggedInView_Day_5_de.png | 3 + ...ytics.impl_AnalyticsOptInView_Day_0_de.png | 4 +- ...ytics.impl_AnalyticsOptInView_Day_1_de.png | 4 +- ...en_FullscreenAnnouncementView_Day_1_de.png | 4 +- ....roomlist_RoomListContextMenu_Day_0_de.png | 4 +- ....roomlist_RoomListContextMenu_Day_1_de.png | 4 +- ....roomlist_RoomListContextMenu_Day_2_de.png | 4 +- ...spacefilters_SpaceFiltersView_Day_0_de.png | 4 +- ...spacefilters_SpaceFiltersView_Day_1_de.png | 4 +- ...changeserver_ChangeServerView_Day_6_de.png | 3 + ...ens.onboarding_OnBoardingView_Day_0_de.png | 4 +- ...ens.onboarding_OnBoardingView_Day_1_de.png | 4 +- ...ens.onboarding_OnBoardingView_Day_2_de.png | 4 +- ...ens.onboarding_OnBoardingView_Day_3_de.png | 4 +- ...ens.onboarding_OnBoardingView_Day_4_de.png | 4 +- ...ens.onboarding_OnBoardingView_Day_5_de.png | 4 +- ...ens.onboarding_OnBoardingView_Day_8_de.png | 4 +- ...eview_AttachmentsPreviewGalleryView_de.png | 3 + ...er_AttachmentSourcePickerMenu_Day_0_de.png | 3 - ...mposer_AttachmentsBottomSheet_Day_0_de.png | 3 + ...s.event_ATimelineItemEventRow_Day_0_de.png | 3 + ...t_TimelineImageWithCaptionRow_Day_0_de.png | 3 - ...t_TimelineVideoWithCaptionRow_Day_0_de.png | 3 - ...msheet_ReadReceiptBottomSheet_Day_0_de.png | 4 +- ...msheet_ReadReceiptBottomSheet_Day_1_de.png | 4 +- ...msheet_ReadReceiptBottomSheet_Day_2_de.png | 4 +- ...msheet_ReadReceiptBottomSheet_Day_3_de.png | 4 +- ...msheet_ReadReceiptBottomSheet_Day_4_de.png | 4 +- ...msheet_ReadReceiptBottomSheet_Day_5_de.png | 4 +- ...ents_TimelineItemEventRowRtlContent_de.png | 3 + ...ineItemEventRowWithReplyOther_Day_1_de.png | 3 - ...imelineItemEventRowWithReply_Day_11_de.png | 3 + ...TimelineItemEventRowWithReply_Day_1_de.png | 3 - ...TimelineItemEventRowWithReply_Day_3_de.png | 3 + ...TimelineItemEventRowWithReply_Day_5_de.png | 3 - ...TimelineItemEventRowWithReply_Day_7_de.png | 3 + ...TimelineItemEventRowWithReply_Day_9_de.png | 3 - ...ine_TimelineViewMessageShield_Day_0_de.png | 4 +- ...es.impl.timeline_TimelineView_Day_0_de.png | 4 +- ...s.impl.timeline_TimelineView_Day_10_de.png | 4 +- ...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 | 4 +- ...es.impl.timeline_TimelineView_Day_1_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_0_de.png | 4 +- ...s.messages.impl_MessagesView_Day_10_de.png | 4 +- ...s.messages.impl_MessagesView_Day_11_de.png | 4 +- ...es.messages.impl_MessagesView_Day_2_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_6_de.png | 4 +- ...es.messages.impl_MessagesView_Day_7_de.png | 4 +- ...es.messages.impl_MessagesView_Day_8_de.png | 4 +- ...es.messages.impl_MessagesView_Day_9_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 +- ...impl.root_PreferencesRootViewDark_6_de.png | 3 + ...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 +- ...mpl.root_PreferencesRootViewLight_6_de.png | 3 + ...mpl.userstatus_UserStatusView_Day_5_de.png | 3 + ...mpl.userstatus_UserStatusView_Day_6_de.png | 3 + ...ureBackupEnterRecoveryKeyView_Day_0_de.png | 4 +- ...et.root_ResetIdentityRootView_Day_0_de.png | 4 +- ...et.root_ResetIdentityRootView_Day_1_de.png | 4 +- ...mePickerHorizontal_DateTime_pickers_de.png | 4 +- ...PickerVerticalDark_DateTime_pickers_de.png | 4 +- ...ickerVerticalLight_DateTime_pickers_de.png | 4 +- ...nents_AvatarActionBottomSheet_Day_0_de.png | 4 +- ...eateDmConfirmationBottomSheet_Day_0_de.png | 4 +- ...eateDmConfirmationBottomSheet_Day_1_de.png | 4 +- ...DeleteConfirmationBottomSheet_Day_0_de.png | 4 +- ...DeleteConfirmationBottomSheet_Day_1_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 | 4 +- ...ser_CaptionWarningBottomSheet_Day_0_de.png | 4 +- screenshots/html/data.js | 2271 +++++++++-------- ...aultNotificationSettingOption_Day_0_en.png | 4 +- ...ltNotificationSettingOption_Night_0_en.png | 4 +- ...efaultNotificationSettingView_Day_0_en.png | 4 +- ...efaultNotificationSettingView_Day_1_en.png | 4 +- ...efaultNotificationSettingView_Day_2_en.png | 4 +- ...efaultNotificationSettingView_Day_3_en.png | 4 +- ...efaultNotificationSettingView_Day_4_en.png | 4 +- ...aultNotificationSettingView_Night_0_en.png | 4 +- ...aultNotificationSettingView_Night_1_en.png | 4 +- ...aultNotificationSettingView_Night_2_en.png | 4 +- ...aultNotificationSettingView_Night_3_en.png | 4 +- ...aultNotificationSettingView_Night_4_en.png | 4 +- ...ions_NotificationSettingsView_Day_0_en.png | 4 +- ...ons_NotificationSettingsView_Day_12_en.png | 4 +- ...ons_NotificationSettingsView_Day_14_en.png | 4 +- ...ons_NotificationSettingsView_Day_15_en.png | 4 +- ...ons_NotificationSettingsView_Day_16_en.png | 4 +- ...ons_NotificationSettingsView_Day_17_en.png | 4 +- ...ions_NotificationSettingsView_Day_1_en.png | 4 +- ...ions_NotificationSettingsView_Day_2_en.png | 4 +- ...ions_NotificationSettingsView_Day_5_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_12_en.png | 4 +- ...s_NotificationSettingsView_Night_14_en.png | 4 +- ...s_NotificationSettingsView_Night_15_en.png | 4 +- ...s_NotificationSettingsView_Night_16_en.png | 4 +- ...s_NotificationSettingsView_Night_17_en.png | 4 +- ...ns_NotificationSettingsView_Night_1_en.png | 4 +- ...ns_NotificationSettingsView_Night_2_en.png | 4 +- ...ns_NotificationSettingsView_Night_5_en.png | 4 +- ...ns_NotificationSettingsView_Night_8_en.png | 4 +- ...ns_NotificationSettingsView_Night_9_en.png | 4 +- ...oomNotificationSettingsOption_Day_0_en.png | 4 +- ...mNotificationSettingsOption_Night_0_en.png | 4 +- ..._RoomNotificationSettingsView_Day_1_en.png | 4 +- ...oomNotificationSettingsView_Night_1_en.png | 4 +- ...dRoomNotificationSettingsView_Day_0_en.png | 4 +- ...oomNotificationSettingsView_Night_0_en.png | 4 +- 247 files changed, 2323 insertions(+), 1521 deletions(-) create mode 100644 features/location/impl/src/main/res/values-in/translations.xml create mode 100644 features/location/impl/src/main/res/values-nb/translations.xml create mode 100644 features/roomaliasresolver/impl/src/main/res/values-fa/translations.xml create mode 100644 libraries/pushproviders/firebase/src/main/res/values-fa/translations.xml create mode 100644 libraries/pushproviders/unifiedpush/src/main/res/values-fa/translations.xml create mode 100644 screenshots/de/appnav.loggedin_LoggedInView_Day_4_de.png create mode 100644 screenshots/de/appnav.loggedin_LoggedInView_Day_5_de.png create mode 100644 screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_6_de.png create mode 100644 screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewGalleryView_de.png delete mode 100644 screenshots/de/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_de.png create mode 100644 screenshots/de/features.messages.impl.messagecomposer_AttachmentsBottomSheet_Day_0_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_de.png delete mode 100644 screenshots/de/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_de.png delete mode 100644 screenshots/de/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowRtlContent_de.png delete mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_de.png delete mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_de.png delete mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_de.png delete mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_de.png create mode 100644 screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_6_de.png create mode 100644 screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_6_de.png create mode 100644 screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_5_de.png create mode 100644 screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_6_de.png diff --git a/features/createroom/impl/src/main/res/values-in/translations.xml b/features/createroom/impl/src/main/res/values-in/translations.xml index 83c51e5a19..82132e8bbd 100644 --- a/features/createroom/impl/src/main/res/values-in/translations.xml +++ b/features/createroom/impl/src/main/res/values-in/translations.xml @@ -3,14 +3,34 @@ "Ruangan baru" "Undang orang-orang" "Terjadi kesalahan saat membuat ruangan" + "Ruang tersebut tidak dapat dibuat karena kesalahan yang tidak diketahui. Coba lagi nanti." + "Tambahkan nama…" + "Ruangan baru" + "Ruang baru" "Hanya orang-orang yang diundang dapat mengakses ruangan ini. Semua pesan terenkripsi secara ujung ke ujung." + "Pribadi" "Siapa pun dapat mencari ruangan ini. Anda dapat mengubah ini kapan pun dalam pengaturan ruangan." + "Siapa pun bisa bergabung." + "Umum" "Siapa pun dapat meminta untuk bergabung dengan ijin administrator atau moderator" "Minta untuk bergabung" + "Siapa pun di %1$s dapat bergabung, tetapi semua orang lain harus meminta akses." + "Ajukan permohonan untuk bergabung" + "Hanya orang-orang yang diundang dapat mengakses ruangan ini. Semua pesan terenkripsi secara ujung ke ujung." + "Pribadi" "Siapa pun dapat bergabung dengan ruangan ini" + "Umum" + "Siapa pun di %1$s dapat bergabung." + "Standar" + "Yang memiliki akses" "Supaya ruangan ini terlihat di direktori ruangan publik, Anda memerlukan alamat ruangan." "Alamat ruangan" "Keterlihatan ruangan" + "(ruang sudah penuh)" + "Jangan menambahkan sesuatu ke ruang yang sudah ada." + "Tidak ada ruang yang dipilih" + "Tambahkan ke ruang" "Topik (opsional)" + "Tambahkan deskripsi…" diff --git a/features/createroom/impl/src/main/res/values-ja/translations.xml b/features/createroom/impl/src/main/res/values-ja/translations.xml index f6f7c71390..3a51c63d61 100644 --- a/features/createroom/impl/src/main/res/values-ja/translations.xml +++ b/features/createroom/impl/src/main/res/values-ja/translations.xml @@ -23,7 +23,7 @@ "公開" "%1$s にいる全員が参加することができます。" "スタンダード" - "参加できるユーザー" + "参加可能なユーザー" "公開ディレクトリで自分を見つけられるようにするには、アドレスが必要です。" "アドレス" "ルームの公開度" diff --git a/features/deactivation/impl/src/main/res/values-nb/translations.xml b/features/deactivation/impl/src/main/res/values-nb/translations.xml index cdff7f886d..6245c8b484 100644 --- a/features/deactivation/impl/src/main/res/values-nb/translations.xml +++ b/features/deactivation/impl/src/main/res/values-nb/translations.xml @@ -1,14 +1,14 @@ - "Bekreft at du vil deaktivere kontoen din. Denne handlingen kan ikke angres." + "Bekreft at du vil slette kontoen din. Denne handlingen kan ikke angres." "Slett alle meldingene mine" "Advarsel: Fremtidige brukere vil kunne se ufullstendige samtaler." - "Deaktivering av kontoen din er %1$s , det vil:" + "Hvis %1$s sletter kontoen din, vil følgende skje:" "irreversibel" "%1$s kontoen din (du kan ikke logge på igjen, og ID-en din kan ikke brukes på nytt)." "Deaktiver permanent" "Fjern deg fra alle chatterom." "Slett kontoinformasjonen din fra vår identitetsserver." "Meldingene dine vil fortsatt være synlige for registrerte brukere, men vil ikke være tilgjengelige for nye eller uregistrerte brukere hvis du velger å slette dem." - "Deaktiver kontoen" + "Slett kontoen" 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 e0dcfe59ef..8d8579178d 100644 --- a/features/deactivation/impl/src/main/res/values-uz/translations.xml +++ b/features/deactivation/impl/src/main/res/values-uz/translations.xml @@ -1,6 +1,6 @@ - "Iltimos, hisobingizni o‘chirishni xohlayotganingizni tasdiqlang. Bu amalni qaytarib bo‘lmaydi." + "Iltimos, hisobingizni oʻchirishni xohlayotganingizni tasdiqlang. Bu amalni qaytarib boʻlmaydi." "Barcha xabarlarimni o‘chirib tashlang" "Ogohlantirish: Kelgusi foydalanuvchilar chala suhbatlarni ko‘rishi mumkin." "Hisobingiz %1$s faolsizlantirilmoqda, u quyidagilarni bajaradi:" diff --git a/features/ftue/impl/src/main/res/values-fa/translations.xml b/features/ftue/impl/src/main/res/values-fa/translations.xml index d41e2e26f1..f87297bc2c 100644 --- a/features/ftue/impl/src/main/res/values-fa/translations.xml +++ b/features/ftue/impl/src/main/res/values-fa/translations.xml @@ -2,8 +2,8 @@ "نمی‌توانید تأیید کنید؟" "ایجاد کلید بازیابی جدید" - "تأیید این افزاره برای برپایی پیام‌رسانی امن." - "تأیید هویتتان" + "گزینش چگونگی تأیید برای برپایی پیام‌رسانی امن." + "تأیید هویت دیجیتالیتان" "استفاده از افزاره‌ای دیگر" "استفاده از کلید بازیابی" "اکنون می‌توانید پیام‌ها را به صورت امن فرستاده و بگیرید و هرکسی که با او گپ می‌زنید نیز می‌تواند به این افزاره اعتماد کند." diff --git a/features/ftue/impl/src/main/res/values-nb/translations.xml b/features/ftue/impl/src/main/res/values-nb/translations.xml index 407e49c2e1..98e5ed7e39 100644 --- a/features/ftue/impl/src/main/res/values-nb/translations.xml +++ b/features/ftue/impl/src/main/res/values-nb/translations.xml @@ -2,7 +2,7 @@ "Kan du ikke bekrefte?" "Opprett en ny gjenopprettingsnøkkel" - "Verifiser denne enheten for å sette opp sikker meldingsutveksling." + "Velg hvordan du vil verifisere deg for å sette opp sikker meldingsutveksling." "Bekreft din digitale identitet" "Bruk en annen enhet" "Bruk gjenopprettingsnøkkel" diff --git a/features/home/impl/src/main/res/values-in/translations.xml b/features/home/impl/src/main/res/values-in/translations.xml index a60d98babb..36512038ba 100644 --- a/features/home/impl/src/main/res/values-in/translations.xml +++ b/features/home/impl/src/main/res/values-in/translations.xml @@ -3,6 +3,8 @@ "Nonaktifkan pengoptimalan baterai untuk aplikasi ini, untuk memastikan semua notifikasi diterima." "Nonaktifkan optimasi" "Notifikasi tidak masuk?" + "Pemberitahuan Anda telah diperbarui—lebih jelas, lebih cepat, dan tidak mengganggu." + "Kami telah memperbarui suara Anda." "Buat kunci pemulihan baru yang dapat digunakan untuk memulihkan riwayat pesan terenkripsi Anda jika Anda kehilangan akses ke perangkat Anda." "Siapkan Kunci pemulihan" "Cadangkan obrolan Anda" @@ -48,6 +50,7 @@ Anda tidak memiliki pesan yang belum dibaca!" "Tandai sebagai dibaca" "Tandai sebagai belum dibaca" "Ruangan ini telah ditingkatkan" + "Ruang Anda" "Sepertinya Anda menggunakan perangkat baru. Verifikasi dengan perangkat lain untuk mengakses pesan terenkripsi Anda selanjutnya." "Verifikasi bahwa ini Anda" diff --git a/features/home/impl/src/main/res/values-nb/translations.xml b/features/home/impl/src/main/res/values-nb/translations.xml index c7455c7c0b..1ff174dc25 100644 --- a/features/home/impl/src/main/res/values-nb/translations.xml +++ b/features/home/impl/src/main/res/values-nb/translations.xml @@ -5,9 +5,9 @@ "Kommer ikke varslene frem?" "Varslingssignalet ditt er oppdatert – tydeligere, raskere og mindre forstyrrende." "Vi har oppdatert lydene dine" - "Gjenopprett din kryptografiske identitet og meldingshistorikk med en gjenopprettingsnøkkel hvis du har mistet alle dine brukte enheter." + "Chattene dine sikkerhetskopieres automatisk med ende-til-ende-kryptering. For å gjenopprette denne sikkerhetskopien og beholde din digitale identitet når du mister tilgang til alle enhetene dine, trenger du gjenopprettingsnøkkelen din." "Hent gjenopprettingsnøkkel" - "Konfigurer gjenoppretting for å beskytte kontoen din" + "Sikkerhetskopier chattene dine" "Verifiser gjenopprettingsnøkkelen for å opprettholde tilgangen til nøkkellageret og meldingshistorikken." "Skriv inn gjenopprettingsnøkkelen din" "Har du glemt din gjenopprettingsnøkkel?" diff --git a/features/invitepeople/impl/src/main/res/values-in/translations.xml b/features/invitepeople/impl/src/main/res/values-in/translations.xml index e112033a06..f8777bf055 100644 --- a/features/invitepeople/impl/src/main/res/values-in/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-in/translations.xml @@ -2,4 +2,8 @@ "Sudah menjadi anggota" "Sudah diundang" + "Saat ini Anda belum memiliki obrolan dengan kontak-kontak ini. Konfirmasikan undangan untuk mengundang mereka ke ruang obrolan ini sebelum melanjutkan." + "Saat ini Anda belum memiliki obrolan apa pun dengan kontak ini. Konfirmasikan undangan ke ruang obrolan ini sebelum melanjutkan." + "Ingin mengundang kontak baru ke ruang ini?" + "Ingin mengundang kontak baru ke ruang ini?" diff --git a/features/invitepeople/impl/src/main/res/values-uz/translations.xml b/features/invitepeople/impl/src/main/res/values-uz/translations.xml index 445a62d318..3828033b63 100644 --- a/features/invitepeople/impl/src/main/res/values-uz/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-uz/translations.xml @@ -2,4 +2,8 @@ "Allaqachon a\'zo" "Allaqachon taklif qilingan" + "Hozirda ushbu kontaktlar bilan hech qanday chatingiz yoʻq. Davom etishdan oldin ularni ushbu xonaga taklif qilishni tasdiqlang." + "Hozirda bu kontakt bilan hech qanday chatingiz yoʻq. Davom etishdan oldin ularni ushbu xonaga taklif qilishni tasdiqlang." + "Bu xonaga yangi kontaktlar taklif qilinsinmi?" + "Bu xonaga yangi kontakt taklif qilinsinmi?" 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 07c329ef6a..f7b0d7f3db 100644 --- a/features/linknewdevice/impl/src/main/res/values-fa/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-fa/translations.xml @@ -13,6 +13,8 @@ "گزینش %1$s" "نتوانست اتّصالی امن به افزارهٔ جدید بسازد. افزاره‌های موجودتان هنوز امنند و نیازی نیست نگرانشان باشید." "اکنون چه؟" + "آزمودن ورود دوباره با کد پاس در صورت مشکل شبکه" + "آزمون شبکهٔ وای‌فایی دیگر یا استفاده از دادهٔ همراهتان به جای وای‌فای در صورت مواجه دوباره با مشکل" "ورود دستی در صورت کار نکردنش" "اتّصال ناامن" "از شما خواسته خواهد شد که دو رقم نشان داده روی این افزاره را وارد کنید." 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 5508993090..8fb4919836 100644 --- a/features/linknewdevice/impl/src/main/res/values-in/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-in/translations.xml @@ -1,16 +1,33 @@ "Pindai kode QR" + "Buka %1$s di laptop atau komputer desktop." "Pindai kode QR dengan perangkat ini" "Siap untuk memindai" + "Buka %1$s di komputer desktop untuk mendapatkan kode QR." + "Angkanya tidak cocok" + "Masukkan kode 2 digit" + "Ini akan memverifikasi bahwa koneksi ke perangkat Anda yang lain aman." + "Masukkan nomor yang ditampilkan di perangkat Anda yang lain" "Penyedia akun Anda tidak mendukung %1$s." "%1$s tidak didukung" + "Penyedia akun Anda tidak mendukung masuk ke perangkat baru menggunakan kode QR." "Kode QR tidak didukung" "Proses masuk dibatalkan di perangkat lain." "Permintaan masuk dibatalkan" "Masa masuk kedaluwarsa. Silakan coba lagi." "Proses masuk tidak selesai tepat waktu" + "Buka %1$s di perangkat lain." "Pilih %1$s" + "Masuk dengan kode QR" + "Pindai kode QR yang ditampilkan di sini dengan perangkat lain." + "Buka %1$s di perangkat lain." + "Komputer desktop" + "Memuat kode QR…" + "Perangkat seluler" + "Jenis perangkat apa yang ingin Anda tautkan?" + "Silakan coba lagi dan pastikan Anda telah memasukkan kode 2 digit dengan benar. Jika angka-angka tersebut masih tidak cocok, hubungi penyedia akun Anda." + "Angkanya tidak cocok" "Koneksi aman tidak dapat dibuat ke perangkat baru. Perangkat Anda yang ada masih aman dan Anda tidak perlu khawatir tentang mereka." "Apa sekarang?" "Coba masuk lagi dengan kode QR jika ini adalah masalah jaringan" @@ -23,6 +40,8 @@ "Permintaan masuk dibatalkan" "Proses masuk ditolak di perangkat lain." "Proses masuk ditolak" + "Anda tidak perlu melakukan hal lain." + "Perangkat Anda yang lain sudah masuk" "Masa masuk kedaluwarsa. Silakan coba lagi." "Proses masuk tidak selesai tepat waktu" "Perangkat Anda yang lain tidak mendukung masuk ke %s dengan kode QR. diff --git a/features/location/impl/src/main/res/values-hr/translations.xml b/features/location/impl/src/main/res/values-hr/translations.xml index 0a294ade1b..8ad85c2dd7 100644 --- a/features/location/impl/src/main/res/values-hr/translations.xml +++ b/features/location/impl/src/main/res/values-hr/translations.xml @@ -2,4 +2,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." + "Nemate dopuštenja za dijeljenje svoje lokacije uživo u ovoj sobi" diff --git a/features/location/impl/src/main/res/values-in/translations.xml b/features/location/impl/src/main/res/values-in/translations.xml new file mode 100644 index 0000000000..0aa9742d0e --- /dev/null +++ b/features/location/impl/src/main/res/values-in/translations.xml @@ -0,0 +1,6 @@ + + + "Riwayat lokasi langsung Anda akan disimpan di ruang obrolan dan dapat dilihat oleh anggota setelah sesi berakhir." + "Pilih berapa lama Anda ingin membagikan lokasi langsung Anda." + "Anda tidak memiliki izin untuk membagikan lokasi real-time Anda di ruang ini" + diff --git a/features/location/impl/src/main/res/values-nb/translations.xml b/features/location/impl/src/main/res/values-nb/translations.xml new file mode 100644 index 0000000000..44ab657a4b --- /dev/null +++ b/features/location/impl/src/main/res/values-nb/translations.xml @@ -0,0 +1,4 @@ + + + "Velg hvor lenge du vil dele din sanntidslokasjon." + diff --git a/features/location/impl/src/main/res/values-uz/translations.xml b/features/location/impl/src/main/res/values-uz/translations.xml index 2b10808d85..e82765de05 100644 --- a/features/location/impl/src/main/res/values-uz/translations.xml +++ b/features/location/impl/src/main/res/values-uz/translations.xml @@ -2,4 +2,5 @@ "Jonli joylashuv tarixingiz chat-xonada saqlanadi va sessiya tugaganidan keyin homiylarga ko‘rinadi." "Jonli joylashuvingiz qancha vaqt ulashilishini tanlang." + "Bu xonada jonli joylashuvingizni ulashish uchun sizda ruxsat yoʻq" 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 c28c891c9a..38c2c11eaa 100644 --- a/features/login/impl/src/main/res/values-fa/translations.xml +++ b/features/login/impl/src/main/res/values-fa/translations.xml @@ -41,6 +41,8 @@ "برقرار کدن اتّصالی امن" "نتوانست اتّصالی امن به افزارهٔ جدید بسازد. افزاره‌های موجودتان هنوز امنند و نیازی نیست نگرانشان باشید." "اکنون چه؟" + "آزمودن ورود دوباره با کد پاس در صورت مشکل شبکه" + "آزمون شبکهٔ وای‌فایی دیگر یا استفاده از دادهٔ همراهتان به جای وای‌فای در صورت مواجه دوباره با مشکل" "ورود دستی در صورت کار نکردنش" "اتّصال ناامن" "از شما خواسته خواهد شد که دو رقم نشان داده روی این افزاره را وارد کنید." 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 4b9f3ffdef..1d29c5b619 100644 --- a/features/login/impl/src/main/res/values-in/translations.xml +++ b/features/login/impl/src/main/res/values-in/translations.xml @@ -37,11 +37,20 @@ "Matrix adalah jaringan terbuka untuk komunikasi yang aman dan terdesentralisasi." "Selamat datang kembali!" "Masuk ke %1$s" + "Buka Element Classic" + "Buka Element Classic di perangkat Anda" + "Buka Pengaturan > Keamanan &amp; Privasi" + "Dalam pengelolaan kunci kriptografi, pilih Pemulihan pesan terenkripsi" + "Ikuti petunjuk berikut untuk mengaktifkan penyimpanan kunci Anda" + "Kembali ke %1$s" + "Aktifkan penyimpanan kunci Anda sebelum melanjutkan ke %1$s" "Versi %1$s" + "Memeriksa akun…" "Masuk secara manual" "Masuk ke %1$s" "Masuk dengan kode QR" "Buat akun" + "Selamat datang kembali!" "Selamat datang di %1$s tercepat yang pernah ada. Berdaya besar untuk kecepatan dan kesederhanaan." "Selamat datang di %1$s. Berdaya penuh, untuk kecepatan dan kesederhanaan." "Berada di elemen Anda" @@ -60,6 +69,8 @@ "Permintaan masuk dibatalkan" "Proses masuk ditolak di perangkat lain." "Proses masuk ditolak" + "Anda tidak perlu melakukan hal lain." + "Perangkat Anda yang lain sudah masuk" "Masa masuk kedaluwarsa. Silakan coba lagi." "Proses masuk tidak selesai tepat waktu" "Perangkat Anda yang lain tidak mendukung masuk ke %s dengan kode QR. 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 6645691b84..befd26d4ce 100644 --- a/features/login/impl/src/main/res/values-nb/translations.xml +++ b/features/login/impl/src/main/res/values-nb/translations.xml @@ -28,7 +28,7 @@ "Hva er adressen til serveren din?" "Velg din server" "Opprett konto" - "Denne kontoen er deaktivert." + "Denne kontoen er slettet." "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." 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 66089a4708..1536b7e499 100644 --- a/features/login/impl/src/main/res/values-vi/translations.xml +++ b/features/login/impl/src/main/res/values-vi/translations.xml @@ -27,7 +27,7 @@ "Đị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ài khoản này đã bị xó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." diff --git a/features/logout/impl/src/main/res/values-nb/translations.xml b/features/logout/impl/src/main/res/values-nb/translations.xml index 136e02fb34..63f3d09c78 100644 --- a/features/logout/impl/src/main/res/values-nb/translations.xml +++ b/features/logout/impl/src/main/res/values-nb/translations.xml @@ -4,15 +4,15 @@ "Fjern denne enheten" "Fjern denne enheten" "Fjerner enheten …" - "Du er i ferd med å logge av din siste sesjon. Hvis du logger av nå, mister du tilgangen til de krypterte meldingene dine." + "Dette er din eneste enhet. Hvis du fjerner den, trenger du en gjenopprettingsnøkkel for å bekrefte din digitale identitet og gjenopprette de krypterte chattene dine neste gang du logger på." "Du er i ferd med å miste tilgangen til dine krypterte chatter" "Nøklene dine ble fortsatt sikkerhetskopiert da du koblet fra. Koble til igjen, slik at nøklene dine kan sikkerhetskopieres før du logger av." "Nøklene dine blir fortsatt sikkerhetskopiert" "Vennligst vent til dette er fullført før du fjerner denne enheten." "Nøklene dine blir fortsatt sikkerhetskopiert" "Fjern denne enheten" - "Du er i ferd med å logge ut av din siste sesjon. Hvis du logger ut nå, mister du tilgangen til de krypterte meldingene dine." + "Dette er din eneste enhet. Hvis du fjerner den, trenger du en gjenopprettingsnøkkel for å bekrefte din digitale identitet og gjenopprette de krypterte chattene dine neste gang du logger på." "Du er i ferd med å miste tilgangen til dine krypterte chatter" - "Du er i ferd med å logge av din siste sesjon. Hvis du logger av nå, kan du miste tilgangen til de krypterte meldingene dine." + "Dette er din eneste enhet. Hvis du fjerner den, trenger du en gjenopprettingsnøkkel for å bekrefte din digitale identitet og gjenopprette de krypterte chattene dine neste gang du logger på." "Sørg for at du har tilgang til gjenopprettingsnøkkelen din før du fjerner denne enheten" 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 03aeae7a0e..0f04f2179a 100644 --- a/features/messages/impl/src/main/res/values-hr/translations.xml +++ b/features/messages/impl/src/main/res/values-hr/translations.xml @@ -16,6 +16,18 @@ "Putovanja i mjesta" "Nedavni emotikoni" "Simboli" + "Okreni sliku vodoravno" + "Okrenuto vodoravno" + "Izvornik" + "Okreni sliku okomito" + "Okrenuto okomito" + "Izvornik" + "Okrenite sliku ulijevo" + + "%1$d stupanj" + "%1$d stupnjevi" + + "Uredi fotografiju" "Opisi možda neće biti vidljivi osobama koji se služe starijim aplikacijama." "Dodirnite za promjenu kvalitete prijenosa videozapisa" "Datoteka se nije mogla prenijeti." @@ -26,6 +38,7 @@ "Stavka %1$d od %2$d" "Optimiziraj kvalitetu slike" "Obrada…" + "Dodaj medij" "Blokiraj korisnika" "Označite ako želite sakriti sve trenutačne i buduće poruke od ovog korisnika" "Ova poruka bit će prijavljena administratoru vašeg matičnog poslužitelja. On neće moći pročitati nijednu šifriranu poruku." 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 0e0ff67a57..d052efb769 100644 --- a/features/messages/impl/src/main/res/values-in/translations.xml +++ b/features/messages/impl/src/main/res/values-in/translations.xml @@ -16,6 +16,11 @@ "Wisata & Tempat" "Emojis Sebelumnya" "Simbol" + "Putar gambar ke kiri" + + "%1$d derajat" + + "Sunting Foto" "Keterangan mungkin tidak terlihat oleh orang yang menggunakan aplikasi lama." "Ketuk untuk mengubah kualitas unggahan video" "Dokumen tidak dapat diunggah." @@ -26,6 +31,7 @@ "Item %1$d dari %2$d" "Optimalkan kualitas gambar" "Memproses…" + "Tambahkan media" "Blokir pengguna" "Centang jika Anda ingin menyembunyikan semua pesan saat ini dan yang akan datang dari pengguna ini" "Pesan ini akan dilaporkan ke administrator homeserver Anda. Mereka tidak akan dapat membaca pesan terenkripsi apa pun." 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 4eb3fd61bb..0f2e0d37be 100644 --- a/features/messages/impl/src/main/res/values-it/translations.xml +++ b/features/messages/impl/src/main/res/values-it/translations.xml @@ -16,6 +16,18 @@ "Viaggi & Luoghi" "Emoji recenti" "Simboli" + "Capovolgi l\'immagine orizzontalmente" + "Capovolto orizzontalmente" + "Originale" + "Capovolgi l\'immagine verticalmente" + "Capovolto verticalmente" + "Originale" + "Ruota l\'immagine verso sinistra" + + "%1$d grado" + "%1$d gradi" + + "Modifica foto" "Le didascalie potrebbero non essere visibili agli utenti di app meno recenti." "Tocca per modificare la qualità di caricamento del video" "Impossibile caricare il file." @@ -26,6 +38,7 @@ "Elemento %1$d di %2$d" "Ottimizza la qualità delle immagini" "Elaborazione…" + "Aggiungi contenuti multimediali" "Blocca utente" "Seleziona se vuoi nascondere tutti i messaggi attuali e futuri di questo utente" "Questo messaggio verrà segnalato all\'amministratore dell\'homeserver. Questi non sarà in grado di leggere i messaggi cifrati." 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 455996fd1a..26d33c4aa1 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,12 @@ "旅・場所" "最近使用" "記号" + "水平に反転" + "垂直に反転" + "元画像" + "垂直に反転" + "水平に反転" + "編集前" "画像を左に回転" "%1$d°" diff --git a/features/messages/impl/src/main/res/values-uz/translations.xml b/features/messages/impl/src/main/res/values-uz/translations.xml index 9c0246ee60..03a1f6ef7e 100644 --- a/features/messages/impl/src/main/res/values-uz/translations.xml +++ b/features/messages/impl/src/main/res/values-uz/translations.xml @@ -16,6 +16,18 @@ "Sayohat va Joylar" "Oxirgi kulgichlar" "Belgilar" + "Rasmni gorizontal ravishda aylantiring" + "Gorizontal ravishda aylantirildi" + "Asl nusxasi" + "Rasmni vertikal ravishda aylantirish" + "Vertikal ravishda aylantirildi" + "Asl nusxasi" + "Rasmni chapga aylantiring" + + "%1$d daraja" + "%1$d daraja" + + "Suratni tahrirlash" "Taglavhalar eski ilovalardan foydalanuvchilarga ko‘rinmasligi mumkin." "Video yuklash sifatini oʻzgartirish uchun bosing" "Faylni yuklab boʻlmadi." @@ -26,6 +38,7 @@ "Element%1$d ning %2$d" "Tasvir sifatini optimallashtirish" "Qayta ishlanmoqda…" + "Media qoʻshish" "Foydalanuvchini bloklash" "Ushbu foydalanuvchidan barcha joriy va kelajakdagi xabarlarni yashirishni xohlayotganingizni tekshiring" "Bu xabar uy serveringiz administratoriga xabar qilinadi. Ular hech qanday shifrlangan xabarlarni o\'qiy olmaydi." 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 d101146f8c..3bd09ce590 100644 --- a/features/preferences/impl/src/main/res/values-hr/translations.xml +++ b/features/preferences/impl/src/main/res/values-hr/translations.xml @@ -59,6 +59,7 @@ "Jeste li spremni za eksperimentiranje?" "Laboratoriji" "Dodatne postavke" + "Ton zvona" "Audiopozivi i videopozivi" "Neusklađenost konfiguracije" "Pojednostavili smo postavke obavijesti kako bismo olakšali pronalaženje mogućnosti. Neke prilagođene postavke koje ste odabrali u prošlosti nisu ovdje prikazane, ali su i dalje aktivne. @@ -77,14 +78,31 @@ Ako nastavite, neke od vaših postavki mogu se promijeniti." "Pozivnice" "Vaš matični poslužitelj ne podržava ovu mogućnost u šifriranim sobama; možda nećete dobiti obavijesti u nekim sobama." "Spominjanja" + "Odaberite drugi zvuk…" + "Trenutačno upotrebljavate %1$s" + "Zvuk poruke" + "Zvuk poruke" "Sve" "Spominjanja" "Obavijesti me za" "Obavijesti me o sobi @soba" + "Prilagođeno" + "Personalizirano zvono" + "Pogreška pri brisanju datoteke" + "Zadano za element" + "Blijeđenje elementa" + "Pogreška pri uvozu datoteke" + "Problem s pregledom zvuka upozorenja" + "Zvuk" + "Pogreška zvuka odbacivanja upozorenja" + "Problem s postavljanjem zvuka upozorenja" + "Stišano" + "Zadano sustavom" "Kako biste primali obavijesti, promijenite %1$s." "postavke sustava" "Obavijesti sustava su isključene" "Obavijesti" + "Crna" "Tamno" "Svijetlo" "Sustav" 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 9c853aed45..3578db804b 100644 --- a/features/preferences/impl/src/main/res/values-in/translations.xml +++ b/features/preferences/impl/src/main/res/values-in/translations.xml @@ -10,6 +10,14 @@ "URL tidak valid, pastikan Anda menyertakan protokol (http/https) dan alamat yang benar." "Sembunyikan avatar dalam permintaan undangan ruangan" "Sembunyikan pratinjau media pada lini masa" + "Uji Coba" + "Jarak yang harus Anda tempuh untuk memicu pembaruan." + "Pastikan \"Lokasi Tepat\" diaktifkan untuk aplikasi ini. Untuk mengubah izin tersebut, buka %1$s." + "Pengaturan aplikasi" + "Pembaruan lokasi secara langsung" + + "Setiap %1$d meter" + "Unggah foto dan video lebih cepat dan kurangi penggunaan data" "Optimalkan kualitas media" "Moderasi dan Keamanan" @@ -43,6 +51,11 @@ "Tidak dapat memperbarui profil" "Edit profil" "Memperbarui profil…" + "Aktifkan balasan utas" + "Aplikasi akan dimulai ulang untuk menerapkan perubahan ini." + "Cobalah ide-ide terbaru kami yang sedang dikembangkan. Fitur-fitur ini belum final; mungkin masih tidak stabil dan dapat berubah." + "Merasa ingin bereksperimen?" + "Uji Coba" "Pengaturan tambahan" "Panggilan audio dan video" "Ketidakcocokan pengaturan" @@ -68,10 +81,12 @@ Jika Anda melanjutkan, beberapa pengaturan Anda dapat berubah." "Sebutan" "Beri tahu saya tentang" "Beri tahu saya pada @room" + "Pengaturan Default Element" "Untuk menerima pemberitahuan, silakan ubah %1$s Anda." "pengaturan sistem" "Pemberitahuan sistem dimatikan" "Notifikasi" + "Hitam" "Gelap" "Terang" "Sistem" 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 73555754fc..3da5e1e6ce 100644 --- a/features/preferences/impl/src/main/res/values-it/translations.xml +++ b/features/preferences/impl/src/main/res/values-it/translations.xml @@ -31,7 +31,7 @@ "Qualità del caricamento video" "Fornitore di notifiche push" "Disattiva l\'editor di testo avanzato per scrivere manualmente in Markdown" - "Conferme di visualizzazione" + "Conferme di lettura" "Se disattivato, le tue conferme di visualizzazione non verranno inviate a nessuno. Riceverai comunque conferme di visualizzazione da altri utenti." "Condividi presenza online" "Se disattivato, non potrai né inviare né ricevere conferme di lettura o notifiche di scrittura." @@ -58,6 +58,7 @@ "Hai voglia di sperimentare?" "Labs" "Impostazioni aggiuntive" + "Suoneria di chiamata" "Chiamate audio e video" "Mancata corrispondenza di configurazione" "Abbiamo semplificato le impostazioni di notifica per rendere le opzioni più facili da trovare. Alcune impostazioni personalizzate che hai scelto in passato non sono mostrate qui, ma sono ancora attive. @@ -76,14 +77,31 @@ Se procedi, alcune delle tue impostazioni potrebbero cambiare." "Inviti" "Il tuo homeserver non supporta questa opzione nelle stanze crifrate, quindi potresti non ricevere notifiche in alcune stanze." "Menzioni" + "Scegli un altro suono…" + "Attualmente si utilizza %1$s" + "Suono messaggi" + "Suono messaggi" "Tutto" "Menzioni" "Avvisami per" "Avvisami con @room" + "Personalizzato" + "Suono personalizzato…" + "Errore durante l\'eliminazione del file" + "Predefinito di Element" + "Dissolvenza di Element" + "Errore durante l\'importazione del file" + "Problema durante l\'anteprima del suono di avviso" + "Suono" + "Ignora l\'errore relativo al suono di avviso" + "Problema con l\'impostazione del suono di avviso" + "Silenzioso" + "Predefinito" "Per ricevere notifiche, modifica le tue %1$s." "impostazioni di sistema" "Notifiche di sistema disattivate" "Notifiche" + "Nero" "Scuro" "Chiaro" "Sistema" 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 884027f9b8..fe241214ba 100644 --- a/features/preferences/impl/src/main/res/values-uz/translations.xml +++ b/features/preferences/impl/src/main/res/values-uz/translations.xml @@ -11,6 +11,14 @@ "Xonaga taklif so‘rovlarida avatarlarni berkitish" "Vaqt jadvalida mediaga razm solishlarni berkitish" "Laboratoriyalar" + "Yangilanishni ishga tushirish uchun harakat qilishingiz kerak boʻlgan masofa" + "Ushbu ilova uchun “Aniq joylashuv” yoqilganligiga ishonch hosil qiling. Ruxsatni oʻzgartirish uchun %1$s ga oʻting." + "Ilova sozlamalari" + "Jonli joylashuv yangilanishlari" + + "Har %1$d metr" + "Har %1$d metr" + "Rasm va videolarni tezroq yuklang va trafik sarfini kamaytiring" "Media sifatini yaxshilash" "Moderatsiya va xavfsizlik" @@ -50,6 +58,7 @@ "Tajribani his qilyapsizmi?" "Laboratoriyalar" "Qo\'shimcha sozlamalar" + "Qoʻngʻroq ohangi" "Audio va video qo\'ng\'iroqlar" "Konfiguratsiya mos kelmasligi" "Variantlarni topishni osonlashtirish uchun bildirishnomalar sozlamalarini soddalashtirdik. Ilgari siz tanlagan baʼzi shaxsiy sozlamalar bu yerda koʻrsatilmaydi, lekin ular hali ham faol. @@ -68,14 +77,31 @@ Davom ettirsangiz, baʼzi sozlamalaringiz oʻzgarishi mumkin." "Taklifnomalar" "Uy serveringiz shifrlangan xonalarda ushbu imkoniyatni qoʻllab-quvvatlamaydi, shuning uchun baʼzi xonalardagi xabarlarni olmasligingiz mumkin." "Eslatmalar" + "Boshqa tovushni tanlang…" + "Hozir foydalanilmoqda: %1$s" + "Xabar ovozi" + "Xabar ovozi" "Hammasi" "Eslatmalar" "Menga xabar bering" "Menga @room orqali xabar bering" + "Maxsus" + "Maxsus ovoz…" + "Faylni oʻchirishda xatolik yuz berdi" + "Element standarti" + "Elementlarning yoʻqolishi" + "Faylni import qilishda xatolik yuz berdi" + "Ogohlantirish ovozini oldindan koʻrishda muammo" + "Ovoz" + "Ogohlantirish ovozi xatosini yopish" + "Ogohlantirish ovozini sozlashda muammo" + "Ovozsiz" + "Tizim standarti" "Bildirishnomalarni olish uchun, iltimos, o\'zingizni %1$singizni o\'zgartiring." "tizim sozlamalari" "Tizim bildirishnomalari o\'chirilgan" "Bildirishnomalar" + "Qora" "Tungi" "Nur" "Tizim" diff --git a/features/preferences/impl/src/main/res/values/localazy.xml b/features/preferences/impl/src/main/res/values/localazy.xml index cca92d0032..7a02bbc839 100644 --- a/features/preferences/impl/src/main/res/values/localazy.xml +++ b/features/preferences/impl/src/main/res/values/localazy.xml @@ -68,7 +68,7 @@ If you proceed, some of your settings may change." "Custom setting per chat" "An error occurred while updating the notification setting." "All messages" - "Mentions and Keywords only" + "Mentions and replies only" "On direct chats, notify me for" "On group chats, notify me for" "Enable notifications on this device" diff --git a/features/rageshake/api/src/main/res/values-uz/translations.xml b/features/rageshake/api/src/main/res/values-uz/translations.xml index 96032fd65f..cfce2a82ef 100644 --- a/features/rageshake/api/src/main/res/values-uz/translations.xml +++ b/features/rageshake/api/src/main/res/values-uz/translations.xml @@ -1,6 +1,6 @@ - "%1$soxirgi marta ishlatilganda qulab tushdi. Biz bilan nosozlik hisobotini baham ko\'rmoqchimisiz?" + "%1$s oxirgi marta ishlatilganda xatolik berdi. Biz bilan nosozlik hisobotini ulashmoqchimisiz?" "Siz hafsalasi pir bo\'lib telefonni silkitayotganga o\'xshaysiz. Xatolar haqida hisobot ekranini ochmoqchimisiz?" "G\'azablanish" "Aniqlash chegarasi" diff --git a/features/rageshake/impl/src/main/res/values-hr/translations.xml b/features/rageshake/impl/src/main/res/values-hr/translations.xml index e49427b2a9..edff9f2254 100644 --- a/features/rageshake/impl/src/main/res/values-hr/translations.xml +++ b/features/rageshake/impl/src/main/res/values-hr/translations.xml @@ -8,6 +8,8 @@ "Opišite problem…" "Ako je moguće, molimo vas da opis bude na engleskom jeziku." "Opis je prekratak; navedite više pojedinosti o tome što se dogodilo. Hvala!" + "Možete unijeti broj povezanog GitHub problema, ako postoji." + "Problem s GitHubom" "Pošalji zapisnike o padu aplikacije" "Dopusti zapisnike" "Vaši su zapisnici preopširni pa ih nije moguće uključiti u ovo izvješće. Molimo vas da nam ih pošaljete na drugi način." diff --git a/features/rageshake/impl/src/main/res/values-in/translations.xml b/features/rageshake/impl/src/main/res/values-in/translations.xml index 0140bfee7a..d58a5ef9ca 100644 --- a/features/rageshake/impl/src/main/res/values-in/translations.xml +++ b/features/rageshake/impl/src/main/res/values-in/translations.xml @@ -14,5 +14,7 @@ "Kirim tangkapan layar" "Log akan disertakan dengan pesan Anda untuk memastikan bahwa semuanya berfungsi dengan baik. Untuk mengirimkan pesan Anda tanpa log, matikan pengaturan ini." "%1$s mengalami kemogokan saat terakhir kali digunakan. Apakah Anda ingin berbagi laporan kerusakan dengan kami?" + "Jika Anda mengalami masalah dengan notifikasi, mengunggah aturan push notifikasi dapat membantu kami menemukan penyebab utamanya. Perlu diingat bahwa aturan ini dapat berisi informasi pribadi, seperti nama tampilan Anda atau kata kunci yang ingin Anda terima notifikasinya." + "Pengaturan notifikasi pengiriman" "Tampilkan catatan" diff --git a/features/rageshake/impl/src/main/res/values-it/translations.xml b/features/rageshake/impl/src/main/res/values-it/translations.xml index 31fb95f9f6..bac6dd5f0f 100644 --- a/features/rageshake/impl/src/main/res/values-it/translations.xml +++ b/features/rageshake/impl/src/main/res/values-it/translations.xml @@ -8,6 +8,8 @@ "Descrivi il problema…" "Se possibile, scrivere la descrizione in inglese." "La descrizione è troppo breve, ti preghiamo di fornire maggiori dettagli sull\'accaduto. Grazie!" + "Puoi inserire il numero di una segnalazione GitHub associata, se presente." + "Segnalazione GitHub" "Invia i log degli arresti anomali" "Consenti i log" "I tuoi log sono troppo grandi, quindi non possono essere inclusi in questo rapporto, inviaceli in un altro modo." diff --git a/features/rageshake/impl/src/main/res/values-uz/translations.xml b/features/rageshake/impl/src/main/res/values-uz/translations.xml index 30e9e1787b..8a955ec449 100644 --- a/features/rageshake/impl/src/main/res/values-uz/translations.xml +++ b/features/rageshake/impl/src/main/res/values-uz/translations.xml @@ -8,12 +8,14 @@ "Muammoni tasvirlab bering…" "Iloji bo\'lsa, tavsifni ingliz tilida yozing." "Tavsif juda qisqa, nima boʻlganligi haqida batafsilroq maʼlumot bering. Rahmat!" + "Agar mavjud boʻlsa, bogʻliq GitHub muammosining raqamini kiritishingiz mumkin." + "GitHub muammosi" "Buzilish jurnallarini yuboring" "Jurnallarga ruxsat bering" "Sizning jurnallaringiz juda katta, shuning uchun bu hisobotga kiritilmaydi, iltimos ularni bizga boshqa usulda yuboring." "Ekran tasvirini yuboring" "Har bir narsa to\'ri ishlayotganiga ishonch hosil qilish uchun xabaringizga jurnallar kiritiladi. Xabarni jurnallarsiz yuborish uchun ushbu sozlamani oʻchiring." - "%1$soxirgi marta ishlatilganda qulab tushdi. Biz bilan nosozlik hisobotini baham ko\'rmoqchimisiz?" + "%1$s oxirgi marta ishlatilganda xatolik berdi. Biz bilan nosozlik hisobotini ulashmoqchimisiz?" "Agar bildirishnomalar bilan bog‘liq muammolarga duch kelayotgan bo‘lsangiz, bildirishnomalarni yetkazish qoidalarini yuklash bizga asosiy sababni aniqlashda yordam beradi. Shuni yodda tutingki, bu qoidalarda shaxsiy ma’lumotlar, masalan, ko‘rsatiladigan ismingiz yoki bildirishnoma olishingiz kerak bo‘lgan kalit so‘zlar kabi ma’lumotlar bo‘lishi mumkin." "Bildirishnoma sozlamalarini yuborish" "Jurnallarni ko'rish" 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 4bcb764219..e381cec856 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-fa/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-fa/translations.xml @@ -32,7 +32,7 @@ "اعضا" "تغییراتی ذخیره نشده دارید." "ذخیرهٔ تغییرات؟" - "هیچ کاربر محرومی در این اتاق نیست." + "هیچ کاربری محروم نشده." "%1$d نفر" "%1$d نفر" @@ -59,6 +59,7 @@ "ناظم‌ها" "مالکان" "بازنشانی اجازه‌ها" + "پس از بازنشانی اجازه‌ها تنظیمات فعلی را از دست خواهید داد." "بازنشانی اجازه‌ها؟" "نقش‌ها" "جزییات اتاق" diff --git a/features/rolesandpermissions/impl/src/main/res/values-hr/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-hr/translations.xml index 7f24535124..fda73c88aa 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-hr/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-hr/translations.xml @@ -6,6 +6,7 @@ "Uklanjanje poruka" "Član" "Pozivanje osoba" + "Dijeljenje lokacije uživo" "Upravljaj prostorom" "Upravljaj sobama" "Upravljanje članovima" diff --git a/features/rolesandpermissions/impl/src/main/res/values-in/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-in/translations.xml index 05844637ea..98f38095de 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-in/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-in/translations.xml @@ -2,9 +2,13 @@ "Hanya admin" "Cekal orang-orang" + "Ubah pengaturan" "Hilangkan pesan" "Semua Anggota" "Boleh mungundang" + "Bagikan lokasi secara langsung" + "Kelola ruang" + "Kelola ruangan" "Kelola anggota" "Pesan dan konten" "Admin dan moderator" @@ -14,6 +18,7 @@ "Ubah nama ruangan" "Ubah topik ruangan" "Kirim pesan" + "Permission" "Edit Admin" "Anda tidak akan dapat mengurungkan tindakan ini. Anda mempromosikan pengguna untuk memiliki tingkat daya yang sama seperti Anda." "Tambahkan Admin?" @@ -34,6 +39,11 @@ "Anda memiliki perubahan yang belum disimpan." "Simpan perubahan?" "Tidak ada pengguna yang dicekal dalam ruangan ini." + + "%1$d Dilarang" + + "Periksa ejaannya atau coba pencarian baru" + "Tidak ada hasil untuk%1$s" "%1$d orang" @@ -44,6 +54,10 @@ "Batalkan cekalan dari ruangan" "Tercekal" "Anggota" + + "%1$d Diundang" + + "Tertunda" "Hanya admin" "Admin dan moderator" "Pemilik" @@ -58,10 +72,12 @@ "Pesan dan konten" "Moderator" "Pemilik" + "Permission" "Atur ulang perizinan" "Setelah Anda mengatur ulang perizinan, Anda akan kehilangan pengaturan Anda saat ini." "Atur ulang perizinan?" "Peran" "Detail ruangan" + "Detail ruang" "Peran dan perizinan" 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 5e00e72504..33ff506375 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-uz/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-uz/translations.xml @@ -6,6 +6,7 @@ "Xabarlarni olib tashlash" "A\'zo" "Odamlarni taklif qiling" + "Jonli joylashuvni ulashish" "Maydonni boshqarish" "Xonalarni boshqarish" "A’zolarni boshqarish" diff --git a/features/roomaliasresolver/impl/src/main/res/values-fa/translations.xml b/features/roomaliasresolver/impl/src/main/res/values-fa/translations.xml new file mode 100644 index 0000000000..4fba81c4f8 --- /dev/null +++ b/features/roomaliasresolver/impl/src/main/res/values-fa/translations.xml @@ -0,0 +1,4 @@ + + + "شکست در دریافت نام مستعار اتاق." + 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 af0cbbe29b..7cdfe409dd 100644 --- a/features/roomdetails/impl/src/main/res/values-fa/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fa/translations.xml @@ -68,7 +68,7 @@ "اطّلاعات اتاق" "موضوع" "به‌روز کردن اتاق…" - "هیچ کاربر محرومی در این اتاق نیست." + "هیچ کاربری محروم نشده." "%1$d نفر" "%1$d نفر" @@ -109,6 +109,7 @@ "ناظم‌ها" "مالکان" "بازنشانی اجازه‌ها" + "پس از بازنشانی اجازه‌ها تنظیمات فعلی را از دست خواهید داد." "بازنشانی اجازه‌ها؟" "نقش‌ها" "جزییات اتاق" 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 d7403329c4..bcdacb99ea 100644 --- a/features/roomdetails/impl/src/main/res/values-in/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-in/translations.xml @@ -1,5 +1,8 @@ + "Anggota baru tidak dapat melihat riwayat" + "Anggota baru dapat melihat riwayat" + "Siapa pun dapat melihat riwayat" "Supaya ruangan ini terlihat di direktori ruangan publik, Anda memerlukan alamat ruangan." "Edit alamat" "Terjadi kesalahan saat memperbarui pengaturan pemberitahuan." @@ -64,6 +67,7 @@ "Profil" "Permintaan untuk bergabung" "Peran dan perizinan" + "Nama" "Keamanan & privasi" "Keamanan" "Bagikan ruangan" @@ -71,6 +75,11 @@ "Topik" "Memperbarui ruangan…" "Tidak ada pengguna yang dicekal dalam ruangan ini." + + "%1$d Dilarang" + + "Periksa ejaannya atau coba pencarian baru" + "Tidak ada hasil untuk%1$s" "%1$d orang" @@ -81,6 +90,10 @@ "Batalkan cekalan dari ruangan" "Tercekal" "Anggota" + + "%1$d Diundang" + + "Tertunda" "Hanya admin" "Admin dan moderator" "Pemilik" @@ -109,6 +122,7 @@ "Pesan dan konten" "Moderator" "Pemilik" + "Permission" "Atur ulang perizinan" "Setelah Anda mengatur ulang perizinan, Anda akan kehilangan pengaturan Anda saat ini." "Atur ulang perizinan?" @@ -118,8 +132,10 @@ "Tandai sebagai dibaca" "Tandai sebagai belum dibaca" "Tambahkan alamat" + "Siapa pun yang berada di ruang yang diizinkan dapat bergabung, tetapi semua orang lain harus meminta akses." "Meminta hak akses pada administrator atau moderator." "Ijin bergabung" + "Siapa pun di %1$s dapat bergabung, tetapi semua orang lain harus meminta akses." "Ya, aktifkan enkripsi" "Setelah diaktifkan, encryption untuk sebuah ruangan tidak dapat dinonaktifkan, Riwayat pesan hanya akan terlihat oleh anggota ruangan sejak mereka diundang atau sejak mereka bergabung dengan ruangan tersebut. Tidak ada orang lain selain anggota ruangan yang dapat membaca pesan. Hal ini dapat mencegah bot dan jembatan bekerja dengan benar. @@ -130,20 +146,28 @@ Kami tidak menyarankan untuk mengaktifkan enkripsi untuk ruangan yang dapat dite "Aktifkan enkripsi ujung ke ujung" "Siapa pun dapat menemukan dan bergabung" "Semua orang" + "Pilih ruang mana yang anggotanya dapat bergabung ke ruangan ini tanpa undangan. %1$s" + "Kelola ruang" "Orang hanya dapat bergabung jika mereka diundang" "Hanya undangan" "Akses ruangan" + "Siapa pun yang berada di area yang diizinkan dapat bergabung." + "Siapa pun di %1$s dapat bergabung." + "Anggota space" "Space saat ini tidak didukung" "Supaya ruangan ini terlihat di direktori ruangan publik, Anda memerlukan alamat ruangan." "Alamat" "Izinkan ruangan ini ditemukan dengan mencari direktori ruangan %1$s publik" + "Izinkan agar dapat ditemukan melalui pencarian di direktori publik." "Tersedia di direktori publik" "Siapa saja (riwayat publik)" + "Perubahan tidak akan memengaruhi pesan lama, hanya pesan baru. %1$s" "Siapa yang bisa membaca riwayat" "Hanya sejak anggota diundang" "Anggota dapat melihat rekaman percakapan sejak memilih opsi ini" "Alamat ruangan adalah cara untuk menemukan dan mengakses ruangan. Ini juga memastikan Anda dapat dengan mudah berbagi ruangan dengan orang lain. Anda dapat memilih untuk menerbitkan ruangan Anda di direktori ruangan publik homeserver Anda." "Penerbitan ruangan" + "Alamat adalah cara untuk menemukan dan mengakses ruangan dan ruang. Ini juga memastikan Anda dapat dengan mudah membagikannya dengan orang lain." "Visibilitas" "Keamanan & privasi" 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 5a65f1a404..bf0ef7424c 100644 --- a/features/roomdetails/impl/src/main/res/values-ja/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ja/translations.xml @@ -1,8 +1,8 @@ "新しいメンバーは過去の内容を確認できない" - "新しいメンバーは過去の内容を確認できる" - "すべてのユーザーが過去の内容を確認できる" + "新規メンバーも過去の内容を確認できます" + "すべてのユーザーが過去の内容を確認できます" "公開ディレクトリで自分を見つけられるようにするには、アドレスが必要です。" "アドレスの編集" "通知設定の更新中に問題が発生しました。" diff --git a/features/roomdetails/impl/src/main/res/values/localazy.xml b/features/roomdetails/impl/src/main/res/values/localazy.xml index 0287b5657b..31851c2603 100644 --- a/features/roomdetails/impl/src/main/res/values/localazy.xml +++ b/features/roomdetails/impl/src/main/res/values/localazy.xml @@ -114,7 +114,7 @@ "Failed setting the mode, please try again." "Your homeserver does not support this option in encrypted rooms, you won\'t get notified in this room." "All messages" - "Mentions and Keywords only" + "Mentions and replies only" "In this room, notify me for" "Admins" "Admins and owners" diff --git a/features/roommembermoderation/impl/src/main/res/values-in/translations.xml b/features/roommembermoderation/impl/src/main/res/values-in/translations.xml index bddbdb0a67..43be3b018c 100644 --- a/features/roommembermoderation/impl/src/main/res/values-in/translations.xml +++ b/features/roommembermoderation/impl/src/main/res/values-in/translations.xml @@ -4,10 +4,12 @@ "Cekal" "Mereka tidak akan dapat bergabung ke ruangan ini lagi jika diundang." "Apakah Anda yakin ingin mencekal anggota ini?" + "Mereka tidak akan dapat bergabung kembali ke space ini meskipun diundang, tetapi mereka tetap akan mempertahankan keanggotaan mereka di room atau subruang mana pun." "Mencekal %1$s" "Hapus" "Pengguna dapat bergabung ke ruangan ini lagi jika diundang." "Apakah Anda yakin ingin menghapus anggota ini?" + "Mereka akan dapat bergabung kembali ke Space ini jika diundang, dan mereka tetap akan mempertahankan keanggotaan mereka di room atau subruang mana pun." "Tampilkan profil" "Keluarkan dari ruangan" "Keluarkan pengguna dan cekal pengguna bergabung lagi di masa mendatang?" 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 7cbe0f1af6..7a8f44f51a 100644 --- a/features/securebackup/impl/src/main/res/values-fi/translations.xml +++ b/features/securebackup/impl/src/main/res/values-fi/translations.xml @@ -20,6 +20,27 @@ "Seuraa ohjeita uuden palautusavaimen luomiseksi" "Tallenna uusi palautusavaimesi salasanojen hallintaohjelmaan tai salattuun muistiinpanoon" "Nollaa tilisi salaus toisella laitteella" + "Antamasi palautusavain ei täsmää" + "Viimeistele määritys" + "Anna palautusavaimesi uudelleen." + "Vahvista palautusavaimesi" + + "Vähintään %1$d merkki. Älä käytä tilisi salasanaa" + "Vähintään %1$d merkkiä. Älä käytä tilisi salasanaa" + + "Vahvuus" + "Salasanan vahvuus: %1$s" + "Kohtalainen" + "Vahva" + "Erittäin vahva" + "Erittäin heikko" + "Heikko" + "Valitse palautusavain, jonka osaat muistaa." + "Anna palautusavain" + "Palautusavaimen vaatimuksia ladataan" + "Jos haluat vaihtaa palautusavaimesi, mene kohtaan Asetukset → Salaus" + "Voit käyttää palautusavainta uusien laitteiden vahvistamiseen tai salattujen keskustelujen palauttamiseen, jos menetät pääsyn kaikkiin laitteisiisi." + "Varmuuskopiointi on nyt täysin määritetty" "Jatka nollausta" "Tilitietosi, yhteystiedot, asetukset ja keskustelulista säilytetään" "Menetät kaiken viestihistorian, joka on tallella vain palvelimella" 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 9c470b8895..618be910fe 100644 --- a/features/securebackup/impl/src/main/res/values-hr/translations.xml +++ b/features/securebackup/impl/src/main/res/values-hr/translations.xml @@ -20,6 +20,27 @@ "Pridržavajte se uputa za izradu novog ključa za oporavak" "Spremite svoj novi ključ za oporavak u upravitelj zaporki ili šifriranu bilješku" "Resetirajte šifriranje za svoj račun pomoću drugog uređaja" + "Ključ za oporavak koji ste unijeli ne odgovara" + "Završi postavljanje" + "Ponovno unesite svoj ključ za oporavak." + "Potvrdite svoj ključ za oporavak" + + "Minimalno %1$d znakova. Nemojte koristiti lozinku računa." + "Minimalno %1$d znakova. Nemojte koristiti lozinku računa." + + "Snaga" + "Jačina lozinke: %1$s" + "Umjereno" + "Jak" + "Vrlo jaka" + "Vrlo slaba" + "Slaba" + "Odaberite ključ za oporavak koji možete zapamtiti." + "Unesite ključ za oporavak" + "Učitavanje zahtjeva za ključ za oporavak" + "Za promjenu ključa za oporavak, idite na Postavke → Šifriranje → Sigurnosna kopija" + "Ključ za oporavak možete koristiti za potvrdu novih uređaja ili vraćanje šifriranih razgovora ako izgubite pristup svim svojim uređajima." + "Vaša sigurnosna kopija je sada potpuno postavljena" "Nastavi s poništavanjem" "Sačuvat će se podatci o vašem računu, kontakti, postavke i popis razgovora" "Izgubit ćete svu povijest poruka koja je pohranjena samo na poslužitelju" diff --git a/features/securebackup/impl/src/main/res/values-in/translations.xml b/features/securebackup/impl/src/main/res/values-in/translations.xml index 2fd2c044fc..3c810938d7 100644 --- a/features/securebackup/impl/src/main/res/values-in/translations.xml +++ b/features/securebackup/impl/src/main/res/values-in/translations.xml @@ -12,6 +12,7 @@ "Masukkan kunci pemulihan" "Penyimpanan kunci Anda saat ini tidak sinkron." "Siapkan Kunci pemulihan" + "Pulihkan identitas kriptografi dan riwayat pesan Anda dengan kunci pemulihan jika Anda kehilangan semua perangkat yang ada." "Buka %1$s di perangkat desktop" "Masuk ke akun Anda lagi" "Saat diminta untuk memverifikasi perangkat Anda, pilih %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 188de2c3df..137d5a39e8 100644 --- a/features/securebackup/impl/src/main/res/values-it/translations.xml +++ b/features/securebackup/impl/src/main/res/values-it/translations.xml @@ -20,6 +20,27 @@ "Segui le istruzioni per creare una nuova chiave di recupero" "Salva la tua nuova chiave di recupero in un gestore di password o in una nota criptata" "Reimposta la crittografia del tuo account utilizzando un altro dispositivo" + "La chiave di recupero che hai inserito non corrisponde" + "Completa la configurazione" + "Inserisci nuovamente la tua chiave di recupero." + "Conferma la tua chiave di recupero" + + "Minimo %1$d carattere. Non usare la password del tuo account" + "Minimo %1$d caratteri. Non usare la password del tuo account" + + "Complessità" + "Complessità della passphrase: %1$s" + "Moderata" + "Sicura" + "Molto sicura" + "Molto debole" + "Debole" + "Scegli una chiave di recupero che puoi ricordare." + "Inserisci una chiave di recupero" + "Caricamento dei requisiti per la chiave di recupero" + "Per modificare la chiave di recupero, vai su Impostazioni → Crittografia → Backup" + "Puoi utilizzare la tua chiave di recupero per confermare nuovi dispositivi o ripristinare le tue chat crittografate se perdi l\'accesso a tutti i tuoi dispositivi." + "Il tuo backup è ora completamente configurato." "Continua il ripristino" "I dettagli del tuo account, i contatti, le preferenze e l\'elenco delle conversazioni verranno conservati" "Perderai la cronologia dei messaggi esistente" 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 b9612c4e09..457f08fcea 100644 --- a/features/securebackup/impl/src/main/res/values-ja/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ja/translations.xml @@ -20,6 +20,26 @@ "指示に従って回復鍵を作成してください" "生成された回復鍵をパスワードマネージャや暗号化に対応するメモアプリに保存してください。" "他の端末を使用して暗号化をリセット" + "入力した回復鍵が一致しません" + "設定完了" + "回復鍵を再度入力してください。" + "回復鍵の確認" + + "%1$d字以上でアカウントのパスワードとは異なるものを設定してください。" + + "強度" + "パスフレーズの強度: %1$s" + "中程度" + "強い" + "とても強い" + "とても弱い" + "弱い" + "思い出せる回復鍵を作成してください。" + "回復鍵の入力" + "回復鍵の要件を読み込み中" + "回復鍵を変更するには、「設定 - 暗号化 - バックアップ」を開いてください。" + "回復鍵は他の端末をすべて使用できない場合に、新しい端末を承認したり暗号化された会話を復元したりするために使用します。" + "バックアップの設定完了" "リセットを続行" "アカウントの情報や連絡先, 設定などは残ります" "サーバー上にのみ存在する過去のメッセージは確認できなくなります" diff --git a/features/securebackup/impl/src/main/res/values-nb/translations.xml b/features/securebackup/impl/src/main/res/values-nb/translations.xml index f65deda870..8d643a52d0 100644 --- a/features/securebackup/impl/src/main/res/values-nb/translations.xml +++ b/features/securebackup/impl/src/main/res/values-nb/translations.xml @@ -2,13 +2,13 @@ "Slett nøkkellagring" "Slå på sikkerhetskopiering" - "Lagre din kryptografiske identitet og meldingsnøkler sikkert på serveren. Dette gjør at du kan se meldingshistorikken din på alle nye enheter. %1$s." + "Dette lar deg se chatloggen din på alle nye enheter, og det er nødvendig for sikkerhetskopiering av chatter og digital identitet. %1$s." "Nøkkellagring" - "Nøkkellagring må være slått på for å konfigurere gjenoppretting." + "Nøkkellagring må være aktivert for å sikkerhetskopiere chattene dine." "Last opp nøkler fra denne enheten" "Tillat nøkkellagring" "Endre gjenopprettingsnøkkel" - "Gjenopprett din kryptografiske identitet og meldingshistorikk med en gjenopprettingsnøkkel hvis du har mistet alle dine brukte enheter." + "Chattene dine sikkerhetskopieres automatisk med ende-til-ende-kryptering. For å gjenopprette denne sikkerhetskopien og beholde din digitale identitet når du mister tilgang til alle enhetene dine, trenger du gjenopprettingsnøkkelen din." "Skriv inn gjenopprettingsnøkkel" "Nøkkellagringen din er for øyeblikket ikke synkronisert." "Hent gjenopprettingsnøkkel" @@ -23,10 +23,10 @@ "Dine kontodetaljer, kontakter, innstillinger og chatteliste vil bli beholdt" "Du mister all meldingshistorikk som bare er lagret på serveren" "Du må verifisere alle eksisterende enheter og kontakter på nytt" - "Tilbakestill identiteten din bare hvis du ikke har tilgang til en annen pålogget enhet og du har mistet gjenopprettingsnøkkelen." - "Kan du ikke bekrefte? Du må tilbakestille identiteten din." + "Tilbakestill bare den digitale identiteten din hvis du ikke har tilgang til en annen bekreftet enhet og du ikke har gjenopprettingsnøkkelen din." + "Kan du ikke bekrefte? Du må tilbakestille den digitale identiteten din." "Slett" - "Du mister de krypterte meldingene dine hvis du er logget ut av alle enheter." + "Du vil miste den krypterte chatloggen din og må tilbakestille den digitale identiteten din hvis du fjerner alle enhetene dine." "Er du sikker på at du vil slette nøkkellagringen?" "Sletting av nøkkellagring vil fjerne din kryptografiske identitet og meldingsnøkler fra serveren og deaktivere følgende sikkerhetsfunksjoner:" "Du vil ikke ha kryptert meldingshistorikk på nye enheter" @@ -61,9 +61,9 @@ "Hent gjenopprettingsnøkkel" "Ja, tilbakestill nå" "Denne prosessen kan ikke angres." - "Er du sikker på at du vil tilbakestille identiteten din?" + "Er du sikker på at du vil tilbakestille den digitale identiteten din?" "En ukjent feil har oppstått. Vennligst sjekk at passordet ditt er riktig og prøv igjen." "Angi…" - "Bekreft at du vil tilbakestille identiteten din." + "Bekreft at du vil tilbakestille din digitale identitet." "Skriv inn passordet til kontoen din for å fortsette" 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 1417de5766..7f24725c82 100644 --- a/features/securebackup/impl/src/main/res/values-ru/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ru/translations.xml @@ -20,6 +20,28 @@ "Следуйте инструкциям, чтобы создать новый ключ восстановления" "Сохраните новый ключ восстановления в менеджере паролей или зашифрованной заметке" "Сбросьте шифрование Вашего аккаунта, используя другое устройство" + "Введенный вами ключ восстановления не совпадает." + "Завершить настройку" + "Введите ваш ключ восстановления еще раз." + "Подтвердите ваш ключ восстановления." + + "Минимальное количество символов: %1$d. Не используйте пароль от своей учетной записи." + "Минимальное количество символов: %1$d. Не используйте пароль от своей учетной записи." + "Минимальное количество символов: %1$d. Не используйте пароль от своей учетной записи." + + "Прочность" + "Надежность парольной фразы: %1$s" + "Умеренный" + "Сильный" + "Очень сильный" + "Очень слабый" + "Слабый" + "Выберите ключ восстановления, который вы сможете запомнить." + "Введите ключ восстановления" + "Загрузка требований к ключу восстановления" + "Чтобы изменить ключ восстановления, перейдите в Настройки → Шифрование → Резервное копирование" + "Вы можете использовать свой ключ восстановления для подтверждения новых устройств или восстановления зашифрованных чатов, если потеряете доступ ко всем своим устройствам." + "Ваша резервная копия полностью настроена." "Продолжить сброс" "Данные вашего аккаунта, контакты, настройки и список чатов будут сохранены" "Вы потеряете историю тех сообщений, которые хранятся только на сервере" diff --git a/features/securityandprivacy/impl/src/main/res/values-in/translations.xml b/features/securityandprivacy/impl/src/main/res/values-in/translations.xml index 9ae4ac9044..9861c08e80 100644 --- a/features/securityandprivacy/impl/src/main/res/values-in/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-in/translations.xml @@ -2,9 +2,16 @@ "Supaya ruangan ini terlihat di direktori ruangan publik, Anda memerlukan alamat ruangan." "Edit alamat" + "Ruang di mana anggota dapat bergabung ke ruangan tanpa undangan." + "Kelola ruang" + "(Ruang tak dikenal)" + "Ruang lain yang bukan merupakan keanggotaan Anda" + "Ruang Anda" "Tambahkan alamat" + "Siapa pun yang berada di ruang yang diizinkan dapat bergabung, tetapi semua orang lain harus meminta akses." "Meminta hak akses pada administrator atau moderator." "Ijin bergabung" + "Siapa pun di %1$s dapat bergabung, tetapi semua orang lain harus meminta akses." "Ya, aktifkan enkripsi" "Setelah diaktifkan, encryption untuk sebuah ruangan tidak dapat dinonaktifkan, Riwayat pesan hanya akan terlihat oleh anggota ruangan sejak mereka diundang atau sejak mereka bergabung dengan ruangan tersebut. Tidak ada orang lain selain anggota ruangan yang dapat membaca pesan. Hal ini dapat mencegah bot dan jembatan bekerja dengan benar. @@ -15,20 +22,28 @@ Kami tidak menyarankan untuk mengaktifkan enkripsi untuk ruangan yang dapat dite "Aktifkan enkripsi ujung ke ujung" "Siapa pun dapat menemukan dan bergabung" "Semua orang" + "Pilih ruang mana yang anggotanya dapat bergabung ke ruangan ini tanpa undangan. %1$s" + "Kelola ruang" "Orang hanya dapat bergabung jika mereka diundang" "Hanya undangan" "Akses ruangan" + "Siapa pun yang berada di area yang diizinkan dapat bergabung." + "Siapa pun di %1$s dapat bergabung." + "Anggota space" "Space saat ini tidak didukung" "Supaya ruangan ini terlihat di direktori ruangan publik, Anda memerlukan alamat ruangan." "Alamat" "Izinkan ruangan ini ditemukan dengan mencari direktori ruangan %1$s publik" + "Izinkan agar dapat ditemukan melalui pencarian di direktori publik." "Tersedia di direktori publik" "Siapa saja (riwayat publik)" + "Perubahan tidak akan memengaruhi pesan lama, hanya pesan baru. %1$s" "Siapa yang bisa membaca riwayat" "Hanya sejak anggota diundang" "Anggota dapat melihat rekaman percakapan sejak memilih opsi ini" "Alamat ruangan adalah cara untuk menemukan dan mengakses ruangan. Ini juga memastikan Anda dapat dengan mudah berbagi ruangan dengan orang lain. Anda dapat memilih untuk menerbitkan ruangan Anda di direktori ruangan publik homeserver Anda." "Penerbitan ruangan" + "Alamat adalah cara untuk menemukan dan mengakses ruangan dan ruang. Ini juga memastikan Anda dapat dengan mudah membagikannya dengan orang lain." "Visibilitas" "Keamanan & privasi" diff --git a/features/space/impl/src/main/res/values-in/translations.xml b/features/space/impl/src/main/res/values-in/translations.xml index f2e50ca04c..f049a0c180 100644 --- a/features/space/impl/src/main/res/values-in/translations.xml +++ b/features/space/impl/src/main/res/values-in/translations.xml @@ -1,8 +1,25 @@ "Pilih Pemilik" + "%1$s (Admin)" + + "Tinggalkan ruangan dan ruang %1$d" + "Pilih room yang ingin Anda tinggalkan di mana Anda bukan satu-satunya administrator:" + "Anda perlu menunjuk admin lain untuk ruang ini sebelum Anda dapat keluar." + "Anda adalah satu-satunya pemilik dari %1$s. Anda harus mengalihkan kepemilikan kepada orang lain sebelum Anda pergi." + "Anda tidak akan dikeluarkan dari ruangan berikut karena Anda adalah satu-satunya administrator:" "Keluar dari %1$s?" + "Anda adalah satu-satunya admin untuk %1$s" + "Transfer kepemilikan" + "Ruangan" + "Menambahkan ruangan tidak akan memengaruhi akses ruangan. Untuk mengubah akses, buka Pengaturan ruangan > Keamanan &amp; privasi." + "Tambahkan ruang pertama Anda" + "Lihat anggota" + "Menghapus ruangan tidak akan memengaruhi akses ruangan. Untuk mengubah akses, buka Info ruangan > Privasi &amp; keamanan." + + "Hapus ruangan %1$d dari %2$s" + "Tinggalkan space" "Peran dan perizinan" "Keamanan & privasi" diff --git a/features/startchat/impl/src/main/res/values-fi/translations.xml b/features/startchat/impl/src/main/res/values-fi/translations.xml index bb59e375e4..ce0741a35e 100644 --- a/features/startchat/impl/src/main/res/values-fi/translations.xml +++ b/features/startchat/impl/src/main/res/values-fi/translations.xml @@ -5,7 +5,7 @@ "Keskustelun aloituksessa tapahtui virhe" "Liity huoneeseen osoitteella" "Osoite ei ole kelvollinen" - "Kirjoita…" + "Kirjoita osoite…" "Täsmäävä huone löytyi" "Huonetta ei löytynyt" "esim. #huoneen-nimi:matrix.org" diff --git a/features/startchat/impl/src/main/res/values-hr/translations.xml b/features/startchat/impl/src/main/res/values-hr/translations.xml index 8f0407fcde..0cd7926ca0 100644 --- a/features/startchat/impl/src/main/res/values-hr/translations.xml +++ b/features/startchat/impl/src/main/res/values-hr/translations.xml @@ -5,7 +5,7 @@ "Došlo je do pogreške prilikom pokretanja razgovora" "Pridruži se sobi putem adrese" "Adresa nije valjana" - "Unos…" + "Unesite adresu…" "Pronađena je odgovarajuća soba" "Soba nije pronađena" "npr. #naziv-sobe:matrix.org" diff --git a/features/startchat/impl/src/main/res/values-hu/translations.xml b/features/startchat/impl/src/main/res/values-hu/translations.xml index 014f7baaac..c9ce9f3c20 100644 --- a/features/startchat/impl/src/main/res/values-hu/translations.xml +++ b/features/startchat/impl/src/main/res/values-hu/translations.xml @@ -5,7 +5,7 @@ "Hiba történt a csevegés indításakor" "Csatlakozás a szobához cím szerint" "Nem érvényes cím" - "Írja be…" + "Cím megadása…" "Megfelelő szoba található" "Szoba nem található" "pl. #szoba-neve:matrix.org" diff --git a/features/startchat/impl/src/main/res/values-it/translations.xml b/features/startchat/impl/src/main/res/values-it/translations.xml index 94818d7ab1..3c58bc6911 100644 --- a/features/startchat/impl/src/main/res/values-it/translations.xml +++ b/features/startchat/impl/src/main/res/values-it/translations.xml @@ -5,7 +5,7 @@ "Si è verificato un errore durante il tentativo di avviare una chat" "Accedi alla stanza tramite indirizzo" "Indirizzo non valido" - "Inserisci…" + "Inserisci l\'indirizzo…" "Stanza trovata" "Stanza non trovata" "ad esempio #room -name:matrix.org" diff --git a/features/startchat/impl/src/main/res/values-ja/translations.xml b/features/startchat/impl/src/main/res/values-ja/translations.xml index ed490becfc..52b287fcc8 100644 --- a/features/startchat/impl/src/main/res/values-ja/translations.xml +++ b/features/startchat/impl/src/main/res/values-ja/translations.xml @@ -5,7 +5,7 @@ "新しい会話を開始する際に問題が発生しました。" "アドレスからルームに参加" "有効なアドレスではありません" - "入力してください…" + "アドレスを入力…" "ルームが見つかりました" "ルームが見つかりません" "例) #room-name:matrix.org" diff --git a/features/startchat/impl/src/main/res/values-nb/translations.xml b/features/startchat/impl/src/main/res/values-nb/translations.xml index ffd8fe9cfc..9b96eee0a1 100644 --- a/features/startchat/impl/src/main/res/values-nb/translations.xml +++ b/features/startchat/impl/src/main/res/values-nb/translations.xml @@ -5,7 +5,7 @@ "Det oppstod en feil når du prøvde å starte en chat" "Bli med i rommet med adresse" "Ikke en gyldig adresse" - "Gå inn…" + "Skriv inn adresse…" "Matchende rom funnet" "Rom ikke funnet" "f.eks. #rom-navn:matrix.org" diff --git a/features/startchat/impl/src/main/res/values-ru/translations.xml b/features/startchat/impl/src/main/res/values-ru/translations.xml index 4a5fd0aef0..0031861825 100644 --- a/features/startchat/impl/src/main/res/values-ru/translations.xml +++ b/features/startchat/impl/src/main/res/values-ru/translations.xml @@ -5,7 +5,7 @@ "Произошла ошибка при попытке начать чат" "Присоединиться к комнате по адресу" "Недействительный адрес" - "Ввести…" + "Введите адрес…" "Комната найдена" "Комната не найдена" "прим. #room-name:matrix.org" 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 3447c07a7d..d68ec29229 100644 --- a/features/verifysession/impl/src/main/res/values-fa/translations.xml +++ b/features/verifysession/impl/src/main/res/values-fa/translations.xml @@ -2,8 +2,8 @@ "نمی‌توانید تأیید کنید؟" "ایجاد کلید بازیابی جدید" - "تأیید این افزاره برای برپایی پیام‌رسانی امن." - "تأیید هویتتان" + "گزینش چگونگی تأیید برای برپایی پیام‌رسانی امن." + "تأیید هویت دیجیتالیتان" "استفاده از افزاره‌ای دیگر" "استفاده از کلید بازیابی" "اکنون می‌توانید پیام‌ها را به صورت امن فرستاده و بگیرید و هرکسی که با او گپ می‌زنید نیز می‌تواند به این افزاره اعتماد کند." diff --git a/features/verifysession/impl/src/main/res/values-nb/translations.xml b/features/verifysession/impl/src/main/res/values-nb/translations.xml index 36a2e39c3d..bb448378cc 100644 --- a/features/verifysession/impl/src/main/res/values-nb/translations.xml +++ b/features/verifysession/impl/src/main/res/values-nb/translations.xml @@ -2,7 +2,7 @@ "Kan du ikke bekrefte?" "Opprett en ny gjenopprettingsnøkkel" - "Verifiser denne enheten for å sette opp sikker meldingsutveksling." + "Velg hvordan du vil verifisere deg for å sette opp sikker meldingsutveksling." "Bekreft din digitale identitet" "Bruk en annen enhet" "Bruk gjenopprettingsnøkkel" @@ -17,7 +17,7 @@ "Kontroller at tallene nedenfor stemmer overens med dem som vises på den andre sesjonen." "Sammenlign tallene" "Nå kan du lese eller sende meldinger sikkert på den andre enheten din." - "Nå kan du stole på identiteten til denne brukeren når du sender eller mottar meldinger." + "Nå kan du stole på den digitale identiteten til denne brukeren når du sender eller mottar meldinger." "Enhet verifisert" "Skriv inn gjenopprettingsnøkkel" "Enten ble forespørselen tidsavbrutt, forespørselen ble avslått eller det var en feil i verifiseringen." diff --git a/libraries/eventformatter/impl/src/main/res/values-ja/translations.xml b/libraries/eventformatter/impl/src/main/res/values-ja/translations.xml index 8613aae2df..4dba7e3303 100644 --- a/libraries/eventformatter/impl/src/main/res/values-ja/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-ja/translations.xml @@ -47,7 +47,7 @@ "あなたがルーム名を削除" "%1$s による変更はありません" "あなたによる変更はありません" - "%1$s はピン留めメッセージを変更しました" + "%1$s がピン留めメッセージを変更" "あなたがピン留めメッセージを変更しました" "%1$s がメッセージをピン留め" "あなたがメッセージをピン留め" diff --git a/libraries/matrixui/src/main/res/values-in/translations.xml b/libraries/matrixui/src/main/res/values-in/translations.xml index e7706afa76..30b3116511 100644 --- a/libraries/matrixui/src/main/res/values-in/translations.xml +++ b/libraries/matrixui/src/main/res/values-in/translations.xml @@ -3,5 +3,7 @@ "Kirim undangan" "Apakah Anda ingin memulai obrolan dengan %1$s?" "Kirim undangan?" + "Saat ini Anda belum memiliki obrolan dengan orang ini. Konfirmasikan undangan sebelum melanjutkan." + "Mau mulai obrolan dengan kontak baru ini?" "%1$s (%2$s) mengundang Anda" diff --git a/libraries/mediaviewer/impl/src/main/res/values-in/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-in/translations.xml index b5c2bde7cb..e4c4218aa7 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-in/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-in/translations.xml @@ -16,6 +16,7 @@ "Nama berkas" "Tidak ada lagi berkas untuk ditampilkan" "Tidak ada lagi media untuk ditampilkan" + "Informasi file" "Diunggah oleh" "Diunggah pada" diff --git a/libraries/mediaviewer/impl/src/main/res/values-uz/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-uz/translations.xml index 8f838c0d26..233d057039 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-uz/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-uz/translations.xml @@ -16,6 +16,7 @@ "Fayl nomi" "Ko‘rsatish uchun boshqa fayllar yo‘q" "Ko‘rsatish uchun boshqa media yo‘q" + "Fayl haqida" "Tomonidan yuklangan" "Yuklangan" diff --git a/libraries/permissions/impl/src/main/res/values-fa/translations.xml b/libraries/permissions/impl/src/main/res/values-fa/translations.xml index 8d566ef035..29ecf36e0c 100644 --- a/libraries/permissions/impl/src/main/res/values-fa/translations.xml +++ b/libraries/permissions/impl/src/main/res/values-fa/translations.xml @@ -1,4 +1,5 @@ + "بررسی امکان نمایش آگاهی‌ها در برنامه." "بررسی اجازه‌ها" diff --git a/libraries/push/impl/src/main/res/values-fa/translations.xml b/libraries/push/impl/src/main/res/values-fa/translations.xml index ef24f09c1e..4afd68e17b 100644 --- a/libraries/push/impl/src/main/res/values-fa/translations.xml +++ b/libraries/push/impl/src/main/res/values-fa/translations.xml @@ -55,9 +55,24 @@ "خدمات گوگل" "خدمت پلی گوگل معتبری پیدا نشد. ممکن است آگاهی‌ها به درستی کار نکنند." "کاربران مسدود" + "گرفتن نام فراهم کنندهٔ کنونی." + "هیچ فراهم کنندهٔ ارسالی گزیده نشده." + "فراهم کنندهٔ ارسال کنونی: %1$s." + "فراهم کنندهٔ ارسال کنونی" + "ازمینان از پشتیبانی برنامه از لااقل یک فراهم کنندهٔ ارسال." + "پشتیبانی از هیچ فراهم کنندهٔ ارسالی پیدا نشد." + "پشتیبانی از فراهم‌کنندهٔ ارسال" + "بررسی توانایی برنامه در نمایش آگاهی." + "روی آگاهی زده نشد." + "نمی‌توان آگاهی را نشان داد." "روی آگاهی کلیک شد!" + "نمایش آگاهی" + "زدن روی آگاهی برای ادامهٔ آزمون" + "اطمینان از این که برنامه ارسال را می‌گیرد." "خطا: فرستنده درخواست را رد کرد." "خطا: %1$s." "خطا. نتوانست فرستادن را بیازماید." "خطا. مهلت زمانی انتظار برای فرستادن سر رسید." + "باز خورد معکوس ارسال %1$d م‌ث طول کشید." + "بررسی بازخورد معکوس ارسال" diff --git a/libraries/push/impl/src/main/res/values-in/translations.xml b/libraries/push/impl/src/main/res/values-in/translations.xml index 0d6dc613ac..465f996ddd 100644 --- a/libraries/push/impl/src/main/res/values-in/translations.xml +++ b/libraries/push/impl/src/main/res/values-in/translations.xml @@ -11,7 +11,12 @@ "%d pemberitahuan" + "Distributor notifikasi UnifiedPush tidak dapat didaftarkan, sehingga Anda tidak akan lagi menerima notifikasi. Silakan periksa pengaturan notifikasi aplikasi dan status distributor push." "Anda memiliki pesan baru." + + "Anda memiliki %d pesan baru." + + "Panggilan masuk" "📹 Panggilan masuk" "** Gagal mengirim — silakan buka ruangan" "Gabung" @@ -33,7 +38,10 @@ "%1$s mengundang Anda untuk bergabung dengan ruangan" "Saya" "%1$s disebut atau dibalas" + "Kami mengundang Anda untuk bergabung di ruang ini." + "%1$s mengundang Anda untuk bergabung ke ruang ini." "Anda sedang melihat pemberitahuan ini! Klik saya!" + "Diskusi di %1$s" "%1$s: %2$s" "%1$s: %2$s %3$s" @@ -49,11 +57,18 @@ "Layanan Google" "Tidak ditemukan Layanan Google Play yang valid. Pemberitahuan mungkin tidak berfungsi dengan baik." "Memeriksa pengguna yang diblokir" + "Lihat pengguna yang diblokir" "Tidak ada pengguna yang diblokir." + + "Anda telah memblokir pengguna %1$d. Anda tidak akan menerima notifikasi dari pengguna tersebut." + "Pengguna yang diblokir" "Dapatkan nama penyedia saat ini." "Tidak ada penyedia notifikasi dorongan yang dipilih." + "Penyedia notifikasi dorongan saat ini: %1$s dan distributor saat ini: %2$s. Namun, distributor %3$s tidak ditemukan. Mungkin aplikasinya sudah dihapus?" + "Penyedia notifikasi dorongan saat ini: %1$s, tetapi belum ada distributor yang dikonfigurasi." "Penyedia notifikasi dorongan saat ini: %1$s." + "Penyedia notifikasi dorongan saat ini: %1$s (%2$s)" "Penyedia notifikasi dorongan saat ini" "Pastikan aplikasi memiliki setidaknya satu penyedia notifikasi dorongan." "Tidak ada penyedia notifikasi dorongan yang ditemukan." diff --git a/libraries/pushproviders/firebase/src/main/res/values-fa/translations.xml b/libraries/pushproviders/firebase/src/main/res/values-fa/translations.xml new file mode 100644 index 0000000000..df11b72c7f --- /dev/null +++ b/libraries/pushproviders/firebase/src/main/res/values-fa/translations.xml @@ -0,0 +1,11 @@ + + + "اطمینان از در دسترس بودن فایربیس." + "فایربیس در دسترس نیست." + "فایربیس در دسترس است." + "بررسی فایربیس" + "اطمینان از در دسترس بودن ژتون فایربیس." + "ژتون فایربیس شناخته نشده." + "ژتون فایربیس: %1$s." + "بررسی ژتون فایربیس" + diff --git a/libraries/pushproviders/unifiedpush/src/main/res/values-fa/translations.xml b/libraries/pushproviders/unifiedpush/src/main/res/values-fa/translations.xml new file mode 100644 index 0000000000..c80e952967 --- /dev/null +++ b/libraries/pushproviders/unifiedpush/src/main/res/values-fa/translations.xml @@ -0,0 +1,6 @@ + + + "اطمینان از در دسترس بودن توزیعگرهای ارسال یکپارچه." + "هیچ توزیعگر ارسال یکپارچه‌ای پیدا نشد." + "بررسی ارسال یکپارچه" + diff --git a/libraries/troubleshoot/impl/src/main/res/values-fa/translations.xml b/libraries/troubleshoot/impl/src/main/res/values-fa/translations.xml index 59f9ca6af6..14b52331c0 100644 --- a/libraries/troubleshoot/impl/src/main/res/values-fa/translations.xml +++ b/libraries/troubleshoot/impl/src/main/res/values-fa/translations.xml @@ -4,7 +4,9 @@ "اجرای آزمون‌ها" "اجرای دوبارهٔ آزمون‌ها" "برخی آزمون‌ها شکست خوردند. بررسی جزییات." + "اجرای آزمون‌ها برای تشخیص مشکلات در پیکربندیتان که می‌تواند باعث شود آگاهی آن‌گونه که انتظار می‌رود رفتار نکنند." "تلاش برای تعمیر" "همهٔ آزمون‌ها با موفّقیت گذرانده شدند." "رفع‌اشکال آگاهی‌ها" + "برخی آزم.ن‌ها نیازمند توجّهتانند. لطفاُ جزییات را بررسی کنید." 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 511581e672..ed250ea8fb 100644 --- a/libraries/ui-strings/src/main/res/values-be/translations.xml +++ b/libraries/ui-strings/src/main/res/values-be/translations.xml @@ -37,7 +37,6 @@ "Прачытана %1$s і %2$d іншымі" "Прачытана %1$s" - "Націсніце, каб паказаць усе" "Выдаліць рэакцыю з %1$s" "Адправіць файлы" "Паказаць пароль" diff --git a/libraries/ui-strings/src/main/res/values-ca/translations.xml b/libraries/ui-strings/src/main/res/values-ca/translations.xml index d8abb7ff73..5a4c1dd516 100644 --- a/libraries/ui-strings/src/main/res/values-ca/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ca/translations.xml @@ -26,7 +26,6 @@ "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" 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 5f45bea93b..ccd15c10c3 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -44,7 +44,6 @@ "Přečetl(a) %1$s a %2$d dalších" "%1$s přečetl(a)" - "Klepnutím zobrazíte vše" "Odstraňit reakci s %1$s" "Odstranit reakci pomocí %1$s" "Avatar místnosti" 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 00e2a39297..bed2fff573 100644 --- a/libraries/ui-strings/src/main/res/values-cy/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cy/translations.xml @@ -45,7 +45,6 @@ "Wedi\'i ddarllen gan %1$s a %2$d arall" "Wedi\'i ddarllen gan %1$s" - "Tapio i ddangos y cyfan" "Wedi dileu adwaith gyda %1$s" "Wedi dileu adwaith gyda %1$s" "Afatar ystafell" 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 ce79b8972b..41fe346190 100644 --- a/libraries/ui-strings/src/main/res/values-da/translations.xml +++ b/libraries/ui-strings/src/main/res/values-da/translations.xml @@ -42,7 +42,6 @@ "Læst af %1$s og %2$d andre" "Læst af%1$s" - "Tryk for at vise alle" "Fjern reaktion med%1$s" "Fjern reaktion med %1$s" "Avatar for rummet" 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 5b7f52cf4e..fe1eaac312 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -41,7 +41,6 @@ "Gelesen von %1$s und %2$d weiteren" "Gelesen von %1$s" - "Tippe, um alle anzuzeigen" "Reaktion mit %1$s entfernen" "Entferne Reaktionen mit %1$s" "Avatar" 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 927ab23afa..5bbfeb20e5 100644 --- a/libraries/ui-strings/src/main/res/values-el/translations.xml +++ b/libraries/ui-strings/src/main/res/values-el/translations.xml @@ -41,7 +41,6 @@ "Διαβάστηκε από %1$s και %2$d ακόμη" "Διαβάστηκε από %1$s" - "Πάτα για εμφάνιση όλων" "Αφαίρεση αντίδρασης με %1$s" "Αφαιρέστε την αντίδραση με %1$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 b03223a70e..c068e23d6c 100644 --- a/libraries/ui-strings/src/main/res/values-es/translations.xml +++ b/libraries/ui-strings/src/main/res/values-es/translations.xml @@ -27,7 +27,6 @@ "Leído por %1$s y %2$d otros" "Leído por %1$s" - "Pulsa para mostrar todo" "Elimina la reacción con %1$s" "Retirar la reacción con %1$s" "Avatar de la sala" 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 2a1d2504ff..dab809f74d 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -4,6 +4,7 @@ "Reageeri: %1$s" "Aadress" "Tunnuspilt" + "Tühjenda otsinguväli" "Vähenda tekstivälja" "Vähenda kasutaja kohta lubatud hääletuskordi" "Suurenda kasutaja kohta lubatud hääletuskordi" @@ -43,13 +44,13 @@ "QR-kood" "Reageeri emotikoniga %1$s" "Reageeri mõne muu emotikoniga" - "Seda lugesid %1$s ja %2$s" + "Eelmist sõnumit lugesid %1$s ja %2$s" - "Seda lugesid %1$s ja veel %2$d kasutaja" - "Seda lugesid %1$s ja veel %2$d kasutajat" + "Eelmist sõnumit luges %1$s ja veel %2$d kasutaja" + "Eelmist sõnumit lugesid %1$s ja veel %2$d kasutajat" - "Seda luges %1$s" - "Vaata kõiki" + "Eelmist sõnumit luges %1$s inimest" + "näita kõiki lugemiskinnitusi" "Eemalda reageerimine %1$s emotikoniga" "Eemalda reageerimine: %1$s" "Jututoa tunnuspilt" @@ -266,6 +267,14 @@ Põhjus: %1$s." "Edasta sõnum" "Sagedasti kasutatud" "Galerii" + + "%1$d manus…" + "%1$d manust…" + + + "%1$d multimeediaobjekt…" + "%1$d multimeediaobjekti…" + "GIF" "Rühmakõne on pooleli" "Pilt" @@ -303,6 +312,7 @@ Põhjus: %1$s." "Kogukonnal pole nime" "Krüptimata" "Võrgust väljas" + "Kõne on pooleli" "Avatud lähtekoodiga litsentsid" "või" "Muud valikud" @@ -432,6 +442,11 @@ Põhjus: %1$s." "Ootan asukoha jagamist reaalajas…" "Kõik võivad ajalugu näha" "Sina" + "Allalaadimist pole saadaval." + "Faili ei leidu" + "Skaneerin…" + "Eelvaade ja allalaadimine on lülitatud välja." + "See fail pole ohutu" "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" @@ -546,7 +561,7 @@ Kas sa oled kindel, et soovid jätkata?" "Kogukonnad" "Jagatud %1$s" "Kaardil" - + "%1$d liitus" "%1$d liitusid" 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 0c046b8bb4..a8e101cbf8 100644 --- a/libraries/ui-strings/src/main/res/values-eu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-eu/translations.xml @@ -28,7 +28,6 @@ "%1$s(e)k eta beste %2$d(e)k irakurri dute" "%1$s(e)k irakurri du" - "Egin tap guztiak ikusteko" "Kendu %1$s erreakzioa" "Gelaren abatarra" "Bidali fitxategiak" 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 c14f281f0d..6d377a9652 100644 --- a/libraries/ui-strings/src/main/res/values-fa/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fa/translations.xml @@ -29,13 +29,12 @@ "نظرسنجی پایان یافته" "واکنش با %1$s" "واکنش با شکلک‌های دیگر" - "خوانده به دست %1$s و %2$s" + "پیام پیشین به دست %1$s و %2$s خوانده شد" - "خوانده شده توسط%1$s و%2$d نفر دیگر" - "خوانده شده توسط%1$s و%2$d نفر دیگر" + "پیام پیشین به دست %1$s و %2$d دیگر خوانده شد" + "پیام پیشین به دست %1$s و %2$d دیگر خوانده شد" - "خوانده به دست %1$s" - "زدن برای نمایش همه" + "پیام قبلی به دست %1$s خوانده شد" "برداشتن واکنش با %1$s" "برداشتن واکنش با %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 096652fbd4..ef7d518779 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -1,9 +1,13 @@ + "Lisää avatar" "Lisää reaktio: %1$s" "Osoite" "Avatar" + "Tyhjennä hakukenttä" "Pienennä viestin tekstikenttä" + "Vähennä sallittujen äänien määrää per henkilö" + "Lisää sallittujen äänien määrää per henkilö" "Poista" "%1$d numero syötetty" @@ -29,6 +33,7 @@ "Sivu %1$d" "Keskeytä" "Ääniviesti, kesto: %1$s, nykyinen sijainti: %2$s" + "Kuvan esikatselu" "PIN-kenttä" "Kiinnitetty sijainti" "Toista" @@ -39,13 +44,13 @@ "QR-koodi" "Lisää reaktio: %1$s" "Reagoi muilla emojeilla" - "%1$s ja %2$s on lukenut viestin" + "%1$s ja %2$s ovat lukeneet edellisen viestin" - "%1$s ja %2$d muu on lukenut viestin" - "%1$s ja %2$d muuta on lukenut viestin" + "%1$s ja %2$d muu ovat lukeneet edellisen viestin" + "%1$s ja %2$d muuta ovat lukeneet edellisen viestin" - "%1$s on lukenut viestin" - "Näytä kaikki napauttamalla" + "%1$s on lukenut edellisen viestin" + "näytä kaikki lukukuittaukset" "Poista reaktio: %1$s" "Poista reaktio: %1$s" "Huoneen avatar" @@ -63,6 +68,7 @@ "Haudattu huone" "Käyttäjän avatar" "Käyttäjävalikko" + "Videon esikatselu" "Näytä avatar" "Näytä tiedot" "Ääniviesti, kesto: %1$s" @@ -191,9 +197,11 @@ "Käännä" "Yritä uudelleen" "Poista kiinnitys" + "Videopuhelu" "Näytä" "Näytä aikajanalla" "Näytä lähde" + "Äänipuhelu" "Kyllä" "Kyllä, yritä uudelleen" "Palvelimesi tukee nyt uutta, nopeampaa protokollaa. Kirjaudu ulos ja takaisin sisään päivittääksesi nyt. Jos teet tämän nyt, voit välttää pakotetun uloskirjautumisen, kun vanha protokolla poistetaan myöhemmin." @@ -214,6 +222,7 @@ "Estetyt käyttäjät" "Kuplat" "Puhelu hylätty" + "Puhelu käynnissä" "Puhelu alkoi" "Hylkäsit puhelun" "Keskustelujen varmuuskopiointi" @@ -257,7 +266,17 @@ Syy: %1$s." "Tiedosto tallennettu Lataukset-kansioon" "Välitä viesti" "Usein käytetyt" + "Galleria" + + "%1$d liite…" + "%1$d liitettä…" + + + "%1$d mediakohde…" + "%1$d mediakohdetta…" + "GIF" + "Ryhmäpuhelu käynnissä" "Kuva" "Vastauksena käyttäjälle %1$s" "Asenna APK" @@ -293,6 +312,7 @@ Syy: %1$s." "Nimetön tila" "Ei salattu" "Ei yhteyttä" + "Puhelussa" "Avoimen lähdekoodin lisenssit" "tai" "Muut vaihtoehdot" @@ -400,6 +420,7 @@ Syy: %1$s." "Poista mykistys" "Puhelu, jota ei tueta" "Tapahtumaa ei tueta" + "%1$s aloitti puhelun" "Käyttäjänimi" "Vahvistus peruttu" "Vahvistus suoritettu" @@ -421,6 +442,11 @@ Syy: %1$s." "Odotetaan reaaliaikaista sijaintia…" "Kuka tahansa voi nähdä historian" "Sinä" + "Lataus ei ole saatavilla." + "Tiedostoa ei löytynyt" + "Skannataan…" + "Esikatselu ja lataus on poistettu käytöstä." + "Tiedosto ei ole turvallinen" "%1$s (%2$s) jakoi tämän viestin, koska et ollut huoneessa, kun se lähetettiin." "%1$s jakoi tämän viestin, koska et ollut huoneessa, kun se lähetettiin." "Tämä huone on määritetty niin, että uudet jäsenet voivat lukea historiaa. %1$s" @@ -482,6 +508,7 @@ Haluatko varmasti jatkaa?" "Vaihtoehdot" "Poista %1$s" "Asetukset" + "Sallitut äänet per henkilö" "Kukaan ei jaa sijaintiaan" "Jaetaan reaaliaikaista sijaintia" @@ -534,6 +561,10 @@ Haluatko varmasti jatkaa?" "Tilat" "Jaettu %1$s" "Kartalla" + + "%1$d osallistujaa" + "%1$d osallistujaa" + "Viestiä ei lähetetty, koska käyttäjän %1$s vahvistettu digitaalinen identiteetti nollattiin." "Viestiä ei lähetetty, koska %1$s ei ole vahvistanut kaikkia laitteitaan." "Viestiä ei lähetetty, koska et ole vahvistanut yhtä tai useampaa laitettasi." 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 cbddbf5f08..a6cbd9b48e 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -4,6 +4,7 @@ "Ajouter une réaction: %1$s" "Adresse" "Avatar" + "Effacer le champ de recherche" "Réduire la taille du composeur" "Supprimer" @@ -46,7 +47,6 @@ "Lu par %1$s et %2$d autres" "Lu par %1$s" - "Taper pour voir toute la liste" "Supprimer la réaction avec %1$s" "Supprimer la réaction avec %1$s" "Avatar du salon" 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 369d8ccce4..03e24aebd3 100644 --- a/libraries/ui-strings/src/main/res/values-hr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hr/translations.xml @@ -1,15 +1,20 @@ + "Dodaj avatara" "Dodaj reakciju: %1$s" "Adresa" "Avatar" + "Izbriši polje za pretragu" "Minimiziraj tekstno polje poruke" + "Smanjenje dopuštenih glasova po osobi" + "Povećanje broja dopuštenih glasova po osobi" "Izbriši" "%1$d unesena znamenka" "%1$d unesene znamenke" "%1$d unesenih znamenaka" + "Trajanje: %1$s" "Uredi avatar" "Potpuna adresa bit će %1$s" "Pojedinosti o šifriranju" @@ -18,6 +23,7 @@ "Informacije" "Pridruži se pozivu" "Idi na dno" + "Skoči na nepročitano" "Pomakni kartu na moju lokaciju" "Samo spominjanja" "Bez zvuka" @@ -28,37 +34,42 @@ "Stranica %1$d" "Pauziraj" "Glasovna poruka, trajanje: %1$s, trenutačno zaustavljeno na: %2$s" + "Pregled fotografije" "Polje za PIN" "Prikvačena lokacija" "Reproduciraj" "Brzina reprodukcije" "Anketa" "Završena anketa" + "Pozicija: %1$s" "QR kod" "Reagiraj s %1$s" "Reagiraj s drugim emotikonima" "Pročitali %1$s i %2$s" - "Pročitao %1$s i ostalih %2$d" - "Pročitala %1$s i ostala %2$d" - "Pročitalo %1$s i ostalih %2$d" + "Prethodnu poruku pročitali su %1$s i %2$d" + "Prethodnu poruku pročitali su %1$s i %2$d drugi" - "Pročitao korisnik %1$s" - "Dodirnite za prikaz svih" + "Prethodnu poruku pročitao/la %1$s" + "prikaži sve potvrde o čitanju" "Ukloni reakciju: %1$s" "Ukloni reakciju s %1$s" "Avatar sobe" "Pošalji datoteke" "Lokacija pošiljatelja" + "Poslao %1$s u %2$s" "Potrebna je vremenski ograničena radnja, imate jednu minutu za potvrdu" "Postavke, potrebna je radnja" "Prikaži zaporku" "Započni poziv" "Započni videopoziv" "Započni glasovni poziv" + "Nit u %1$s" + "Teme u %1$s" "Soba označena za uklanjanje" "Korisnički avatar" "Korisnički izbornik" + "Pretpregled videozapisa" "Prikaži avatar" "Prikaži pojedinosti" "Glasovna poruka, trajanje: %1$s" @@ -73,6 +84,7 @@ "Poziv" "Odustani" "Otkaži za sada" + "Odaberite datoteku" "Odaberi fotografiju" "Očisti" "Zatvori" @@ -94,6 +106,7 @@ "Odbij i blokiraj" "Izbriši" "Izbriši račun" + "Izbriši datoteku" "Izbriši anketu" "Poništi sve odabire" "Onemogući" @@ -185,9 +198,11 @@ "Prevedi" "Pokušajte ponovno" "Otkvači" + "Videopoziv" "Prikaz" "Prikaži na vremenskoj traci" "Prikaži izvor" + "Glasovni poziv" "Da" "Da, pokušaj ponovno" "Vaš poslužitelj sada podržava novi, brži protokol. Odjavite se i ponovno prijavite da biste odmah izvršili nadogradnju. Ako to sada napravite, izbjeći ćete prisilnu odjavu kada se poslije ukloni stari protokol." @@ -208,6 +223,7 @@ "Blokirani korisnici" "Mjehurići" "Poziv je odbijen" + "Poziv je u tijeku" "Poziv je započeo" "Odbili ste poziv" "Sigurnosna kopija razgovora" @@ -251,7 +267,9 @@ Razlog: %1$s ." "Datoteka je spremljena u preuzimanja" "Proslijedi poruku" "Često korišteno" + "Galerija" "GIF" + "Grupni poziv u tijeku" "Slika" "Kao odgovor osobi %1$s" "Instaliraj APK" @@ -301,6 +319,7 @@ Razlog: %1$s ." "Pričekajte…" "Jeste li sigurni da želite završiti ovu anketu?" "Anketa: %1$s" + "Anketa" "Ukupno glasova: %1$s" "Rezultati će se objaviti nakon što završi anketa" @@ -399,6 +418,7 @@ Razlog: %1$s ." "Uključi zvuk" "Nepodržani poziv" "Nepodržani događaj" + "%1$s je započeo poziv" "Korisničko ime" "Provjera je otkazana" "Provjera je dovršena" @@ -420,6 +440,11 @@ Razlog: %1$s ." "Čekanje lokacije uživo…" "Svatko može vidjeti povijest" "Vi" + "Preuzimanje nije dostupno." + "Datoteka nije pronađena" + "Skeniranje…" + "Pregled i preuzimanje su onemogućeni." + "Datoteka nije sigurna" "%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" @@ -471,6 +496,9 @@ Jeste li sigurni da želite nastaviti?" "Žao nam je, došlo je do pogreške" "🔐️ Pridruži mi se u %1$s" "Hej, razgovaraj sa mnom u aplikaciji %1$s: %2$s" + "Dijeljenje lokacije uživo" + "Dijeljenje lokacije u tijeku" + "%1$s Lokacija uživo" "%1$s Android" "Snažno protresi za prijavu pogreške" "Snimka zaslona" @@ -478,6 +506,7 @@ Jeste li sigurni da želite nastaviti?" "Mogućnosti" "Ukloni %1$s" "Postavke" + "Dozvoljeni glasovi po osobi" "Nitko ne dijeli svoju lokaciju" "Dijeljenje lokacije uživo" @@ -532,6 +561,10 @@ Jeste li sigurni da želite nastaviti?" "Prostori" "Dijeljeno %1$s" "Na karti" + + "%1$d se pridružio" + "%1$d se pridružio" + "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." @@ -543,4 +576,6 @@ Jeste li sigurni da želite nastaviti?" "Nemate pristup ovoj poruci" "Nije moguće dešifrirati poruku" "Ova je poruka blokirana jer niste potvrdili svoj uređaj ili zato što pošiljatelj treba potvrditi vaš identitet." + "Vaš je uređaj prestar, potreban je uređaj s Androidom 8 ili novijim." + "Renderiranje mapa nije podržano" 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 131f6d5957..af1c071227 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -4,7 +4,10 @@ "Reakció hozzáadása: %1$s" "Cím" "Profilkép" + "Keresőmező törlése" "Üzenet szövegmezőjének minimalizálása" + "Személyenként engedélyezett szavazatok számának csökkentése" + "Személyenként engedélyezett szavazatok számának növelése" "Törlés" "%1$d megadott számjegy" @@ -30,6 +33,7 @@ "%1$d. oldal" "Szüneteltetés" "Hangüzenet, időtartam:%1$s, jelenlegi pozíció:%2$s" + "Fénykép előnézete" "PIN-mező" "Rögzített hely" "Lejátszás" @@ -40,13 +44,13 @@ "QR-kód" "Reagálás a következővel: %1$s" "Reagálás más emodzsikkal" - "Olvasta: %1$s és %2$s" + "Az előző üzenetet olvasta: %1$s és %2$s" - "Olvasta: %1$s és még %2$d felhasználó" - "Olvasta: %1$s és még %2$d felhasználó" + "Az előző üzenetet olvasta: %1$s és még %2$d felhasználó" + "Az előző üzenetet olvasta: %1$s és még %2$d felhasználó" - "Olvasta: %1$s" - "Koppintson az összes megjelenítéséhez" + "Az előző üzenetet olvasta: %1$s" + "összes olvasási visszajelzés megjelenítése" "Reakció eltávolítása: %1$s" "Reakció eltávolítása: %1$s" "Szoba profilképe" @@ -64,6 +68,7 @@ "Elévült szoba" "Felhasználói profilkép" "Felhasználói menü" + "Videó előnézete" "Profilkép megtekintése" "Részletek megtekintése" "Hangüzenet, időtartam: %1$s" @@ -192,9 +197,11 @@ "Fordítás" "Próbálja újra" "Kitűzés feloldása" + "Videóhívás" "Megtekintés" "Megtekintés az idővonalon" "Forrás megtekintése" + "Hanghívás" "Igen" "Igen, újrapróbálkozás" "A kiszolgálója mostantól egy új, gyorsabb protokollt támogat. A frissítéshez jelentkezzen ki, majd jelentkezzen be újra. Ha ezt most megteszi, elkerülheti a kényszerített kijelentkeztetést a régi protokollt eltávolításakor." @@ -215,6 +222,7 @@ "Letiltott felhasználók" "Buborékok" "Hívás elutasítva" + "Hívás folyamatban" "A hívás elindult" "Elutasított egy hívást" "Csevegés biztonsági mentése" @@ -258,7 +266,9 @@ Ok: %1$s." "A fájl a Letöltések mappába mentve" "Üzenet továbbítása" "Gyakran használt" + "Galéria" "GIF" + "Csoportos hívás folyamatban" "Kép" "Válasz erre: %1$s" "APK telepítése" @@ -400,6 +410,7 @@ Ok: %1$s." "Némítás feloldása" "Nem támogatott hívás" "Nem támogatott esemény" + "%1$s hívást indított" "Felhasználónév" "Az ellenőrzés megszakítva" "Az ellenőrzés befejeződött" @@ -421,6 +432,11 @@ Ok: %1$s." "Várakozás az élő helymeghatározásra…" "Bárki láthatja az előzményeket" "Ön" + "A letöltés nem érhető el." + "A fájl nem található" + "Keresés…" + "Az előnézet és a letöltés le van tiltva." + "A fájl nem biztonságos" "%1$s (%2$s) megosztotta ezt az üzenetet, mivel Ön nem volt a szobában, amikor elküldték." "%1$s megosztotta ezt az üzenetet, mivel Ön nem volt a szobában, amikor elküldték." "Az elküldött üzenetek megosztásra kerülnek a szobába meghívott új tagokkal.%1$s" @@ -482,6 +498,7 @@ Biztos, hogy folytatja?" "Lehetőségek" "Eltávolítás: %1$s" "Beállítások" + "Személyenként engedélyezett szavazatok száma" "Senki sem osztja meg a tartózkodási helyét" "Élő helymegosztás" @@ -534,6 +551,10 @@ Biztos, hogy folytatja?" "Terek" "Megosztva %1$s" "A térképen" + + "%1$d csatlakozott" + "%1$d csatlakozott" + "Az üzenet nem lett elküldve, mert %1$s ellenőrzött digitális személyazonossága alaphelyzetbe lett állítva." "Az üzenet nem lett elküldve, mert %1$s nem ellenőrizte az összes eszközét." "Az üzenet nem lett elküldve, mert egy vagy több eszközét nem ellenőrizte." 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 95b5aa4112..ac74be0e8e 100644 --- a/libraries/ui-strings/src/main/res/values-in/translations.xml +++ b/libraries/ui-strings/src/main/res/values-in/translations.xml @@ -1,19 +1,23 @@ "Tambahkan reaksi: %1$s" + "Alamat" "Avatar" "Minimalkan bidang teks message" "Hapus" "%1$d digit dimasukkan" + "Durasi: %1$s" "Sunting Avatar" "Alamat lengkapnya adalah%1$s" "Detail enkripsi" "Perluas kolom teks pesan" "Sembunyikan kata sandi" + "Informasi" "Bergabung dalam panggilan" "Lompat ke bawah" + "Lompat ke pesan yang belum dibaca" "Geser peta ke lokasi saya" "Hanya sebutan" "Dibisukan" @@ -25,24 +29,34 @@ "Jeda" "Pesan suara, durasi: %1$s, posisi saat ini: %2$s" "Kolom PIN" + "Lokasi yang ditandai" "Putar" + "Kecepatan pemutaran" "Jajak pendapat" "Jajak pendapat berakhir" + "Posisi: %1$s" + "Kode QR" "Bereaksi dengan %1$s" "Reaksi dengan emoji lain" - "Dibaca oleh %1$s dan %2$s" + "Pesan sebelumnya dibaca oleh %1$s dan %2$s" - "Dibaca oleh %1$s dan %2$d lainnya" + "Pesan sebelumnya telah dibaca oleh %1$s dan %2$d orang lainnya" - "Dibaca oleh %1$s" - "Ketuk untuk melihat semua" + "Pesan sebelumnya dibaca oleh %1$s" "Hapus reaksi dengan %1$s" "Hapus reaksi dengan %1$s" "Avatar ruangan" "Kirim berkas" + "Lokasi pengirim" + "Dikirim oleh %1$s pada %2$s." "Tindakan terbatas waktu diperlukan, Anda memiliki satu menit untuk memverifikasi" + "Pengaturan, tindakan yang diperlukan" "Tampilkan kata sandi" "Mulai panggilan" + "Mulai panggilan video" + "Mulai panggilan suara" + "Diskusi di %1$s" + "Utas di %1$s" "Ruangan yang ditandai" "Avatar pengguna" "Menu pengguna" @@ -54,11 +68,13 @@ "Avatar Anda" "Terima" "Tambahkan keterangan" + "Tambahkan ruangan yang sudah ada" "Tambahkan ke lini masa" "Kembali" "Panggil" "Batal" "Batalkan untuk saat ini" + "Pilih Berkas" "Pilih foto" "Hapus" "Tutup" @@ -73,25 +89,33 @@ "Salin teks" "Buat" "Buat room" + "Ciptakan ruang" "Nonaktifkan" "Nonaktifkan akun" "Tolak" "Tolak dan blokir" + "Hapus" + "Hapus akun" "Hapus jajak pendapat" + "Batalkan semua pilihan" "Nonaktifkan" "Abaikan" "Abaikan" "Selesai" + "Unduh" "Edit" "Edit keterangan" "Edit jajak pendapat" "Aktifkan" "Akhiri jajak pendapat" "Masukkan PIN" + "Jelajahi ruang publik" "Selesai" "Lupa kata sandi?" "Teruskan" "Kembali" + "Buka role &amp; permission" + "Buka Pengaturan" "Abaikan" "Undang" "Undang orang-orang" @@ -106,8 +130,11 @@ "Tinggalkan space" "Muat lainnya" "Kelola akun" + "Kelola akun &amp; perangkat" "Kelola perangkat" + "Kelola ruangan" "Kirim pesan" + "Perkecil" "Berikutnya" "Tidak" "Jangan sekarang" @@ -136,12 +163,14 @@ "Coba dekripsi ulang" "Simpan" "Cari" + "Pilih semua" "Kirim" "Kirim pesan tersunting" "Kirim pesan" "Kirim pesan suara" "Bagikan" "Bagikan tautan" + "Bagikan lokasi secara langsung" "Tampilkan" "Masuk lagi" "Hapus device dari akun" @@ -152,8 +181,10 @@ "Mulai dari awal" "Mulai verifikasi" "Ketuk untuk memuat peta" + "Berhenti" "Ambil foto" "Ketuk untuk opsi" + "Terjemahkan" "Coba lagi" "Lepaskan sematan" "Lihat" @@ -175,13 +206,17 @@ "Anda telah keluar dari sesi." "Penampilan" "Audio" + "Beta" "Pengguna yang diblokir" "Gelembung" + "Panggilan ditolak" "Panggilan dimulai" + "Anda menolak panggilan" "Pencadangan percakapan" "Disalin ke papan klip" "Hak cipta" "Membuat ruangan…" + "Menciptakan ruang…" "Permintaan dibatalkan" "Keluar dari ruangan" "Ruang tersisa" @@ -201,6 +236,7 @@ "Berkas kosong" "Enkripsi" "Enkripsi diaktifkan" + "Berakhir pada %1$s" "Masukkan PIN Anda" "Eror" "Terjadi kesalahan, Anda mungkin tidak menerima notifikasi pesan baru. Silakan memecahkan masalah notifikasi dari pengaturan. @@ -210,6 +246,7 @@ Alasan: %1$s." "Gagal" "Favorit" "Difavoritkan" + "Menyinkronkan notifikasi" "Berkas" "Berkas dihapus" "Berkas disimpan" @@ -222,8 +259,12 @@ Alasan: %1$s." "Pasang APK" "ID Matrix ini tidak dapat ditemukan, sehingga undangan mungkin tidak diterima." "Meninggalkan ruangan" + "Meninggalkan ruang" "Baris disalin ke papan klip" "Tautan disalin ke papan klip" + "Tautkan perangkat baru" + "Lokasi langsung" + "Lokasi langsung berakhir" "Memuat…" "Memuat lebih banyak…" @@ -234,17 +275,21 @@ Alasan: %1$s." "Pesan" "Tindakan pesan" + "Pesan Gagal Terkitim" "Tata letak pesan" "Pesan dihapus" "Modern" "Bisukan" + "Nama" "%1$s (%2$s)" "Tidak ada hasil" "Tidak ada nama ruangan" + "Tidak ada nama ruang" "Tidak terenkripsi" "Luring" "Lisensi sumber terbuka" "atau" + "Pilihan lain" "Kata sandi" "Orang" "Tautan Permanen" @@ -261,8 +306,10 @@ Alasan: %1$s." "Menyiapkan…" "Kebijakan privasi" + "Pribadi" "Ruangan pribadi" "Space pribadi" + "Umum" "Ruangan publik" "Space publik" "Reaksi" @@ -270,6 +317,7 @@ Alasan: %1$s." "Alasan" "Kunci pemulihan" "Menyegarkan…" + "Menghapus…" "%1$d balasan" @@ -277,9 +325,13 @@ Alasan: %1$s." "Laporkan masalah" "Laporan terkirim" "Penyunting teks kaya" + "Peran" "Ruangan" "Nama ruangan" "misalnya, nama proyek Anda" + + "Ruangan %1$d" + "Perubahan disimpan" "Menyimpan" "Layar kunci" @@ -288,6 +340,9 @@ Alasan: %1$s." "Keamanan" "Dilihat oleh" "Pilih akun" + + "%1$d terpilih" + "Kirim ke" "Mengirim…" "Pengiriman gagal" @@ -298,19 +353,29 @@ Alasan: %1$s." "URL Server" "Pengaturan" "Berbagi ruang" + "Anggota baru dapat melihat riwayat" + "Lokasi langsung yang dibagikan" "Lokasi terbagi" + "Ruang bersama" "Melepaskan perangkat" "Ada yang salah" "Kami mengalami masalah. Silakan coba lagi." "Space" + "Anggota space" + "Ruang ini tentang apa?" + + "Ruang %1$d" + "Memulai obrolan…" "Stiker" "Berhasil" + "Disarankan" "Saran" "Menyinkronkan" "Teks" "Pemberitahuan pihak ketiga" "Utas" + "Utas" "Topik" "Apa yang dibahas di room ini?" "Tidak dapat mendekripsi" @@ -341,13 +406,19 @@ Alasan: %1$s." "Pesan suara" "Menunggu…" "Menunggu pesan ini" + "Menunggu lokasi real-time…" + "Siapa pun dapat melihat riwayat" "Anda" + "%1$s (%2$s) membagikan pesan ini karena Anda tidak berada di ruangan saat pesan ini dikirim." + "%1$s membagikan pesan ini karena Anda tidak berada di ruangan saat pesan ini dikirim." + "Ruangan ini telah dikonfigurasi agar anggota baru dapat membaca riwayat. %1$s" "Identitas %1$s telah diatur ulang. %2$s" "Identitas %2$s %1$s telah diatur ulang. %3$s" "(%1$s)" "Identitasnya %1$s sudah diatur ulang." "Identitas %2$s %1$s telah diatur ulang. %3$s" "Tolak verifikasi" + "Izinkan akses" "Tautan %1$s membawa Anda ke situs lain %2$s Apakah Anda yakin ingin melanjutkan?" @@ -377,6 +448,7 @@ Apakah Anda yakin ingin melanjutkan?" "%1$s tidak dapat mengakses lokasi Anda. Silakan coba lagi nanti." "Gagal mengunggah pesan suara Anda." "Ruangan tidak ada lagi atau undangan tidak lagi valid." + "Silakan aktifkan GPS Anda untuk mengakses fitur berbasis lokasi." "Pesan tidak ditemukan" "%1$s tidak memiliki izin untuk mengakses lokasi Anda. Anda dapat mengaktifkan akses di Pengaturan." "%1$s tidak memiliki izin untuk mengakses lokasi Anda. Aktifkan akses di bawah ini." @@ -388,6 +460,9 @@ Apakah Anda yakin ingin melanjutkan?" "Maaf, terjadi kesalahan" "🔐️ Bergabunglah dengan saya di %1$s" "Hai, bicaralah dengan saya di %1$s: %2$s" + "Pembagian lokasi langsung" + "Sedang berbagi lokasi" + "Lokasi Langsung %1$s" "%1$s Android" "Rageshake untuk melaporkan kutu" "Tangkapan layar" @@ -395,6 +470,12 @@ Apakah Anda yakin ingin melanjutkan?" "Opsi" "Hapus %1$s" "Pengaturan" + "Tidak ada yang membagikan lokasinya" + "Berbagi lokasi secara langsung" + + "%1$d orang" + + "Di peta" "Gagal memilih media, silakan coba lagi." "Tekan pesan dan pilih “%1$s” untuk disertakan di sini." "Sematkan pesan penting agar mudah ditemukan" @@ -418,6 +499,7 @@ Apakah Anda yakin ingin melanjutkan?" "Pesan dalam %1$s" "Buka" "Kurangi" + "Berbagi lokasi secara langsung" "Sudah melihat ruangan ini!" "%1$s dari %2$s" "%1$s Pesan yang disematkan" @@ -430,9 +512,14 @@ Apakah Anda yakin ingin melanjutkan?" "Buka di Google Maps" "Buka di OpenStreetMap" "Bagikan lokasi ini" + "Opsi Berbagi" "Space yang Anda buat atau ikuti." "%1$s • %2$s" + "Ciptakan ruang untuk menata ruangan." + "Ruang %1$s" "Space" + "Dibagikan %1$s" + "Di peta" "Pesan tidak terkirim karena identitas terverifikasi %1$s telah diatur ulang." "Pesan tidak terkirim karena %1$s belum memverifikasi semua perangkat." "Pesan tidak terkirim karena Anda belum memverifikasi satu atau beberapa perangkat Anda." 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 d1ec78d920..394e043e07 100644 --- a/libraries/ui-strings/src/main/res/values-it/translations.xml +++ b/libraries/ui-strings/src/main/res/values-it/translations.xml @@ -1,14 +1,19 @@ + "Aggiungi avatar" "Aggiungi reazione: %1$s" "Indirizzo" "Avatar" + "Cancella campo di ricerca" "Riduci al minimo il campo di testo del messaggio" + "Riduci il numero di voti consentiti per persona" + "Aumenta il numero di voti consentiti per persona" "Elimina" "%1$d cifra inserita" "%1$d cifre inserite" + "Durata: %1$s" "Modifica avatar" "L\'indirizzo completo sarà %1$s" "Dettagli sulla crittografia" @@ -17,6 +22,7 @@ "Info" "Entra in chiamata" "Vai alla fine" + "Vai ai messaggi non letti" "Sposta la mappa sulla mia posizione" "Solo menzioni" "Silenziato" @@ -27,36 +33,42 @@ "Pagina %1$d" "Pausa" "Messaggio vocale, durata: %1$s, posizione attuale: %2$s" + "Anteprima foto" "Campo del PIN" "Posizione fissata" "Riproduci" "Velocità di riproduzione" "Sondaggio" "Sondaggio terminato" + "Posizione: %1$s" "Codice QR" "Reagisci con %1$s" "Reagisci con altri emoji" - "Visualizzato da %1$s e %2$s" + "Messaggio precedente letto da %1$s e %2$s" - "Visualizzato da %1$s e %2$d altro" - "Visualizzato da %1$s e altri %2$d" + "Messaggio precedente letto da %1$s e %2$d altro" + "Messaggio precedente letto da %1$s e %2$d altri" - "Visualizzato da %1$s" - "Tocca per mostrare tutti" + "Messaggio precedente letto da %1$s" + "mostra tutte le conferme di lettura" "Rimuovi la reazione con %1$s" "Rimuovere la reazione con %1$s" "Avatar della stanza" "Invia file" "Posizione del mittente" + "Inviato da %1$s alle %2$s" "Azione richiesta a tempo limitato, hai un minuto per la verifica" "Impostazioni, azione richiesta" "Mostra password" "Avvia una chiamata" "Avvia una videochiamata" "Avvia una chiamata vocale" + "Discussione in %1$s" + "Discussioni in %1$s" "Stanza obsoleta" "Avatar utente" "Menu utente" + "Anteprima video" "Visualizza avatar" "Visualizza dettagli" "Messaggio vocale, durata: %1$s" @@ -93,6 +105,7 @@ "Rifiuta e blocca" "Elimina" "Elimina account" + "Elimina file" "Elimina sondaggio" "Deseleziona tutti" "Disabilita" @@ -184,9 +197,11 @@ "Traduci" "Riprova" "Rimuovi dai fissati" + "Videochiamata" "Visualizza" "Visualizza nella conversazione" "Vedi codice sorgente" + "Chiamata vocale" "Sì" "Sì, riprova" "Il tuo server ora supporta un nuovo protocollo più veloce. Esci e rientra per effettuare l\'aggiornamento. Se lo fai ora, eviterai una disconnessione forzata quando il vecchio protocollo verrà rimosso in seguito." @@ -207,6 +222,7 @@ "Utenti bloccati" "Fumetti" "Chiamata rifiutata" + "Chiamata in corso" "Chiamata avviata" "Hai rifiutato una chiamata" "Backup della chat" @@ -250,7 +266,9 @@ Motivo:. %1$s" "File salvato" "Inoltra messaggio" "Usati di frequente" + "Galleria" "GIF" + "Chiamata di gruppo in corso" "Immagine" "In risposta a %1$s" "Installa APK" @@ -298,6 +316,7 @@ Motivo:. %1$s" "Attendere prego…" "Vuoi davvero terminare questo sondaggio?" "Sondaggio: %1$s" + "Sondaggio" "Voti totali: %1$s" "I risultati verranno mostrati al termine del sondaggio" @@ -392,6 +411,7 @@ Motivo:. %1$s" "Annulla silenzioso" "Chiamata non supportata" "Evento non supportato" + "%1$s ha avviato una chiamata" "Nome utente" "Verifica annullata" "Verifica completata" @@ -413,6 +433,10 @@ Motivo:. %1$s" "In attesa della posizione in tempo reale…" "Chiunque può vedere la cronologia" "Tu" + "Download non disponibile." + "File non trovato" + "L\'anteprima e il download sono stati disabilitati." + "Il file non è sicuro" "%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" @@ -464,6 +488,7 @@ 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 posizione in tempo reale" "Condivisione della posizione in corso" "%1$s Posizione in tempo reale" "%1$s Android" @@ -473,6 +498,7 @@ Sei sicuro di voler continuare?" "Risposte" "Rimuovi %1$s" "Impostazioni" + "Voti consentiti per persona" "Nessuno sta condividendo la propria posizione" "Condivisione posizione in tempo reale" @@ -536,4 +562,6 @@ Sei sicuro di voler continuare?" "Non hai accesso a questo messaggio" "Impossibile decifrare il messaggio" "Questo messaggio è stato bloccato perché non hai verificato il tuo dispositivo o perché il mittente deve verificare la tua identità digitale." + "Il tuo dispositivo è troppo vecchio, è necessario un dispositivo con Android 8 o versioni successive." + "Il rendering delle mappe non è supportato" 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 a9bdedc1c1..9ab50981dc 100644 --- a/libraries/ui-strings/src/main/res/values-ja/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ja/translations.xml @@ -1,9 +1,12 @@ + "アバターを追加" "リアクションを追加: %1$s" "アドレス" "アバター" "入力欄を縮小" + "一人あたりの投票権を減らす" + "一人あたりの投票権を増やす" "削除" "%1$d 桁入力済" @@ -28,6 +31,7 @@ "%1$d ページ" "一時停止" "音声メッセージ 長さ: %1$s 再生位置: %2$s" + "画像のプレビュー" "PIN入力欄" "ピン留めした位置情報" "再生" @@ -43,7 +47,6 @@ "既読: %1$s ほか %2$d 人" "%1$s 既読" - "タップしてすべて表示" "%1$s リアクションを削除" "%1$s リアクションを削除" "ルームのアバター" @@ -61,6 +64,7 @@ "埋没したルーム" "ユーザーのアバター" "ユーザーメニュー" + "動画のプレビュー" "アバターを表示" "詳細を表示" "音声メッセージ 長さ: %1$s" @@ -189,9 +193,11 @@ "翻訳" "もう一度やり直してください" "ピン留めを解除" + "ビデオ通話" "表示" "タイムラインで表示" "ソースコードを表示" + "音声通話" "はい" "再試行する" "使用しているサーバーがより高速な新しいプロトコルに対応しました。将来、古いプロトコルへの対応が打ち切られ、強制的にログアウトされる可能性があるため、今すぐにログアウトし、再度ログインし直すことを推奨します。" @@ -212,6 +218,7 @@ "ブロックしたユーザー" "ふきだし" "通話を拒否しました" + "通話が進行中" "通話を開始しました" "通話を拒否しました" "チャットをバックアップ" @@ -255,7 +262,9 @@ "ファイルはダウンロードに保存されました" "メッセージを転送" "頻繁に使用" + "ギャラリー" "GIF" + "グループ通話が進行中" "画像" "%1$s に返信" "APK をインストール" @@ -391,6 +400,7 @@ "ミュート解除" "非対応の通話" "非対応のイベント" + "%1$s が通話を開始" "ユーザー名" "検証がキャンセルされました" "検証完了" @@ -446,7 +456,7 @@ "この端末では既に %1$s としてログインしています。" "Matrix Authentication Service とアカウント作成に対応するため、このホームサーバーはアップグレードが必要です。" "固定リンクの作成に失敗しました" - "%1$s でマップを読み込めません。時間を置いて再度お試しください。" + "%1$s で地図を読み込めません。時間を置いて再度お試しください。" "メッセージの読み込みに失敗しました" "%1$s は現在地にアクセスできませんでした。時間を置いて再度お試しください。" "音声メッセージの送信に失敗しました。" @@ -473,6 +483,7 @@ "選択肢" "%1$s を削除" "設定" + "一人あたりの投票数" "誰も位置情報を共有していません" "ライブ位置情報を共有しています" @@ -522,7 +533,7 @@ "%1$s スペース" "スペース" "%1$s 共有" - "マップ上" + "地図上" "%1$s の検証済みのデジタルIDがリセットされたため、メッセージは送信されませんでした。" "%1$s に未検証の端末が存在するため、メッセージは送信されませんでした。" "未検証の端末が存在するため、メッセージは送信されませんでした。" @@ -534,4 +545,6 @@ "このメッセージにアクセスできません" "メッセージの復号化に失敗" "この端末を検証していないか、送信者があなたのデジタルIDを検証していないため、このメッセージはブロックされました。" + "使用している端末が古すぎます。Android 8以上が必要です。" + "地図のレンダリングに対応していません" 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 2be4e43d61..fff6af16fd 100644 --- a/libraries/ui-strings/src/main/res/values-ka/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ka/translations.xml @@ -23,7 +23,6 @@ "წაკითხულია %1$s და %2$d-ს ადამიანის მიერ" "წაიკითხეს: %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 6336a8de92..3010ef136c 100644 --- a/libraries/ui-strings/src/main/res/values-ko/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ko/translations.xml @@ -43,7 +43,6 @@ "읽은 사람 %1$s 그리고 %2$d 다른 사람들" "%1$s 님이 읽음" - "모두 표시하려면 탭하세요" "반응 제거: %1$s" "%1$s 반응을 제거하세요" "방 아바타" 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 aa594f8027..60ee544965 100644 --- a/libraries/ui-strings/src/main/res/values-nb/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nb/translations.xml @@ -35,13 +35,12 @@ "QR-kode" "Reager med %1$s" "Reager med andre emojier" - "Lest av %1$s og %2$s" + "Forrige melding lest av %1$s og %2$s" - "Lest av %1$s og %2$d andre" - "Lest av %1$s og %2$d andre" + "Forrige melding lest av %1$s og %2$d annen" + "Forrige melding lest av %1$s og %2$d andre" - "Lest av %1$s" - "Trykk for å vise alle" + "Forrige melding lest av %1$s" "Fjern reaksjonen med %1$s" "Fjern reaksjonen med %1$s" "Romavatar" @@ -120,6 +119,7 @@ "Forlat område" "Last inn mer" "Administrer konto" + "Administrer konto og enheter" "Administrer enheter" "Administrer rom" "Melding" @@ -170,6 +170,7 @@ "Begynn på nytt" "Start verifisering" "Trykk for å laste inn kart" + "Stopp" "Ta bilde" "Trykk for alternativer" "Oversett" @@ -231,6 +232,7 @@ "Mislyktes" "Favoritt" "Favoritt" + "Synkroniserer varsler …" "Fil" "Fil slettet" "Fil lagret" @@ -247,6 +249,8 @@ "Linje kopiert til utklippstavlen" "Lenke kopiert til utklippstavlen" "Koble til ny enhet" + "Sanntidslokasjon" + "Sanntidslokasjon er avsluttet" "Laster inn…" "Laster inn mer…" @@ -340,6 +344,7 @@ "Innstillinger" "Del område" "Nye medlemmer ser historikk" + "Delt lokasjon i sanntid" "Delt posisjon" "Delt område" "Fjerner enheten" @@ -366,7 +371,7 @@ "Kan ikke dekryptere" "Sendt fra en usikker enhet" "Du har ikke tilgang til denne meldingen" - "Avsenderens verifiserte identitet ble tilbakestilt" + "Avsenderens verifiserte digitale identitet ble tilbakestilt" "Invitasjoner kunne ikke sendes til en eller flere brukere." "Kunne ikke sende invitasjon(er)" "Lås opp" @@ -391,16 +396,17 @@ "Talemelding" "Venter…" "Venter på denne meldingen" + "Venter på sanntidslokasjon…" "Alle kan se historikk" "Du" "%1$s (%2$s) delte denne meldingen siden du ikke var i rommet da den ble sendt." "%1$s delte denne meldingen siden du ikke var i rommet da den ble sendt." "Dette rommet er konfigurert slik at nye medlemmer kan lese historikken.%1$s" - "%1$s\'s identitet ble tilbakestilt. %2$s" - "%1$ss %2$s-identitet ble tilbakestilt. %3$s" + "%1$ss digitale identitet ble tilbakestilt. %2$s" + "%1$ss digitale identitet %2$s ble tilbakestilt. %3$s" "(%1$s)" - "%1$ss identitet ble tilbakestilt." - "%1$ss %2$s identitet ble tilbakestilt. %3$s" + "%1$ss digitale identitet ble tilbakestilt." + "%1$ss digitale identitet %2$s ble tilbakestilt. %3$s" "Trekk tilbake verifisering" "Tillat tilgang" "Lenken %1$s tar deg til et annet nettsted %2$s @@ -458,11 +464,11 @@ Er du sikker på at du vil fortsette?" "%1$d Festede meldinger" "Festede meldinger" - "Du er i ferd med å gå til %1$s kontoen din for å tilbakestille identiteten din. Etterpå blir du tatt tilbake til appen." - "Kan du ikke bekrefte? Gå til kontoen din for å tilbakestille identiteten din." + "Du er i ferd med å gå til din %1$s for å tilbakestille din digitale identitet. Etterpå blir du ført tilbake til appen." + "Kan du ikke bekrefte? Gå til kontoen din for å tilbakestille den digitale identiteten din." "Trekk tilbake verifikasjon og send" "Du kan trekke tilbake verifiseringen og sende denne meldingen likevel, eller du kan avbryte for nå og prøve igjen senere etter at du har reverifisert %1$s." - "Meldingen din ble ikke sendt fordi %1$ss verifiserte identitet er tilbakestilt" + "Meldingen din ble ikke sendt fordi %1$s verifiserte digitale identitet ble tilbakestilt" "Send melding uansett" "%1$s bruker én eller flere uverifiserte enheter. Du kan sende meldingen uansett, eller du kan avbryte foreløpig og prøve igjen senere etter at %2$s har verifisert alle enhetene sine." "Meldingen din ble ikke sendt fordi %1$s ikke har bekreftet alle enhetene" @@ -486,6 +492,7 @@ Er du sikker på at du vil fortsette?" "Åpne i Google Maps" "Åpne i OpenStreetMap" "Del valgt lokasjon" + "Delingsalternativer" "Områder du har opprettet eller blitt med i." "%1$s • %2$s" "Opprett område for å organisere rom" @@ -493,7 +500,7 @@ Er du sikker på at du vil fortsette?" "Områder" "Delt %1$s" "På kartet" - "Meldingen ble ikke sendt fordi %1$ss verifiserte identitet er tilbakestilt." + "Meldingen ble ikke sendt fordi %1$s verifiserte digitale identitet ble tilbakestilt." "Meldingen ble ikke sendt fordi %1$s ikke har verifisert alle enheter." "Meldingen ble ikke sendt fordi du ikke har verifisert en eller flere av enhetene dine." "Posisjon" @@ -503,5 +510,5 @@ Er du sikker på at du vil fortsette?" "Du må verifisere denne enheten for å få tilgang til historiske meldinger" "Du har ikke tilgang til denne meldingen" "Kan ikke dekryptere meldingen" - "Denne meldingen ble blokkert enten fordi du ikke har bekreftet enheten din, eller fordi avsenderen må bekrefte identiteten din." + "Denne meldingen ble blokkert enten fordi du ikke verifiserte enheten din, eller fordi avsenderen må verifisere din digitale identitet." 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 3edeeb00a0..e13f4bace4 100644 --- a/libraries/ui-strings/src/main/res/values-nl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nl/translations.xml @@ -34,7 +34,6 @@ "Gelezen door %1$s en %2$d anderen" "Gelezen door %1$s" - "Tik om alles weer te geven" "Verwijder reactie met %1$s" "Reactie met %1$s verwijderen" "Kamerafbeelding" 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 e07f564f3b..fcea19da49 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -4,6 +4,7 @@ "Dodaj reakcję: %1$s" "Adres" "Awatar" + "Wyczyść pole wyszukiwania" "Zmniejsz pole tekstowe wiadomości" "Zmniejsz liczbę głosów dozwolonych na osobę" "Zwiększ liczbę głosów dozwolonych na osobę" @@ -44,14 +45,14 @@ "Kod QR" "Zareaguj z %1$s" "Zareaguj innym emoji" - "Odczytane przez %1$s i %2$s" + "Poprzednia wiadomość przeczytana przez %1$s i %2$s" - "Odczytano przez %1$s i %2$d inną" - "Odczytano przez %1$s i %2$d innych" - "Odczytano przez %1$s i %2$d innych" + "Poprzednia wiadomość przeczytana przez %1$s i %2$d inną osobę" + "Poprzednia wiadomość przeczytana przez %1$s i %2$d inne osoby" + "Poprzednia wiadomość przeczytana przez %1$s i %2$d innych osób" - "Odczytane przez %1$s" - "Stuknij, aby pokazać wszystkich" + "Poprzednia wiadomość przeczytana przez %1$s" + "pokaż wszystkie potwierdzenia odczytu" "Usuń reakcję %1$s" "Usuń reakcję z %1$s" "Awatar pokoju" @@ -441,6 +442,11 @@ Powód: %1$s." "Czekam na lokalizację na żywo…" "Każdy może zobaczyć historię" "Ty" + "Pobieranie niedostępne." + "Nie znaleziono pliku" + "Skanuję…" + "Podgląd i pobieranie zostały wyłączone." + "Ten plik nie jest bezpieczny" "%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" @@ -557,10 +563,10 @@ Czy na pewno chcesz kontynuować?" "Przestrzenie" "Udostępnianie %1$s" "Na mapie" - - "+ %1$d dołączył" - "+ %1$d dołączyło" - "+ %1$d dołączyło" + + "%1$d dołączyła" + "%1$d dołączyły" + "%1$d dołączyło" "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ń." 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 8ba2d1f107..474d1c8917 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 @@ -37,7 +37,6 @@ "Lido por %1$s e outros %2$d" "Lido por %1$s" - "Toque para mostrar tudo" "Remover reação com %1$s" "Remover reação com %1$s" "Avatar da sala" 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 0acc939565..e8d32ee72e 100644 --- a/libraries/ui-strings/src/main/res/values-pt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt/translations.xml @@ -37,7 +37,6 @@ "Lida por %1$s e %2$d outros" "Lida por %1$s" - "Toca para mostrar tudo" "Remover reação com %1$s" "Remover reação com %1$s" "Ícone da sala" 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 dfd68686ce..bdb220c9a0 100644 --- a/libraries/ui-strings/src/main/res/values-ro/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ro/translations.xml @@ -44,7 +44,6 @@ "Citit de %1$s și incă %2$d" "Citit de %1$s" - "Atingeți pentru a le afișa pe toate" "Îndepărtați reacția cu %1$s" "Îndepărtați reacția %1$s" "Avatarul camerei" 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 5c53c600d5..cd711bf18b 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -1,9 +1,13 @@ + "Добавить аватар" "Добавить реакцию: %1$s" "Адрес" "Аватар" + "Очистить поле поиска" "Свернуть поле ввода" + "Уменьшить количество голосов, разрешенных на одного человека" + "Увеличь количество голосов, разрешенных на одного человека" "Удалить" "Введена %1$d цифра" @@ -30,6 +34,7 @@ "Страница %1$d" "Приостановить" "Голосовое сообщение, длительность: %1$s, текущая позиция: %2$s" + "Пред. просмотр фото" "Поле PIN-кода" "Закреплённое местоположение" "Воспроизвести" @@ -42,12 +47,12 @@ "Реакция с помощью эмодзи" "Прочитано %1$s и %2$s" - "Прочитано %1$s и %2$d другим" - "Прочитано %1$s и %2$d другими" - "Прочитано %1$s и %2$d другими" + "Предыдущее сообщение прочитано пользователями %1$s и %2$d." + "Предыдущее сообщение прочитано пользователями %1$s и %2$d." + "Предыдущие сообщения прочитаны пользователями %1$s и %2$d." - "Прочитано %1$s" - "Нажмите, чтобы показать все" + "Предыдущее сообщение прочитали %1$s человек" + "показать все уведомления о прочтении" "Удалить реакцию с %1$s" "Удалить реакцию %1$s" "Аватар комнаты" @@ -65,6 +70,7 @@ "Брошенная комната" "Аватар пользователя" "Меню пользователя" + "Видео-превью" "Просмотреть аватар" "Подробнее" "Голосовое сообщение, продолжительность: %1$s" @@ -193,9 +199,11 @@ "Перевести" "Повторить попытку" "Открепить" + "Видеозвонок" "Просмотреть" "Просмотреть в хронологии" "Показать источник" + "Голосовой звонок" "Да" "Да, попробовать ещё раз" "Теперь Ваш сервер поддерживает новый, более быстрый протокол. Чтобы обновить его прямо сейчас, выйдите и войдите в свою учётную запись снова. Сделав это сейчас, Вы сможете избежать принудительного выхода из системы при последующем удалении старого протокола." @@ -216,6 +224,7 @@ "Заблокированные пользователи" "Пузыри" "Вызов отклонен" + "Звонок выполняется" "Звонок начат" "Ты отклонил звонок" "Резервная копия чатов" @@ -259,7 +268,9 @@ "Файл сохранен в «Загрузки»" "Переслать сообщение" "Часто используемые" + "Галерея" "GIF" + "Выполняется групповой звонок" "Изображение" "В ответ %1$s" "Установить APK" @@ -409,6 +420,7 @@ "Вкл. звук" "Неподдерживаемый вызов" "Неподдерживаемое событие" + "%1$s начал звонок" "Имя пользователя" "Подтверждение отменено" "Подтверждение завершено" @@ -430,6 +442,10 @@ "Ожидание трансляции местоположения…" "Любой может видеть историю" "Вы" + "Загрузка недоступна." + "Файл не найден" + "Пред. просмотр и загрузка отключены." + "Файл небезопасен" "%1$s (%2$s) поделился(ась) этим сообщением, поскольку Вас не было в комнате, когда оно было отправлено." "%1$s поделился(ась) этим сообщением, поскольку Вас не было в комнате, когда оно было отправлено." "Эта комната настроена так, что новые участники могут видеть историю. %1$s" @@ -491,6 +507,7 @@ "Параметры" "Удалить %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 11f4b22005..f4f03fd3b8 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -41,7 +41,6 @@ "Prečítal/a %1$s a %2$d ďalších" "Prečítal/a %1$s" - "Ťuknutím zobrazíte všetko" "Odstrániť reakciu s %1$s" "Odstrániť reakciu s %1$s" "Obrázok miestnosti" 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 28dd63d425..ea7ba155c4 100644 --- a/libraries/ui-strings/src/main/res/values-sv/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sv/translations.xml @@ -37,7 +37,6 @@ "Läst av %1$s och %2$d andra" "Läst av %1$s" - "Tryck för att visa alla" "Ta bort reaktionen med %1$s" "Ta bort reaktion med %1$s" "Rumsavatar" 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 d500b57507..5bbce8a391 100644 --- a/libraries/ui-strings/src/main/res/values-tr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-tr/translations.xml @@ -1,6 +1,7 @@ "Tepki ekle:%1$s" + "Adres" "Profil resmi" "Mesaj metin alanını küçült" "Sil" @@ -8,13 +9,16 @@ "%1$d basamak girildi" "%1$d basamak girildi" + "Süre: %1$s" "Fotoğrafı düzenle" "Tam adres %1$s olacaktır" "Şifreleme ayrıntıları" "Mesaj metin alanını genişlet" "Şifreyi gizle" + "Bilgi" "Aramaya katıl" "Aşağıya atla" + "Okunmamış olana atla" "Haritayı konumuma taşı" "Yalnızca bahsetmeler" "Sessiz" @@ -37,7 +41,6 @@ "%1$s ve %2$d diğer kişi tarafından okundu" "Okuyan %1$s" - "Tümünü göstermek için dokunun" "Tepkimeyi kaldır %1$s" "%1$s ile verilen tepkiyi kaldır" "Oda avatarı" 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 b84b3b92cd..aabea67405 100644 --- a/libraries/ui-strings/src/main/res/values-uk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uk/translations.xml @@ -4,6 +4,7 @@ "Додати реакцію: %1$s" "Адреса" "Аватар" + "Очистити поле пошуку" "Згорнути поле тексту повідомлення" "Зменшити кількість голосів, дозволених на одну особу" "Збільшити кількість голосів, дозволених на одну особу" @@ -44,14 +45,14 @@ "QR-код" "Реагувати з%1$s" "Відреагувати іншими смайликами" - "Прочитано %1$s та %2$s" + "Попереднє повідомлення прочитали %1$s та %2$s" - "Прочитано %1$s та %2$d іншим" - "Прочитано %1$s та %2$d іншими" - "Прочитано %1$s та %2$d іншими" + "Попереднє повідомлення прочитали %1$s та ще %2$d користувач" + "Попереднє повідомлення прочитали %1$s та ще %2$d користувачі" + "Попереднє повідомлення прочитали %1$s та ще %2$d користувачів" - "Прочитано %1$s" - "Натисніть, щоб показати все" + "Попереднє повідомлення прочитано користувачем %1$s" + "показати всі підтвердження прочитання" "Видалити реакцію з %1$s" "Прибрати реакцію %1$s" "Аватар кімнати" @@ -441,6 +442,10 @@ "Очікування геолокації…" "Будь-хто може переглянути історію" "Ви" + "Завантаження недоступне." + "Файл не знайдено" + "Попередній перегляд і завантаження вимкнено." + "Файл не є безпечним" "%1$s (%2$s) поділився цим повідомленням, оскільки вас не було в кімнаті, коли його надіслали." "%1$s поділився цим повідомленням, оскільки вас не було в кімнаті, коли його надіслали." "Згідно із налаштувань цієї кімнати, нові учасники можуть переглядати історію. %1$s" @@ -557,11 +562,6 @@ "Простори" "Надано доступ %1$s" "На карті" - - "+ %1$d приєднується" - "+ %1$d приєднуються" - "+ %1$d приєднуються" - "Повідомлення не надіслано, оскільки звірена цифрова ідентичність %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 accba4556c..63a3d7c185 100644 --- a/libraries/ui-strings/src/main/res/values-ur/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ur/translations.xml @@ -27,7 +27,6 @@ "%1$s اور %2$d دیگر نے لڑھا" "%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 63e1756a23..6a21c6aea6 100644 --- a/libraries/ui-strings/src/main/res/values-uz/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uz/translations.xml @@ -9,13 +9,16 @@ "%1$d ta raqam kiritildi" "%1$d ta raqam kiritildi" + "Davomiyligi: %1$s" "Avatarni tahrirlash" "To\'liq manzil %1$s bo\'ladi" "Shifrlash tafsilotlari" "Xabar matni maydonini kengaytirish" "Parolni yashirish" + "Maʻlumot" "Qoʻngʻiroqga qoʻshilish" "Pastga o\'tish" + "Oʻqilmaganlarga oʻtish" "Xaritani mening joylashuvimga o\'tkazish" "Faqat eslatmalar" "Ovozsiz" @@ -32,6 +35,7 @@ "Ijro tezligi" "So\'ro\'vnoma" "So‘rovnoma yakunlandi" + "Lavozimi: %1$s" "QR kodi" "%1$s bilan munosabat bildiring" "Boshqa hisbelgilar bilan munosabat bildiring" @@ -41,17 +45,20 @@ "%1$s va %2$d boshqa kishilar tomonidan oʻqildi" "Muallif: %1$s bilan oʻqish" - "Hammasini ko\'rsatish uchun bosing" "Reaktsiyani olib tashlang: %1$s" "%1$s bilan reaktsiyani olib tashlang" "Xona avatari" "Fayllarni yuborish" "Yuboruvchining joylashuvi" + "%1$s tomonidan %2$s da yuborildi" "Amal bajarish vaqti cheklangan, tasdiqlash uchun bir daqiqa vaqtingiz bor" + "Sozlamalar, harakat talab qilinadi" "Parolni ko\'rsatish" "Qoʻngʻiroqni boshlash" "Video chaqiruvni boshlash" "Ovozli qo‘ng‘iroq qilish" + "%1$s ichidagi mavzu" + "%1$s ichidagi mavzular" "Arxivlangan xona" "Foydalanuvchi avatari" "Foydalanuvchi menyusi" @@ -69,6 +76,7 @@ "Qoʻngʻiroq" "Bekor qilish" "Hozircha bekor qilish" + "Faylni tanlang" "Fotosuratni tanlang" "Tozalash" "Yopish" @@ -88,12 +96,16 @@ "Hisobni faolsizlantirish" "Rad etish" "Rad etish va bloklash" + "Oʻchirish" + "Akkauntni oʻchirish" + "Faylni oʻchirish" "So‘rovnomani o‘chirish" "Hammasini bekor qilish" "Oʻchirish" "Bekor qilish" "Bekor qilish" "Bajarildi" + "Yuklab olish" "Tahrirlash" "Sarlavhani tahrirlash" "So‘rovnomani tahrirlash" @@ -200,7 +212,9 @@ "Beta" "Bloklangan foydalanuvchilar" "Pufakchalar" + "Qoʻngʻiroq rad etildi" "Qoʻngʻiroq boshlandi" + "Siz qoʻngʻiroqni rad etdingiz" "Chatning zaxira nusxasi" "Buferga nusxa koʻchirildi" "Mualliflik huquqi" @@ -290,6 +304,7 @@ Sababi:%1$s." "Iltimos kuting…" "Haqiqatan ham bu soʻrovnomani tugatmoqchimisiz?" "So‘rov:%1$s" + "Soʻroʻvnoma" "Jami ovozlar:%1$s" "Natijalar soʻrovnoma tugagandan soʻng koʻrsatiladi" @@ -456,6 +471,9 @@ Davom etasizmi?" "Kechirasiz, xatolik yuz berdi" "🔐️ Menga qo\'shiling%1$s" "Hey, men bilan gaplash%1$s :%2$s" + "Jonli joylashuvni ulashish" + "Joylashuvni ulashish jarayoni davom etmoqda" + "%1$s jonli joylashuvi" "%1$sAndroid" "Xato haqida xabar berish uchun G\'azablanish" "Skrinshot" @@ -464,6 +482,12 @@ Davom etasizmi?" "%1$sni olib tashlash" "Sozlamalar" "Hech kim joylashuvini ulashmayapti" + "Jonli joylashuvni ulashish" + + "%1$d kishi" + "%1$d odamlar" + + "Xaritada" "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" @@ -520,4 +544,6 @@ Davom etasizmi?" "Sizni ushbu xabarga ruxsatingiz yoʻq" "Xabarni shifrini ochib bo‘lmadi" "Qurilmangizni tasdiqlamaganingiz yoki yuboruvchi raqamli shaxsingizni tasdiqlashi kerakligi sababli bu xabar bloklandi." + "Qurilmangiz juda eski, Android 8 yoki undan keyingi versiyadagi qurilma talab qilinadi." + "Xaritalarni renderlash qoʻllab-quvvatlanmaydi" 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 5cfbe26fba..3da8d7f394 100644 --- a/libraries/ui-strings/src/main/res/values-vi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-vi/translations.xml @@ -39,7 +39,6 @@ "%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" 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 71159b78e4..f54a9cc5a5 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 @@ -39,7 +39,6 @@ "%1$s 與其他 %2$d 個人已讀" "%1$s 已讀" - "點擊以顯示全部" "移除 %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 bd0844f822..e91509ab3f 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -4,6 +4,7 @@ "添加反应:%1$s" "地址" "头像" + "清除搜索框" "最小化消息文本框" "减少每人允许的投票数" "增加每人允许的投票数" @@ -42,12 +43,12 @@ "二维码" "使用 %1$s 反应" "使用其它 Emoji 做出反应" - "%1$s 和 %2$s 已读" + "上一个消息已被 %1$s 与 %2$s 阅读" - "%1$s 及其他 %2$d 人已读" + "上一个消息已被 %1$s 与 %2$d 及其他人阅读" - "%1$s 已读" - "点击以显示全部" + "上一个消息已被 %1$s 阅读" + "显示所有已读回执" "移除反应:%1$s" "移除反应:%1$s" "房间头像" @@ -55,6 +56,7 @@ "发送方位置" "由 %1$s 发送于 %2$s" "请求的操作有时间限制,你有 1 分钟的时间来验证" + "设置,需要操作" "显示密码" "开始通话" "开始视频通话" @@ -263,6 +265,12 @@ "转发消息" "常用" "图库" + + "%1$d 个附件…" + + + "%1$d 个媒体项目…" + "GIF" "群组通话进行中" "图片" @@ -298,6 +306,7 @@ "未命名空间" "未加密" "离线" + "通话中" "开源许可证" "或" "其它选项" @@ -422,6 +431,11 @@ "正在等待实时位置…" "任何人都可以看到历史" "你" + "无法下载。" + "文件未找到" + "正在扫描…" + "预览与下载功能已被禁用。" + "此文件不安全" "由于你当时不在房间内,%1$s(%2$s)已将消息向你共享。" "由于你当时不在房间内,%1$s 已将消息向你共享。" "此房间已配置为允许新成员阅读历史。%1$s" @@ -534,8 +548,8 @@ "空间" "已共享 %1$s" "在地图上" - - "+ %1$d 人已加入" + + "%1$d 已加入" "消息未能发送,因为 %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 b032c41d4b..485b9b9d59 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -50,7 +50,6 @@ "Previous message read by %1$s and %2$d others" "Previous message read by %1$s" - "Tap to show all" "show all read receipts" "Remove reaction: %1$s" "Remove reaction with %1$s" @@ -313,6 +312,7 @@ Reason: %1$s." "No space name" "Not encrypted" "Offline" + "On a call" "Open source licenses" "or" "Other options" @@ -442,6 +442,11 @@ Reason: %1$s." "Waiting for live location…" "Anyone can see history" "You" + "Download not available." + "File not found" + "Scanning…" + "Preview and download have been disabled." + "The file is not safe" "%1$s (%2$s) shared this message since you were not in the room when it was sent." "%1$s shared this message since you were not in the room when it was sent." "This room has been configured so that new members can read history. %1$s" @@ -556,9 +561,9 @@ Are you sure you want to continue?" "Spaces" "Shared %1$s" "On the map" - - "+ %1$d joined" - "+ %1$d joined" + + "%1$d joined" + "%1$d joined" "Message not sent because %1$s’s verified digital identity was reset." "Message not sent because %1$s has not verified all devices." diff --git a/screenshots/de/appnav.loggedin_LoggedInView_Day_4_de.png b/screenshots/de/appnav.loggedin_LoggedInView_Day_4_de.png new file mode 100644 index 0000000000..3b70c1ec3f --- /dev/null +++ b/screenshots/de/appnav.loggedin_LoggedInView_Day_4_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:337bc943f30e9299407a8eb2522ba3b235e4ad3dd60124c6eed74d820c436e1e +size 33957 diff --git a/screenshots/de/appnav.loggedin_LoggedInView_Day_5_de.png b/screenshots/de/appnav.loggedin_LoggedInView_Day_5_de.png new file mode 100644 index 0000000000..813eabac12 --- /dev/null +++ b/screenshots/de/appnav.loggedin_LoggedInView_Day_5_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:965c273b07a73a52cb3395c4ab2a6213e8927205798007c7805a00e49ccc7c75 +size 34914 diff --git a/screenshots/de/features.analytics.impl_AnalyticsOptInView_Day_0_de.png b/screenshots/de/features.analytics.impl_AnalyticsOptInView_Day_0_de.png index 53d0163f0c..e01a6c204f 100644 --- a/screenshots/de/features.analytics.impl_AnalyticsOptInView_Day_0_de.png +++ b/screenshots/de/features.analytics.impl_AnalyticsOptInView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0513d6133ff6ea84f83ac90c00aa2a91d054106b5ba52401cec345b0e1da1749 -size 85066 +oid sha256:2f97140e7b2253fc19655ec678b2181a3ceb16d1b7d45c99f8c6ad227fe4309d +size 83803 diff --git a/screenshots/de/features.analytics.impl_AnalyticsOptInView_Day_1_de.png b/screenshots/de/features.analytics.impl_AnalyticsOptInView_Day_1_de.png index 95b3686f95..b088635a2f 100644 --- a/screenshots/de/features.analytics.impl_AnalyticsOptInView_Day_1_de.png +++ b/screenshots/de/features.analytics.impl_AnalyticsOptInView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f81637ebfbee865dd0740ea8e5158042371dd05b8e98663c2b2a88062ffb5cb -size 86660 +oid sha256:3b9ba02266f44a4e73dfed54bd429aad8c9a8ee3813075d643a906cab0951d56 +size 85850 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 index 08a29ff28c..89470baf5e 100644 --- a/screenshots/de/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_de.png +++ b/screenshots/de/features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae20cc867db5b7163b12ed8afd841a704673d6539ea543b573dd0f7c560988c7 -size 59775 +oid sha256:3169a975fd8dc050f28c46d273d1d766b7b829ead7217171dc8693e99febfbfd +size 62340 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 3419248cbe..1db3060b52 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:9af82b0e785a85acb47d0b02b682c659bc13dbff01eb969f367d2ee413b6cbb1 -size 25165 +oid sha256:7763b052961efdb42fbae39e078ffb00c0f62b084b477862d07f0ec5be5d2f2d +size 23815 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 706b96c796..aa7855c162 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:37dc07b7be3f81a8b3925e1325baecff04dc2f3cd92316140f969610b6362169 -size 25691 +oid sha256:20528ffe999003d019f3d1484f12cbb1c37b3d0fea363c423cec0033ebeaf732 +size 25622 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 b8c5829e1e..2270819756 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:ace88630fc2d12ce8f9f610683626ff9d8ad8d3a18564791d3abdcff5743ed46 -size 27731 +oid sha256:c307ff5d16e3f24467d068711fdbeb39b0623201cfa2562ae47b0c954133ae63 +size 27662 diff --git a/screenshots/de/features.home.impl.spacefilters_SpaceFiltersView_Day_0_de.png b/screenshots/de/features.home.impl.spacefilters_SpaceFiltersView_Day_0_de.png index e1e8184d83..eb7173e6c0 100644 --- a/screenshots/de/features.home.impl.spacefilters_SpaceFiltersView_Day_0_de.png +++ b/screenshots/de/features.home.impl.spacefilters_SpaceFiltersView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c3a74c4106a32d6493c3589376668e5d3fef84e53281eb22d38f74ffe29af76 -size 32359 +oid sha256:1a314cfc59b86daa7dcde11117b8769f763e8b668771d42aadd7c54314e4b097 +size 32246 diff --git a/screenshots/de/features.home.impl.spacefilters_SpaceFiltersView_Day_1_de.png b/screenshots/de/features.home.impl.spacefilters_SpaceFiltersView_Day_1_de.png index 083edaa450..a916eaabaa 100644 --- a/screenshots/de/features.home.impl.spacefilters_SpaceFiltersView_Day_1_de.png +++ b/screenshots/de/features.home.impl.spacefilters_SpaceFiltersView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:96f48988c05ddb25b0a5cbc9eb5c8ac82ae54ef61c0e50081d148140f819ce1d -size 18842 +oid sha256:626c9fa9f44a69dbbc4aaf8b12782e7311f458440837d3d5bee811b2eb3b2e11 +size 18732 diff --git a/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_6_de.png b/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_6_de.png new file mode 100644 index 0000000000..b3b113479c --- /dev/null +++ b/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_6_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0d8a20c8d08202b9f6b393345c1e4ceec0511184bb54f05386a654a492fdc791 +size 33594 diff --git a/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_0_de.png b/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_0_de.png index 2a450d1a6b..613d3f3187 100644 --- a/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_0_de.png +++ b/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe3adc472fa03a75aed60fb611319ab155bc6d9bf60c1da9a5b65cab0821d3de -size 314324 +oid sha256:1cc00314a0e4c77304c8721bb65bcd792d8efbbd6c275ef41ea2729055f196b1 +size 315719 diff --git a/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_1_de.png b/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_1_de.png index bf73067a10..b771b4915e 100644 --- a/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_1_de.png +++ b/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:add9881336231b639b38b183a7b8d382204fd4dc8e173a145c6ee1f1e815fa0e -size 309781 +oid sha256:c289148733adcab13f0a58a4b7405d01e9a2a97d9942cb86e8790c609cc667ce +size 310987 diff --git a/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_2_de.png b/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_2_de.png index 5b4bd40afa..40c0db72d8 100644 --- a/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_2_de.png +++ b/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:959ec8deb13aa0af9982855037afbc8a97e13b4aa2396c3d69c897514e24eb70 -size 312815 +oid sha256:c92e79c2203992171fcb7f89e7f2474dc4637e1a32d12c3d3a0391b82be2acc9 +size 313974 diff --git a/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_3_de.png b/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_3_de.png index c9d282055d..2f1bfa0312 100644 --- a/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_3_de.png +++ b/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f546d4756c41db91f70e668de0cd6902edae4953396d0577121b48660f258348 -size 307243 +oid sha256:321008e9dc350a67fa56bc3c3b11d3556107be9475f7195bbf31547adb8703ca +size 308360 diff --git a/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_4_de.png b/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_4_de.png index 3a859fe640..1f79459486 100644 --- a/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_4_de.png +++ b/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd6115c0f4cf6d99439c2246036cefb4720ae52311f43eb89f41872290d9f77f -size 307698 +oid sha256:4504fba00287a8c95d204f21681182ff88427fd97f5cc18f5c0bf8728bc131a5 +size 308826 diff --git a/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_5_de.png b/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_5_de.png index 56d446fd5c..1c53fc44b0 100644 --- a/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_5_de.png +++ b/screenshots/de/features.login.impl.screens.onboarding_OnBoardingView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2115ee0514c103d1ea7b271dcff34297a284fd7007422be5c36df362a1a06c30 -size 317095 +oid sha256:c2617d02d1c5e2b5f6e1d456bb2306f1cda05639f206b7ad7503bc8a4da0a4b9 +size 318509 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 index 0157c6d961..529e3e8ddd 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d508cdc9742a8a2ff545599b106c0a57c84987d11940a03d416a69ff957aea4a -size 315614 +oid sha256:336844a35b925383f7b0c621339f0f6d9b0e81b7a85d18e688d0dd279ffba965 +size 317025 diff --git a/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewGalleryView_de.png b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewGalleryView_de.png new file mode 100644 index 0000000000..ddd7968542 --- /dev/null +++ b/screenshots/de/features.messages.impl.attachments.preview_AttachmentsPreviewGalleryView_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:13d5e217d05992d797a34ec634e7900ab48cceddc02f169ad21ddaebbd985417 +size 344738 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 deleted file mode 100644 index 198bd4553b..0000000000 --- a/screenshots/de/features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1ff21ba8a011e0aedbbcad919f46db1a26895ae6e286335055532f43dbf505de -size 27661 diff --git a/screenshots/de/features.messages.impl.messagecomposer_AttachmentsBottomSheet_Day_0_de.png b/screenshots/de/features.messages.impl.messagecomposer_AttachmentsBottomSheet_Day_0_de.png new file mode 100644 index 0000000000..ee70305497 --- /dev/null +++ b/screenshots/de/features.messages.impl.messagecomposer_AttachmentsBottomSheet_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a4f6b58fa98326481361ddf06120893f1ed6e10c21263370a75c3df40c3989d +size 28885 diff --git a/screenshots/de/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_de.png new file mode 100644 index 0000000000..08169845d5 --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:86eac241e9084cc830ff13d231908da2eb0dff246aa5cac64dddaac68a5d5f13 +size 295298 diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_de.png deleted file mode 100644 index fc985de87d..0000000000 --- a/screenshots/de/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3f358da2b9b0521c14e525bcb2bd41c29c96aacaf5f007546e6d362bde2ee3fb -size 612526 diff --git a/screenshots/de/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_de.png deleted file mode 100644 index 80857358e7..0000000000 --- a/screenshots/de/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:54e71f45db31e8664c42f8c05feb91ae839589e00cb89d12088c15c85fb9f25f -size 607824 diff --git a/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_de.png index 3d6777c3ef..6608cb71fb 100644 --- a/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_de.png +++ b/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:50d81c9637b36a3839f3841a4d1f65488f39bf16a52f0020271d338287a28497 -size 6612 +oid sha256:96ebb1034e9c1cde970b8d08a105680635094cb29bc7a93283efde4dc7479f38 +size 7508 diff --git a/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_de.png b/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_de.png index 48bbc48ce6..7bb4340051 100644 --- a/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_de.png +++ b/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa8c5988aed0f6fe5410a0d41d830219b8410affceec47550c99266d117229be -size 12075 +oid sha256:426fc2459594895f93aa5bf927d4eba6fe669fe64929b989e6eb24d0306253dc +size 12990 diff --git a/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_de.png b/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_de.png index 15d7ce090b..e29010bb94 100644 --- a/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_de.png +++ b/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e1a516032bb42e6cc8ff2b6156e2ef51b3594175ff0f930c60746f1ecbdd3747 -size 17551 +oid sha256:4417893ca77c6184649bc67c9506399a13970c212a6eeb266248d8715e976ce4 +size 18371 diff --git a/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_de.png b/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_de.png index 29e9875fc6..72f9ddf029 100644 --- a/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_de.png +++ b/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91bcbed96e60b91add3e54ecd8c49d8400da22d140e729163fdf7e0ab0ce390c -size 22475 +oid sha256:bf8906ea32496154c8c975b29704a43a41bb14aaa968cf0689804dbed99b85b0 +size 23691 diff --git a/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_de.png b/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_de.png index d5a93418bd..039ed716a3 100644 --- a/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_de.png +++ b/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4f1126706d818d83b1c98981f86cf16e598faee83d41144a92b050d6da697a6 -size 26822 +oid sha256:8d224cfd3ea545b5c2309e3df31176ac71b2c1ed499891a258867d38aa3e33e0 +size 28713 diff --git a/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_de.png b/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_de.png index ac9fe882de..6782f4eb5c 100644 --- a/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_de.png +++ b/screenshots/de/features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4b5c7ad54feda5ffcd065e6c1ac204ecc52388808abb41dac8b95aaf72a6d51 -size 32198 +oid sha256:b56716874cfc93e2273065b05252d931f78c689b7e5f555fe57e4b812e0209b8 +size 33393 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowRtlContent_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowRtlContent_de.png new file mode 100644 index 0000000000..6b064426a0 --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowRtlContent_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f6de442459a257ad7c5478d0dccdea61876b3b742e0fbec623b96c307abf3eb9 +size 54875 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_de.png deleted file mode 100644 index 7ddac02717..0000000000 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a4ac79f3b8fb4e231244bd96b244a4f2526d6ed28d558f9d50734d83bbb74992 -size 363909 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_de.png new file mode 100644 index 0000000000..c4943b892c --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c410e853089cc2c4a2c48a00dd9a8babc8095aed72bb4625057444710559c6c +size 368129 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_de.png deleted file mode 100644 index 68f8148879..0000000000 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6ca8cf82aa8ab1bdad56a27584b27789402aeb7ad8fadd038280a376fb75a72c -size 345094 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_de.png new file mode 100644 index 0000000000..cececc229a --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0c6dafaa41849af00d5097a85bd88e3a054a0a9e41c0466a08e6ff8dd6102b2 +size 356857 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_de.png deleted file mode 100644 index 133fd3903f..0000000000 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:426d1c844a8c88281c5fa4c61916d93278fdfd38f8cdf2dc54bf1a821f2de3eb -size 397167 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_de.png new file mode 100644 index 0000000000..9fcf389708 --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9daeee1aaa04247da3c8bb5aaae9947aab1ed2d2057995e53d6ebdb63e5cd356 +size 355848 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_de.png deleted file mode 100644 index b10f9741b9..0000000000 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3ec1b0244dab22414c6719b3309426e13128d0c70fb67dc66cd8a60d42521fd0 -size 355411 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_de.png b/screenshots/de/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_de.png index cae7c17e53..3062308e8d 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineViewMessageShield_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c5d32513f0719f9221b026b97b429919fdf18401ba00c01cf535688afe626a11 -size 37370 +oid sha256:6483f92e760dca0d653b1e9f36cb06c1b29fb701683c66c948c125ac827d33d1 +size 37372 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_0_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_0_de.png index d943fa3931..cda283f1fc 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_0_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ce84c70d73ebc3582466e6006229d8f67b8fc7b906fad90fa9be9bb19bf506f -size 50253 +oid sha256:598a8bcb37545d3c83ac69046e58ce26d461e8f9269990408f73c839ff5e1e16 +size 49217 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 index 7ba4cfc7cb..14d74e57d1 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_10_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:20d88acd1cec244527f3f1ae3ac49cdea7ba2e0f4710ef30eec90f8eb5d6093e -size 87253 +oid sha256:71a258a6539c326fc6f35351bcd784764109b576f865f31417ddab3c55ba1454 +size 86602 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 23715fd683..a95c21081c 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:0914e81c505541a4f000240469e746964c5f476a7884403616015fab62f23663 -size 51743 +oid sha256:51690868d5930e021d45b1d4f447cfde6fcbb2f320416b3cae5fe55483f5c341 +size 50721 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 44e66cdc1e..c1a3515674 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:fa15ce3aa51c83819e6fbdf235e6f732b0db187ea49344279b01614efd9ff6a3 -size 63456 +oid sha256:4bc359cde481814e09a7c0918a3d5f377b0ca96798ee038581380b1cbcba4b88 +size 62431 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 04e605318e..b536053f62 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:961a9289be61a16372087c645302e4043d71f73c4440e24473941a9a6aa41daa -size 48104 +oid sha256:74fed26d5bafd17821dc61836a9302bfc759db0107ef19da8b009818332891e2 +size 47073 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 e6bbd0bdff..5a6904ef5a 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:fb03835fff5c4d27009fd19af5494b71501445184f6cb984e39fa175e430fbbc -size 72082 +oid sha256:4459b9fa2ac7562450259a5e8c014ab249b8750aa8de791c7e4edbbd5172528d +size 71108 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 7169b684d9..6c490a5681 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:f9bb51eda6e69e8cd532a3adebbd33267580fdccc904c91e741cb2e8026f0b79 -size 57796 +oid sha256:77cd41e2d6902aa727ee5213a28fb46339c6c50f957655a365e3baa2414a8e60 +size 56792 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 c3563a3472..350b3ddf02 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:5b88d255f070df4fad03371c64ce31e080a35999352a6a87cc10f83d8d5da99c -size 64506 +oid sha256:0552b0c6ceb44e7f7fc02f4cb8046227a4cb9bafaedb1ac6b258e1b422601dc7 +size 63621 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 abb112a538..4168e1659a 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:4c119e44d9f51d0b4786f06092d3d0138ef69b363c43303164b0aac0629b324e -size 69840 +oid sha256:878106a56c776eb874a45b437de9f8c0927f0a780c292ffcd3f9f36646b0cfbd +size 69216 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_1_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_1_de.png index 7903997156..7f586108f8 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_1_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6e9bf77f3d736fdd106c9e5143a0e80a016cd4d5aac1dacaf5d7a4bfb91d3b0e -size 71973 +oid sha256:766c0c2b712d3f056c49b01caf8f4bbbfd5333d6fc74d78ab15c77b2e346a629 +size 70985 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 2cc385f926..4bea9b9924 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:a6325d21da32e6def01f35803b4823d037076f0c96c24d864fad33b0a7d9a7b7 -size 65731 +oid sha256:1fae2619d733f6a70870f65375dd7447001f354c23ff8549ac7b81c26c652e0c +size 64852 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 1d36e3c163..986d70ca02 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:853058d4d90fc9d39115263ab74e7813ab6a52844cc56cc4a30c3dcb42e291b9 -size 70016 +oid sha256:0aa831f247faf488c08b52fd4ad8327d31a8e43fd5800837ceb26e338109b98f +size 69141 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 9dcacf8924..2169108b6a 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:bb6ca0ade3d54ffc371ea734a0aba16d27b192b8a602e79355cdc45d1a3fb33b -size 56639 +oid sha256:863d0f7143afbcb73208708b0c3dce663a1d8f61375be6eb1a7492db3d4dd319 +size 55922 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 63497b4081..c4032cf79e 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:a7cf06d5921dae7bbdd3b774e38ac6fcbad724261c1adef9ad93ff992fcc7669 -size 51515 +oid sha256:e05bd647e42856eb414da2ce27b1a86a4d110ee26fb74d6c445da87595357f91 +size 50789 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_11_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_11_de.png index 98dd645229..8b581b4305 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_11_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b13eb680dca1d551d843b92dff0062a58781c6c9c1fe713e35c26412b6addf6 -size 68596 +oid sha256:5b33243d95e6c67be43deef8957507f45bc414d567bb9e30248fcdf1c70010a9 +size 68125 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_2_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_2_de.png index 8adc642f5b..df2cb30789 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_2_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4256d5f9b4e2eaa1133e80cb406077b3c936748b7ded0b8a5d236b8cd0333e6 -size 59686 +oid sha256:32e140ac0594359e4002ee9ff48ca357624bbf0e05a5c786b0415ce0728cd447 +size 58987 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 9cfff702c3..bbdfa31595 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:4d4c8687f4067cb9de6cdecffe70d9a91471ab6298a601b64336211459fd03da -size 55948 +oid sha256:074d5b065f8b241dae63459003f0bf584c4438d988c3a37120ca841a18df5554 +size 55874 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 7cbc28b7a1..e96ade4870 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:9b254226cc6b00d4871855a5c566d2f35cbbabe2048a58f12e86cd07372a2d91 -size 54071 +oid sha256:45987e3267c869b82157fd50dbd9e302db2979a23d1f27e56f192ba99c17fe06 +size 53451 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 88897e9150..b8f567f755 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:10845895f042e2fabfdf9ab573ceaac779ee30ecede1c76e5bc68d78b51bf985 -size 60476 +oid sha256:946da5862ccc26ab6d19628130c19ef21e576e0d94cbe92fdc67eee3d0e1d332 +size 60376 diff --git a/screenshots/de/features.messages.impl_MessagesView_Day_6_de.png b/screenshots/de/features.messages.impl_MessagesView_Day_6_de.png index 8e7a228bc5..d56f545423 100644 --- a/screenshots/de/features.messages.impl_MessagesView_Day_6_de.png +++ b/screenshots/de/features.messages.impl_MessagesView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c96790b440ae277d655e935d5b88725b1e1d42dd7d13dda89c958e9a96b7002e -size 48006 +oid sha256:ec8bc3bca6ebb38164361af648346fce98254913b191fd6aeb7a5bbcc7c0f0e6 +size 47930 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 7c18c364e1..4e8a6bc030 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:4bf1fd981150ed276bafe5b2e4f710c47ad423c085267ba65070b1a2806ca078 -size 59937 +oid sha256:aaad087eef1f82067b7345ae3114c9a5ee27b10ba37c0dd06b85bf6c3886f56c +size 59237 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 194a69f62b..b3f0f2fea4 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:cd28a4f1e30c5ef7db0cd167a3d0328af7b969ccd7c35f616472dc2ab02b5c4a -size 57867 +oid sha256:22e5597cab58568048c5be1d8a0efc7f9efce5b304d0b043614f37ef63a7e2b9 +size 57161 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 b713fac540..8544991eb9 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:e08f56a74a85de1d5e792dbc17a409f95c0a72df49b3c2538814442fdd63d4a9 -size 65018 +oid sha256:38781af0edcaf2072fabb3f1edc783fef4a674f66ee15ba787851ff4e8fa4a23 +size 64456 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 28a5fae9af..1e32baa819 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:52c61b6e8b5322667cab679c5d9bbf5b6a0dbec6bfd8c8df2e1367df849593a0 -size 43932 +oid sha256:1586c25251df5634a3fcfc572b1926875213fa1af7e456490e064650b13e99cd +size 44059 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 0105d69f9d..565e2fde0d 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:b987a54cc2967aab79fbbff1e2b133071483559b3eec87f0e87468652ca0fa96 -size 26764 +oid sha256:ffd7acae43a61f98605e7f8a6de3e00f8432e8ab42974e2d0e0f3d37550c8ab3 +size 29907 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 d8c7cd2d67..8ba326f935 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:bb537b9cd5288885487fa2c23f7d93d80d64b125ec824530c9dbc3c3be0ce91b -size 37934 +oid sha256:1ada78ec8fb22e50de9f0ef54fce8f8d5f6ab23948b9cb32334dc8034bc7aad6 +size 40880 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 0c8e2fe1a5..411cc0b223 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:09ea4ed4f9abe47b57ec34d46bbc52e1740a55c299012a8ce565cfe807a63947 -size 27766 +oid sha256:ff0bc0d1615172e9120e42415b2b660042507234a5ee783a226f4a274c4e9b44 +size 30945 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 b84fd55ce2..82fc1769ff 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:8daa203d69b6e75a33fffdaacb58368fb23cf80ceb9b9f1c09173aabc3106bcd -size 29089 +oid sha256:98087aa1557fcaa46245813d37424d28696d83220d1187d4b5dc4cee1727010c +size 32167 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 a96aa07639..cf40424682 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:ca5475ad46a4e9041b965454d13140fb66f4a79fd43a1c411a619a9be2188812 -size 20947 +oid sha256:93ff2a28aa016436780474d98042223d0d9e72f877003c0f476b3755ab6e92ad +size 33739 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_6_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_6_de.png new file mode 100644 index 0000000000..7d1e4fb3ba --- /dev/null +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_6_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe73ab4a3aae2660068503f2fcdb5aad12c20d0ce3ff202036cf820929a649c5 +size 20954 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 becff12dda..5296434550 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:a91738f516c04ee2ce383535e14084977dad3ad75adc2099614b53b107309e41 -size 45423 +oid sha256:a8e596b8e70ff79e8dbeed82f6053e03eef3073907bd26929c34f0022f3fbd65 +size 45634 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 2b3134576a..2a6d57344e 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:3084be95d6aef18c27e62c21b2d2bbf3eddf305ebcb07bd42b9d26e0d019b527 -size 27683 +oid sha256:2693253d4c1cf72c36f8f75fb823f2b1e173ffdf3c3c7ba9f1e688de6d8c26e8 +size 30987 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 4d8a4b92a2..fab99fdd74 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:8ac9746cb6f4154eb1d9ca97d5d4ee6cc301ef1a0754614872af4be1c5d69deb -size 38865 +oid sha256:9519a47ab91235acb3cfc3f361dc01ac7fc0361aedcf7b4a9aaae3419468edb7 +size 41934 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 597f641b83..06ad4f1cfb 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:ac67f10c25ad4f4873dab015f494cd9d34b880bcc5e846f90b963a052c6e31f3 -size 28677 +oid sha256:a39b5c91cb8e9b75a2935cca6561e83570eebd917873dc87b596c43f2d0716f0 +size 31932 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 44db3098af..1d51c3caa5 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:9453ad930d644293a3437cdb5a169e901ced8f9b86e8c41154f9871484ac5085 -size 30028 +oid sha256:fe34b39b3bd4bd5a9d78f1cd2165de9334fde9544f6abc8b40862af14b33e470 +size 33277 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 928a53ba64..883a5ef83f 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:8cbbde65a12a8618dc211b8a33e876d757ea0571ce69de6156e5f2f32a59e0e7 -size 21337 +oid sha256:b3b12da7a34e250eb3669edcf2d1fafccd059ecf133e388bfcec581437201c97 +size 34957 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_6_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_6_de.png new file mode 100644 index 0000000000..7c853c2348 --- /dev/null +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_6_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e32c86006cae6c771bd03d7360083882cb0673370af3f8c070406718b5cee39f +size 21351 diff --git a/screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_5_de.png b/screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_5_de.png new file mode 100644 index 0000000000..a990081be5 --- /dev/null +++ b/screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_5_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6912bbfad9bbeb0e1ec60836c06f60a5d0a0c5998c5a3f4c2f94b6f9c3fa0c65 +size 13059 diff --git a/screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_6_de.png b/screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_6_de.png new file mode 100644 index 0000000000..f26ea3b198 --- /dev/null +++ b/screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_6_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fab56595919a19506abeafc8abc93772643a63f3aae77f0619abb87df2341e18 +size 11833 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 186d5c4500..44eb24b2f7 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:85c622ee5e7cc5377b07b9df0d6ed856551200af720101f084c56260d5024516 -size 43767 +oid sha256:3aa8259805201e40926ad24b4ac815c38ad03c06df4a931342d954704899366e +size 43769 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 6c25e2f248..0b6f65c0a8 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:3af95d96750feab55d52e066e2201c38224b1b280c9b995fcbfa1a92b2d2472a -size 69083 +oid sha256:89e37a5045fdc07b873fd0eda7f3f15a7b61b12f2372a3e2af4e343c3ecb1b38 +size 66427 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 829944fbc8..5e1b0b263e 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:da0280b7c12febde1947781a235d844063bfbf0c7402ceb7585627484135ae86 -size 51293 +oid sha256:8b0f235103342097a27a35a3074159605b07ac1832ed00fded323802ae48c1ba +size 51740 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 6a392c8059..b49effb11c 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:48ae8baa9ed17971852d6d6c0022196ca076d6df67ebcf16046929ae11d91e0d -size 50565 +oid sha256:08deed13b615f02c6aad8882d31bf7ab96e19ea307f1c8be46f1e974577111be +size 51485 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 bf3926ade2..fab11f5752 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:e050acd07312ef4e19b85323ec4c061f9320fde6291a2818e58771257caf777d -size 25803 +oid sha256:f943d5d123ad9fdf2fec6efd264c0244d3812322d95b260aa991f9623b0a8272 +size 26303 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 58f0d723a0..8ee210f067 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:cba578353fc5d7e9e9327b0ebc89b8aad9e3743014b3fffb93538bb89fb9026b -size 25479 +oid sha256:367a4f93f0da8e225e687dd38e0e105d01daf8ca7ba70ec43244f635d20b67ba +size 25875 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 012c3b1574..6515e1941b 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:fbebdd9012c183c27ed79a3cb1dd5b823f73025756d9875c0c5a7af6f126dfa1 -size 14153 +oid sha256:3a1b49fdd3b81f6d54a46418077c056cd800fc302b728a2990ef5d4d3d5346a8 +size 14087 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 6b49ae7f1a..46c9400c15 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:4484ff8dbba915c439270cbebab45c503d94dc82c7641a674153d88aa2aa3143 -size 28017 +oid sha256:21afb343518b65bbc7680a20773f22cfd64c3ba49dd8ffd79ff014cb5736bea2 +size 27903 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 752973ddb4..6d22e26217 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:402ca214ecc34d4a5a5faf7583a879ab26e6c64b86904034dfa050a27a7b7a2d -size 38789 +oid sha256:f313eb3ee7bee0318926978f3afc04770ace66afceb46642815639a81b56ab91 +size 38713 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 efb7231b4f..55774e1975 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:c39fc1f4b149531f599f5ea69087685f63750f584f53fd98f9457f6e8e1a026d -size 35492 +oid sha256:c5af78c7459ce08692bcb56684731f1c6cfd4e57c9d51616c0790e05da7f93ef +size 35402 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 index 4ecdcd8c5e..1e041d2614 100644 --- a/screenshots/de/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a5bfe153d49c2cf8cfb0305034bd062c3196f11e89e745a3da9965d1148870a -size 47632 +oid sha256:fae6f5291c4986f2b2e1ea03b0ddf8c46aa242d3a0a3450102832ab88aaea6da +size 47581 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 d85fe69c5f..65b515536b 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:e1cc73791a8414dade986244167c7d88ccd5bb536dc199e0f1e6736084c0bcee -size 46331 +oid sha256:aa0b269eebc66e7eabe746ed5ef0084d3bffad2917b68b923c115bbe8fa27ac2 +size 46267 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 7d8fe0b73d..334f0f6adf 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:8c1ff9cf31ea0032caef0627f33bfd9b8ddd58680dffb5e85dfaedc5468cf82a -size 44252 +oid sha256:d554025c1de34290ba025e749aa9a545b856dc82861741c5ca0376c3a30fa09a +size 44157 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 8505e6b854..d002c262a0 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:02c306b493d6c77de9e1e54467561cec9d39012e59a88c02b95efe9071b41061 -size 51630 +oid sha256:387e0c1758216fe412a0cd17e452841c972e9ddc02abd460104b034c54b15780 +size 51554 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 67b61583b1..4bcc26f8f4 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:2bc723ee90bcd7038d78ccf738422daca8a0b0d54f9e86512399230912281d9a -size 33332 +oid sha256:650813d92f195938bb1765e17e293a3cd0987f7724e073e7bc193ca68b964b62 +size 33222 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 index 5fba5a29ce..d4340ee6a1 100644 --- a/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_4_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ac1909851db8c2ec3cf6e7a4238ba76108860ea72fe4c855e11b7df2358230c8 -size 45708 +oid sha256:0174293973cb765e2ba4d2c638ada5d59c94e406b4c2994dcc693a5787b1a821 +size 45643 diff --git a/screenshots/de/libraries.textcomposer_CaptionWarningBottomSheet_Day_0_de.png b/screenshots/de/libraries.textcomposer_CaptionWarningBottomSheet_Day_0_de.png index 3d58de2aa2..70d18cca11 100644 --- a/screenshots/de/libraries.textcomposer_CaptionWarningBottomSheet_Day_0_de.png +++ b/screenshots/de/libraries.textcomposer_CaptionWarningBottomSheet_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57dbf5af4c4e2eb8a753887c40d3bc8c4f315062a7b2a74c9bceba8d754c970d -size 21086 +oid sha256:fce3a984f4e7f561b404928c649b56d836ab4e99d2eb937e45af0635cc2a82c2 +size 20999 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index bb10f230a1..759f39cb02 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,108 +1,107 @@ // Generated file, do not edit 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",20630,], +["features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components.event_ATimelineItemEventRow_Night_0_en",20647,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20644,], ["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",20630,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20630,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20630,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20630,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20630,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20630,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20630,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20630,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20630,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20630,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20630,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20644,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20644,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20644,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20644,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20644,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20644,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20644,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20644,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20644,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20644,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20644,], ["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",20630,], -["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20630,], +["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20644,], +["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20644,], ["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",20630,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20630,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20630,], +["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20644,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20644,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20644,], ["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",20630,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20630,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20630,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20630,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20630,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20630,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20630,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20630,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20630,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20630,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20630,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20630,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20630,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20630,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20630,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20630,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20630,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20630,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20630,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20630,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20630,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20630,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20644,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20644,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20644,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20644,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20644,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20644,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20644,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20644,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20644,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20644,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20644,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20644,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20644,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20644,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20644,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20644,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20644,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20644,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20644,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20644,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20644,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20644,], ["libraries.designsystem.theme.components_AllIcons_Icons_en","",0,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20630,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20630,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20630,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20630,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20630,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20644,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20644,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20644,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20644,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20644,], ["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",20630,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20630,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20630,], -["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20630,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20644,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20644,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20644,], +["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20644,], ["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",20630,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20644,], ["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",20630,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20644,], ["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",20630,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20644,], ["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","",20630,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_en","",20630,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en","",20630,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_en","",20630,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_en","",20630,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_en","",20630,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_6_en","",20630,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_7_en","",20630,], -["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20630,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_en","",20644,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_en","",20644,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en","",20644,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_en","",20644,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_en","",20644,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_en","",20644,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_6_en","",20644,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_7_en","",20644,], ["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,], @@ -112,20 +111,22 @@ 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","",20630,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20630,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20630,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20630,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20630,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20630,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20630,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20630,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20630,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_9_en","",20630,], +["features.messages.impl.messagecomposer_AttachmentsBottomSheet_Day_0_en","features.messages.impl.messagecomposer_AttachmentsBottomSheet_Night_0_en",20647,], +["features.messages.impl.attachments.preview_AttachmentsPreviewGalleryView_en","",20647,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20644,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20644,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20644,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20644,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20644,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20644,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20644,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20644,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20644,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_9_en","",20644,], ["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",20630,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20644,], ["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,], @@ -155,22 +156,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",20630,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20644,], ["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",20630,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20630,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20630,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20630,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20630,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20630,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20630,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20644,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20644,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20644,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20644,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20644,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20644,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20644,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20630,], -["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20630,], -["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20630,], -["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20630,], -["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20630,], +["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20644,], +["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20644,], +["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20644,], +["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20644,], +["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20644,], ["features.rageshake.impl.bugreport_BugReportViewNight_0_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_1_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_2_en","",0,], @@ -181,141 +182,142 @@ 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",20630,], -["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20630,], +["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20644,], +["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20644,], ["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",20630,], +["features.messages.impl.timeline.components_CallMenuItem_Day_6_en","features.messages.impl.timeline.components_CallMenuItem_Night_6_en",20644,], ["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",20630,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20630,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20630,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20630,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20630,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20630,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20630,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20630,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20630,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20630,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20630,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20630,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20630,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20630,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20630,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20644,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20644,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20644,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20644,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20644,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20644,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20644,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20644,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20644,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20644,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20644,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20644,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20644,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20644,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20644,], ["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",20630,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20630,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20630,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20630,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20630,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20630,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20630,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20630,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20630,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20630,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20630,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20644,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20644,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20644,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20644,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20644,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20644,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20644,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20644,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20644,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20644,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20644,], ["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",20630,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20630,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20630,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20630,], -["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20630,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20644,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20644,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20644,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20644,], +["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20644,], +["features.login.impl.changeserver_ChangeServerView_Day_6_en","features.login.impl.changeserver_ChangeServerView_Night_6_en",20647,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20630,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20644,], ["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",20630,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20630,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20630,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20630,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20630,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20630,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20630,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20630,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20644,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20644,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20644,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20644,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20644,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20644,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20644,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20644,], ["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",20630,], +["features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en","features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en",20644,], ["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",20630,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20630,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20630,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20630,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20630,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20630,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20630,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20644,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20644,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20644,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20644,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20644,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20644,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20644,], ["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","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20630,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20630,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20630,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20630,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20630,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20630,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20644,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20644,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20644,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20644,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20644,], ["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",20630,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20630,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20630,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20630,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20630,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20630,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20630,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20630,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20630,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20630,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20630,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20630,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20630,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20630,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20630,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20630,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20630,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20630,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20630,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20630,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20644,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20644,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20644,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20644,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20644,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20644,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20644,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20644,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20644,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20644,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20644,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20644,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20644,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20644,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20644,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20644,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20644,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20644,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20644,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20644,], ["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","",20630,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20630,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20630,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20630,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20630,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20630,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20630,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20644,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20644,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20644,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20644,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20644,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20644,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20644,], ["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",20630,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20630,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20630,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20644,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20644,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20644,], ["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",20630,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20644,], ["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",20630,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20630,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20630,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20630,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20630,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20630,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20630,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20630,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20630,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20644,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20644,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20644,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20644,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20644,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20644,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20644,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20644,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20644,], ["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,], @@ -328,50 +330,51 @@ 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",20630,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20630,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20630,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20630,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20630,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20630,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20630,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20630,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20630,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20630,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20630,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20630,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20630,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20630,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20644,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20644,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20644,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20644,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20644,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20644,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20644,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20644,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20644,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20644,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20644,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20644,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20644,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20644,], ["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,], ["libraries.designsystem.atomic.atoms_ElementLogoAtomLarge_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomLarge_Night_0_en",0,], ["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_EmojiItemWithPopup_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_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",20630,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20630,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20644,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20644,], ["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",20630,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20630,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20630,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20630,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20630,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20630,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20630,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20630,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20630,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20630,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20630,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20630,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20630,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20630,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20630,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20630,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20630,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20630,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en",20644,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20644,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20644,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20644,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20644,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20644,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20644,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20644,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20644,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20644,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20644,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20644,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20644,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20644,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20644,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20644,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20644,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20644,], ["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,], @@ -391,52 +394,52 @@ 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",20630,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20630,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20630,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20644,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20644,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20644,], ["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",20630,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20630,], +["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20644,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20644,], ["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",20630,], +["features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_en","features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_1_en",20644,], ["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",20630,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20630,], -["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20630,], -["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20630,], -["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20630,], +["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20644,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20644,], +["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20644,], +["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20644,], +["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20644,], ["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",20630,], -["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20630,], +["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20644,], +["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20644,], ["features.home.impl_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20630,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20630,], +["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20644,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20644,], ["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",20630,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20630,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20630,], -["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20630,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20630,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20630,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20630,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20630,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20630,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20630,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20630,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20630,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20630,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20644,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20644,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20644,], +["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20644,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20644,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20644,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20644,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20644,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20644,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20644,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20644,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20644,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20644,], ["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",20630,], +["libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en","libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en",20644,], ["libraries.designsystem.ruler_HorizontalRuler_Day_0_en","libraries.designsystem.ruler_HorizontalRuler_Night_0_en",0,], ["libraries.designsystem.theme.components_IconButton_Buttons_en","",0,], ["libraries.designsystem.theme.components_IconColorButton_Day_0_en","libraries.designsystem.theme.components_IconColorButton_Night_0_en",0,], @@ -448,8 +451,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",20630,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20630,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20644,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20644,], ["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,], @@ -457,119 +460,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",20630,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20644,], ["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",20630,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20644,], ["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",20630,], -["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20630,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20644,], +["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20644,], ["features.verifysession.impl.incoming_IncomingVerificationViewA11y_en","",0,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20630,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20630,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20630,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20630,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20630,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20630,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20630,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20630,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20630,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20630,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20630,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20630,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20630,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20630,], -["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,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20644,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20644,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20644,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20644,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20644,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20644,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20644,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20644,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20644,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20644,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20644,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20644,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20644,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20644,], ["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",20630,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20630,], -["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20630,], +["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20644,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20644,], +["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20644,], ["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",20630,], +["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20644,], ["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",20630,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20630,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20630,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20630,], +["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20644,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20644,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20644,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20644,], ["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",20630,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20630,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20630,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20630,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20630,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20630,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20630,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20630,], +["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20644,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20644,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20644,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20644,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20644,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20644,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20644,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20644,], ["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",20630,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20630,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20630,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20630,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20630,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20630,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20630,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20630,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20630,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20630,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20630,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20630,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20630,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20630,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20630,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20630,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20630,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20630,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20630,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20630,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20630,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20630,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20630,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20630,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20630,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20630,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20630,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20630,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20630,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20630,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20630,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20630,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20630,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20630,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20644,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20644,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20644,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20644,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20644,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20644,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20644,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20644,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20644,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20644,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20644,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20644,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20644,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20644,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20644,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20644,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20644,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20644,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20644,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], -["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20630,], -["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20630,], +["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20644,], +["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20644,], ["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",20630,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20630,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20630,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20630,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20630,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20630,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20630,], -["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20630,], -["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20630,], -["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20630,], -["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20630,], -["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20630,], -["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20630,], -["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20630,], -["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20630,], -["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20630,], -["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20630,], -["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20630,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20644,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20644,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20644,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20644,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20644,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20644,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20644,], +["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20644,], +["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20644,], +["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20644,], +["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20644,], +["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20644,], +["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20644,], +["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20644,], +["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20644,], +["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20644,], +["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20644,], +["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20644,], ["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",20630,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20630,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20630,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20630,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20630,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20630,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en",20644,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20644,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20644,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20644,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20644,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20644,], ["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",20630,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20644,], ["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,], @@ -622,48 +623,50 @@ 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",20630,], +["features.location.api_LiveLocationSharingBanner_Day_0_en","features.location.api_LiveLocationSharingBanner_Night_0_en",20644,], ["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",20630,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20644,], ["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",20630,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20630,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20630,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20644,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20644,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20644,], ["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",20630,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20630,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20630,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20630,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20630,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20630,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20630,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20630,], -["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20630,], -["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20630,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20630,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20630,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20630,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20630,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20630,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20630,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20630,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20630,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20630,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20630,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20630,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20630,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20630,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20630,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20630,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20630,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20630,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20644,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20644,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20644,], +["appnav.loggedin_LoggedInView_Day_4_en","appnav.loggedin_LoggedInView_Night_4_en",20647,], +["appnav.loggedin_LoggedInView_Day_5_en","appnav.loggedin_LoggedInView_Night_5_en",20647,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20644,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20644,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20644,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20644,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20644,], +["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20644,], +["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20644,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20644,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20644,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20644,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20644,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20644,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20644,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20644,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20644,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20644,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20644,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20644,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20644,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20644,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20644,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20644,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20644,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20644,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20630,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20630,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20630,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20630,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20644,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20644,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20644,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20644,], ["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,], @@ -676,29 +679,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",20630,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20630,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20630,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20630,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20630,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20630,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_4_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_4_en",20630,], -["libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en",20630,], -["libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en",20630,], -["libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_2_en",20630,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20630,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20630,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20630,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20630,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20630,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20630,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20630,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20630,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20630,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20630,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20630,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20630,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20630,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20644,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20644,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20644,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20644,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20644,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20644,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_4_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_4_en",20644,], +["libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en",20644,], +["libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en",20644,], +["libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_2_en",20644,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20644,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20644,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20644,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20644,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20644,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20644,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20644,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20644,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20644,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20644,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20644,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20644,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20644,], ["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,], @@ -706,10 +709,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","",20630,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20630,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20644,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20644,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20630,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20644,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en","",0,], @@ -719,20 +722,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","",20630,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",20644,], ["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","",20630,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en","",20630,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en","",20644,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en","",20644,], ["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","",20630,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20630,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20644,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20644,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20630,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20644,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_17_en","",0,], @@ -742,12 +745,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","",20630,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20644,], ["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","",20630,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_7_en","",20630,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_6_en","",20644,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_7_en","",20644,], ["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,], @@ -756,7 +759,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",20630,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20644,], ["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,], @@ -765,7 +768,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",20630,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20644,], ["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,], @@ -774,24 +777,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",20630,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20630,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20630,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20630,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20630,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20630,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20630,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20630,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20630,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20630,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20630,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20630,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20630,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20630,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20630,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20630,], +["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20644,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20644,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20644,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20644,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20644,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20644,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20644,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20644,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20644,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20644,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20644,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20644,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20644,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20644,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20644,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20644,], ["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",20630,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20644,], ["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,], @@ -802,128 +805,128 @@ 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",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_14_en","features.preferences.impl.notifications_NotificationSettingsView_Night_14_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_15_en","features.preferences.impl.notifications_NotificationSettingsView_Night_15_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_16_en","features.preferences.impl.notifications_NotificationSettingsView_Night_16_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_17_en","features.preferences.impl.notifications_NotificationSettingsView_Night_17_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_18_en","features.preferences.impl.notifications_NotificationSettingsView_Night_18_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_19_en","features.preferences.impl.notifications_NotificationSettingsView_Night_19_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_20_en","features.preferences.impl.notifications_NotificationSettingsView_Night_20_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20630,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20630,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20630,], +["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_14_en","features.preferences.impl.notifications_NotificationSettingsView_Night_14_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_15_en","features.preferences.impl.notifications_NotificationSettingsView_Night_15_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_16_en","features.preferences.impl.notifications_NotificationSettingsView_Night_16_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_17_en","features.preferences.impl.notifications_NotificationSettingsView_Night_17_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_18_en","features.preferences.impl.notifications_NotificationSettingsView_Night_18_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_19_en","features.preferences.impl.notifications_NotificationSettingsView_Night_19_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_20_en","features.preferences.impl.notifications_NotificationSettingsView_Night_20_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20644,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20644,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20644,], ["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",20630,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20630,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20630,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20630,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20630,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20630,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20630,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20630,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20630,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20644,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20644,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20644,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20644,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20644,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20644,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20644,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20644,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20644,], ["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",20630,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20630,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20630,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20630,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20644,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20644,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20644,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20644,], ["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",20630,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20630,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20630,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20630,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20630,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20630,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20630,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20630,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20630,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20644,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20644,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20644,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20644,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20644,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20644,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20644,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20644,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20644,], ["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",20630,], -["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20630,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20630,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20630,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20630,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20630,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20644,], +["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20644,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20644,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20644,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20644,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20644,], ["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_PinUnlockViewCompact_0_en","",20633,], -["features.lockscreen.impl.unlock_PinUnlockViewCompact_1_en","",20633,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_10_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_10_en",20633,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_10_en","features.lockscreen.impl.unlock_PinUnlockView_Night_10_en",20633,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_8_en","features.lockscreen.impl.unlock_PinUnlockView_Night_8_en",20630,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_9_en","features.lockscreen.impl.unlock_PinUnlockView_Night_9_en",20630,], +["features.lockscreen.impl.unlock_PinUnlockViewCompact_0_en","",20644,], +["features.lockscreen.impl.unlock_PinUnlockViewCompact_1_en","",20644,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_10_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_10_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_10_en","features.lockscreen.impl.unlock_PinUnlockView_Night_10_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_8_en","features.lockscreen.impl.unlock_PinUnlockView_Night_8_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_9_en","features.lockscreen.impl.unlock_PinUnlockView_Night_9_en",20644,], ["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",20630,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20630,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20630,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20630,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20630,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20630,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20630,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20630,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20630,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20630,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20630,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20630,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20630,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20630,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20644,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20644,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20644,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20644,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20644,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20644,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20644,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20644,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20644,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20644,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20644,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20644,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20644,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20644,], ["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",20630,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20630,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20630,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20630,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20630,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20644,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20644,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20644,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20644,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20644,], ["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",20630,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20630,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20630,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20630,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20630,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20630,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20630,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20630,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20630,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20630,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20630,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20644,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20644,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20644,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20644,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20644,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20644,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20644,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20644,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20644,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20644,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20644,], ["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,], @@ -937,227 +940,229 @@ 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","",20630,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20630,], -["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20630,], -["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20630,], -["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20630,], -["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20630,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20630,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20630,], -["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20630,], -["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20630,], -["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20630,], -["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20630,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20644,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20644,], +["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20644,], +["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20644,], +["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20644,], +["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20644,], +["features.preferences.impl.root_PreferencesRootViewDark_6_en","",20647,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20644,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20644,], +["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20644,], +["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20644,], +["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20644,], +["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20644,], +["features.preferences.impl.root_PreferencesRootViewLight_6_en","",20647,], ["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","",20630,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20630,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20644,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20644,], ["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",20630,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20630,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20630,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20630,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20630,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20630,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20630,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20630,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20630,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20630,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20630,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20630,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20630,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20630,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20630,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20630,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20630,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20630,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20630,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20630,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20630,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20630,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20630,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20630,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20630,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20630,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20630,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20644,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20644,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20644,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20644,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20644,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20644,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20644,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20644,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20644,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20644,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20644,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20644,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20644,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20644,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20644,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20644,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20644,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20644,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20644,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20644,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20644,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20644,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20644,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20644,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20644,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20644,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20644,], ["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",20630,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20630,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20644,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20644,], ["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",20630,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20630,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20630,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20630,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20630,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20630,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20630,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20630,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20630,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20630,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20630,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20630,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20630,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20630,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20630,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20630,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20630,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20630,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20630,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20630,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20630,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20644,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20644,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20644,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20644,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20644,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20644,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20644,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20644,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20644,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20644,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20644,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20644,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20644,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20644,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20644,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20644,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20644,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20644,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20644,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20644,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20644,], ["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",20630,], +["features.location.api_RenderingMapsNotSupportedDialog_Day_0_en","features.location.api_RenderingMapsNotSupportedDialog_Night_0_en",20644,], ["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",20630,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20630,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20630,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20630,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20630,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20630,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20630,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20630,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20630,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20630,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20630,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20630,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20630,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20630,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20630,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20630,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20630,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20644,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20644,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20644,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20644,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20644,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20644,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20644,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20644,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20644,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20644,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20644,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20644,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20644,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20644,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20644,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20644,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20644,], ["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",20630,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20630,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20630,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20630,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20630,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20630,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20630,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20630,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20630,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20630,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20630,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20630,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20630,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20644,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20644,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20644,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20644,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20644,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20644,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20644,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20644,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20644,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20644,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20644,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20644,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20644,], ["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",20630,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20630,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20644,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20644,], ["features.roomdetails.impl_RoomDetailsA11y_en","",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_20_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_21_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_22_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20630,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20630,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20630,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20630,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20630,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20630,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20630,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20630,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20630,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20630,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20630,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20630,], -["features.roomdetails.impl_RoomDetails_0_en","",20630,], -["features.roomdetails.impl_RoomDetails_10_en","",20630,], -["features.roomdetails.impl_RoomDetails_11_en","",20630,], -["features.roomdetails.impl_RoomDetails_12_en","",20630,], -["features.roomdetails.impl_RoomDetails_13_en","",20630,], -["features.roomdetails.impl_RoomDetails_14_en","",20630,], -["features.roomdetails.impl_RoomDetails_15_en","",20630,], -["features.roomdetails.impl_RoomDetails_16_en","",20630,], -["features.roomdetails.impl_RoomDetails_17_en","",20630,], -["features.roomdetails.impl_RoomDetails_18_en","",20630,], -["features.roomdetails.impl_RoomDetails_19_en","",20630,], -["features.roomdetails.impl_RoomDetails_1_en","",20630,], -["features.roomdetails.impl_RoomDetails_20_en","",20630,], -["features.roomdetails.impl_RoomDetails_21_en","",20630,], -["features.roomdetails.impl_RoomDetails_22_en","",20630,], -["features.roomdetails.impl_RoomDetails_2_en","",20630,], -["features.roomdetails.impl_RoomDetails_3_en","",20630,], -["features.roomdetails.impl_RoomDetails_4_en","",20630,], -["features.roomdetails.impl_RoomDetails_5_en","",20630,], -["features.roomdetails.impl_RoomDetails_6_en","",20630,], -["features.roomdetails.impl_RoomDetails_7_en","",20630,], -["features.roomdetails.impl_RoomDetails_8_en","",20630,], -["features.roomdetails.impl_RoomDetails_9_en","",20630,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20630,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20630,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20630,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20630,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20630,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20630,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20630,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20630,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20630,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_20_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_21_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_22_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20644,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20644,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20644,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20644,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20644,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20644,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20644,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20644,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20644,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20644,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20644,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20644,], +["features.roomdetails.impl_RoomDetails_0_en","",20644,], +["features.roomdetails.impl_RoomDetails_10_en","",20644,], +["features.roomdetails.impl_RoomDetails_11_en","",20644,], +["features.roomdetails.impl_RoomDetails_12_en","",20644,], +["features.roomdetails.impl_RoomDetails_13_en","",20644,], +["features.roomdetails.impl_RoomDetails_14_en","",20644,], +["features.roomdetails.impl_RoomDetails_15_en","",20644,], +["features.roomdetails.impl_RoomDetails_16_en","",20644,], +["features.roomdetails.impl_RoomDetails_17_en","",20644,], +["features.roomdetails.impl_RoomDetails_18_en","",20644,], +["features.roomdetails.impl_RoomDetails_19_en","",20644,], +["features.roomdetails.impl_RoomDetails_1_en","",20644,], +["features.roomdetails.impl_RoomDetails_20_en","",20644,], +["features.roomdetails.impl_RoomDetails_21_en","",20644,], +["features.roomdetails.impl_RoomDetails_22_en","",20644,], +["features.roomdetails.impl_RoomDetails_2_en","",20644,], +["features.roomdetails.impl_RoomDetails_3_en","",20644,], +["features.roomdetails.impl_RoomDetails_4_en","",20644,], +["features.roomdetails.impl_RoomDetails_5_en","",20644,], +["features.roomdetails.impl_RoomDetails_6_en","",20644,], +["features.roomdetails.impl_RoomDetails_7_en","",20644,], +["features.roomdetails.impl_RoomDetails_8_en","",20644,], +["features.roomdetails.impl_RoomDetails_9_en","",20644,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20644,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20644,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20644,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20644,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20644,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20644,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20644,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20644,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20644,], ["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",20630,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20630,], -["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20630,], -["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20630,], -["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20630,], -["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20630,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20630,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20630,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20630,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20630,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20630,], +["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20644,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20644,], +["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20644,], +["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20644,], +["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20644,], +["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20644,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20644,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20644,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20644,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20644,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20644,], ["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",20630,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20630,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20630,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20630,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20630,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20630,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20630,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20630,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20630,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20630,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20630,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20630,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20630,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20630,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20630,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20630,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20630,], +["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20644,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20644,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20644,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20644,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20644,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20644,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20644,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20644,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20644,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20644,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20644,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20644,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20644,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20644,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20644,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20644,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20644,], ["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",20630,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20630,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20630,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20630,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20630,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20630,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20630,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20630,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20644,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20644,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20644,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20644,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20644,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20644,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20644,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20644,], ["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",20630,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20630,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20630,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20630,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20630,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20630,], -["libraries.roomselect.impl_RoomSelectView_Day_6_en","libraries.roomselect.impl_RoomSelectView_Night_6_en",20633,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20644,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20644,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20644,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20644,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20644,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20644,], +["libraries.roomselect.impl_RoomSelectView_Day_6_en","libraries.roomselect.impl_RoomSelectView_Night_6_en",20644,], ["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,], @@ -1180,16 +1185,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",20630,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20630,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20630,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20630,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20630,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20630,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20630,], -["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20630,], +["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20644,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20644,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20644,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20644,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20644,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20644,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20644,], +["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20644,], ["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",20630,], +["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20644,], ["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,], @@ -1198,119 +1203,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",20630,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20644,], ["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",20630,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20630,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20644,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20644,], ["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",20630,], -["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20630,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20630,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20630,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20630,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20630,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20630,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20630,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20644,], +["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20644,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20644,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20644,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20644,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20644,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20644,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20644,], ["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","",20630,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20644,], ["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","",20630,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20630,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20630,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20630,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20630,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20630,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20630,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20630,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20630,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20630,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20630,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20630,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20630,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20630,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20630,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20630,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20630,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20630,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20630,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20630,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20630,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20630,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20630,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20630,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20630,], -["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20630,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20644,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20644,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20644,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20644,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20644,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20644,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20644,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20644,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20644,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20644,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20644,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20644,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20644,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20644,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20644,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20644,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20644,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20644,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20644,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20644,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20644,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20644,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20644,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20644,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20644,], +["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20644,], ["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,], @@ -1333,39 +1338,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",20630,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20630,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20630,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20630,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20630,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20630,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20630,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20630,], -["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20630,], -["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20630,], -["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20630,], -["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20630,], -["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20630,], -["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20630,], -["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20630,], -["features.location.impl.share_ShareLocationView_Day_7_en","features.location.impl.share_ShareLocationView_Night_7_en",20630,], -["features.location.impl.share_ShareLocationView_Day_8_en","features.location.impl.share_ShareLocationView_Night_8_en",20630,], -["features.location.impl.share_ShareLocationView_Day_9_en","features.location.impl.share_ShareLocationView_Night_9_en",20630,], +["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20644,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20644,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20644,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20644,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20644,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20644,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20644,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20644,], +["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20644,], +["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20644,], +["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20644,], +["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20644,], +["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20644,], +["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20644,], +["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20644,], +["features.location.impl.share_ShareLocationView_Day_7_en","features.location.impl.share_ShareLocationView_Night_7_en",20644,], +["features.location.impl.share_ShareLocationView_Day_8_en","features.location.impl.share_ShareLocationView_Night_8_en",20644,], +["features.location.impl.share_ShareLocationView_Day_9_en","features.location.impl.share_ShareLocationView_Night_9_en",20644,], ["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",20630,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20630,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20630,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20630,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20630,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20630,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20630,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20630,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20630,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20630,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_1_en",20630,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20630,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20644,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20644,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20644,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20644,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20644,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20644,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20644,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20644,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20644,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20644,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_1_en",20644,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20644,], ["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,], @@ -1374,107 +1379,108 @@ export const screenshots = [ ["libraries.designsystem.components.list_SingleSelectionListItemSelectedInTrailingContent_Single_selection_List_item_-_selection_in_trailing_content_List_items_en","",0,], ["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,], +["features.messages.impl.timeline.components.customreaction.picker_SkinTonePicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_SkinTonePicker_Night_0_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",20630,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20644,], ["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",20630,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20630,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20630,], -["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20630,], -["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20630,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20644,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20644,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20644,], +["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20644,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20644,], ["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",20630,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20630,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20630,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20630,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20630,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20630,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20630,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20630,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20630,], -["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20630,], -["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20630,], -["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20630,], -["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20630,], -["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20630,], -["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20630,], -["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20630,], -["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20630,], -["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20630,], -["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20630,], -["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20630,], -["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20630,], -["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20630,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20644,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20644,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20644,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20644,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20644,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20644,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20644,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20644,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20644,], +["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20644,], +["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20644,], +["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20644,], +["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20644,], +["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20644,], +["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20644,], +["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20644,], +["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20644,], +["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20644,], +["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20644,], +["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20644,], +["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20644,], +["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20644,], ["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",20630,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20630,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20630,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20630,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20630,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20630,], +["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20644,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20644,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20644,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20644,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20644,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20644,], ["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",20630,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20644,], ["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",20630,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20644,], ["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",20630,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20630,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20630,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20630,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20630,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20630,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20630,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20630,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20630,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20630,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20630,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20630,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20630,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20630,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20630,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20630,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20630,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20630,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20630,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20630,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20630,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20630,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20630,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20630,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20630,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20630,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20630,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20630,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20630,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20630,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20630,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20630,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20630,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20630,], -["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20630,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20630,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20630,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20630,], +["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20644,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20644,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20644,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20644,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20644,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20644,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20644,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20644,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20644,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20644,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20644,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20644,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20644,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20644,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20644,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20644,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20644,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20644,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20644,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20644,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20644,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20644,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20644,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20644,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20644,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20644,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20644,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20644,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20644,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20644,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20644,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20644,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20644,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20644,], +["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20644,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20644,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20644,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20644,], ["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",20630,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20630,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20644,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20644,], ["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,], @@ -1487,103 +1493,125 @@ 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",20630,], -["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20630,], +["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20644,], +["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20644,], ["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","",20630,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20630,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20630,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20644,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20644,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20644,], ["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",20630,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20630,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20644,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20644,], ["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,], -["features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en",20633,], +["features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en",0,], +["features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Night_0_en",0,], +["features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_1_en",0,], ["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",20630,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20644,], ["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",20630,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20630,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20630,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20630,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20630,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20630,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20630,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20630,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20630,], -["features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en",20633,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20644,], +["features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en",20644,], ["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,], +["features.messages.impl.timeline.components_TimelineItemEventRowRtlContent_en","",20647,], ["features.messages.impl.timeline.components_TimelineItemEventRowShield_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowShield_Night_0_en",0,], ["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",20630,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20630,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20644,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20644,], ["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",20630,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20630,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20630,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20644,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20644,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_0_en",0,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_1_en",0,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_2_en",0,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_3_en",0,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_4_en",0,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_5_en","features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_5_en",0,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_6_en","features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_6_en",0,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_7_en",0,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_8_en",0,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20644,], ["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",20630,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20630,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en",20630,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en",20633,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en",20630,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en",20630,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",20633,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",20630,], -["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",20630,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en",20633,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en",20630,], -["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",20630,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",20633,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20630,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20644,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20644,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en",20644,], +["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",20644,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en",20644,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en",20647,], +["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",20644,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",20647,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20644,], +["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",20644,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en",20647,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20644,], +["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",20644,], ["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","",20630,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20644,], ["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",20630,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20630,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20630,], +["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_0_en",0,], +["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_1_en",0,], +["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_2_en",0,], +["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_3_en",0,], +["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_4_en",0,], +["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_5_en",0,], +["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_6_en",0,], +["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_7_en",0,], +["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_8_en",0,], +["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_9_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_9_en",0,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20644,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20644,], ["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",20630,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20644,], ["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",20630,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20630,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20630,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20630,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20630,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20630,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20630,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20630,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20630,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20644,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20644,], ["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",20630,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20630,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20644,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20644,], ["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",20630,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20644,], ["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,], @@ -1592,8 +1620,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",20630,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20630,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20644,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20644,], ["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,], @@ -1608,8 +1636,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",20630,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20630,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20644,], ["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,], @@ -1631,89 +1659,100 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemVoiceView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemVoiceView_Night_8_en",0,], ["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",20633,], -["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20630,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20630,], -["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20630,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20630,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20630,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20630,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20630,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20630,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20630,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20630,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20630,], +["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",20644,], +["features.messages.impl.timeline_TimelineViewWithReadMarkerBothIndicators_Day_0_en","features.messages.impl.timeline_TimelineViewWithReadMarkerBothIndicators_Night_0_en",0,], +["features.messages.impl.timeline_TimelineViewWithReadMarkerJumpToUnreadIndicatorOnly_Day_0_en","features.messages.impl.timeline_TimelineViewWithReadMarkerJumpToUnreadIndicatorOnly_Night_0_en",0,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20644,], +["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20644,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20644,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20644,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20644,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20644,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20644,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20644,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20644,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20644,], ["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",20630,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20644,], ["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",20630,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20644,], ["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",20630,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20630,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20630,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20630,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20630,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20630,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20630,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20630,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20644,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20644,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20644,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20644,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20644,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20644,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20644,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20644,], ["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",20630,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20630,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20630,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20630,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20630,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20630,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20644,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20644,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20644,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20644,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20644,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20644,], ["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","",20630,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20644,], ["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",20630,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20630,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20630,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20630,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20644,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20644,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20644,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20644,], ["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",20630,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20644,], ["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",20630,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20644,], ["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",20630,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20630,], -["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20630,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20630,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20630,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20630,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20630,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20630,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20630,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20630,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20630,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20630,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20630,], +["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20644,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20644,], +["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20644,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20644,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20644,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20644,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20644,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20644,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20644,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20644,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20644,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20644,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20644,], +["features.preferences.impl.userstatus_UserStatusView_Day_0_en","features.preferences.impl.userstatus_UserStatusView_Night_0_en",0,], +["features.preferences.impl.userstatus_UserStatusView_Day_1_en","features.preferences.impl.userstatus_UserStatusView_Night_1_en",0,], +["features.preferences.impl.userstatus_UserStatusView_Day_2_en","features.preferences.impl.userstatus_UserStatusView_Night_2_en",0,], +["features.preferences.impl.userstatus_UserStatusView_Day_3_en","features.preferences.impl.userstatus_UserStatusView_Night_3_en",0,], +["features.preferences.impl.userstatus_UserStatusView_Day_4_en","features.preferences.impl.userstatus_UserStatusView_Night_4_en",0,], +["features.preferences.impl.userstatus_UserStatusView_Day_5_en","features.preferences.impl.userstatus_UserStatusView_Night_5_en",20647,], +["features.preferences.impl.userstatus_UserStatusView_Day_6_en","features.preferences.impl.userstatus_UserStatusView_Night_6_en",20647,], ["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",20630,], -["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20630,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20644,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20644,], ["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",20630,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20644,], ["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,], ["features.viewfolder.impl.folder_ViewFolderView_Day_1_en","features.viewfolder.impl.folder_ViewFolderView_Night_1_en",0,], +["libraries.designsystem.components.visuallist_VisualListItem_Day_0_en","libraries.designsystem.components.visuallist_VisualListItem_Night_0_en",0,], +["libraries.designsystem.components.visuallist_VisualList_Day_0_en","libraries.designsystem.components.visuallist_VisualList_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_0_en","libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_1_en","libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_1_en",0,], ["libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_2_en","libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_2_en",0,], diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en.png index df8657de3b..3c017856d5 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a573de9b093c38946eba2d8bfdccc4c448277646731f283938f2847756fad1de -size 34171 +oid sha256:bc9a6e9b1a289cbb56c9cfdf98c978a143255f5309631ab689a180af919c239b +size 32570 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en.png index 9658070812..931348ff0b 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9eecfb5438fcd1529fcebdd49fc697e6dc5d61823dce05ff2a6d808b44e1c9c4 -size 32911 +oid sha256:aa031cddbc8816d55baa0b6945c23a16079edd3e2c5da5cd96523322461257d1 +size 31466 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en.png index cbda488267..26b9256252 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:731d4139bd4b0f2876e5df8a481b34e4ed4678f518b81c1e101aca07fab6e54a -size 42155 +oid sha256:1712b1dfc855f85cc6dc1ae50ce989f75734e5166e033a75d00de0af48387d4b +size 40271 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en.png index 63eeb0da9c..3553072509 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8581ef2719ba34504891e9a5ef46b7cd06d3daca5894b8d664eb067d55a76355 -size 42004 +oid sha256:39e5c9887e310603142b98518eb708a3afb966e75b2c081aeb54dfcfdf15747d +size 40120 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en.png index 4fd802402b..c41a7592db 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a3402b8a8458654e8c1c1a7efa81af45f8038b85bea027bcd9b2476812ef385 -size 35520 +oid sha256:c2cf996aa6d928e03305a1c0794853f52d21b36ac428dc3ba74901a4bed4b13c +size 34082 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en.png index 9dfb896c03..339471e5e5 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:76b6c58712a347586493d9857aa5de12da23bb2603f925f72a2b59f4a3ba7196 -size 37916 +oid sha256:e907ace209ad950d47b40d9e237cab07d6611c4b96aafc916c7c406ad995aeaa +size 36785 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en.png index 6f434d15ee..4d7496d290 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae04c1ccea9073ab548d08995c427b904318bc3aefebd278622d71b2ff89f8ad -size 55578 +oid sha256:c566c8fa13f5364f4e806b99bf0b7851ea04353607784f0184aed12b802245c2 +size 53719 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en.png index ac43ffb23c..67cef98faa 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08baa541e27b1c029e18bdb843c1915997f7234e496c2c8c7583d8a888044f05 -size 41768 +oid sha256:2af900ed5fe55894f175d4c7df02af8ff20ea2e519cc86f8b6ba4cae26809e32 +size 39924 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en.png index 00ca9c12de..b4e0884041 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:426db78c889d357ed94977990d2d4ab8194bb48ec4d0466cd54baa8ed1676809 -size 41654 +oid sha256:c81117519620428e5dcfecef86a777d7b42baa6af05a58136d8f4af57f0973f3 +size 39804 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en.png index b5076580c8..8b39c3a773 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5cfdfb972fcd32e87c8357567875aef7f26597e09a5aabe80173b4ee758cf92a -size 34760 +oid sha256:581cda2a65344128a0837150fe8be145de6a2eb921c153ba36186fa0a2adf67c +size 33532 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en.png index 6cc3a12c88..2736e1dc69 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35e801a6bbfdf73c93a3887e8097685144b33ed7bad142901e878e474ac0f437 -size 35692 +oid sha256:10b1e2ea092fb9c48217ab6f61569fc1d243e24b0f153f20ed0685470db46fa8 +size 34692 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en.png index fbf89da91f..e32928dd40 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8674e93ab6223d1bde21df6688482df5adc16a345339d593c363018b126cbc26 -size 54706 +oid sha256:118d4c3ada1bb42ecb9e5ff4d0d92317d99d0e00bb730c0f8bc85085e60001d7 +size 52759 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 08ae236377..275a6bf885 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:c0aacf68449e737c3c357e974cb8756c65e60db7578885ff9ce4bb726d31bc00 -size 52008 +oid sha256:c57b776992a9e756f97a264ab7fec15439403c596d4b97daa268e0f4fb6416e9 +size 51323 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_12_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_12_en.png index 22d0e1eef7..97ac976470 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e41f07dc61af91ef995d2b04cdaf9d78e733189d03b04a4992184e8e1134364d -size 58640 +oid sha256:f57b21a60a713da80f1dd3b56e688ad27828cbea0050310404b3b7abbeafcaef +size 58055 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 index ee21ee384a..615716fbc3 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:47ec77ef02122184cab59688e5ba3f9aadf8875fff73175402c3da499f591ba1 -size 43317 +oid sha256:680a2bcd62cfa4ed20676867a90459f698b139ff717873e4e7448f2e741b6b66 +size 42733 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 index 8fcb545029..66885bf2f2 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c9e7fc37451a08d7f0e8b1ad2d0dcd75f428114fc8985dc430dbe4b1c913309 -size 41879 +oid sha256:b6474f0d9c28fb325a44be95de932923d16d6f87863598e9ab83b709baa5f3af +size 41295 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 index 41a60a992a..d3807c3f60 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c14ee768960796a0d31d6f7de0590a3cde41918eff0aa7e9158392a4a4fce703 -size 43173 +oid sha256:4c2ec04a123614eddc0d6e51d1feb87680297c5c3f01e81a9f0be3685b768471 +size 42589 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 index a421925d73..d680c645a6 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:44f18c872ab94dba349b9b58d285aefa3e32e79676f37f63ed9c50fe1de68e49 -size 43046 +oid sha256:d51086d86f6ad1dc8ab93941274df67e612f03ca945e9f3e844c55aaae1b3316 +size 42463 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 a421925d73..d680c645a6 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:44f18c872ab94dba349b9b58d285aefa3e32e79676f37f63ed9c50fe1de68e49 -size 43046 +oid sha256:d51086d86f6ad1dc8ab93941274df67e612f03ca945e9f3e844c55aaae1b3316 +size 42463 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 bbf9e79392..bcc418b5c0 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:d1803afde307769d808a1c4f9f764da822ee5a774d3c159524b66852942157c6 -size 39980 +oid sha256:6e837aa7be784a94b00a930dd8e902c83f3330fe1c5c3a6274b8e6ef3a6ab3c7 +size 39431 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 a421925d73..d680c645a6 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:44f18c872ab94dba349b9b58d285aefa3e32e79676f37f63ed9c50fe1de68e49 -size 43046 +oid sha256:d51086d86f6ad1dc8ab93941274df67e612f03ca945e9f3e844c55aaae1b3316 +size 42463 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 a421925d73..d680c645a6 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:44f18c872ab94dba349b9b58d285aefa3e32e79676f37f63ed9c50fe1de68e49 -size 43046 +oid sha256:d51086d86f6ad1dc8ab93941274df67e612f03ca945e9f3e844c55aaae1b3316 +size 42463 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 a421925d73..d680c645a6 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:44f18c872ab94dba349b9b58d285aefa3e32e79676f37f63ed9c50fe1de68e49 -size 43046 +oid sha256:d51086d86f6ad1dc8ab93941274df67e612f03ca945e9f3e844c55aaae1b3316 +size 42463 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 e9066fcbff..d7f4fe3394 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:7019689badf7430a8a3a12eeaafb575de4b08fc2872a383d694085b4ae41f6cf -size 50545 +oid sha256:0cfbbb76875b4e18100d9a8793aae106da7396f2087054ea7312b379815c53c7 +size 49874 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_12_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_12_en.png index f8026d34c5..3913f4525c 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57d7d8d9e6f0867662121cdde52e32ef7be19760bcf534c2f4586e0d57cba03c -size 56878 +oid sha256:25ebb66460a8f9aac4ea2da291986b42f3651afe5d282ec6688c386e9ec1b83f +size 56242 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 index 2e127ed838..3161a1b000 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d93a5e5632ffff786845b69b532994642d04c2d306ede1d8f246ac157a73682e -size 41882 +oid sha256:5a8ff42ee34d5b3e7d9da11c7c7dcad793b3a2a0200fb141d5c65ce273807fff +size 41237 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 index 71d599d5d9..9240bb941b 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:89456057ead8933e7ebf3c2f4210da1fb92a1c9d4fee10ceb832cc0d3fe3797e -size 40524 +oid sha256:d9add786691cd3c839db57e32eaa79acf7c917764edf9f583010073d650c1326 +size 39877 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 index f22aa4e4b2..e5165092e3 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:44ca73c0eb048a81f77d2dd70f785261024419ef77fa0a809ee101019db82c62 -size 41695 +oid sha256:2c4415998c4229610437f89f7d931f213e670aca74efd2047d6fd2334777ad9c +size 41049 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 index 56981dc8a6..5c444905af 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4adf5e05b575aff79e8e0ae1bc039e147b014190cea303abc3dd9e1df6f33cb -size 41684 +oid sha256:7a59478f08ca086e1f60a9a5b925e9745d4e344b6b585116f55bcc503f3305a3 +size 41040 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 56981dc8a6..5c444905af 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:a4adf5e05b575aff79e8e0ae1bc039e147b014190cea303abc3dd9e1df6f33cb -size 41684 +oid sha256:7a59478f08ca086e1f60a9a5b925e9745d4e344b6b585116f55bcc503f3305a3 +size 41040 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 242258f056..4eac5775bd 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:afd1e21c834ecd9c3d0405749ea458672d2ac785c9f4d615ba2d780879d11a42 -size 38489 +oid sha256:59731c89e55eb564fa2d3e572c99a16d3ad88ee1a5e16d4e4d83e1008ea299ba +size 37999 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 56981dc8a6..5c444905af 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:a4adf5e05b575aff79e8e0ae1bc039e147b014190cea303abc3dd9e1df6f33cb -size 41684 +oid sha256:7a59478f08ca086e1f60a9a5b925e9745d4e344b6b585116f55bcc503f3305a3 +size 41040 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 56981dc8a6..5c444905af 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:a4adf5e05b575aff79e8e0ae1bc039e147b014190cea303abc3dd9e1df6f33cb -size 41684 +oid sha256:7a59478f08ca086e1f60a9a5b925e9745d4e344b6b585116f55bcc503f3305a3 +size 41040 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 56981dc8a6..5c444905af 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:a4adf5e05b575aff79e8e0ae1bc039e147b014190cea303abc3dd9e1df6f33cb -size 41684 +oid sha256:7a59478f08ca086e1f60a9a5b925e9745d4e344b6b585116f55bcc503f3305a3 +size 41040 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en.png index b4a2bcaef5..e78051b2eb 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec30fb3b59ee64c596f8b164a9845d797f1d5f60cfcc4a463bfd795d91308dbb -size 29476 +oid sha256:a61fbd3a88240c2e846ddcb235a9c656ad974eb148f96b66cc2811965260da22 +size 28715 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en.png index ab1896c7b3..a9059f984f 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:afb8299f98451448cca06d4356a7591fc05a0383fc8b3afe4690452215c0ee06 -size 28680 +oid sha256:597830f7117feeb6cfe3a9db25bffe060efe5f505a5d39e40b210a5ce4ff0347 +size 28085 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en.png index 366bf36bc6..81b844f361 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5cbfb1852861ab4ba92355cf0c3e59919e2209338cf299cdae39791472674d3 -size 35398 +oid sha256:9ca893611301a03342d21d6fb3b173d69d579fd063fb346a07ebd54b91613366 +size 34613 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en.png index 7aa4fbc6c2..653179d981 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12374c4bc5ad2290b98319d3301ba365d6d3d3d3c74e3705a621272179bd149f -size 34316 +oid sha256:29c5fd69085f619352bd1f674150e1af3b3b512a06f3f29810e0dd2d13c1787e +size 33537 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en.png index 53af40cb76..9aeebb2177 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8199a0e7db5d347e402400b5b87928a0f86e8995e2d359eb5dfcf53f7f7e3599 -size 22617 +oid sha256:d87aed1fad3eab0c41d8fc284c0224df596b3dcbf9e2c82a5eaff8f10448c17f +size 21839 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en.png index 50b3ff649e..a6ffc4590d 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:23b1936c894d405a52cd1db59430e60b74b2d47f2d5834be1b2a738d05445cbf -size 21909 +oid sha256:2b41d47c1a1e7359c4b991a1ba7a0585dccbeb1400b2b424f7240134c63c8492 +size 21148 From cf21bb1045d5bff83f5a9277c7649787f1a5f41d Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 13 Jul 2026 14:25:10 +0200 Subject: [PATCH 104/383] update sdk to 26.07.13 --- .../android/features/messages/impl/timeline/TimelineView.kt | 1 + gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) 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 077640212c..7db220dd01 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 @@ -652,6 +652,7 @@ private fun TimelineViewWithReadMarker( onReadReceiptClick = {}, forceJumpToBottomVisibility = true, forceJumpToReadMarkerVisibility = true, + onJoinCallClick = { }, ) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ef95884507..051953c8b9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -185,7 +185,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.06.30" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.07.13" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From 8b78259b17d4a3a7c13253be2a2a69ef0698aab1 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 13 Jul 2026 14:25:25 +0200 Subject: [PATCH 105/383] Temporary implem for sdk changes on beacon --- .../libraries/matrix/api/notification/NotificationData.kt | 6 ++++++ .../TimelineEventToNotificationContentMapper.kt | 2 ++ 2 files changed, 8 insertions(+) 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 c58a458865..6edb361215 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 @@ -89,6 +89,9 @@ sealed interface NotificationContent { val senderId: UserId, val question: String, ) : MessageLike + + // TODO put real implementation + data object Beacon : MessageLike } sealed interface StateEvent : NotificationContent { @@ -116,6 +119,9 @@ sealed interface NotificationContent { data class RoomTopic(val topic: String) : StateEvent data object SpaceChild : StateEvent data object SpaceParent : StateEvent + + // TODO put real implementation + data object Beacon : StateEvent } data class Invite( 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 84fd2e80e8..8afe6cba40 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 @@ -71,6 +71,7 @@ private fun StateEventContent.toContent(): NotificationContent.StateEvent { is StateEventContent.RoomTopic -> NotificationContent.StateEvent.RoomTopic(topic) StateEventContent.SpaceChild -> NotificationContent.StateEvent.SpaceChild StateEventContent.SpaceParent -> NotificationContent.StateEvent.SpaceParent + StateEventContent.BeaconInfo -> NotificationContent.StateEvent.Beacon } } @@ -108,6 +109,7 @@ private fun MessageLikeEventContent.toContent(senderId: UserId): NotificationCon ) MessageLikeEventContent.Sticker -> NotificationContent.MessageLike.Sticker is MessageLikeEventContent.Poll -> NotificationContent.MessageLike.Poll(senderId, question) + MessageLikeEventContent.Beacon -> NotificationContent.MessageLike.Beacon } } } From 33f1eb9cf8642613f4bfe1e71aa30e3105f98922 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 13 Jul 2026 14:38:08 +0200 Subject: [PATCH 106/383] fix detekt errors --- .../components/ActiveCallTimelineItemView.kt | 13 ++++++++----- .../event/TimelineItemRtcNotificationContent.kt | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt index e034f4ad4d..fd2364316d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt @@ -130,7 +130,8 @@ internal fun ActiveCallTimelineItemView( GroupCallBody( event, state, - Modifier.weight(1f) + Modifier + .weight(1f) .padding(top = 12.dp, bottom = 12.dp) ) } @@ -169,7 +170,7 @@ internal fun ActiveCallTimelineItemView( } @Composable -private fun DirectMessageCallBody(state: RtcNotificationState.Active, modifier: Modifier) { +private fun DirectMessageCallBody(state: RtcNotificationState.Active, modifier: Modifier = Modifier) { Row( verticalAlignment = Alignment.Top, modifier = modifier @@ -201,7 +202,8 @@ private fun DirectMessageCallBody(state: RtcNotificationState.Active, modifier: url = user.avatarUrl, size = AvatarSize.ActiveCallItem ) - }.toImmutableList(), + } + .toImmutableList(), avatarType = AvatarType.User, overlapRatio = 0.5f, lastOnTop = true, @@ -217,7 +219,7 @@ private fun DirectMessageCallBody(state: RtcNotificationState.Active, modifier: } @Composable -private fun GroupCallBody(event: TimelineItem.Event, state: RtcNotificationState.Active, modifier: Modifier) { +private fun GroupCallBody(event: TimelineItem.Event, state: RtcNotificationState.Active, modifier: Modifier = Modifier) { Column(modifier = modifier) { Text( text = stringResource(CommonStrings.common_group_call_in_progress), @@ -261,7 +263,8 @@ private fun GroupCallBody(event: TimelineItem.Event, state: RtcNotificationState url = user.avatarUrl, size = AvatarSize.ActiveCallItem ) - }.toImmutableList(), + } + .toImmutableList(), avatarType = AvatarType.User, overlapRatio = 0.5f, lastOnTop = true, 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 7d3ec21817..c48641982f 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 @@ -14,7 +14,7 @@ import io.element.android.libraries.matrix.api.user.MatrixUser // State of the call, for now only isDeclined but in the future could be missed, active. sealed interface RtcNotificationState { - /** Call is currently active **/ + /** Call is currently active. **/ data class Active( val joinedMembers: List, val isJoined: Boolean, From a1801c7225e56ced36db13c160f6866a4ae75b4b Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 13 Jul 2026 14:53:48 +0200 Subject: [PATCH 107/383] fixup Beacon missing imports --- .../impl/notifications/DefaultNotifiableEventResolver.kt | 6 ++++++ 1 file changed, 6 insertions(+) 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 2f3fa9b0b7..8955e9164c 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 @@ -56,6 +56,7 @@ import io.element.android.libraries.push.impl.db.PushRequest 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.impl.notifications.model.ResolvedPushEvent.* import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.toolbox.api.strings.StringProvider import timber.log.Timber @@ -322,6 +323,11 @@ class DefaultNotifiableEventResolver( Timber.tag(loggerTag.value).d("Ignoring notification for state event ${content.javaClass.simpleName}") throw NotificationResolverException.EventFilteredOut } + NotificationContent.MessageLike.Beacon, + NotificationContent.StateEvent.Beacon -> { + Timber.tag(loggerTag.value).d("Beacon - Not yet implemented") + throw NotificationResolverException.EventFilteredOut + } } } From aaba63ca609b36ecd8a99bb5e04e882a2b1ac3d8 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 13 Jul 2026 15:20:17 +0200 Subject: [PATCH 108/383] fix duplicate string --- libraries/ui-strings/src/main/res/values/localazy.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 3f91120c0a..485b9b9d59 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -502,10 +502,6 @@ Are you sure you want to continue?" "Location sharing in progress" "%1$s Live Location" "%1$s Android" - - "%1$d joined" - "%1$d joined" - "Rageshake to report bug" "Screenshot" "%1$s: %2$s" From f9112cc583f56c85ece8b5c07cf07144783d452b Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 13 Jul 2026 15:57:55 +0200 Subject: [PATCH 109/383] Collapse runs of deleted messages in the timeline (#7195) * Collapse runs of deleted messages in the timeline (#7111) * Collapse runs of deleted messages in the timeline Collapse a run of three or more consecutive deleted messages into a single expandable group, reusing the existing state-change grouping (the same way element-web does it) instead of showing one "Message removed" placeholder per deletion. The header shows the count only ("N deleted messages"); the Rust SDK does not expose who performed the redaction, so we don't attribute it. On by default. Runs shorter than three are left as individual placeholders, and day dividers and read receipts are preserved (a run is broken by any non-redacted item, so a day is never emptied). Run the collapse as the final step of TimelineItemGrouper.group() instead of a separate pass in the presenter, as suggested in review. Kept as its own finalization step rather than via canBeGrouped() so the group stays all redacted and the count-only header is preserved. The group id is resolved through the grouper's existing id registry, like the other groups, so it stays stable however the run grows and the user's expand/collapse state is kept across timeline updates. * Replace temporary strings with final ones * Update screenshots --------- Co-authored-by: Hi Dude! Co-authored-by: manfrommedan Co-authored-by: ElementBot --- .../impl/timeline/TimelineStateProvider.kt | 18 ++ .../TimelineItemGroupedEventsRow.kt | 46 ++++- .../impl/timeline/groups/Groupability.kt | 8 + .../timeline/groups/TimelineItemGrouper.kt | 57 +++++- .../impl/src/main/res/values/localazy.xml | 4 + .../impl/timeline/CollapseRedactedRunsTest.kt | 183 ++++++++++++++++++ .../impl/timeline/TimelinePresenterTest.kt | 23 +++ .../impl/timeline/groups/GroupabilityTest.kt | 60 ++++++ .../groups/TimelineItemGrouperTest.kt | 28 +++ .../tests/konsist/KonsistPreviewTest.kt | 1 + ...omreaction_EmojiItemWithPopup_Day_0_en.png | 4 +- ...reaction_EmojiItemWithPopup_Night_0_en.png | 4 +- ...s.event_ATimelineItemEventRow_Day_0_en.png | 4 +- ...event_ATimelineItemEventRow_Night_0_en.png | 4 +- ...t_TimelineImageWithCaptionRow_Day_0_en.png | 4 +- ...TimelineImageWithCaptionRow_Night_0_en.png | 4 +- ...t_TimelineVideoWithCaptionRow_Day_0_en.png | 4 +- ...TimelineVideoWithCaptionRow_Night_0_en.png | 4 +- ...lineItemRedactedMessagesGroup_Day_0_en.png | 3 + ...neItemRedactedMessagesGroup_Night_0_en.png | 3 + ...blockedusers_BlockedUsersView_Day_4_en.png | 4 +- ...blockedusers_BlockedUsersView_Day_5_en.png | 4 +- ...ockedusers_BlockedUsersView_Night_4_en.png | 4 +- ...ockedusers_BlockedUsersView_Night_5_en.png | 4 +- ...mpl.userstatus_UserStatusView_Day_5_en.png | 4 +- ...mpl.userstatus_UserStatusView_Day_6_en.png | 4 +- ...l.userstatus_UserStatusView_Night_5_en.png | 4 +- ...l.userstatus_UserStatusView_Night_6_en.png | 4 +- ...impl_RoomMemberModerationView_Day_5_en.png | 4 +- ...impl_RoomMemberModerationView_Day_7_en.png | 4 +- ...pl_RoomMemberModerationView_Night_5_en.png | 4 +- ...pl_RoomMemberModerationView_Night_7_en.png | 4 +- ...orizontalFloatingToolbarNoFab_Day_0_en.png | 4 +- ...izontalFloatingToolbarNoFab_Night_0_en.png | 4 +- ...nts_HorizontalFloatingToolbar_Day_0_en.png | 4 +- ...s_HorizontalFloatingToolbar_Night_0_en.png | 4 +- tools/localazy/config.json | 1 + 37 files changed, 477 insertions(+), 54 deletions(-) create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/CollapseRedactedRunsTest.kt create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/GroupabilityTest.kt create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemRedactedMessagesGroup_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemRedactedMessagesGroup_Night_0_en.png 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 fc7cd844fa..61b5c690a4 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 @@ -21,6 +21,7 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItemRead import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo import io.element.android.features.messages.impl.timeline.model.anAggregatedReaction import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent 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.aTimelineItemDaySeparatorModel @@ -255,6 +256,23 @@ internal fun aGroupedEvents( ) } +internal fun aRedactedMessagesGroupedEvents( + id: UniqueId = UniqueId("redacted_group"), + count: Int = 4, +): TimelineItem.GroupedEvents { + val events = (0 until count).map { index -> + aTimelineItemEvent( + eventId = EventId("\$redacted_$index"), + content = TimelineItemRedactedContent, + ) + } + return TimelineItem.GroupedEvents( + id = id, + events = events.toImmutableList(), + aggregatedReadReceipts = persistentListOf(), + ) +} + internal fun aTimelineRoomInfo( name: String = ROOM_NAME, isDm: Boolean = false, 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 ed927956df..a49952b272 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 @@ -19,12 +19,14 @@ import io.element.android.features.messages.impl.R import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.TimelineRoomInfo import io.element.android.features.messages.impl.timeline.aGroupedEvents +import io.element.android.features.messages.impl.timeline.aRedactedMessagesGroupedEvents import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView import io.element.android.features.messages.impl.timeline.components.group.GroupHeaderView import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData 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.groups.isRedactedMessagesGroup import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionEvent import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionState @@ -147,12 +149,18 @@ private fun TimelineItemGroupedEventsRowContent( }, ) { Column(modifier = modifier.animateContentSize()) { + val count = timelineItem.events.size + // A group made entirely of redacted events is a collapsed run of deleted messages + // (element-web style); anything else is the regular run of room state changes. For the + // redacted case we show only the count: the SDK does not expose who performed the redaction, + // and showing the original authors would be misleading. + val headerText = if (timelineItem.isRedactedMessagesGroup()) { + pluralStringResource(R.plurals.screen_room_timeline_redacted_messages, count, count) + } else { + pluralStringResource(R.plurals.screen_room_timeline_state_changes, count, count) + } GroupHeaderView( - text = pluralStringResource( - id = R.plurals.screen_room_timeline_state_changes, - count = timelineItem.events.size, - timelineItem.events.size - ), + text = headerText, isExpanded = isExpanded, isHighlighted = !isExpanded && timelineItem.events.any { it.isEvent(focusedEventId) }, onClick = onExpandGroupClick, @@ -252,3 +260,31 @@ internal fun TimelineItemGroupedEventsRowContentCollapsePreview() = ElementPrevi eventSink = {}, ) } + +@PreviewsDayNight +@Composable +internal fun TimelineItemRedactedMessagesGroupPreview() = ElementPreview { + // A collapsed run of deleted messages, shown as a single "N removed messages" header. + TimelineItemGroupedEventsRowContent( + isExpanded = false, + onExpandGroupClick = {}, + timelineItem = aRedactedMessagesGroupedEvents(count = 11), + timelineMode = Timeline.Mode.Live, + timelineRoomInfo = aTimelineRoomInfo(), + timelineProtectionState = aTimelineProtectionState(), + focusedEventId = null, + isLastOutgoingMessage = false, + displayThreadSummaries = false, + onClick = {}, + onLongClick = {}, + onLinkLongClick = {}, + inReplyToClick = {}, + onUserDataClick = {}, + onLinkClick = {}, + onReactionClick = { _, _ -> }, + onReactionLongClick = { _, _ -> }, + onMoreReactionsClick = {}, + onReadReceiptClick = {}, + eventSink = {}, + ) +} 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 8ebfcfc9d2..431942378a 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 @@ -44,6 +44,14 @@ 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 +/** + * Return true when every event in the group is a redacted (deleted) message, i.e. the group is a + * collapsed run of deleted messages rather than the usual run of room state changes. Used to pick + * the group header label. An empty group is not considered a redacted group. + */ +internal fun TimelineItem.GroupedEvents.isRedactedMessagesGroup(): Boolean = + events.isNotEmpty() && events.all { it.content is TimelineItemRedactedContent } + /** * Return true if the Event can be grouped in a collapse/expand block * When [canBeGrouped] returns a value, [canBeDisplayedInBubbleBlock] MUST return the opposite value. diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouper.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouper.kt index 6af4f8be6a..2e01e53828 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouper.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouper.kt @@ -12,6 +12,7 @@ import androidx.annotation.VisibleForTesting import dev.zacsweers.metro.Inject import dev.zacsweers.metro.SingleIn import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent import io.element.android.libraries.di.RoomScope import io.element.android.libraries.matrix.api.core.UniqueId import kotlinx.collections.immutable.toImmutableList @@ -47,7 +48,8 @@ class TimelineItemGrouper { if (currentGroup.isNotEmpty()) { result.addGroup(groupIds, currentGroup) } - return result + // Finally, fold runs of consecutive deleted messages into a single group (element-web style). + return result.collapseRedactedRuns(groupIds) } } @@ -89,3 +91,56 @@ private fun MutableMap.getOrPutGroupId(timelineItems: List.collapseRedactedRuns(groupIds: MutableMap): List { + val result = mutableListOf() + val run = mutableListOf() + + fun flushRun() { + when { + run.isEmpty() -> Unit + run.size < MIN_REDACTED_RUN_SIZE -> result.addAll(run) + else -> { + val events = run.reversed() + result.add( + TimelineItem.GroupedEvents( + id = UniqueId(groupIds.getOrPutGroupId(events)), + events = events.toImmutableList(), + aggregatedReadReceipts = events.flatMap { it.readReceiptState.receipts }.toImmutableList(), + ) + ) + } + } + run.clear() + } + + for (item in this) { + if (item is TimelineItem.Event && item.content is TimelineItemRedactedContent) { + run.add(item) + } else { + flushRun() + result.add(item) + } + } + flushRun() + return result +} diff --git a/features/messages/impl/src/main/res/values/localazy.xml b/features/messages/impl/src/main/res/values/localazy.xml index 173a4e78ad..e4790feba0 100644 --- a/features/messages/impl/src/main/res/values/localazy.xml +++ b/features/messages/impl/src/main/res/values/localazy.xml @@ -79,6 +79,10 @@ "Show more" "Show reactions summary" "New" + + "%1$d removed message" + "%1$d removed messages" + "%1$d room change" "%1$d room changes" diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/CollapseRedactedRunsTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/CollapseRedactedRunsTest.kt new file mode 100644 index 0000000000..8ccce4c995 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/CollapseRedactedRunsTest.kt @@ -0,0 +1,183 @@ +/* + * 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 + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.messages.impl.timeline.components.receipt.aReadReceiptData +import io.element.android.features.messages.impl.timeline.groups.collapseRedactedRuns +import io.element.android.features.messages.impl.timeline.groups.computeGroupIdWith +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.event.TimelineItemRedactedContent +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UniqueId +import kotlinx.collections.immutable.toImmutableList +import org.junit.Test + +class CollapseRedactedRunsTest { + private val groupIds = mutableMapOf() + + private fun redacted(id: String) = aTimelineItemEvent( + eventId = EventId(id), + content = TimelineItemRedactedContent, + ) + + @Test + fun `collapses a run of three or more redacted events into a single group`() { + val r1 = redacted("\$R1") + val r2 = redacted("\$R2") + val r3 = redacted("\$R3") + val result = listOf(r1, r2, r3).collapseRedactedRuns(groupIds) + assertThat(result).hasSize(1) + val group = result.single() as TimelineItem.GroupedEvents + // Stored oldest-first (the input is newest-first), like the existing grouper. + assertThat(group.events.map { it.eventId }).containsExactly( + EventId("\$R3"), + EventId("\$R2"), + EventId("\$R1"), + ).inOrder() + // Group id comes from the shared registry, keyed like the other groups (oldest member). + assertThat(group.id).isEqualTo(computeGroupIdWith(r3)) + } + + @Test + fun `leaves a run shorter than three as individual tiles`() { + val r1 = redacted("\$R1") + val r2 = redacted("\$R2") + val result = listOf(r1, r2).collapseRedactedRuns(groupIds) + assertThat(result).containsExactly(r1, r2).inOrder() + } + + @Test + fun `keeps surrounding events and only collapses the redacted run between them`() { + val newest = aTimelineItemEvent(eventId = EventId("\$NEW")) + val r1 = redacted("\$R1") + val r2 = redacted("\$R2") + val r3 = redacted("\$R3") + val oldest = aTimelineItemEvent(eventId = EventId("\$OLD")) + val result = listOf(newest, r1, r2, r3, oldest).collapseRedactedRuns(groupIds) + assertThat(result).hasSize(3) + assertThat(result.first()).isEqualTo(newest) + assertThat(result.last()).isEqualTo(oldest) + assertThat(result[1]).isInstanceOf(TimelineItem.GroupedEvents::class.java) + assertThat((result[1] as TimelineItem.GroupedEvents).events).hasSize(3) + } + + @Test + fun `a day separator breaks a run so each side is evaluated on its own`() { + val r1 = redacted("\$R1") + val r2 = redacted("\$R2") + val r3 = redacted("\$R3") + val sep = aTimelineItemDaySeparator() + val r4 = redacted("\$R4") + val r5 = redacted("\$R5") + val result = listOf(r1, r2, r3, sep, r4, r5).collapseRedactedRuns(groupIds) + // First run (3) collapses, the separator passes through, the second run (2) stays as tiles. + assertThat(result).hasSize(4) + assertThat(result.first()).isInstanceOf(TimelineItem.GroupedEvents::class.java) + assertThat(result[1]).isEqualTo(sep) + assertThat(result[2]).isEqualTo(r4) + assertThat(result[3]).isEqualTo(r5) + } + + @Test + fun `does not collapse a run interrupted by a non-redacted event`() { + val r1 = redacted("\$R1") + val r2 = redacted("\$R2") + val between = aTimelineItemEvent(eventId = EventId("\$MID")) + val r3 = redacted("\$R3") + val result = listOf(r1, r2, between, r3).collapseRedactedRuns(groupIds) + assertThat(result).containsExactly(r1, r2, between, r3).inOrder() + } + + @Test + fun `collapses a long run into a single group keeping every event`() { + val run = (1..5).map { redacted("\$R$it") } + val result = run.collapseRedactedRuns(groupIds) + assertThat(result).hasSize(1) + assertThat((result.single() as TimelineItem.GroupedEvents).events).hasSize(5) + } + + @Test + fun `collapses each qualifying run independently`() { + val firstRun = (1..3).map { redacted("\$A$it") } + val separator = aTimelineItemEvent(eventId = EventId("\$SEP")) + val secondRun = (1..3).map { redacted("\$B$it") } + val result = (firstRun + separator + secondRun).collapseRedactedRuns(groupIds) + assertThat(result).hasSize(3) + assertThat(result[0]).isInstanceOf(TimelineItem.GroupedEvents::class.java) + assertThat(result[1]).isEqualTo(separator) + assertThat(result[2]).isInstanceOf(TimelineItem.GroupedEvents::class.java) + // The two groups get distinct ids so their expand state does not bleed into one another. + assertThat((result[0] as TimelineItem.GroupedEvents).id) + .isNotEqualTo((result[2] as TimelineItem.GroupedEvents).id) + } + + @Test + fun `collapses a run that sits at the very end of the list`() { + val newest = aTimelineItemEvent(eventId = EventId("\$NEW")) + val run = (1..3).map { redacted("\$R$it") } + val result = (listOf(newest) + run).collapseRedactedRuns(groupIds) + assertThat(result).hasSize(2) + assertThat(result.first()).isEqualTo(newest) + assertThat(result.last()).isInstanceOf(TimelineItem.GroupedEvents::class.java) + } + + @Test + fun `leaves a single redacted event untouched`() { + val r1 = redacted("\$R1") + assertThat(listOf(r1).collapseRedactedRuns(groupIds)).containsExactly(r1) + } + + @Test + fun `aggregates the read receipts of every event in the collapsed group`() { + fun redactedWithReceipt(id: String, receiptIndex: Int) = aTimelineItemEvent( + eventId = EventId(id), + content = TimelineItemRedactedContent, + readReceiptState = TimelineItemReadReceipts( + receipts = listOf(aReadReceiptData(receiptIndex)).toImmutableList(), + ), + ) + val run = listOf( + redactedWithReceipt("\$R1", 0), + redactedWithReceipt("\$R2", 1), + redactedWithReceipt("\$R3", 2), + ) + val group = run.collapseRedactedRuns(groupIds).single() as TimelineItem.GroupedEvents + assertThat(group.aggregatedReadReceipts).hasSize(3) + } + + @Test + fun `an existing grouped item breaks the run and is passed through untouched`() { + val stateGroup = aGroupedEvents(id = UniqueId("state")) + val run = (1..3).map { redacted("\$R$it") } + val result = (run + stateGroup).collapseRedactedRuns(groupIds) + assertThat(result).hasSize(2) + assertThat(result.first()).isInstanceOf(TimelineItem.GroupedEvents::class.java) + assertThat(result.last()).isEqualTo(stateGroup) + } + + @Test + fun `is a no-op on an empty list`() { + assertThat(emptyList().collapseRedactedRuns(groupIds)).isEmpty() + } + + @Test + fun `the group id survives the run growing at either end`() { + val r1 = redacted("\$R1") + val r2 = redacted("\$R2") + val r3 = redacted("\$R3") + val first = listOf(r1, r2, r3).collapseRedactedRuns(groupIds).single() as TimelineItem.GroupedEvents + // A newer adjacent message gets redacted and older history loads in: the id must not move, + // or the user's expanded group would snap shut on the update. + val grown = listOf(redacted("\$R0"), r1, r2, r3, redacted("\$R4")) + .collapseRedactedRuns(groupIds) + .single() as TimelineItem.GroupedEvents + assertThat(grown.id).isEqualTo(first.id) + } +} 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 f8f23b35f1..a8be3f3836 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 @@ -44,6 +44,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.RedactedContent 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 @@ -865,6 +866,28 @@ class TimelinePresenterTest { } } + @Test + fun `present - collapses a run of three or more redacted events into a single group`() = runTest { + val timeline = FakeTimeline( + timelineItems = flowOf( + (0 until 3).map { index -> + MatrixTimelineItem.Event( + uniqueId = UniqueId("redacted_$index"), + event = anEventTimelineItem(eventId = EventId("\$R$index"), content = RedactedContent), + ) + } + ), + ) + val presenter = createTimelinePresenter(timeline = timeline) + presenter.test { + val state = consumeItemsUntilPredicate { it.timelineItems.size == 1 }.last() + val group = state.timelineItems.single() + assertThat(group).isInstanceOf(TimelineItem.GroupedEvents::class.java) + assertThat((group as TimelineItem.GroupedEvents).events).hasSize(3) + cancelAndIgnoreRemainingEvents() + } + } + @Test fun `present - reaction ordering`() = runTest { val timelineItems = MutableStateFlow(emptyList()) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/GroupabilityTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/GroupabilityTest.kt new file mode 100644 index 0000000000..fde84ca77a --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/GroupabilityTest.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.features.messages.impl.timeline.groups + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.messages.impl.timeline.aGroupedEvents +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.TimelineItemRedactedContent +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UniqueId +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList +import org.junit.Test + +class GroupabilityTest { + private fun redacted(id: String) = aTimelineItemEvent( + eventId = EventId(id), + content = TimelineItemRedactedContent, + ) + + private fun groupOf(vararg events: TimelineItem.Event) = TimelineItem.GroupedEvents( + id = UniqueId("group"), + events = events.toList().toImmutableList(), + aggregatedReadReceipts = persistentListOf(), + ) + + @Test + fun `a group made only of redacted events is a redacted messages group`() { + val group = groupOf(redacted("\$R1"), redacted("\$R2"), redacted("\$R3")) + assertThat(group.isRedactedMessagesGroup()).isTrue() + } + + @Test + fun `a group of state changes is not a redacted messages group`() { + // aGroupedEvents builds a run of state events. + assertThat(aGroupedEvents().isRedactedMessagesGroup()).isFalse() + } + + @Test + fun `a group mixing redacted and non-redacted events is not a redacted messages group`() { + val group = groupOf(redacted("\$R1"), aTimelineItemEvent(eventId = EventId("\$E")), redacted("\$R2")) + assertThat(group.isRedactedMessagesGroup()).isFalse() + } + + @Test + fun `an empty group is not a redacted messages group`() { + val group = TimelineItem.GroupedEvents( + id = UniqueId("group"), + events = persistentListOf(), + aggregatedReadReceipts = persistentListOf(), + ) + assertThat(group.isRedactedMessagesGroup()).isFalse() + } +} diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt index 726646f5e9..005eb5730e 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/groups/TimelineItemGrouperTest.kt @@ -15,6 +15,7 @@ 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.event.TimelineItemRedactedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateEventContent import io.element.android.features.messages.impl.timeline.model.virtual.aTimelineItemDaySeparatorModel import io.element.android.libraries.designsystem.components.avatar.anAvatarData @@ -169,4 +170,31 @@ class TimelineItemGrouperTest { // Then assertThat(actualGroupId).isEqualTo(expectedGroupId) } + + @Test + fun `a run of three or more redacted events is collapsed into a single group as a final step`() { + val r0 = aGroupableItem.copy(id = UniqueId("r0"), content = TimelineItemRedactedContent) + val r1 = aGroupableItem.copy(id = UniqueId("r1"), content = TimelineItemRedactedContent) + val r2 = aGroupableItem.copy(id = UniqueId("r2"), content = TimelineItemRedactedContent) + val result = sut.group(listOf(r0, r1, r2)) + assertThat(result).isEqualTo( + listOf( + TimelineItem.GroupedEvents( + id = computeGroupIdWith(r2), + // Stored oldest-first (the input is newest-first) with the id keyed by the + // oldest member through the shared registry, like the other groups. + events = listOf(r2, r1, r0).toImmutableList(), + aggregatedReadReceipts = emptyList().toImmutableList(), + ) + ) + ) + } + + @Test + fun `a run of fewer than three redacted events is left untouched`() { + val r0 = aGroupableItem.copy(id = UniqueId("r0"), content = TimelineItemRedactedContent) + val r1 = aGroupableItem.copy(id = UniqueId("r1"), content = TimelineItemRedactedContent) + val result = sut.group(listOf(r0, r1)) + assertThat(result).isEqualTo(listOf(r0, r1)) + } } 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 fdb4e27ef0..8a088e8e93 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 @@ -158,6 +158,7 @@ class KonsistPreviewTest { "TimelineItemGroupedEventsRowContentCollapsePreview", "TimelineItemGroupedEventsRowContentExpandedPreview", "TimelineItemImageViewHideMediaContentPreview", + "TimelineItemRedactedMessagesGroupPreview", "TimelineItemVideoViewHideMediaContentPreview", "TimelineItemVoiceViewUnifiedPreview", "TimelineVideoWithCaptionRowPreview", diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png index a2b35f18ca..912b90b537 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c5572491b675a16724cd9e33ebb477c82edf285fa07d57ebef09c670fcaaddf1 -size 21285 +oid sha256:4746d11c30648f7c517b0880021e5a1dc6ed2819af6c800b081b0d842ac2c384 +size 5325 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png index 9c425cec6e..45011fea4d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:290a2be6838445739b0181006f9fea87337a85cfed3573c153e9f503c66624a6 -size 4994 +oid sha256:eede6f990a7a1dbddee1cd9e722b30600160d475ad2ae72faebcb773f52aaa7b +size 20793 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 index 38a81d10b8..08169845d5 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4420dfe9f6f95411093eb1c17825a389a31d7a5d5ef146129e5872cdd5d87aff -size 295295 +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 index 06dd93b269..3f12875a5b 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:578a3707102c7754f607c3a14f94f32cafa30ee570db174386533c484cb4773c -size 295031 +oid sha256:7076c9a44a433cd9eeca536365ae262d39b4ad99a8f854faadec272cb1b82031 +size 294992 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en.png index fc985de87d..29e7582971 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f358da2b9b0521c14e525bcb2bd41c29c96aacaf5f007546e6d362bde2ee3fb -size 612526 +oid sha256:d6441c572f64d99bc119d649e5e6422fe516b9d097f310ccbd99a9ddded9609f +size 612494 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en.png index 90bee6c117..176ebfa36b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a709de55bc68cf12064ebdbde92c0a99bef3252958d7966540458d253e8c12c2 -size 611422 +oid sha256:5a867dda82242d2b13bd4bc84a9f1c9b8b7b99c030e19a6cce39b2f828b517f3 +size 611488 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en.png index 80857358e7..f792a1663a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:54e71f45db31e8664c42f8c05feb91ae839589e00cb89d12088c15c85fb9f25f -size 607824 +oid sha256:e3bb005a88e9a4d2bb850478ee8ac2c4f31d32625bd6d2abf455fade461cd399 +size 607806 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en.png index 8733429e34..18319e718f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8bb505fe6d67669339c9366f8ee5bc75974e223837d95e76e637455a51c18711 -size 606787 +oid sha256:4a2a57f5547f98b9ac2d8bf7195a1e4b49e03834e8866c6cc76660a6a3b16e74 +size 606823 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemRedactedMessagesGroup_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemRedactedMessagesGroup_Day_0_en.png new file mode 100644 index 0000000000..b367521180 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemRedactedMessagesGroup_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2a83859b4c8ef66b7d22008760b66af367affd8e6c1d7cdc099a122fea64f924 +size 7548 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemRedactedMessagesGroup_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemRedactedMessagesGroup_Night_0_en.png new file mode 100644 index 0000000000..52a7b44ea1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemRedactedMessagesGroup_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e5d132c02fe441f9bc654ae5fad86e8409413869637f147a9853ceb8883d9f12 +size 7270 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png index 074820e157..7cca911c45 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7caacb336793b8ae4b83e9a10a82325e25e8b3c036f881898ed28688250eb6e0 -size 55744 +oid sha256:26e14b77fa3c3aeaea58782309e6de8b9047e07945009322990ebf5f4c283309 +size 52770 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png index 2af459c158..7cca911c45 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:28a95d4b7ebca92c4e0467f3ecd9acdaf7f6257604d190f5d088a9a25e87d637 -size 55305 +oid sha256:26e14b77fa3c3aeaea58782309e6de8b9047e07945009322990ebf5f4c283309 +size 52770 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png index 616c06bf46..a68f886f73 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ce2519906f1aaf34700ca9ba4bdeaa72030f1f5aff3f7e24352a1435ac67d98 -size 53966 +oid sha256:e5a2e306087a967849f61872b56a83f194d1a76df5723f0bbae6e6e2f4a98c63 +size 55725 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png index 36d19c6b72..616c06bf46 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7dfa2767c55a81d3f121b8fa55443b7b05f9369e91639b80e0be349863799ad7 -size 55438 +oid sha256:0ce2519906f1aaf34700ca9ba4bdeaa72030f1f5aff3f7e24352a1435ac67d98 +size 53966 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png index 7ef9b7ae0a..1f73455d54 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d19e7a09114e76294a0626e5d617cf55fe7c13a0188a7d5b364f57c0d9daedc1 -size 12123 +oid sha256:b5dc5c492ed3fd552e77c0be85b639d55bc7e976f15b761f927b0b80ecca601d +size 12115 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png index 3e18858873..0ca6f66438 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:42f03759fcffbb750181168256130b6a94a1fcf91ee028e69a19a6e3b68ed0e8 -size 11711 +oid sha256:5896eb5df6f5398bdb94e74280d0d5c04b6a5a53c2378b7377c60fa58eef544b +size 12013 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index 1e04c3e7d7..a687241151 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bbc8c05e6f6818d00282228f52424ebe93e6e3dca3431d742e8c652d56460d6 -size 11712 +oid sha256:e7ce8a8c6b4d1692e4b127b7f17f507552666c631893025082c385b93d835a73 +size 11726 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png index 8e1b9c99d2..a1d1c5ec8e 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66f6d0d6b03ee4c999cd4edc9c6ae567d31b8b537ca6f9cc8fbe436d06ce80ab -size 11643 +oid sha256:8b93c08531efbeacb55f84b17ac793a7b226e5a2db7bc5072e94bc040cd1e9bc +size 11386 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png index 73b8b8e50c..5c597300e4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e8a3ad99763929d2783147814e44fa9ec7e7efb7b99949e3580f23c38fb5d971 -size 9398 +oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 +size 3853 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png index 5c597300e4..f8a1f24b34 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 -size 3853 +oid sha256:1342b6427f5b2e3075ae3ccee60bf1d3b11afaccf3e152643d6ef2d65c21b54e +size 9108 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png index d47bf90664..4ae7279fe7 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c -size 3664 +oid sha256:410a8596d4c70b9a3856d959d6d71ade8e831e8581ff410c9900957a93b3eb50 +size 8114 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png index a87d89c701..d47bf90664 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f3a0cb5d9bae6725a1c527f3d9575aabf85d3edf63a28d9faa23f4f0b65e2d0 -size 7624 +oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c +size 3664 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png index ee5c582240..58546b8522 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75de341f705bb22955f9399180519b65ad59c2e1917317d56e50ea4db78f35bc -size 12102 +oid sha256:30357bf18792db5ab20085010251170a724ffe8c00313facd04ee704e806af64 +size 10982 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png index fedead0fa8..52fd9b9693 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4811667dec0f32accc5e2c8a5dd5c0b34017fcff8d1e0376ee7a4708426bca0f -size 9838 +oid sha256:58b9491aaa5554b89d86c62a5c9c44975367538c6baa5562f8dc5768f76d8264 +size 8705 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png index 38ad0e4b56..83302d6ba4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:326d59cf768b2dbd96eb7964d54c8eda509a5cd57c6e62087625e3314da0bb4d -size 13658 +oid sha256:16dee1dfe746cd40dac9fe8f0af3ecb42cd14bab5cc490917b589beed065ed1b +size 14686 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png index 4da2a98aca..687e0d436a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef0dc4d53daeb986f378b6e4d85928b4b6729336c89cf21e642c88c53688a3ab -size 10292 +oid sha256:d57df7110371c9224e232b707d6a1b10ce14afcb56c803a78220792f2a0d4cf2 +size 11354 diff --git a/tools/localazy/config.json b/tools/localazy/config.json index 93e1c71759..5753fe5f47 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -271,6 +271,7 @@ "screen_room_message.*", "screen_room_retry.*", "screen_room_timeline.*", + "screen\\.room\\.timeline.*", "screen\\.room_timeline.*", "screen_room_typing.*", "screen\\.image_edition\\..*", From 09b7732c1b1c278a40de03084a0c8403ab8ba4d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 14 Jul 2026 15:45:26 +0200 Subject: [PATCH 110/383] Fix API breaks: - Add `Beacon` variants for `NotificationData`. - Add `call` and `status` to `UserProfile`. --- .../libraries/matrix/api/notification/NotificationData.kt | 3 +++ .../TimelineEventToNotificationContentMapper.kt | 2 ++ .../android/libraries/matrix/impl/RustMatrixClientTest.kt | 2 ++ .../matrix/impl/fixtures/factories/UserProfile.kt | 6 ++++++ .../libraries/matrix/impl/fixtures/fakes/FakeFfiClient.kt | 3 ++- .../impl/notifications/DefaultNotifiableEventResolver.kt | 7 ++++++- 6 files changed, 21 insertions(+), 2 deletions(-) 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 c58a458865..8a4891a5bf 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 @@ -89,6 +89,8 @@ sealed interface NotificationContent { val senderId: UserId, val question: String, ) : MessageLike + + data object Beacon : MessageLike } sealed interface StateEvent : NotificationContent { @@ -116,6 +118,7 @@ sealed interface NotificationContent { data class RoomTopic(val topic: String) : StateEvent data object SpaceChild : StateEvent data object SpaceParent : StateEvent + data object BeaconInfo : StateEvent } data class Invite( 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 84fd2e80e8..e4914019ea 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 @@ -71,6 +71,7 @@ private fun StateEventContent.toContent(): NotificationContent.StateEvent { is StateEventContent.RoomTopic -> NotificationContent.StateEvent.RoomTopic(topic) StateEventContent.SpaceChild -> NotificationContent.StateEvent.SpaceChild StateEventContent.SpaceParent -> NotificationContent.StateEvent.SpaceParent + StateEventContent.BeaconInfo -> NotificationContent.StateEvent.BeaconInfo } } @@ -108,6 +109,7 @@ private fun MessageLikeEventContent.toContent(senderId: UserId): NotificationCon ) MessageLikeEventContent.Sticker -> NotificationContent.MessageLike.Sticker is MessageLikeEventContent.Poll -> NotificationContent.MessageLike.Poll(senderId, question) + MessageLikeEventContent.Beacon -> NotificationContent.MessageLike.Beacon } } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt index 745fbf02d5..49cf59a954 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt @@ -90,6 +90,8 @@ class RustMatrixClientTest { userId = userId, displayName = A_USER_NAME, avatarUrl = AN_AVATAR_URL, + status = null, + call = null, ) }, ), diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/UserProfile.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/UserProfile.kt index 8713e08f1c..947e6e7aa1 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/UserProfile.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/UserProfile.kt @@ -9,14 +9,20 @@ package io.element.android.libraries.matrix.impl.fixtures.factories import io.element.android.libraries.matrix.test.A_USER_ID +import org.matrix.rustcomponents.sdk.UserCall import org.matrix.rustcomponents.sdk.UserProfile +import org.matrix.rustcomponents.sdk.UserStatus internal fun aRustUserProfile( userId: String = A_USER_ID.value, displayName: String = "displayName", avatarUrl: String = "avatarUrl", + status: UserStatus? = null, + call: UserCall? = null, ) = UserProfile( userId = userId, displayName = displayName, avatarUrl = avatarUrl, + status = status, + call = call, ) 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 4c23744d53..efae379415 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 @@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl.fixtures.fakes import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSession +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustUserProfile import io.element.android.libraries.matrix.test.A_DEVICE_ID import io.element.android.libraries.matrix.test.A_HOMESERVER_URL import io.element.android.libraries.matrix.test.A_USER_ID @@ -49,7 +50,7 @@ class FakeFfiClient( private val session: Session = aRustSession(), private val clearCachesResult: () -> Unit = { lambdaError() }, private val withUtdHook: (UnableToDecryptDelegate) -> Unit = { lambdaError() }, - private val getProfileResult: (String) -> UserProfile = { UserProfile(userId = userId, displayName = null, avatarUrl = null) }, + private val getProfileResult: (String) -> UserProfile = { aRustUserProfile() }, private val homeserverLoginDetailsResult: () -> HomeserverLoginDetails = { lambdaError() }, private val getStoreSizesResult: () -> StoreSizes = { lambdaError() }, private val createRoomResult: (CreateRoomParameters) -> String = { lambdaError() }, 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 2f3fa9b0b7..0b2ae5be2c 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 @@ -299,6 +299,10 @@ class DefaultNotifiableEventResolver( Timber.tag(loggerTag.value).d("Ignoring notification for sticker") throw NotificationResolverException.EventFilteredOut } + NotificationContent.MessageLike.Beacon -> { + Timber.tag(loggerTag.value).d("Ignoring notification for beacon") + throw NotificationResolverException.EventFilteredOut + } is NotificationContent.StateEvent.RoomMemberContent, NotificationContent.StateEvent.PolicyRuleRoom, NotificationContent.StateEvent.PolicyRuleServer, @@ -318,7 +322,8 @@ class DefaultNotifiableEventResolver( NotificationContent.StateEvent.RoomTombstone, is NotificationContent.StateEvent.RoomTopic, NotificationContent.StateEvent.SpaceChild, - NotificationContent.StateEvent.SpaceParent -> { + NotificationContent.StateEvent.SpaceParent, + NotificationContent.StateEvent.BeaconInfo -> { Timber.tag(loggerTag.value).d("Ignoring notification for state event ${content.javaClass.simpleName}") throw NotificationResolverException.EventFilteredOut } From 1619155b87407812caa133485ce3a0fdf250cf30 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Jul 2026 15:48:26 +0200 Subject: [PATCH 111/383] Update dependency io.github.sergio-sastre.ComposablePreviewScanner:android to v0.9.1 (#7201) 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 90dd5c39bc..80b428bf8f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -175,7 +175,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.9.0" +test_composable_preview_scanner = "io.github.sergio-sastre.ComposablePreviewScanner:android:0.9.1" 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 3bb7fe97e651bed2daa541d4887ba3bbf1bebf64 Mon Sep 17 00:00:00 2001 From: Timo <16718859+toger5@users.noreply.github.com> Date: Tue, 14 Jul 2026 17:49:40 +0200 Subject: [PATCH 112/383] Default to dark theme for EC (#7162) * Default to dark theme for EC (this is the intended design on light and dark system configuration) * Use `theme=dark` url param for element call * Update CallScreenPresenter.kt --- .../call/impl/ui/CallScreenPresenter.kt | 3 +- .../call/impl/ui/ElementCallActivity.kt | 37 +++++++++++-------- 2 files changed, 22 insertions(+), 18 deletions(-) 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 7d8e20967f..cc3468a845 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 @@ -22,7 +22,6 @@ import dev.zacsweers.metro.Assisted 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.CallData import io.element.android.features.call.impl.data.WidgetMessage import io.element.android.features.call.impl.utils.ActiveCallManager @@ -84,7 +83,7 @@ class CallScreenPresenter( var ignoreWebViewError by rememberSaveable { mutableStateOf(false) } var webViewError by remember { mutableStateOf(null) } val languageTag = languageTagProvider.provideLanguageTag() - val theme = if (ElementTheme.isLightTheme) "light" else "dark" + val theme = "dark" DisposableEffect(Unit) { coroutineScope.launch { 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 26df7c160c..9a093ff5a6 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,6 +38,7 @@ import androidx.core.view.WindowInsetsControllerCompat import androidx.lifecycle.Lifecycle import dev.zacsweers.metro.Inject import io.element.android.compound.colors.SemanticColorsLightDark +import io.element.android.compound.theme.ForcedDarkElementTheme 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 @@ -143,24 +144,28 @@ class ElementCallActivity : compoundDark = colors.dark, buildMeta = buildMeta, ) { - val state = presenter.present() - eventSink = state.eventSink - LaunchedEffect(state.isCallActive) { - if (state.isCallActive) { - setCallIsActive() + ForcedDarkElementTheme( + colors = colors, + ) { + val state = presenter.present() + eventSink = state.eventSink + LaunchedEffect(state.isCallActive) { + if (state.isCallActive) { + setCallIsActive() + } } + CallScreenView( + state = state, + pipState = pipState, + onConsoleMessage = { + consoleMessageLogger.log("ElementCall", it) + }, + requestPermissions = { permissions, callback -> + requestPermissionCallback = callback + requestPermissionsLauncher.launch(permissions) + } + ) } - CallScreenView( - state = state, - pipState = pipState, - onConsoleMessage = { - consoleMessageLogger.log("ElementCall", it) - }, - requestPermissions = { permissions, callback -> - requestPermissionCallback = callback - requestPermissionsLauncher.launch(permissions) - } - ) } } } From c86307dead2f7f93971e23edb2346aefe5d5b752 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 13 Jul 2026 19:54:40 +0100 Subject: [PATCH 113/383] Render push notifications for knocks The homeserver's new MSCxxxx knock push rule notifies members who can act on a knock; the push resolver previously filtered every m.room.member state event out, so the push produced no notification. Split RoomMemberContent out of the filtered-out catch-all and render membership=knock as "Requested to join" from the knocking user (other membership changes stay filtered out). Co-Authored-By: Claude Fable 5 --- .../DefaultNotifiableEventResolver.kt | 25 ++++++++++++++++++- .../impl/src/main/res/values/temporary.xml | 11 ++++++++ .../DefaultNotifiableEventResolverTest.kt | 22 ++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 libraries/push/impl/src/main/res/values/temporary.xml 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 2f3fa9b0b7..bf9390533a 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 @@ -36,6 +36,7 @@ import io.element.android.libraries.matrix.api.media.isPreviewEnabled 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.permalink.PermalinkParser +import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType @@ -299,7 +300,29 @@ class DefaultNotifiableEventResolver( Timber.tag(loggerTag.value).d("Ignoring notification for sticker") throw NotificationResolverException.EventFilteredOut } - is NotificationContent.StateEvent.RoomMemberContent, + is NotificationContent.StateEvent.RoomMemberContent -> { + // MSCxxxx: the homeserver pushes knocks to users who can act on them. + if (content.membershipState == RoomMembershipState.KNOCK) { + val notifiableMessageEvent = buildNotifiableMessageEvent( + sessionId = userId, + senderId = content.userId, + roomId = roomId, + eventId = eventId, + noisy = isNoisy, + timestamp = this.timestamp, + senderDisambiguatedDisplayName = getDisambiguatedDisplayName(content.userId), + body = stringProvider.getString(R.string.notification_knock_request_body), + roomName = roomDisplayName, + roomIsDm = isDm, + roomAvatarPath = roomAvatarUrl, + senderAvatarPath = senderAvatarUrl, + ) + ResolvedPushEvent.Event(notifiableMessageEvent) + } else { + Timber.tag(loggerTag.value).d("Ignoring notification for membership ${content.membershipState}") + throw NotificationResolverException.EventFilteredOut + } + } NotificationContent.StateEvent.PolicyRuleRoom, NotificationContent.StateEvent.PolicyRuleServer, NotificationContent.StateEvent.PolicyRuleUser, diff --git a/libraries/push/impl/src/main/res/values/temporary.xml b/libraries/push/impl/src/main/res/values/temporary.xml new file mode 100644 index 0000000000..7a569d555e --- /dev/null +++ b/libraries/push/impl/src/main/res/values/temporary.xml @@ -0,0 +1,11 @@ + + + + + "Requested to join" + 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 e196ddb0ec..d188cd0fee 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 @@ -627,6 +627,28 @@ class DefaultNotifiableEventResolverTest : RobolectricTest() { assertThat(result.getEvent(request)).isEqualTo(Result.success(expectedResult)) } + @Test + fun `resolve RoomMemberContent knock`() = runTest { + val sut = createDefaultNotifiableEventResolver( + notificationResult = Result.success( + mapOf( + AN_EVENT_ID to Result.success(aNotificationData( + content = NotificationContent.StateEvent.RoomMemberContent( + userId = A_USER_ID_2, + membershipState = RoomMembershipState.KNOCK + ) + )) + ) + ) + ) + val request = aPushRequest(A_SESSION_ID, A_ROOM_ID, AN_EVENT_ID, "firebase") + val result = sut.resolveEvents(A_SESSION_ID, listOf(request)) + val expectedResult = ResolvedPushEvent.Event( + aNotifiableMessageEvent(body = "Requested to join") + ) + assertThat(result.getEvent(request)).isEqualTo(Result.success(expectedResult)) + } + @Test fun `resolve RoomMemberContent other`() = runTest { val sut = createDefaultNotifiableEventResolver( From 34293eb8240a05a6264dc1a5ec87b0dccd67736f Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Tue, 14 Jul 2026 13:24:33 +0100 Subject: [PATCH 114/383] Refer to the knock push rule by its published MSC number (MSC4506) Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01Uk8aPxHn3BHCe52L226jdG --- .../push/impl/notifications/DefaultNotifiableEventResolver.kt | 2 +- libraries/push/impl/src/main/res/values/temporary.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 bf9390533a..47f97404a3 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 @@ -301,7 +301,7 @@ class DefaultNotifiableEventResolver( throw NotificationResolverException.EventFilteredOut } is NotificationContent.StateEvent.RoomMemberContent -> { - // MSCxxxx: the homeserver pushes knocks to users who can act on them. + // MSC4506: the homeserver pushes knocks to users who can act on them. if (content.membershipState == RoomMembershipState.KNOCK) { val notifiableMessageEvent = buildNotifiableMessageEvent( sessionId = userId, diff --git a/libraries/push/impl/src/main/res/values/temporary.xml b/libraries/push/impl/src/main/res/values/temporary.xml index 7a569d555e..494f2ee441 100644 --- a/libraries/push/impl/src/main/res/values/temporary.xml +++ b/libraries/push/impl/src/main/res/values/temporary.xml @@ -6,6 +6,6 @@ --> - + "Requested to join" From afdf07b23e1ca829c758b315fd9e4ffcb2eb8e2a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 08:36:59 +0200 Subject: [PATCH 115/383] Update dependency io.github.zxing-cpp:android to v3.1.0 (#7206) 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 80b428bf8f..027fe03526 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -220,7 +220,7 @@ 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" opusencoder = "io.element.android:opusencoder:1.2.0" -zxing_cpp = "io.github.zxing-cpp:android:3.0.2" +zxing_cpp = "io.github.zxing-cpp:android:3.1.0" google_zxing = "com.google.zxing:core:3.5.4" google_guava = "com.google.guava:guava:33.6.0-android" From e915cd242ba0b18a474fceb92584342711544eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Wischer?= <33184634+unclejay80@users.noreply.github.com> Date: Wed, 15 Jul 2026 09:23:54 +0200 Subject: [PATCH 116/383] Expose current/max progress values to accessibility services (#7209) --- .../theme/components/LinearProgressIndicator.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/LinearProgressIndicator.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/LinearProgressIndicator.kt index 04f08166b7..77946dd5ab 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/LinearProgressIndicator.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/LinearProgressIndicator.kt @@ -16,6 +16,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.platform.LocalInspectionMode +import androidx.compose.ui.semantics.ProgressBarRangeInfo +import androidx.compose.ui.semantics.progressBarRangeInfo +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @@ -32,7 +35,9 @@ fun LinearProgressIndicator( strokeCap: StrokeCap = ProgressIndicatorDefaults.LinearStrokeCap, ) { androidx.compose.material3.LinearProgressIndicator( - modifier = modifier, + modifier = modifier.semantics { + progressBarRangeInfo = ProgressBarRangeInfo(progress(), 0f..1f) + }, progress = progress, gapSize = gapSize, color = color, @@ -63,7 +68,9 @@ fun LinearProgressIndicator( ) } else { androidx.compose.material3.LinearProgressIndicator( - modifier = modifier, + modifier = modifier.semantics { + progressBarRangeInfo = ProgressBarRangeInfo.Indeterminate + }, color = color, gapSize = gapSize, trackColor = trackColor, From f794cb9f063cbc0dede429b593967fe1b6814c20 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 15 Jul 2026 09:49:06 +0200 Subject: [PATCH 117/383] Revert "Expose current/max progress values to accessibility services (#7209)" This reverts commit e915cd242ba0b18a474fceb92584342711544eb1. --- .../theme/components/LinearProgressIndicator.kt | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/LinearProgressIndicator.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/LinearProgressIndicator.kt index 77946dd5ab..04f08166b7 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/LinearProgressIndicator.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/LinearProgressIndicator.kt @@ -16,9 +16,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.platform.LocalInspectionMode -import androidx.compose.ui.semantics.ProgressBarRangeInfo -import androidx.compose.ui.semantics.progressBarRangeInfo -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @@ -35,9 +32,7 @@ fun LinearProgressIndicator( strokeCap: StrokeCap = ProgressIndicatorDefaults.LinearStrokeCap, ) { androidx.compose.material3.LinearProgressIndicator( - modifier = modifier.semantics { - progressBarRangeInfo = ProgressBarRangeInfo(progress(), 0f..1f) - }, + modifier = modifier, progress = progress, gapSize = gapSize, color = color, @@ -68,9 +63,7 @@ fun LinearProgressIndicator( ) } else { androidx.compose.material3.LinearProgressIndicator( - modifier = modifier.semantics { - progressBarRangeInfo = ProgressBarRangeInfo.Indeterminate - }, + modifier = modifier, color = color, gapSize = gapSize, trackColor = trackColor, From 03f3e8b3e08f7987686c2a59ddc821dde5c4d556 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 15 Jul 2026 10:56:50 +0200 Subject: [PATCH 118/383] Try fixing DM creation in Maestro (#7204) * Try fixing DM creation in Maestro * Also handle 'invite new people to this room' with first invite to aRoomName * Try adding a room list clean up sub-flow * No need to press back button after successful invites * Looks like 'hideKeyboard' works as 'back' and messes up with the navigation. Try using the workaround described in https://docs.maestro.dev/reference/commands-available/hidekeyboard#workarounds --- .maestro/tests/roomList/cleanUpRoomList.yaml | 21 +++++++++++++++++++ .../tests/roomList/createAndDeleteDM.yaml | 11 +++++++++- .../tests/roomList/createAndDeleteRoom.yaml | 14 +++++++++---- .maestro/tests/roomList/roomList.yaml | 1 + .../invitepeople/impl/InvitePeopleView.kt | 4 ++-- 5 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 .maestro/tests/roomList/cleanUpRoomList.yaml diff --git a/.maestro/tests/roomList/cleanUpRoomList.yaml b/.maestro/tests/roomList/cleanUpRoomList.yaml new file mode 100644 index 0000000000..3d9fb3d6e4 --- /dev/null +++ b/.maestro/tests/roomList/cleanUpRoomList.yaml @@ -0,0 +1,21 @@ +appId: ${MAESTRO_APP_ID} +--- +# Clean up the room list if it was left in a bad state by previous tests +- runFlow: + when: + visible: 'aRoomName' + commands: + - longPressOn: 'aRoomName' + - tapOn: + text: "Leave room" + index: 0 + - tapOn: "Leave" +- runFlow: + when: + visible: ${MAESTRO_INVITEE1_MXID} + commands: + - longPressOn: ${MAESTRO_INVITEE1_MXID} + - tapOn: + text: "Leave room" + index: 0 + - tapOn: "Leave" diff --git a/.maestro/tests/roomList/createAndDeleteDM.yaml b/.maestro/tests/roomList/createAndDeleteDM.yaml index eed576c04f..8372d6dbc9 100644 --- a/.maestro/tests/roomList/createAndDeleteDM.yaml +++ b/.maestro/tests/roomList/createAndDeleteDM.yaml @@ -7,7 +7,16 @@ appId: ${MAESTRO_APP_ID} - tapOn: text: ${MAESTRO_INVITEE1_MXID} index: 1 -- tapOn: "Continue" +- runFlow: + when: + visible: 'Start a chat with this new contact?' + commands: + - tapOn: 'Continue' +- runFlow: + when: + visible: 'Send invite?' + commands: + - tapOn: 'Send invite' - takeScreenshot: build/maestro/330-createAndDeleteDM - tapOn: "maestroelement2" - scroll diff --git a/.maestro/tests/roomList/createAndDeleteRoom.yaml b/.maestro/tests/roomList/createAndDeleteRoom.yaml index adf9d7cf29..6b4d745fae 100644 --- a/.maestro/tests/roomList/createAndDeleteRoom.yaml +++ b/.maestro/tests/roomList/createAndDeleteRoom.yaml @@ -15,6 +15,12 @@ appId: ${MAESTRO_APP_ID} text: ${MAESTRO_INVITEE1_MXID} index: 1 - tapOn: "Finish" +- runFlow: + when: + visible: 'Invite new contact to this room?' + commands: + - tapOn: + id: "confirm_invite_unknown" - tapOn: "aRoomName" - tapOn: "Invite" # assert there's 1 member and 1 invitee @@ -23,6 +29,10 @@ appId: ${MAESTRO_APP_ID} - tapOn: text: ${MAESTRO_INVITEE2_MXID} index: 1 +# Hide keyboard by tapping on an external element in case it's displayed, otherwise it will 'eat' the back button press +- tapOn: + # Navigation title + text: "Invite people" - tapOn: "Invite" - runFlow: when: @@ -30,10 +40,6 @@ appId: ${MAESTRO_APP_ID} 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" - scrollUntilVisible: direction: DOWN element: diff --git a/.maestro/tests/roomList/roomList.yaml b/.maestro/tests/roomList/roomList.yaml index 5cc9e269c5..704d983b7d 100644 --- a/.maestro/tests/roomList/roomList.yaml +++ b/.maestro/tests/roomList/roomList.yaml @@ -1,5 +1,6 @@ appId: ${MAESTRO_APP_ID} --- +- runFlow: cleanUpRoomList.yaml - runFlow: searchRoomList.yaml - takeScreenshot: build/maestro/300-RoomList - runFlow: timeline/timeline.yaml 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 2bbd64c977..0ee3559aa3 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 @@ -302,13 +302,13 @@ private fun InvitePeopleConfirmModal( text = stringResource(CommonStrings.action_remove), onClick = onRemove, leadingIcon = IconSource.Vector(CompoundIcons.Close()), - modifier = Modifier.weight(1f).testTag(TestTags.confirmInviteUnknown), + modifier = Modifier.weight(1f), ) Button( text = stringResource(CommonStrings.action_invite), onClick = onInvite, leadingIcon = IconSource.Vector(CompoundIcons.Check()), - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f).testTag(TestTags.confirmInviteUnknown), ) } } From e4d66619264d852f74b380c3c1a50b7f3cfbada4 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 15 Jul 2026 12:18:22 +0200 Subject: [PATCH 119/383] fixup: import --- .../push/impl/notifications/DefaultNotifiableEventResolver.kt | 1 - 1 file changed, 1 deletion(-) 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 8955e9164c..98490c98b4 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 @@ -56,7 +56,6 @@ import io.element.android.libraries.push.impl.db.PushRequest 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.impl.notifications.model.ResolvedPushEvent.* import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.toolbox.api.strings.StringProvider import timber.log.Timber From 62cc7e0505e461722548ee79882bc72693c724a9 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 15 Jul 2026 13:29:16 +0200 Subject: [PATCH 120/383] Allow homeserver to disable encryption in Element Pro (#7198) * Allow HS to disable encryption in Element Pro Add `force_disable_e2ee` support in the Element well known retriever and cache to allow a homeserver to disable encrypted room creation and enabling encryption in an existing room in Element Pro clients * Bump enterprise repo back to `main` branch --- enterprise | 2 +- features/createroom/impl/build.gradle.kts | 2 ++ .../configureroom/ConfigureRoomPresenter.kt | 4 ++- .../impl/ConfigureRoomPresenterTest.kt | 29 +++++++++++++++++++ .../api/SessionEnterpriseService.kt | 2 ++ .../impl/DefaultSessionEnterpriseService.kt | 1 + .../test/FakeSessionEnterpriseService.kt | 5 ++++ .../securityandprivacy/impl/build.gradle.kts | 2 ++ .../impl/root/SecurityAndPrivacyPresenter.kt | 7 +++++ .../impl/root/SecurityAndPrivacyState.kt | 3 +- .../root/SecurityAndPrivacyStateProvider.kt | 2 ++ .../root/SecurityAndPrivacyPresenterTest.kt | 19 ++++++++++++ .../libraries/matrix/test/FakeMatrixClient.kt | 8 ++--- .../wellknown/api/ElementWellKnown.kt | 1 + .../impl/InternalElementWellKnown.kt | 2 ++ .../libraries/wellknown/impl/Mapper.kt | 1 + .../DefaultSessionWellknownRetrieverTest.kt | 8 ++++- .../impl/DefaultWellknownRetrieverTest.kt | 6 +++- .../features/wellknown/test/Fixtures.kt | 2 ++ 19 files changed, 97 insertions(+), 9 deletions(-) diff --git a/enterprise b/enterprise index bc38a11f95..cca96c4fc2 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit bc38a11f95988cc1bbc209decb998f21c465ded0 +Subproject commit cca96c4fc24b6e2fd1ccf9265c8283ac9bf63dc0 diff --git a/features/createroom/impl/build.gradle.kts b/features/createroom/impl/build.gradle.kts index 13a195e940..2cd3961ead 100644 --- a/features/createroom/impl/build.gradle.kts +++ b/features/createroom/impl/build.gradle.kts @@ -43,6 +43,7 @@ dependencies { implementation(libs.coil.compose) implementation(projects.libraries.featureflag.api) implementation(projects.features.invitepeople.api) + implementation(projects.features.enterprise.api) api(projects.features.createroom.api) testCommonDependencies(libs, true) @@ -53,4 +54,5 @@ dependencies { testImplementation(projects.libraries.permissions.test) testImplementation(projects.features.startchat.test) testImplementation(projects.libraries.featureflag.test) + testImplementation(projects.features.enterprise.test) } 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 0d74ca05bf..abedc2bd49 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 @@ -24,6 +24,7 @@ import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject import im.vector.app.features.analytics.plan.CreatedRoom +import io.element.android.features.enterprise.api.SessionEnterpriseService import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runCatchingUpdatingState @@ -73,6 +74,7 @@ class ConfigureRoomPresenter( private val featureFlagService: FeatureFlagService, private val roomAliasHelper: RoomAliasHelper, private val mediaOptimizationConfigProvider: MediaOptimizationConfigProvider, + private val sessionEnterpriseService: SessionEnterpriseService, ) : Presenter { @AssistedFactory interface Factory { @@ -256,7 +258,7 @@ class ConfigureRoomPresenter( CreateRoomParameters( name = config.roomName, topic = config.topic, - isEncrypted = true, + isEncrypted = !sessionEnterpriseService.isEncryptionDisabledByHomeserver(), isDirect = false, visibility = RoomVisibility.Private, historyVisibilityOverride = RoomHistoryVisibility.Invited, 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 c0c4a8a5fe..046d00a5c6 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 @@ -20,11 +20,13 @@ import io.element.android.features.createroom.impl.configureroom.CreateRoomConfi import io.element.android.features.createroom.impl.configureroom.JoinRuleItem import io.element.android.features.createroom.impl.configureroom.RoomAddress import io.element.android.features.createroom.impl.configureroom.RoomVisibilityState +import io.element.android.features.enterprise.test.FakeSessionEnterpriseService 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.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.room.RoomInfo import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias import io.element.android.libraries.matrix.api.room.alias.RoomAliasHelper @@ -56,6 +58,7 @@ import io.element.android.services.analytics.api.AnalyticsService 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.matching import io.element.android.tests.testutils.robolectric.RobolectricTest import io.element.android.tests.testutils.test import io.mockk.mockk @@ -517,6 +520,30 @@ class ConfigureRoomPresenterTest : RobolectricTest() { } } + @Test + fun `present - creating a private room when encryption is disabled by the HS creates it unencrypted`() = runTest { + val sessionEnterpriseService = FakeSessionEnterpriseService(isEncryptionDisabledResult = { true }) + val createRoomLambda = lambdaRecorder> { Result.success(A_ROOM_ID) } + val matrixClient = createMatrixClient().apply { + createRoomResult = createRoomLambda + } + val presenter = createConfigureRoomPresenter( + matrixClient = matrixClient, + sessionEnterpriseService = sessionEnterpriseService, + ) + presenter.test { + val initialState = initialState() + + initialState.eventSink(ConfigureRoomEvents.JoinRuleChanged(JoinRuleItem.PrivateVisibility.Private)) + initialState.eventSink(ConfigureRoomEvents.CreateRoom) + + assertThat(awaitItem().createRoomAction.isLoading()).isTrue() + assertThat(awaitItem().createRoomAction.isSuccess()).isTrue() + + createRoomLambda.assertions().isCalledOnce().with(matching { !it.isEncrypted }) + } + } + private suspend fun TurbineTestContext.initialState(): ConfigureRoomState { skipItems(1) return awaitItem() @@ -552,6 +579,7 @@ class ConfigureRoomPresenterTest : RobolectricTest() { permissionsPresenter: PermissionsPresenter = FakePermissionsPresenter(), isKnockFeatureEnabled: Boolean = true, mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), + sessionEnterpriseService: FakeSessionEnterpriseService = FakeSessionEnterpriseService(isEncryptionDisabledResult = { false }), ) = ConfigureRoomPresenter( isSpace = isSpace, initialParentSpaceId = initialParenSpaceId, @@ -566,5 +594,6 @@ class ConfigureRoomPresenterTest : RobolectricTest() { mapOf(FeatureFlags.Knock.key to isKnockFeatureEnabled) ), mediaOptimizationConfigProvider = mediaOptimizationConfigProvider, + sessionEnterpriseService = sessionEnterpriseService, ) } 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 f87dc743e8..ee005a0b6b 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 @@ -12,5 +12,7 @@ interface SessionEnterpriseService { suspend fun isElementCallAvailable(): Boolean suspend fun tweakMasUrl(url: String): String + suspend fun isEncryptionDisabledByHomeserver(): Boolean + suspend fun init() } 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 9aafcd343c..3ac10d8a08 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 @@ -17,4 +17,5 @@ class DefaultSessionEnterpriseService : SessionEnterpriseService { override suspend fun init() = Unit override suspend fun tweakMasUrl(url: String): String = url override suspend fun isElementCallAvailable(): Boolean = true + override suspend fun isEncryptionDisabledByHomeserver(): Boolean = false } 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 0bcad13033..e198fca867 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 @@ -15,6 +15,7 @@ import io.element.android.tests.testutils.simulateLongTask class FakeSessionEnterpriseService( private val isElementCallAvailableResult: () -> Boolean = { lambdaError() }, private val tweakMasUrlResult: (String) -> String = { lambdaError() }, + private val isEncryptionDisabledResult: () -> Boolean = { lambdaError() }, ) : SessionEnterpriseService { override suspend fun init() { } @@ -26,4 +27,8 @@ class FakeSessionEnterpriseService( override suspend fun isElementCallAvailable(): Boolean = simulateLongTask { isElementCallAvailableResult() } + + override suspend fun isEncryptionDisabledByHomeserver(): Boolean { + return isEncryptionDisabledResult() + } } diff --git a/features/securityandprivacy/impl/build.gradle.kts b/features/securityandprivacy/impl/build.gradle.kts index bb9764eb60..d42bdef883 100644 --- a/features/securityandprivacy/impl/build.gradle.kts +++ b/features/securityandprivacy/impl/build.gradle.kts @@ -41,10 +41,12 @@ dependencies { implementation(projects.libraries.uiStrings) implementation(projects.services.analytics.api) implementation(projects.libraries.featureflag.api) + implementation(projects.features.enterprise.api) testCommonDependencies(libs, true) testImplementation(projects.services.analytics.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.testtags) + testImplementation(projects.features.enterprise.test) } 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 48ab41a820..32517cd18d 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 @@ -22,6 +22,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.enterprise.api.SessionEnterpriseService import io.element.android.features.securityandprivacy.api.SecurityAndPrivacyPermissions import io.element.android.features.securityandprivacy.api.securityAndPrivacyPermissions import io.element.android.features.securityandprivacy.impl.SecurityAndPrivacyNavigator @@ -63,6 +64,7 @@ class SecurityAndPrivacyPresenter( private val matrixClient: MatrixClient, private val room: JoinedRoom, private val featureFlagService: FeatureFlagService, + private val sessionEnterpriseService: SessionEnterpriseService, ) : Presenter { @AssistedFactory interface Factory { @@ -83,6 +85,10 @@ class SecurityAndPrivacyPresenter( val homeserverName = remember { matrixClient.userIdServerName() } val roomInfo by room.roomInfoFlow.collectAsState() + val isEncryptionDisabledByHomeserver by produceState(false) { + value = sessionEnterpriseService.isEncryptionDisabledByHomeserver() + } + val savedIsVisibleInRoomDirectory = remember { mutableStateOf>(AsyncData.Uninitialized) } LaunchedEffect(Unit) { isRoomVisibleInRoomDirectory(savedIsVisibleInRoomDirectory) @@ -247,6 +253,7 @@ class SecurityAndPrivacyPresenter( isSpace = roomInfo.isSpace, selectableJoinedSpaces = selectableJoinedSpaces, spaceSelectionMode = spaceSelectionMode, + isEncryptionDisabledByHomeserver = isEncryptionDisabledByHomeserver, 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 26e77b3c70..ddba5d0caa 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 @@ -27,6 +27,7 @@ data class SecurityAndPrivacyState( // the settings the user wants to apply. val editedSettings: SecurityAndPrivacySettings, val homeserverName: String, + val isEncryptionDisabledByHomeserver: Boolean, val showEnableEncryptionConfirmation: Boolean, private val isKnockEnabled: Boolean, val saveAction: AsyncAction, @@ -84,7 +85,7 @@ data class SecurityAndPrivacyState( editedSettings.roomAccess.canConfigureRoomVisibility() val showHistoryVisibilitySection = permissions.canChangeHistoryVisibility && !isSpace - val showEncryptionSection = permissions.canChangeEncryption && !isSpace + val showEncryptionSection = !isEncryptionDisabledByHomeserver && permissions.canChangeEncryption && !isSpace @Composable fun spaceMemberDescription(): String { 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 19124302e3..998d61b564 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,6 +138,7 @@ fun aSecurityAndPrivacyState( isSpace: Boolean = false, selectableJoinedSpaces: Set = emptySet(), spaceSelectionMode: SpaceSelectionMode = SpaceSelectionMode.None, + isEncryptionDisabledByHomeserver: Boolean = false, eventSink: (SecurityAndPrivacyEvent) -> Unit = {} ) = SecurityAndPrivacyState( editedSettings = editedSettings, @@ -150,5 +151,6 @@ fun aSecurityAndPrivacyState( isSpace = isSpace, selectableJoinedSpaces = selectableJoinedSpaces.toImmutableSet(), spaceSelectionMode = spaceSelectionMode, + isEncryptionDisabledByHomeserver = isEncryptionDisabledByHomeserver, 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 34b4222053..0b5133fe6a 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 @@ -8,6 +8,7 @@ package io.element.android.features.securityandprivacy.impl.root import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.test.FakeSessionEnterpriseService import io.element.android.features.securityandprivacy.impl.FakeSecurityAndPrivacyNavigator import io.element.android.features.securityandprivacy.impl.SecurityAndPrivacyNavigator import io.element.android.features.securityandprivacy.impl.manageauthorizedspaces.SpaceSelectionStateHolder @@ -1046,6 +1047,20 @@ class SecurityAndPrivacyPresenterTest { } } + @Test + fun `present - showEncryptionSection is false if the HS disabled encryption`() = runTest { + val sessionEnterpriseService = FakeSessionEnterpriseService(isEncryptionDisabledResult = { true }) + val presenter = createSecurityAndPrivacyPresenter( + sessionEnterpriseService = sessionEnterpriseService, + ) + presenter.test { + skipItems(1) + + // The HS has disabled encryption, so the encryption section should not be shown + assertThat(awaitItem().showEncryptionSection).isFalse() + } + } + private fun roomPermissions( canChangeRoomAccess: Boolean = true, canChangeHistoryVisibility: Boolean = true, @@ -1084,6 +1099,9 @@ class SecurityAndPrivacyPresenterTest { ), ), spaceSelectionStateHolder: SpaceSelectionStateHolder = SpaceSelectionStateHolder(), + sessionEnterpriseService: FakeSessionEnterpriseService = FakeSessionEnterpriseService( + isEncryptionDisabledResult = { false }, + ) ): SecurityAndPrivacyPresenter { return SecurityAndPrivacyPresenter( room = room, @@ -1091,6 +1109,7 @@ class SecurityAndPrivacyPresenterTest { navigator = navigator, featureFlagService = featureFlagService, spaceSelectionStateHolder = spaceSelectionStateHolder, + sessionEnterpriseService = sessionEnterpriseService, ) } } 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 dc7593904d..1c9fcfa482 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 @@ -126,7 +126,7 @@ class FakeMatrixClient( private val getMapStyleUrlResult: () -> Result = { lambdaError() }, private val getDatabaseSizesLambda: () -> Result = { lambdaError() }, private val resetWellKnownConfigLambda: () -> Result = { lambdaError() }, - override val contentScanner: ContentScanner? = null + override val contentScanner: ContentScanner? = null, ) : MatrixClient { var setDisplayNameCalled: Boolean = false private set @@ -144,7 +144,7 @@ class FakeMatrixClient( private val _userProfile: MutableStateFlow = MutableStateFlow(MatrixUser(sessionId, userDisplayName, userAvatarUrl)) override val userProfile: StateFlow = _userProfile - private var createRoomResult: Result = Result.success(A_ROOM_ID) + var createRoomResult: (CreateRoomParameters) -> Result = { Result.success(A_ROOM_ID) } private var createDmResult: Result = Result.success(A_ROOM_ID) private var findDmResult: Result = Result.success(A_ROOM_ID) private val getRoomResults = mutableMapOf() @@ -193,7 +193,7 @@ class FakeMatrixClient( } override suspend fun createRoom(createRoomParams: CreateRoomParameters): Result = simulateLongTask { - return createRoomResult + return createRoomResult(createRoomParams) } override suspend fun createDM(userId: UserId): Result = simulateLongTask { @@ -297,7 +297,7 @@ class FakeMatrixClient( // Mocks fun givenCreateRoomResult(result: Result) { - createRoomResult = result + createRoomResult = { result } } fun givenCreateDmResult(result: Result) { 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 45448f66c2..a9c42b7121 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 @@ -17,4 +17,5 @@ data class ElementWellKnown( val identityProviderAppScheme: String?, val customRecoveryPassphrase: CustomRecoveryPassphrase?, val contentScannerUrl: String?, + val forceDisableE2EE: Boolean?, ) 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 ad60caefa5..c585264f55 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 @@ -46,6 +46,8 @@ data class InternalElementWellKnown( val customRecoveryPassphrase: InternalCustomRecoveryPassphrase? = null, @SerialName("content_scanner_url") val contentScannerUrl: String? = null, + @SerialName("force_disable_e2ee") + val forceDisableE2EE: Boolean? = null, ) @Serializable 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 420dea2bae..c4d15e7325 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 @@ -31,6 +31,7 @@ fun InternalElementWellKnown.map() = ElementWellKnown( identityProviderAppScheme = identityProviderAppScheme, customRecoveryPassphrase = customRecoveryPassphrase?.toPublic(), contentScannerUrl = contentScannerUrl, + forceDisableE2EE = forceDisableE2EE, ) private fun InternalCustomRecoveryPassphrase.toPublic(): CustomRecoveryPassphrase { 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 ec939b9988..6a2a12774b 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 @@ -50,6 +50,7 @@ class DefaultSessionWellknownRetrieverTest { identityProviderAppScheme = null, customRecoveryPassphrase = null, contentScannerUrl = null, + forceDisableE2EE = null, ) ) ) @@ -77,6 +78,7 @@ class DefaultSessionWellknownRetrieverTest { identityProviderAppScheme = "an_app_scheme", customRecoveryPassphrase = null, contentScannerUrl = "https://content-scanner.example.com", + forceDisableE2EE = false, ) ) ) @@ -108,6 +110,7 @@ class DefaultSessionWellknownRetrieverTest { identityProviderAppScheme = null, contentScannerUrl = null, customRecoveryPassphrase = null, + forceDisableE2EE = null, ) ) ) @@ -255,6 +258,7 @@ class DefaultSessionWellknownRetrieverTest { identityProviderAppScheme = "an_app_scheme", customRecoveryPassphrase = null, contentScannerUrl = "https://content-scanner.example.com", + forceDisableE2EE = false, ) ) ) @@ -303,6 +307,7 @@ class DefaultSessionWellknownRetrieverTest { identityProviderAppScheme = "an_app_scheme", customRecoveryPassphrase = null, contentScannerUrl = "https://content-scanner.example.com", + forceDisableE2EE = false, ) ) ) @@ -340,7 +345,8 @@ class DefaultSessionWellknownRetrieverTest { "brand_color": "#FF0000", "notification_sound": "a_notification_sound.flac", "idp_app_scheme": "an_app_scheme", - "content_scanner_url": "https://content-scanner.example.com" + "content_scanner_url": "https://content-scanner.example.com", + "force_disable_e2ee": false, }""" } } diff --git a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt index 0e9288f658..3ee5b2b91f 100644 --- a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt +++ b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt @@ -50,6 +50,7 @@ class DefaultWellknownRetrieverTest { identityProviderAppScheme = null, customRecoveryPassphrase = null, contentScannerUrl = null, + forceDisableE2EE = null, ) ) ) @@ -72,6 +73,7 @@ class DefaultWellknownRetrieverTest { identityProviderAppScheme = "an_app_scheme", customRecoveryPassphrase = null, contentScannerUrl = "https://content-scanner.example.com", + forceDisableE2EE = false, ) ) ) @@ -101,6 +103,7 @@ class DefaultWellknownRetrieverTest { identityProviderAppScheme = null, contentScannerUrl = null, customRecoveryPassphrase = null, + forceDisableE2EE = null, ) ) ) @@ -266,7 +269,8 @@ class DefaultWellknownRetrieverTest { "brand_color": "#FF0000", "notification_sound": "a_notification_sound.flac", "idp_app_scheme": "an_app_scheme", - "content_scanner_url": "https://content-scanner.example.com" + "content_scanner_url": "https://content-scanner.example.com", + "force_disable_e2ee": false }""" } } 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 8ec8874ad9..941e5f4cc7 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 @@ -20,6 +20,7 @@ fun anElementWellKnown( identityProviderAppScheme: String? = null, customRecoveryPassphrase: CustomRecoveryPassphrase? = null, contentScannerUrl: String? = null, + forceDisableE2EE: Boolean? = null, ) = ElementWellKnown( registrationHelperUrl = registrationHelperUrl, enforceElementPro = enforceElementPro, @@ -29,6 +30,7 @@ fun anElementWellKnown( identityProviderAppScheme = identityProviderAppScheme, customRecoveryPassphrase = customRecoveryPassphrase, contentScannerUrl = contentScannerUrl, + forceDisableE2EE = forceDisableE2EE, ) fun aCustomRecoveryPassphrase( From d0b4a21cfe05ee73dbdf80dc1218de9fc705032b Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 15 Jul 2026 15:01:35 +0200 Subject: [PATCH 121/383] Fix timelines not loading after marking a room as read from notification when app was killed (#7202) This can only happen when the app was killed by the OS and then you received some notification. This notification action creates a new `DefaultSessionPreferencesStore` when trying to fetch `isSendPublicReadReceiptsEnabled`, which would contain a different session coroutine scope than the one created when instantiating the navigation graph (`@SessionCoroutineScope`), resulting in flows that never emit any items and close automatically as 'completed'. This in turn prevented the timeline items subscription in `TimelinePresenter` from progressing, since we're also checking `isRenderReadReceiptsEnabled` there, which is closed and in turn closes the timeline items flow. --- .../android/x/di/DefaultSessionGraphFactory.kt | 2 +- .../NotificationBroadcastReceiverHandler.kt | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/io/element/android/x/di/DefaultSessionGraphFactory.kt b/app/src/main/kotlin/io/element/android/x/di/DefaultSessionGraphFactory.kt index 9631713bb6..5bfe082ffe 100644 --- a/app/src/main/kotlin/io/element/android/x/di/DefaultSessionGraphFactory.kt +++ b/app/src/main/kotlin/io/element/android/x/di/DefaultSessionGraphFactory.kt @@ -15,7 +15,7 @@ import io.element.android.libraries.matrix.api.MatrixClient @ContributesBinding(AppScope::class) class DefaultSessionGraphFactory( - private val appGraph: AppGraph + private val appGraph: AppGraph, ) : SessionGraphFactory { override fun create(client: MatrixClient): Any { return appGraph.sessionGraphFactory.create(client) 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 cb9ef8c82d..8dedb3325c 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 @@ -105,13 +105,21 @@ class NotificationBroadcastReceiverHandler( @Suppress("unused") private fun handleMarkAsRead(sessionId: SessionId, roomId: RoomId, threadId: ThreadId?) = appCoroutineScope.launch { val client = matrixClientProvider.getOrRestore(sessionId).getOrNull() ?: return@launch - val isSendPublicReadReceiptsEnabled = sessionPreferencesStore.get(sessionId, this).isSendPublicReadReceiptsEnabled().first() + val isSendPublicReadReceiptsEnabled = sessionPreferencesStore.get( + sessionId = sessionId, + // Make sure `sessionCoroutineScope` is used here, otherwise we'll have several instances using different coroutines, + // and it will not work as expected. + sessionCoroutineScope = client.sessionCoroutineScope, + ).isSendPublicReadReceiptsEnabled().first() val receiptType = if (isSendPublicReadReceiptsEnabled) { ReceiptType.READ } else { ReceiptType.READ_PRIVATE } - val room = client.getJoinedRoom(roomId) ?: return@launch + + val (room, needsDestroy) = activeRoomsHolder.getActiveRoomMatching(sessionId, roomId)?.let { it to false } + ?: client.getJoinedRoom(roomId)?.let { it to true } + ?: return@launch val timeline = if (threadId != null) { room.createTimeline(CreateTimelineParams.Threaded(threadId)).getOrNull() } else { @@ -131,6 +139,10 @@ class NotificationBroadcastReceiverHandler( if (timeline?.mode != Timeline.Mode.Live) { timeline?.close() } + + if (needsDestroy) { + room.destroy() + } } private fun handleSmartReply( From d732f043dc3fcdda1df39aa62fa445bf55ccb018 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 15:38:20 +0200 Subject: [PATCH 122/383] Update dependency org.matrix.rustcomponents:sdk-android to v26.07.15 (#7216) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update dependency org.matrix.rustcomponents:sdk-android to v26.07.15 * Fix API breaks: add `status` and `call` parameters to `aRustRoomMember` helper --------- 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/RoomMember.kt | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9debb63d59..2c725427d2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -185,7 +185,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.07.13" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.07.15" # 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/RoomMember.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomMember.kt index 6b4f958d84..e4ea392197 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 @@ -12,6 +12,8 @@ import io.element.android.libraries.matrix.api.core.UserId import org.matrix.rustcomponents.sdk.MembershipState import org.matrix.rustcomponents.sdk.PowerLevel import org.matrix.rustcomponents.sdk.RoomMember +import org.matrix.rustcomponents.sdk.UserCall +import org.matrix.rustcomponents.sdk.UserStatus import uniffi.matrix_sdk.RoomMemberRole internal fun aRustRoomMember( @@ -25,6 +27,8 @@ internal fun aRustRoomMember( role: RoomMemberRole = RoomMemberRole.USER, membershipChangeReason: String? = null, isServiceMember: Boolean = false, + status: UserStatus? = null, + call: UserCall? = null, ) = RoomMember( userId = userId.value, displayName = displayName, @@ -36,4 +40,6 @@ internal fun aRustRoomMember( suggestedRoleForPowerLevel = role, membershipChangeReason = membershipChangeReason, isServiceMember = isServiceMember, + status = status, + call = call, ) From 4187f9814d85d63f4096a5d6dcb95c1c2c1fa924 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 15 Jul 2026 15:44:43 +0200 Subject: [PATCH 123/383] Setting version for the release 26.07.1 --- plugins/src/main/kotlin/Versions.kt | 2 +- tools/manifest/gplay/release/aaptDump.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 237aa9ad67..a1e25e8180 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -45,7 +45,7 @@ private const val versionMonth = 7 * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 0 +private const val versionReleaseNumber = 1 object Versions { /** diff --git a/tools/manifest/gplay/release/aaptDump.txt b/tools/manifest/gplay/release/aaptDump.txt index 2bac911ec3..be6bcdaf8a 100644 --- a/tools/manifest/gplay/release/aaptDump.txt +++ b/tools/manifest/gplay/release/aaptDump.txt @@ -1,4 +1,4 @@ -package: name='io.element.android.x' versionCode='202607000' versionName='26.07.0' platformBuildVersionName='17' platformBuildVersionCode='37' compileSdkVersion='37' compileSdkVersionCodename='17' +package: name='io.element.android.x' versionCode='202607010' versionName='26.07.1' platformBuildVersionName='17' platformBuildVersionCode='37' compileSdkVersion='37' compileSdkVersionCodename='17' sdkVersion:'24' targetSdkVersion:'37' uses-permission: name='android.permission.POST_NOTIFICATIONS' From 0524b3c274ec80e82ee03aaa7d46e5fb529b9608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 15 Jul 2026 15:46:58 +0200 Subject: [PATCH 124/383] Adding fastlane file for version 26.07.1 --- fastlane/metadata/android/en-US/changelogs/202607010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/202607010.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202607010.txt b/fastlane/metadata/android/en-US/changelogs/202607010.txt new file mode 100644 index 0000000000..5ffe3749c2 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202607010.txt @@ -0,0 +1,2 @@ +Main changes in this version: bug fixes and improvements, including fixing the local network permission usage in Android 17. +Full changelog: https://github.com/element-hq/element-x-android/releases From 8de8826b1f72471b5a888ffc33056eff5cbbf243 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2026 15:53:26 +0200 Subject: [PATCH 125/383] Merge pull request #7188 from element-hq/renovate/roborazzi Update roborazzi to v1.67.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 2c725427d2..52f59e898c 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.64.0" +roborazzi = "1.67.0" # Jetbrain datetime = "0.8.0" From 058b494d82a8b75965441df647351b1cb63e87cc Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 15 Jul 2026 14:17:15 +0000 Subject: [PATCH 126/383] Update screenshots --- ...es.preferences.impl.userstatus_UserStatusView_Day_5_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_5_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_6_en.png | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png index 1f73455d54..270dbe6d1e 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5dc5c492ed3fd552e77c0be85b639d55bc7e976f15b761f927b0b80ecca601d -size 12115 +oid sha256:195338046951366fd2345fdc8471e3e2b2786723c8bfffa9fa9057929c608afb +size 12113 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index a687241151..fb72cafe03 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e7ce8a8c6b4d1692e4b127b7f17f507552666c631893025082c385b93d835a73 -size 11726 +oid sha256:4ef1b643a16b5a94c75f8bb845c36d3cbc7f7ed96a0cac32fdb9f0b09d26b4d1 +size 11747 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png index a1d1c5ec8e..ce1258d2ac 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b93c08531efbeacb55f84b17ac793a7b226e5a2db7bc5072e94bc040cd1e9bc -size 11386 +oid sha256:ce754ce205fd864e01828659aff42ab19dccf7c921c1c733ed1757f1b2122309 +size 11403 From b69f299adbf7942fc11af7bc91c74b3d59c580f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 15 Jul 2026 15:44:43 +0200 Subject: [PATCH 127/383] Setting version for the release 26.07.1 --- plugins/src/main/kotlin/Versions.kt | 2 +- tools/manifest/gplay/release/aaptDump.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 237aa9ad67..a1e25e8180 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -45,7 +45,7 @@ private const val versionMonth = 7 * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 0 +private const val versionReleaseNumber = 1 object Versions { /** diff --git a/tools/manifest/gplay/release/aaptDump.txt b/tools/manifest/gplay/release/aaptDump.txt index 2bac911ec3..be6bcdaf8a 100644 --- a/tools/manifest/gplay/release/aaptDump.txt +++ b/tools/manifest/gplay/release/aaptDump.txt @@ -1,4 +1,4 @@ -package: name='io.element.android.x' versionCode='202607000' versionName='26.07.0' platformBuildVersionName='17' platformBuildVersionCode='37' compileSdkVersion='37' compileSdkVersionCodename='17' +package: name='io.element.android.x' versionCode='202607010' versionName='26.07.1' platformBuildVersionName='17' platformBuildVersionCode='37' compileSdkVersion='37' compileSdkVersionCodename='17' sdkVersion:'24' targetSdkVersion:'37' uses-permission: name='android.permission.POST_NOTIFICATIONS' From 936ce45784399fe7566304736c5591434a2fac73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 15 Jul 2026 15:46:58 +0200 Subject: [PATCH 128/383] Adding fastlane file for version 26.07.1 --- fastlane/metadata/android/en-US/changelogs/202607010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/202607010.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202607010.txt b/fastlane/metadata/android/en-US/changelogs/202607010.txt new file mode 100644 index 0000000000..5ffe3749c2 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202607010.txt @@ -0,0 +1,2 @@ +Main changes in this version: bug fixes and improvements, including fixing the local network permission usage in Android 17. +Full changelog: https://github.com/element-hq/element-x-android/releases From e79181d1454ddf01ef73ad63bbb6cc7d3872d36c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 15 Jul 2026 16:27:00 +0200 Subject: [PATCH 129/383] Changelog for version 26.07.1 --- CHANGES.md | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index f31b91bc97..07ffafd3d6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,73 @@ +Changes in Element X v26.07.1 +============================= + + + +## What's Changed +### ✨ Features +* Scroll to unread messages by @bmarty in https://github.com/element-hq/element-x-android/pull/7024 +### 🙌 Improvements +* Collapse runs of deleted messages in the timeline by @manfrommedan in https://github.com/element-hq/element-x-android/pull/7195 +* Allow homeserver to disable encryption in Element Pro by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7198 +### 🐛 Bugfixes +* Fix jump-to-unread requiring two taps for an out-of-window read marker by @jennaharris7 in https://github.com/element-hq/element-x-android/pull/6943 +* Add content description to video preview for screen readers by @bmarty in https://github.com/element-hq/element-x-android/pull/7137 +* Fix accessibility for message composer input and read receipts button by @bmarty in https://github.com/element-hq/element-x-android/pull/7135 +* Add accessibility label to search input by @bmarty in https://github.com/element-hq/element-x-android/pull/7133 +* Fix timeline reading order distorted when TalkBack is active by @bmarty in https://github.com/element-hq/element-x-android/pull/7138 +* Add programmatic label and focus indicator to PIN entry field by @bmarty in https://github.com/element-hq/element-x-android/pull/7132 +* Fix timelines not loading after marking a room as read from notification when app was killed by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7202 +### 🗣 Translations +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/7192 +### 🧱 Build +* Bump the default Gradle daemon heap to match what CI already uses by @PolynomialDivision in https://github.com/element-hq/element-x-android/pull/7152 +* Update screenshots by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7155 +* Update GitHub templates by @bmarty in https://github.com/element-hq/element-x-android/pull/7170 +* Add check on merged manifest by @bmarty in https://github.com/element-hq/element-x-android/pull/7172 +* Fix AAPT dump missing and reordering some permissions by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7193 +* Try fixing DM creation in Maestro by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7204 +### 🚧 In development 🚧 +* Support gallery messages by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6519 +* Support gallery messages by @bmarty in https://github.com/element-hq/element-x-android/pull/7112 +* Initial content scanner integration by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7139 +* WIP : Set user status by @ganfra in https://github.com/element-hq/element-x-android/pull/7094 +### Dependency upgrades +* Update dependency io.sentry:sentry-android to v8.44.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7093 +* Update dependency org.maplibre.gl:android-sdk to v13.3.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7129 +* Update actions/setup-java action to v5.4.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7143 +* Update danger/danger-js action to v13.0.10 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7142 +* Update dependency io.sentry:sentry-android to v8.46.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7140 +* Update dependencyAnalysis to v3.16.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7144 +* Update plugin gms_google_services to v4.5.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7086 +* Update dependency androidx.compose.material3:material3 to v1.5.0-alpha21 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7007 +* Update dependency androidx.compose.material3:material3 to v1.5.0-alpha22 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7158 +* Update metro to v1.3.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7168 +* Update dependency io.sentry:sentry-android to v8.47.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7178 +* Update dependency androidx.compose:compose-bom to v2026.06.01 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7174 +* Update dependency org.jetbrains.kotlinx:kotlinx-collections-immutable to v0.5.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7180 +* Update dependency io.github.sergio-sastre.ComposablePreviewScanner:android to v0.9.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7201 +* Update dependency io.github.zxing-cpp:android to v3.1.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7206 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.07.13 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7194 +* Update dependency androidx.sqlite:sqlite-ktx to v2.7.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7177 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.07.15 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7216 +### Others +* Timeline: jump-to-unread FAB and mark-as-read shortcut by @jennaharris7 in https://github.com/element-hq/element-x-android/pull/6694 +* Iterate on visual list by @bmarty in https://github.com/element-hq/element-x-android/pull/7141 +* Fix wrong avatar shown in the thread list's top bar by @bxdxnn in https://github.com/element-hq/element-x-android/pull/7044 +* Update onboarding screen text style by @bmarty in https://github.com/element-hq/element-x-android/pull/7157 +* Add full SVG support by @bxdxnn in https://github.com/element-hq/element-x-android/pull/7020 +* Add skin tone picker to the emoji picker by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6917 +* Fix the message edit being lost when attaching media by @manfrommedan in https://github.com/element-hq/element-x-android/pull/7090 +* Cleanup AndroidManifest.xml files. by @bmarty in https://github.com/element-hq/element-x-android/pull/7171 +* Handle local network permission - Android 17 by @ganfra in https://github.com/element-hq/element-x-android/pull/7165 +* Add item count text as the placeholder for in reply to box for galleries by @bxdxnn in https://github.com/element-hq/element-x-android/pull/7176 +* Default to dark theme for EC by @toger5 in https://github.com/element-hq/element-x-android/pull/7162 + +## New Contributors +* @PolynomialDivision made their first contribution in https://github.com/element-hq/element-x-android/pull/7152 + +**Full Changelog**: https://github.com/element-hq/element-x-android/compare/v26.07.0...v26.07.1 + Changes in Element X v26.07.0 ============================= From 938eabae70ec175141dde280293b99a739d77e3c Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 15 Jul 2026 16:34:24 +0200 Subject: [PATCH 130/383] fixup: poste merge error --- .../impl/notifications/DefaultNotifiableEventResolver.kt | 5 ----- 1 file changed, 5 deletions(-) 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 d35f16bd04..0b2ae5be2c 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 @@ -327,11 +327,6 @@ class DefaultNotifiableEventResolver( Timber.tag(loggerTag.value).d("Ignoring notification for state event ${content.javaClass.simpleName}") throw NotificationResolverException.EventFilteredOut } - NotificationContent.MessageLike.Beacon, - NotificationContent.StateEvent.Beacon -> { - Timber.tag(loggerTag.value).d("Beacon - Not yet implemented") - throw NotificationResolverException.EventFilteredOut - } } } From a6b5eb4dce8639ca753b25ce07c090cfda4526e0 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 15 Jul 2026 21:22:23 +0200 Subject: [PATCH 131/383] Extract expired-share handling into a helper method --- .../DefaultActiveLiveLocationShareManager.kt | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) 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 36744664cb..33ce06454d 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 @@ -141,6 +141,18 @@ class DefaultActiveLiveLocationShareManager( } override suspend fun onLocationUpdate(location: Location) { + val active = stopExpiredShares() + Timber.d("ActiveLiveLocationShareManager received location update for ${active.size} active share(s)") + active.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 stopExpiredShares(): List { val nowMillis = clock.epochMillis() val (expired, active) = localSharingRoomIds.value.partition { roomId -> val timeout = timeouts[roomId] ?: return@partition false @@ -150,15 +162,7 @@ class DefaultActiveLiveLocationShareManager( Timber.d("ActiveLiveLocationShareManager location tick detected expired share for room $roomId, stopping") stopShare(roomId) } - val activeSharesCount = active.size - Timber.d("ActiveLiveLocationShareManager received location update for $activeSharesCount active share(s)") - active.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") - } - } + return active } private suspend fun sendLiveLocation(roomId: RoomId, location: Location): Result { From a6aa29f37517084a69597d7d6dddbb5dd52ab792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Wischer?= Date: Wed, 15 Jul 2026 22:05:04 +0200 Subject: [PATCH 132/383] Expose formatting toggle state to accessibility services FormattingOption used clearAndSetSemantics with only a contentDescription, so the Bold/Italic/Underline toggle buttons never exposed whether they were currently active to TalkBack. Add a stateDescription reflecting the selected/unselected state alongside the existing contentDescription. New a11y_active / a11y_inactive strings added to temporary.xml for Localazy import. --- .../textcomposer/components/FormattingOption.kt | 12 ++++++++++++ .../ui-strings/src/main/res/values/temporary.xml | 2 ++ 2 files changed, 14 insertions(+) diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOption.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOption.kt index db133a9a09..6afec35dfe 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOption.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/FormattingOption.kt @@ -23,14 +23,17 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector +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.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.Icon +import io.element.android.libraries.ui.strings.CommonStrings @Composable internal fun FormattingOption( @@ -52,6 +55,8 @@ internal fun FormattingOption( FormattingOptionState.Default -> ElementTheme.colors.iconSecondary FormattingOptionState.Disabled -> ElementTheme.colors.iconDisabled } + val activeStateDescription = stringResource(CommonStrings.a11y_active) + val inactiveStateDescription = stringResource(CommonStrings.a11y_inactive) Box( modifier = modifier .clickable( @@ -77,6 +82,13 @@ internal fun FormattingOption( ) .clearAndSetSemantics { this.contentDescription = contentDescription + if (toggleable) { + this.stateDescription = if (state == FormattingOptionState.Selected) { + activeStateDescription + } else { + inactiveStateDescription + } + } } ) { Box( diff --git a/libraries/ui-strings/src/main/res/values/temporary.xml b/libraries/ui-strings/src/main/res/values/temporary.xml index a192e2c9df..c0573cc6c2 100644 --- a/libraries/ui-strings/src/main/res/values/temporary.xml +++ b/libraries/ui-strings/src/main/res/values/temporary.xml @@ -10,4 +10,6 @@ "Jump to first unread message" Allow access to local network Your homeserver is on your local network. To connect, Element needs permission to reach other devices on this network. + Active + Inactive From 9c6e7b4464c265b5c5105357d260ebef009df537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Wischer?= Date: Wed, 15 Jul 2026 22:07:33 +0200 Subject: [PATCH 133/383] Add Button role to clickable icons and text on login/onboarding screens Several clickable elements on the login and onboarding flows (the account provider list items, the search clear icon, the login clear icon, and the hidden dev-mode version tap) use plain Modifier.clickable without a semantics role. Screen readers announce these as generic elements instead of buttons, so users relying on TalkBack cannot tell they are interactive. Add role = Role.Button to each clickable modifier, and reuse the existing clear-icon content description as onClickLabel where one is available. --- .../accountprovider/AccountProviderOtherView.kt | 3 ++- .../impl/accountprovider/AccountProviderView.kt | 3 ++- .../screens/loginpassword/LoginPasswordView.kt | 14 ++++++++++---- .../impl/screens/onboarding/OnBoardingView.kt | 3 ++- .../SearchAccountProviderView.kt | 14 ++++++++++---- 5 files changed, 26 insertions(+), 11 deletions(-) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderOtherView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderOtherView.kt index fd5c7b8019..8b9b22022e 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderOtherView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderOtherView.kt @@ -18,6 +18,7 @@ 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.Role import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons @@ -40,7 +41,7 @@ fun AccountProviderOtherView( Column( modifier = modifier .fillMaxWidth() - .clickable { onClick() } + .clickable(role = Role.Button) { onClick() } ) { HorizontalDivider() Row( diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderView.kt index 5130bf1ad8..fcf4dac3b1 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderView.kt @@ -19,6 +19,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.semantics.Role import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -45,7 +46,7 @@ fun AccountProviderView( Column( modifier = modifier .fillMaxWidth() - .clickable { onClick() } + .clickable(role = Role.Button) { onClick() } ) { HorizontalDivider() Column( 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 feb1d3d53a..06a1641644 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 @@ -36,6 +36,7 @@ import androidx.compose.ui.focus.FocusDirection import androidx.compose.ui.platform.LocalAutofillManager import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.contentType import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.input.ImeAction @@ -211,10 +212,15 @@ private fun LoginForm( singleLine = true, trailingIcon = if (loginFieldState.isNotEmpty()) { { - Box(Modifier.clickable { - loginFieldState = "" - eventSink(LoginPasswordEvents.SetLogin("")) - }) { + Box( + Modifier.clickable( + onClickLabel = stringResource(CommonStrings.action_clear), + role = Role.Button, + ) { + loginFieldState = "" + eventSink(LoginPasswordEvents.SetLogin("")) + } + ) { Icon( imageVector = CompoundIcons.Close(), contentDescription = stringResource(CommonStrings.action_clear), 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 be86bbee9c..bf96b2dbe0 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 @@ -27,6 +27,7 @@ import androidx.compose.ui.BiasAlignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -336,7 +337,7 @@ private fun OnBoardingButtons( } else { Text( modifier = Modifier - .clickable { + .clickable(role = Role.Button) { state.eventSink(OnBoardingEvents.OnVersionClick) } .padding(16.dp), diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderView.kt index 55c2c28f5b..8335dde112 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/searchaccountprovider/SearchAccountProviderView.kt @@ -34,6 +34,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusDirection import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.PreviewParameter @@ -125,10 +126,15 @@ fun SearchAccountProviderView( singleLine = true, trailingIcon = if (userInputState.isNotEmpty()) { { - Box(Modifier.clickable { - userInputState = "" - eventSink(SearchAccountProviderEvents.UserInput("")) - }) { + Box( + Modifier.clickable( + onClickLabel = stringResource(CommonStrings.action_clear), + role = Role.Button, + ) { + userInputState = "" + eventSink(SearchAccountProviderEvents.UserInput("")) + } + ) { Icon( imageVector = CompoundIcons.Close(), contentDescription = stringResource(CommonStrings.action_clear) From ea61942cccf0e9b049b8bc4069fc13ab9076516d Mon Sep 17 00:00:00 2001 From: mxandreas Date: Thu, 16 Jul 2026 07:58:22 +0100 Subject: [PATCH 134/383] Do not enforce MDM-configured homeserver to login via QR-code. --- .../login/impl/screens/qrcode/scan/QrCodeScanPresenter.kt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenter.kt index 2f93d5b214..699ea68852 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenter.kt @@ -97,13 +97,6 @@ class QrCodeScanPresenter( val data = qrCodeLoginDataFactory.parseQrCodeData(code).onFailure { Timber.e(it, "Error parsing QR code data") }.getOrThrow() - val serverName = data.serverName() - if (serverName != null) { - defaultAccountProviderAccessControl.assertIsAllowedToConnectToAccountProvider( - title = serverName, - accountProviderUrl = serverName, - ) - } data }.runCatchingUpdatingState(codeScannedAction) }.invokeOnCompletion { From 67cb11f6d0650a45e94437be9a521088b7e99dd8 Mon Sep 17 00:00:00 2001 From: mxandreas Date: Thu, 16 Jul 2026 08:25:47 +0100 Subject: [PATCH 135/383] Fix tests and remove unused code. --- .../qrcode/scan/QrCodeScanPresenter.kt | 1 - .../qrcode/scan/QrCodeScanPresenterTest.kt | 38 ------------------- 2 files changed, 39 deletions(-) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenter.kt index 699ea68852..904d591738 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenter.kt @@ -39,7 +39,6 @@ class QrCodeScanPresenter( private val qrCodeLoginDataFactory: MatrixQrCodeLoginDataFactory, private val qrCodeLoginManager: QrCodeLoginManager, private val coroutineDispatchers: CoroutineDispatchers, - private val defaultAccountProviderAccessControl: DefaultAccountProviderAccessControl, ) : Presenter { private var isScanning by mutableStateOf(true) diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenterTest.kt index 65a0713f64..07baa22484 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenterTest.kt @@ -66,44 +66,6 @@ class QrCodeScanPresenterTest { } } - @Test - fun `present - scanned QR code successfully, but homeserver not allowed`() = runTest { - val qrCodeLoginDataFactory = FakeMatrixQrCodeLoginDataFactory( - parseQrCodeLoginDataResult = { - Result.success( - FakeMatrixQrCodeLoginData( - serverNameResult = { "example.com" } - ) - ) - } - ) - val presenter = createQrCodeScanPresenter( - qrCodeLoginDataFactory = qrCodeLoginDataFactory, - enterpriseService = FakeEnterpriseService( - isAllowedToConnectToHomeserverResult = { false }, - defaultHomeserverListResult = { listOf("element.io") }, - ) - ) - presenter.test { - val initialState = awaitItem() - initialState.eventSink(QrCodeScanEvents.QrCodeScanned(byteArrayOf())) - assertThat(awaitItem().isScanning).isFalse() - assertThat(awaitItem().authenticationAction.isLoading()).isTrue() - awaitItem().also { state -> - assertThat( - (state.authenticationAction - .errorOrNull() as AccountProviderAccessException.UnauthorizedAccountProviderException).unauthorisedAccountProviderTitle - ) - .isEqualTo("example.com") - assertThat( - (state.authenticationAction - .errorOrNull() as AccountProviderAccessException.UnauthorizedAccountProviderException).authorisedAccountProviderTitles - ) - .containsExactly("element.io") - } - } - } - @Test fun `present - scanned QR code failed and can be retried`() = runTest { val qrCodeLoginDataFactory = FakeMatrixQrCodeLoginDataFactory( From 5ab3ed1f0979c277507b7b370845aed21a13f961 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 16 Jul 2026 09:30:51 +0200 Subject: [PATCH 136/383] fix test compilation --- .../android/features/messages/impl/timeline/TimelineViewTest.kt | 2 ++ 1 file changed, 2 insertions(+) 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 dc63817e99..5e95401b80 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 @@ -218,6 +218,7 @@ private fun AndroidComposeUiTest.setTimelineView( onReadReceiptClick: (TimelineItem.Event) -> Unit = EnsureNeverCalledWithParam(), onGalleryItemClick: (TimelineItem.Event, Int) -> Unit = EnsureNeverCalledWithTwoParams(), forceJumpToBottomVisibility: Boolean = false, + onJoinCallClick: (isAudioCall: Boolean) -> Unit = EnsureNeverCalledWithParam(), ) { setSafeContent(clearAndroidUiDispatcher = true) { TimelineView( @@ -234,6 +235,7 @@ private fun AndroidComposeUiTest.setTimelineView( onReadReceiptClick = onReadReceiptClick, onGalleryItemClick = onGalleryItemClick, forceJumpToBottomVisibility = forceJumpToBottomVisibility, + onJoinCallClick = onJoinCallClick, ) } } From 16bfca1e16533e0ca897eef70ddf03e12d457250 Mon Sep 17 00:00:00 2001 From: mxandreas Date: Thu, 16 Jul 2026 08:34:07 +0100 Subject: [PATCH 137/383] Remove unused code. --- .../login/impl/screens/qrcode/scan/QrCodeScanPresenter.kt | 1 - .../login/impl/screens/qrcode/scan/QrCodeScanPresenterTest.kt | 1 - 2 files changed, 2 deletions(-) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenter.kt index 904d591738..5e298604a4 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenter.kt @@ -17,7 +17,6 @@ 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.login.impl.accesscontrol.DefaultAccountProviderAccessControl import io.element.android.features.login.impl.qrcode.QrCodeLoginManager import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenterTest.kt index 07baa22484..b0b83f8c24 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenterTest.kt @@ -12,7 +12,6 @@ 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.login.impl.accesscontrol.DefaultAccountProviderAccessControl -import io.element.android.features.login.impl.changeserver.AccountProviderAccessException import io.element.android.features.login.impl.qrcode.FakeQrCodeLoginManager import io.element.android.features.wellknown.test.FakeWellknownRetriever import io.element.android.libraries.core.coroutine.CoroutineDispatchers From 0d03472c60af111e085342a2d5fb5153a31ed086 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 16 Jul 2026 09:59:51 +0200 Subject: [PATCH 138/383] Content scanner (Element Pro): scan timeline events for unsafe content (#7159) * Simplify how event content with captions are displayed The caption component will now be added in `TimelineItemEventContentView` instead of separately in each `TimelineItem__View` component * Make sure `CoilMediaFetcher` methods to fetch media throw errors We need to catch them later to check if the content scanner marked some thumbnails or medias as invalid/unsafe in `AsyncImage` instances * Add a `ContentScannerService` that allows us to manually scan a list of medias in an event and then update and store the results The results take the form of `ContentValidationValue`, stored in a `ContentValidationState` instance tied to the event * Create `EventContentValidationCache` to keep the `ContentValidationStates` for events in a room * Expose `EventContentValidationCache` to Compose using `LocalEventContentValidationState` Also add a couple of helper functions to avoid having to manually remember the states * Use the new components to display invalid content in the timeline items * Add `blurhash` to most media items so we can use it while validating the thumbnails/medias * Fix custom layout issues with screenshot and UI tests * Also check the validation state for replied-to events in the composer * Fix and add tests * Handle unrecoverable content validation errors too: display a 'not found' UI * Improve the performance of `EqualWidthColumn` for the single item case * Update screenshots --------- Co-authored-by: ElementBot --- .../api/ContentScannerService.kt | 23 ++ features/contentscanner/impl/build.gradle.kts | 1 + .../impl/DefaultContentScannerService.kt | 56 +++ .../DefaultEventContentValidationCache.kt | 39 ++ .../di/AlwaysValidContentScannerService.kt | 29 ++ .../impl/di/ContentScannerModule.kt | 42 ++ .../impl/DefaultContentScannerServiceTest.kt | 217 +++++++++++ .../DefaultEventContentValidationCacheTest.kt | 44 +++ .../impl/di/ContentScannerModuleTest.kt | 54 +++ features/messages/impl/build.gradle.kts | 1 + .../messages/impl/MessagesFlowNode.kt | 6 + .../features/messages/impl/MessagesNode.kt | 4 + .../features/messages/impl/MessagesView.kt | 7 + .../MessageComposerPresenter.kt | 12 + .../pinned/list/PinnedMessagesListView.kt | 5 +- .../messages/impl/timeline/TimelineEvent.kt | 8 + .../impl/timeline/TimelinePresenter.kt | 11 +- .../timeline/components/ContentPadding.kt | 3 +- .../timeline/components/MessageEventBubble.kt | 13 +- .../TimelineItemContentScannerPreviews.kt | 320 ++++++++++++++++ .../components/TimelineItemEventRow.kt | 113 ++++-- .../TimelineItemGroupedEventsRow.kt | 9 +- .../timeline/components/TimelineItemRow.kt | 6 +- .../components/TimelineItemStateEventRow.kt | 8 +- .../event/TimelineItemAttachmentView.kt | 64 ++-- .../TimelineItemAttachmentsContentProvider.kt | 1 - .../event/TimelineItemAttachmentsListView.kt | 169 ++++++--- .../components/event/TimelineItemAudioView.kt | 4 +- .../event/TimelineItemEventContentView.kt | 359 ++++++++++++------ .../components/event/TimelineItemFileView.kt | 4 +- .../TimelineItemGalleryContentProvider.kt | 3 +- .../event/TimelineItemGalleryView.kt | 96 +++-- .../components/event/TimelineItemImageView.kt | 177 +++------ .../event/TimelineItemStickerView.kt | 33 +- .../components/event/TimelineItemTextView.kt | 4 + .../components/event/TimelineItemVideoView.kt | 131 ++----- .../components/event/TimelineItemVoiceView.kt | 18 +- .../layout/ContentAvoidingLayout.kt | 12 + .../event/TimelineItemAudioContentProvider.kt | 2 - .../model/event/TimelineItemEventContent.kt | 19 + .../event/TimelineItemEventContentProvider.kt | 3 +- .../event/TimelineItemFileContentProvider.kt | 2 - .../event/TimelineItemVideoContentProvider.kt | 10 +- .../protection/TimelineProtectionEvent.kt | 7 + .../protection/TimelineProtectionPresenter.kt | 17 +- .../timeline/util/AsyncImageStateHandler.kt | 41 ++ ...essageComposerPresenterSlashCommandTest.kt | 3 + .../MessageComposerPresenterTest.kt | 3 + .../impl/timeline/TimelinePresenterTest.kt | 5 + .../impl/timeline/TimelineViewTest.kt | 12 +- .../TimelineProtectionPresenterTest.kt | 47 +++ .../util/AsyncImageStateHandlerTest.kt | 104 +++++ .../components/EqualWidthColumn.kt | 39 +- .../api/timeline/item/event/EventContent.kt | 31 ++ .../api/timeline/item/event/MessageType.kt | 8 + .../matrix/ui/media/CoilMediaFetcher.kt | 6 +- .../contentvalidation/ContentErrorView.kt | 93 +++++ .../ContentValidationState.kt | 197 ++++++++++ .../EventContentValidationCache.kt | 20 + .../InMemoryEventContentValidationCache.kt | 29 ++ .../contentvalidation/InvalidContentView.kt | 46 +++ .../LocalEventContentValidationState.kt | 72 ++++ .../contentvalidation/NotFoundContentView.kt | 46 +++ .../ui/messages/reply/InReplyToDetails.kt | 6 + .../matrix/ui/messages/reply/InReplyToView.kt | 53 ++- .../mediaviewer/api/GalleryItemData.kt | 1 + .../mediaviewer/api/MediaViewerEntryPoint.kt | 2 + .../impl/DefaultMediaViewerEntryPoint.kt | 2 + .../impl/datasource/EventItemFactory.kt | 5 + .../impl/gallery/root/MediaGalleryFlowNode.kt | 4 + .../impl/gallery/ui/VideoItemView.kt | 2 + .../mediaviewer/impl/model/MediaItem.kt | 10 + .../impl/model/MediaItemFactories.kt | 2 + .../viewer/GalleryMediaGalleryDataSource.kt | 2 + .../viewer/SingleMediaGalleryDataSource.kt | 3 + .../impl/DefaultMediaViewerEntryPointTest.kt | 1 + .../impl/datasource/EventItemFactoryTest.kt | 5 + .../TimelineMediaGalleryDataSourceTest.kt | 1 + .../GalleryMediaGalleryDataSourceTest.kt | 10 + .../impl/viewer/MediaViewerPresenterTest.kt | 2 + .../SingleMediaGalleryDataSourceTest.kt | 3 + .../textcomposer/ComposerModeView.kt | 33 +- .../tests/konsist/KonsistArchitectureTest.kt | 1 + .../tests/konsist/KonsistPreviewTest.kt | 13 +- .../src/test/kotlin/base/ScreenshotTest.kt | 3 + ...omreaction_EmojiItemWithPopup_Day_0_en.png | 4 +- ...reaction_EmojiItemWithPopup_Night_0_en.png | 4 +- ...s.event_ATimelineItemEventRow_Day_0_en.png | 4 +- ...event_ATimelineItemEventRow_Night_0_en.png | 4 +- ...t_TimelineImageWithCaptionRow_Day_0_en.png | 3 - ...TimelineImageWithCaptionRow_Night_0_en.png | 3 - ...melineItemAttachmentsListView_Day_1_en.png | 4 +- ...lineItemAttachmentsListView_Night_1_en.png | 4 +- ...s.event_TimelineItemAudioView_Day_3_en.png | 3 - ...s.event_TimelineItemAudioView_Day_4_en.png | 3 - ...event_TimelineItemAudioView_Night_3_en.png | 3 - ...event_TimelineItemAudioView_Night_4_en.png | 3 - ...ts.event_TimelineItemFileView_Day_3_en.png | 3 - ...ts.event_TimelineItemFileView_Day_4_en.png | 3 - ....event_TimelineItemFileView_Night_3_en.png | 3 - ....event_TimelineItemFileView_Night_4_en.png | 3 - ...event_TimelineItemGalleryView_Day_0_en.png | 4 +- ...event_TimelineItemGalleryView_Day_6_en.png | 4 +- ...event_TimelineItemGalleryView_Day_7_en.png | 4 +- ...event_TimelineItemGalleryView_Day_9_en.png | 4 +- ...ent_TimelineItemGalleryView_Night_0_en.png | 4 +- ...ent_TimelineItemGalleryView_Night_6_en.png | 4 +- ...ent_TimelineItemGalleryView_Night_7_en.png | 4 +- ...ent_TimelineItemGalleryView_Night_9_en.png | 4 +- ...s.event_TimelineItemVideoView_Day_4_en.png | 3 + ...event_TimelineItemVideoView_Night_4_en.png | 3 + ...t_TimelineVideoWithCaptionRow_Day_0_en.png | 3 - ...TimelineVideoWithCaptionRow_Night_0_en.png | 3 - ...entsViewScanningContentFailed_Day_0_en.png | 3 + ...tsViewScanningContentFailed_Night_0_en.png | 3 + ...eItemAudioViewScanningContent_Day_0_en.png | 3 + ...temAudioViewScanningContent_Night_0_en.png | 3 + ...lineItemEventRowDisambiguated_Day_0_en.png | 4 +- ...neItemEventRowDisambiguated_Night_0_en.png | 4 +- ...melineItemEventRowWithGallery_Day_5_en.png | 4 +- ...melineItemEventRowWithGallery_Day_6_en.png | 4 +- ...melineItemEventRowWithGallery_Day_7_en.png | 4 +- ...melineItemEventRowWithGallery_Day_8_en.png | 4 +- ...lineItemEventRowWithGallery_Night_5_en.png | 4 +- ...lineItemEventRowWithGallery_Night_6_en.png | 4 +- ...lineItemEventRowWithGallery_Night_7_en.png | 4 +- ...lineItemEventRowWithGallery_Night_8_en.png | 4 +- ...mEventRowWithReplyInformative_Day_0_en.png | 4 +- ...mEventRowWithReplyInformative_Day_1_en.png | 4 +- ...ventRowWithReplyInformative_Night_0_en.png | 4 +- ...ventRowWithReplyInformative_Night_1_en.png | 4 +- ...ineItemEventRowWithReplyOther_Day_0_en.png | 4 +- ...ineItemEventRowWithReplyOther_Day_1_en.png | 4 +- ...eItemEventRowWithReplyOther_Night_0_en.png | 4 +- ...eItemEventRowWithReplyOther_Night_1_en.png | 4 +- ...TimelineItemEventRowWithReply_Day_0_en.png | 4 +- ...imelineItemEventRowWithReply_Day_10_en.png | 4 +- ...imelineItemEventRowWithReply_Day_11_en.png | 4 +- ...TimelineItemEventRowWithReply_Day_1_en.png | 4 +- ...TimelineItemEventRowWithReply_Day_2_en.png | 4 +- ...TimelineItemEventRowWithReply_Day_3_en.png | 4 +- ...TimelineItemEventRowWithReply_Day_4_en.png | 4 +- ...TimelineItemEventRowWithReply_Day_5_en.png | 4 +- ...TimelineItemEventRowWithReply_Day_6_en.png | 4 +- ...TimelineItemEventRowWithReply_Day_7_en.png | 4 +- ...TimelineItemEventRowWithReply_Day_8_en.png | 4 +- ...TimelineItemEventRowWithReply_Day_9_en.png | 4 +- ...melineItemEventRowWithReply_Night_0_en.png | 4 +- ...elineItemEventRowWithReply_Night_10_en.png | 4 +- ...elineItemEventRowWithReply_Night_11_en.png | 4 +- ...melineItemEventRowWithReply_Night_1_en.png | 4 +- ...melineItemEventRowWithReply_Night_2_en.png | 4 +- ...melineItemEventRowWithReply_Night_3_en.png | 4 +- ...melineItemEventRowWithReply_Night_4_en.png | 4 +- ...melineItemEventRowWithReply_Night_5_en.png | 4 +- ...melineItemEventRowWithReply_Night_6_en.png | 4 +- ...melineItemEventRowWithReply_Night_7_en.png | 4 +- ...melineItemEventRowWithReply_Night_8_en.png | 4 +- ...melineItemEventRowWithReply_Night_9_en.png | 4 +- ...neItemFileViewScanningContent_Day_0_en.png | 3 + ...ItemFileViewScanningContent_Night_0_en.png | 3 + ...leryViewScanningContentFailed_Day_0_en.png | 3 + ...ryViewScanningContentFailed_Night_0_en.png | 3 + ...eItemImageViewScanningContent_Day_0_en.png | 3 + ...temImageViewScanningContent_Night_0_en.png | 3 + ...lineItemScanningContentFailed_Day_0_en.png | 3 + ...neItemScanningContentFailed_Night_0_en.png | 3 + ...ningContentWithInvalidReplies_Day_0_en.png | 3 + ...ngContentWithInvalidReplies_Night_0_en.png | 3 + ...nningContentWithRepliesFailed_Day_0_en.png | 3 + ...ingContentWithRepliesFailed_Night_0_en.png | 3 + ...temStickerViewScanningContent_Day_0_en.png | 3 + ...mStickerViewScanningContent_Night_0_en.png | 3 + ...eItemVideoViewScanningContent_Day_0_en.png | 3 + ...temVideoViewScanningContent_Night_0_en.png | 3 + ...eItemVoiceViewScanningContent_Day_0_en.png | 3 + ...temVoiceViewScanningContent_Night_0_en.png | 3 + ...validation_InvalidContentView_Day_0_en.png | 3 + ...lidation_InvalidContentView_Night_0_en.png | 3 + ...alidation_NotFoundContentView_Day_0_en.png | 3 + ...idation_NotFoundContentView_Night_0_en.png | 3 + ...s.reply_ReplyToInvalidContent_Day_0_en.png | 3 + ...reply_ReplyToInvalidContent_Night_0_en.png | 3 + ....reply_ReplyToNotFoundContent_Day_0_en.png | 3 + ...eply_ReplyToNotFoundContent_Night_0_en.png | 3 + ...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 +- ...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 | 4 +- tools/detekt/detekt.yml | 1 + 241 files changed, 2881 insertions(+), 828 deletions(-) create mode 100644 features/contentscanner/api/src/main/kotlin/io/element/android/features/contentscanner/api/ContentScannerService.kt create mode 100644 features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.kt create mode 100644 features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultEventContentValidationCache.kt create mode 100644 features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/di/AlwaysValidContentScannerService.kt create mode 100644 features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/di/ContentScannerModule.kt create mode 100644 features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerServiceTest.kt create mode 100644 features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultEventContentValidationCacheTest.kt create mode 100644 features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/di/ContentScannerModuleTest.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemContentScannerPreviews.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/util/AsyncImageStateHandler.kt create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/util/AsyncImageStateHandlerTest.kt create mode 100644 libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentErrorView.kt create mode 100644 libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentValidationState.kt create mode 100644 libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/EventContentValidationCache.kt create mode 100644 libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/InMemoryEventContentValidationCache.kt create mode 100644 libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/InvalidContentView.kt create mode 100644 libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/LocalEventContentValidationState.kt create mode 100644 libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/NotFoundContentView.kt delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_3_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_4_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_3_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_4_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_3_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_4_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_3_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_4_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAudioViewScanningContent_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAudioViewScanningContent_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemFileViewScanningContent_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemFileViewScanningContent_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemGalleryViewScanningContentFailed_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemGalleryViewScanningContentFailed_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemImageViewScanningContent_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemImageViewScanningContent_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentFailed_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentFailed_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemStickerViewScanningContent_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemStickerViewScanningContent_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVideoViewScanningContent_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVideoViewScanningContent_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVoiceViewScanningContent_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVoiceViewScanningContent_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_InvalidContentView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_InvalidContentView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Night_0_en.png diff --git a/features/contentscanner/api/src/main/kotlin/io/element/android/features/contentscanner/api/ContentScannerService.kt b/features/contentscanner/api/src/main/kotlin/io/element/android/features/contentscanner/api/ContentScannerService.kt new file mode 100644 index 0000000000..cc5fca38a0 --- /dev/null +++ b/features/contentscanner/api/src/main/kotlin/io/element/android/features/contentscanner/api/ContentScannerService.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.contentscanner.api + +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.scanner.ContentScanner +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState + +/** + * Service to perform security scans in the contents for a given event and media source. + * + * The default implementation (FOSS) always returns a valid state. + * This will only process media when a [ContentScanner] is provided when building the client in Pro. + */ +fun interface ContentScannerService { + fun scan(eventId: EventId, mediaSources: List, contentValidationState: ContentValidationState) +} diff --git a/features/contentscanner/impl/build.gradle.kts b/features/contentscanner/impl/build.gradle.kts index 53e8843b1d..34558a182e 100644 --- a/features/contentscanner/impl/build.gradle.kts +++ b/features/contentscanner/impl/build.gradle.kts @@ -32,4 +32,5 @@ dependencies { testImplementation(libs.test.truth) testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) + testImplementation(projects.tests.testutils) } diff --git a/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.kt b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.kt new file mode 100644 index 0000000000..5cc8b9e315 --- /dev/null +++ b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.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.features.contentscanner.impl + +import io.element.android.features.contentscanner.api.ContentScannerService +import io.element.android.libraries.core.coroutine.CoroutineDispatchers +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.scanner.ContentScanner +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import java.io.IOException + +/** + * Default implementation of [ContentScannerService] that uses a [ContentScanner] to scan media sources. + */ +class DefaultContentScannerService( + private val contentScanner: ContentScanner, + private val coroutineScope: CoroutineScope, + coroutineDispatchers: CoroutineDispatchers, +) : ContentScannerService { + private val context = coroutineDispatchers.io.limitedParallelism(4) + + override fun scan(eventId: EventId, mediaSources: List, contentValidationState: ContentValidationState) { + for (mediaSource in mediaSources) { + val url = mediaSource.safeUrl + val currentState = contentValidationState.getCurrentMediaState(url) + if (currentState != ContentValidationValue.Unknown) continue + contentValidationState.update(url, ContentValidationValue.Loading) + + coroutineScope.launch(context) { + contentScanner.scan(mediaSource) + .onSuccess { isValid -> + val contentValidationValue = if (isValid) ContentValidationValue.Valid else ContentValidationValue.Invalid + contentValidationState.update(url, contentValidationValue) + } + .onFailure { exception -> + if (exception is IOException) { + // If it's an IO-related exception, we can retry later, so we don't store the error + contentValidationState.update(url, ContentValidationValue.Unknown) + } else { + // For other exceptions, we cache the failure + contentValidationState.update(url, ContentValidationValue.UnrecoverableError(exception)) + } + } + } + } + } +} diff --git a/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultEventContentValidationCache.kt b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultEventContentValidationCache.kt new file mode 100644 index 0000000000..af4618dd28 --- /dev/null +++ b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultEventContentValidationCache.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.contentscanner.impl + +import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.SingleIn +import io.element.android.libraries.di.RoomScope +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.scanner.ContentScanner +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.EventContentValidationCache +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState +import timber.log.Timber +import java.util.concurrent.ConcurrentHashMap + +@SingleIn(RoomScope::class) +@ContributesBinding(RoomScope::class) +class DefaultEventContentValidationCache( + private val contentScanner: ContentScanner?, +) : EventContentValidationCache { + private val cache = ConcurrentHashMap() + + override operator fun get(eventId: EventId): ContentValidationState { + return cache.getOrPut(eventId) { + if (contentScanner != null) { + DefaultContentValidationState() + } else { + Timber.v("Content scanner is not available, returning NoopContentValidationState for eventId: $eventId") + NoopContentValidationState() + } + } + } +} diff --git a/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/di/AlwaysValidContentScannerService.kt b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/di/AlwaysValidContentScannerService.kt new file mode 100644 index 0000000000..6170f3e153 --- /dev/null +++ b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/di/AlwaysValidContentScannerService.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.contentscanner.impl.di + +import io.element.android.features.contentscanner.api.ContentScannerService +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.media.MediaSource +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue + +/** + * Noop implementation of [ContentScannerService] that always returns success. + * + * This is used when the content scanner feature is not enabled or available. + */ +class AlwaysValidContentScannerService : ContentScannerService { + override fun scan(eventId: EventId, mediaSources: List, contentValidationState: ContentValidationState) { + // Always return success for the noop implementation + for (mediaSource in mediaSources) { + val url = mediaSource.safeUrl + contentValidationState.update(url, ContentValidationValue.Valid) + } + } +} diff --git a/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/di/ContentScannerModule.kt b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/di/ContentScannerModule.kt new file mode 100644 index 0000000000..9446a603b2 --- /dev/null +++ b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/di/ContentScannerModule.kt @@ -0,0 +1,42 @@ +/* + * 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.contentscanner.impl.di + +import dev.zacsweers.metro.BindingContainer +import dev.zacsweers.metro.ContributesTo +import dev.zacsweers.metro.Provides +import dev.zacsweers.metro.SingleIn +import io.element.android.features.contentscanner.api.ContentScannerService +import io.element.android.features.contentscanner.impl.DefaultContentScannerService +import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.di.RoomScope +import io.element.android.libraries.di.annotations.RoomCoroutineScope +import io.element.android.libraries.matrix.api.scanner.ContentScanner +import kotlinx.coroutines.CoroutineScope + +@BindingContainer +@ContributesTo(RoomScope::class) +object ContentScannerModule { + @Provides + @SingleIn(RoomScope::class) + fun providesContentScannerService( + contentScanner: ContentScanner?, + @RoomCoroutineScope coroutineScope: CoroutineScope, + coroutineDispatchers: CoroutineDispatchers, + ): ContentScannerService { + return if (contentScanner != null) { + DefaultContentScannerService( + contentScanner = contentScanner, + coroutineScope = coroutineScope, + coroutineDispatchers = coroutineDispatchers, + ) + } else { + AlwaysValidContentScannerService() + } + } +} diff --git a/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerServiceTest.kt b/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerServiceTest.kt new file mode 100644 index 0000000000..accdf0ff37 --- /dev/null +++ b/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerServiceTest.kt @@ -0,0 +1,217 @@ +/* + * 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.contentscanner.impl + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.matrix.api.media.MediaSource +import io.element.android.libraries.matrix.api.scanner.ContentScanner +import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.media.aMediaSource +import io.element.android.libraries.matrix.test.scanner.FakeContentScanner +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue +import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState +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.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Test +import java.io.FileNotFoundException + +@OptIn(ExperimentalCoroutinesApi::class) +class DefaultContentScannerServiceTest { + @Test + fun `scan with no media sources returns valid`() = runTest { + val scanLambda = lambdaRecorder> { Result.success(true) } + val scanner = FakeContentScanner(scan = scanLambda) + val contentValidationState = DefaultContentValidationState() + createDefaultContentScannerService( + contentScanner = scanner, + ).scan( + eventId = AN_EVENT_ID, + mediaSources = emptyList(), + contentValidationState = contentValidationState, + ) + + scanLambda.assertions().isNeverCalled() + assertThat(contentValidationState.getCurrentOverallState()).isEqualTo(ContentValidationValue.Valid) + } + + @Test + fun `scan with single media source`() = runTest { + val scanLambda = lambdaRecorder> { Result.success(false) } + val scanner = FakeContentScanner(scan = scanLambda) + val contentValidationState = DefaultContentValidationState() + + val mediaSource = aMediaSource("https://example.com/media.jpg") + createDefaultContentScannerService( + contentScanner = scanner, + ).scan( + eventId = AN_EVENT_ID, + mediaSources = listOf(mediaSource), + contentValidationState = contentValidationState, + ) + + runCurrent() + + scanLambda.assertions().isCalledOnce().with(value(mediaSource)) + assertThat(contentValidationState.getCurrentOverallState()).isEqualTo(ContentValidationValue.Invalid) + } + + @Test + fun `scan with several media sources`() = runTest { + val mediaSourceA = aMediaSource("https://example.com/mediaA.jpg") + val mediaSourceB = aMediaSource("https://example.com/mediaB.jpg") + + val scanLambda = lambdaRecorder> { source -> + when (source) { + mediaSourceA -> Result.success(true) + mediaSourceB -> Result.success(false) + else -> error("Unexpected media source: $source") + } + } + val scanner = FakeContentScanner(scan = scanLambda) + val contentValidationState = DefaultContentValidationState() + + createDefaultContentScannerService( + contentScanner = scanner, + ).scan( + eventId = AN_EVENT_ID, + mediaSources = listOf(mediaSourceA, mediaSourceB), + contentValidationState = contentValidationState, + ) + + runCurrent() + + scanLambda.assertions().isCalledExactly(2) + assertThat(contentValidationState.getMediaStateFlow(mediaSourceA.safeUrl).first()).isEqualTo(ContentValidationValue.Valid) + assertThat(contentValidationState.getMediaStateFlow(mediaSourceB.safeUrl).first()).isEqualTo(ContentValidationValue.Invalid) + assertThat(contentValidationState.overallStateFlow.first()).isEqualTo(ContentValidationValue.Invalid) + } + + @Test + fun `scan won't be repeated for sources which are already being scanned`() = runTest { + val scanLambda = lambdaRecorder> { Result.success(false) } + val scanner = FakeContentScanner(scan = scanLambda) + val contentValidationState = DefaultContentValidationState() + + val mediaSource = aMediaSource("https://example.com/media.jpg") + val service = createDefaultContentScannerService( + contentScanner = scanner, + ) + + // First scan attempt + service.scan( + eventId = AN_EVENT_ID, + mediaSources = listOf(mediaSource), + contentValidationState = contentValidationState, + ) + + // Immediately after, a new scan attempt is made for the same media source + service.scan( + eventId = AN_EVENT_ID, + mediaSources = listOf(mediaSource), + contentValidationState = contentValidationState, + ) + + runCurrent() + + // The scan action was done just once, and the overall state is invalid as expected + scanLambda.assertions().isCalledOnce().with(value(mediaSource)) + assertThat(contentValidationState.getCurrentOverallState()).isEqualTo(ContentValidationValue.Invalid) + } + + @Test + fun `scan won't be repeated for sources which already have a cached value`() = runTest { + val scanLambda = lambdaRecorder> { Result.success(false) } + val scanner = FakeContentScanner(scan = scanLambda) + val contentValidationState = NoopContentValidationState(ContentValidationValue.Valid) + + val mediaSource = aMediaSource("https://example.com/media.jpg") + val service = createDefaultContentScannerService( + contentScanner = scanner, + ) + + service.scan( + eventId = AN_EVENT_ID, + mediaSources = listOf(mediaSource), + contentValidationState = contentValidationState, + ) + + runCurrent() + + scanLambda.assertions().isNeverCalled() + } + + @Test + fun `if a scan fails with a recoverable error, the content validation value will be back to Unknown`() = runTest { + val scanLambda = lambdaRecorder> { Result.failure(FileNotFoundException("Some IO exception")) } + val scanner = FakeContentScanner(scan = scanLambda) + val contentValidationState = DefaultContentValidationState() + + val mediaSource = aMediaSource("https://example.com/media.jpg") + val service = createDefaultContentScannerService( + contentScanner = scanner, + ) + + service.scan( + eventId = AN_EVENT_ID, + mediaSources = listOf(mediaSource), + contentValidationState = contentValidationState, + ) + + runCurrent() + + scanLambda.assertions().isCalledOnce().with(value(mediaSource)) + assertThat(contentValidationState.getCurrentMediaState(mediaSource.safeUrl)).isEqualTo(ContentValidationValue.Unknown) + assertThat(contentValidationState.getCurrentOverallState()).isEqualTo(ContentValidationValue.Unknown) + } + + @Test + fun `if a scan fails with an unrecoverable error, the content validation value will be back to UnrecoverableError`() = runTest { + val error = OutOfMemoryError("BOOM") + val scanLambda = lambdaRecorder> { Result.failure(error) } + val scanner = FakeContentScanner(scan = scanLambda) + val contentValidationState = DefaultContentValidationState() + + val mediaSource = aMediaSource("https://example.com/media.jpg") + val service = createDefaultContentScannerService( + contentScanner = scanner, + ) + + service.scan( + eventId = AN_EVENT_ID, + mediaSources = listOf(mediaSource), + contentValidationState = contentValidationState, + ) + + runCurrent() + + scanLambda.assertions().isCalledOnce().with(value(mediaSource)) + assertThat(contentValidationState.getCurrentMediaState(mediaSource.safeUrl)).isEqualTo(ContentValidationValue.UnrecoverableError(error)) + assertThat(contentValidationState.getCurrentOverallState()).isEqualTo(ContentValidationValue.UnrecoverableError(error)) + } + + private fun TestScope.createDefaultContentScannerService( + contentScanner: ContentScanner = FakeContentScanner(), + sessionCoroutineScope: CoroutineScope = backgroundScope, + coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(), + ): DefaultContentScannerService { + return DefaultContentScannerService( + contentScanner = contentScanner, + coroutineScope = sessionCoroutineScope, + coroutineDispatchers = coroutineDispatchers + ) + } +} diff --git a/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultEventContentValidationCacheTest.kt b/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultEventContentValidationCacheTest.kt new file mode 100644 index 0000000000..5a7bfa07b9 --- /dev/null +++ b/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultEventContentValidationCacheTest.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.contentscanner.impl + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.scanner.ContentScanner +import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.scanner.FakeContentScanner +import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState +import org.junit.Test + +class DefaultEventContentValidationCacheTest { + @Test + fun `get returns NoopContentValidationState when ContentScanner is null`() { + // Given + val contentScanner: ContentScanner? = null + val cache = DefaultEventContentValidationCache(contentScanner) + + // When + val state = cache[AN_EVENT_ID] + + // Then + assertThat(state).isInstanceOf(NoopContentValidationState::class.java) + } + + @Test + fun `get returns an actual DefaultContentValidationState when ContentScanner is not null`() { + // Given + val contentScanner: ContentScanner? = FakeContentScanner() + val cache = DefaultEventContentValidationCache(contentScanner) + + // When + val state = cache[AN_EVENT_ID] + + // Then + assertThat(state).isInstanceOf(DefaultContentValidationState::class.java) + } +} diff --git a/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/di/ContentScannerModuleTest.kt b/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/di/ContentScannerModuleTest.kt new file mode 100644 index 0000000000..8c3834d696 --- /dev/null +++ b/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/di/ContentScannerModuleTest.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.contentscanner.impl.di + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.contentscanner.impl.DefaultContentScannerService +import io.element.android.libraries.matrix.api.scanner.ContentScanner +import io.element.android.libraries.matrix.test.scanner.FakeContentScanner +import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class ContentScannerModuleTest { + @Test + fun `ContentScannerModule provides NoopContentScannerService when ContentScanner is null`() = runTest { + // Given + val contentScanner: ContentScanner? = null + val sessionCoroutineScope = backgroundScope + val coroutineDispatchers = testCoroutineDispatchers() + + // When + val contentScannerService = ContentScannerModule.providesContentScannerService( + contentScanner = contentScanner, + coroutineScope = sessionCoroutineScope, + coroutineDispatchers = coroutineDispatchers, + ) + + // Then + assertThat(contentScannerService).isInstanceOf(AlwaysValidContentScannerService::class.java) + } + + @Test + fun `ContentScannerModule provides DefaultContentScannerService when ContentScanner is not null`() = runTest { + // Given + val contentScanner: ContentScanner? = FakeContentScanner() + val sessionCoroutineScope = backgroundScope + val coroutineDispatchers = testCoroutineDispatchers() + + // When + val contentScannerService = ContentScannerModule.providesContentScannerService( + contentScanner = contentScanner, + coroutineScope = sessionCoroutineScope, + coroutineDispatchers = coroutineDispatchers, + ) + + // Then + assertThat(contentScannerService).isInstanceOf(DefaultContentScannerService::class.java) + } +} diff --git a/features/messages/impl/build.gradle.kts b/features/messages/impl/build.gradle.kts index 2661f7e330..116a3a7c41 100644 --- a/features/messages/impl/build.gradle.kts +++ b/features/messages/impl/build.gradle.kts @@ -62,6 +62,7 @@ dependencies { implementation(projects.libraries.uiUtils) implementation(projects.libraries.testtags) implementation(projects.features.networkmonitor.api) + implementation(projects.features.contentscanner.api) implementation(projects.services.analytics.compose) implementation(projects.services.appnavstate.api) implementation(projects.services.toolbox.api) 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 cbab26fe54..88a90f6c7d 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 @@ -57,6 +57,7 @@ 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.TimelineItemVideoContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent +import io.element.android.features.messages.impl.timeline.model.event.blurHash import io.element.android.features.messages.impl.timeline.model.event.duration import io.element.android.features.poll.api.create.CreatePollEntryPoint import io.element.android.features.poll.api.create.CreatePollMode @@ -155,6 +156,7 @@ class MessagesFlowNode( val mediaSource: MediaSource, val thumbnailSource: MediaSource?, val canUseOverlay: Boolean, + val blurHash: String?, ) : NavTarget @Parcelize @@ -377,6 +379,7 @@ class MessagesFlowNode( mediaInfo = navTarget.mediaInfo, mediaSource = navTarget.mediaSource, thumbnailSource = navTarget.thumbnailSource, + blurHash = navTarget.blurHash, ) val callback = object : MediaViewerEntryPoint.Callback { override fun onDone() { @@ -828,6 +831,7 @@ class MessagesFlowNode( mediaSource = galleryItem.mediaSource, thumbnailSource = galleryItem.thumbnailSource, type = galleryItem.type.toMediaViewerType(), + blurHash = galleryItem.blurhash, ) }.reversed() NavTarget.GalleryViewer( @@ -861,6 +865,7 @@ class MessagesFlowNode( mediaSource = attachment.mediaSource, thumbnailSource = attachment.thumbnailSource, type = GalleryItemData.Type.File, + blurHash = null, ) }.reversed() NavTarget.GalleryViewer( @@ -920,6 +925,7 @@ class MessagesFlowNode( mediaSource = mediaSource, thumbnailSource = thumbnailSource, canUseOverlay = canUseOverlay, + blurHash = content.blurHash(), ) } 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 a7e8846047..18c02d8f40 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,8 @@ 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.media.contentvalidation.EventContentValidationCache +import io.element.android.libraries.matrix.ui.media.contentvalidation.LocalEventContentValidationState 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 @@ -97,6 +99,7 @@ class MessagesNode( private val permalinkParser: PermalinkParser, private val knockRequestsBannerRenderer: KnockRequestsBannerRenderer, private val roomMemberModerationRenderer: RoomMemberModerationRenderer, + private val eventContentValidationCache: EventContentValidationCache, ) : Node(buildContext, plugins = plugins), MessagesNavigator { data class Inputs( val focusedEventId: EventId?, @@ -261,6 +264,7 @@ class MessagesNode( val canUseOverlay = !isTalkbackActive() && !hasExternalKeyboard() CompositionLocalProvider( LocalTimelineItemPresenterFactories provides timelineItemPresenterFactories, + LocalEventContentValidationState provides eventContentValidationCache, ) { val state = presenter.present() 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 8887424dc6..ec014a4ff6 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 @@ -123,6 +123,8 @@ import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue +import io.element.android.libraries.matrix.ui.media.contentvalidation.LocalEventContentValidationState import io.element.android.libraries.textcomposer.model.TextEditorState import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.wysiwyg.link.Link @@ -148,6 +150,8 @@ fun MessagesView( forceJumpToBottomVisibility: Boolean = false, knockRequestsBannerView: @Composable () -> Unit, ) { + val eventContentValidationState = LocalEventContentValidationState.current + OnLifecycleEvent { _, event -> state.voiceMessageComposerState.eventSink(VoiceMessageComposerEvent.LifecycleEvent(event)) } @@ -170,6 +174,9 @@ fun MessagesView( fun onContentClick(event: TimelineItem.Event) { Timber.v("onMessageClick= ${event.id}") + val eventId = event.eventId ?: return + if (eventContentValidationState[eventId].getCurrentOverallState() != ContentValidationValue.Valid) return + val hideKeyboard = onEventContentClick(state.timelineState.isLive, event) if (hideKeyboard) { localView.hideKeyboard() 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 eaa00f427e..80dd21b7b3 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 @@ -31,6 +31,7 @@ import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject import im.vector.app.features.analytics.plan.Composer import im.vector.app.features.analytics.plan.Interaction +import io.element.android.features.contentscanner.api.ContentScannerService 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 @@ -61,8 +62,12 @@ 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.powerlevels.use import io.element.android.libraries.matrix.api.timeline.TimelineException +import io.element.android.libraries.matrix.api.timeline.item.event.mediaSources import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId +import io.element.android.libraries.matrix.ui.media.contentvalidation.EventContentValidationCache import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails +import io.element.android.libraries.matrix.ui.messages.reply.content +import io.element.android.libraries.matrix.ui.messages.reply.eventId import io.element.android.libraries.matrix.ui.messages.reply.map import io.element.android.libraries.mediapickers.api.PickerProvider import io.element.android.libraries.mediaupload.api.MediaOptimizationConfigProvider @@ -135,6 +140,8 @@ class MessageComposerPresenter( private val notificationConversationService: NotificationConversationService, private val slashCommandService: SlashCommandService, private val featureFlagService: FeatureFlagService, + private val contentScannerService: ContentScannerService, + private val contentValidationCache: EventContentValidationCache, ) : Presenter { @AssistedFactory interface Factory { @@ -848,6 +855,11 @@ class MessageComposerPresenter( setText(newComposerMode.content, markdownTextEditorState, richTextEditorState, requestFocus = true) } else -> { + if (currentComposerMode is MessageComposerMode.Reply) { + val mediaSources = currentComposerMode.replyToDetails.content()?.mediaSources() ?: return@launch + val contentValidationState = contentValidationCache[currentComposerMode.replyToDetails.eventId()] + contentScannerService.scan(currentComposerMode.replyToDetails.eventId(), mediaSources, contentValidationState) + } // When coming from edit, just clear the composer as it'd be weird to reset a volatile draft in this scenario. if (currentComposerMode.isEditing) { setText("", markdownTextEditorState, richTextEditorState) 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 b4fe504ab1..bdad9ba631 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 @@ -36,7 +36,6 @@ import io.element.android.features.messages.impl.timeline.components.event.Timel import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.TimelineItemPollContent -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.poll.api.pollcontent.PollTitleView import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule @@ -290,9 +289,9 @@ private fun TimelineItemEventContentViewWrapper( ) } else { TimelineItemEventContentView( + eventId = event.eventId, content = event.content, - hideMediaContent = timelineProtectionState.hideMediaContent(event.eventId, event.isMine), - onShowContentClick = { timelineProtectionState.eventSink(TimelineProtectionEvent.ShowContent(event.eventId)) }, + timelineProtectionState = timelineProtectionState, onGalleryItemClick = onGalleryItemClick, onLinkClick = onLinkClick, onLinkLongClick = onLinkLongClick, 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 5330fc00d3..cfc3672ca3 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 @@ -13,7 +13,9 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem 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.ThreadId +import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState import kotlin.time.Duration sealed interface TimelineEvent { @@ -61,4 +63,10 @@ sealed interface TimelineEvent { ) : TimelineItemPollEvent data object StopLiveLocationShare : TimelineItemEvent + + data class ValidateMedia( + val eventId: EventId, + val mediaSources: List, + val validationState: ContentValidationState + ) : 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 00039dc1af..9a33299cd0 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 @@ -35,6 +35,8 @@ 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.virtual.TimelineItemReadMarkerModel import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemTypingNotificationModel +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.typing.TypingNotificationState import io.element.android.features.messages.impl.userEventPermissions import io.element.android.features.messages.impl.voicemessages.timeline.RedactedVoiceMessageManager @@ -64,6 +66,7 @@ import io.element.android.services.analytics.api.finishLongRunningTransaction import io.element.android.services.analyticsproviders.api.AnalyticsUserData import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.combine @@ -98,6 +101,7 @@ class TimelinePresenter( private val analyticsService: AnalyticsService, private val liveLocationShareManager: ActiveLiveLocationShareManager, private val markAsFullyRead: MarkAsFullyRead, + private val timelineProtectionPresenter: Presenter, ) : Presenter { private val tag = "TimelinePresenter" @@ -157,6 +161,8 @@ class TimelinePresenter( value = featureFlagService.isFeatureEnabled(FeatureFlags.JumpToUnread) } + val timelineProtectionState = timelineProtectionPresenter.present() + fun handleEvent(event: TimelineEvent) { when (event) { is TimelineEvent.LoadMore -> { @@ -252,6 +258,9 @@ class TimelinePresenter( focusedEventId = event.focusedEvent, ) } + is TimelineEvent.ValidateMedia -> { + timelineProtectionState.eventSink(TimelineProtectionEvent.ValidateContent(event.eventId, event.mediaSources, event.validationState)) + } } } @@ -259,7 +268,7 @@ class TimelinePresenter( timelineItemsFactory.timelineItems .onEach { newTimelineItems -> timelineItemIndexer.process(newTimelineItems) - timelineItems = newTimelineItems + timelineItems = newTimelineItems.toImmutableList() analyticsService.run { finishLongRunningTransaction(DisplayFirstTimelineItems) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ContentPadding.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ContentPadding.kt index f7c3627b2a..d6f2bd3161 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ContentPadding.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ContentPadding.kt @@ -11,5 +11,6 @@ package io.element.android.features.messages.impl.timeline.components enum class ContentPadding { Textual, Media, - CaptionedMedia + CaptionedMedia, + InvalidContent, } 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 80bd342d01..1ebdc34c6c 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 @@ -19,7 +19,9 @@ import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ripple import androidx.compose.runtime.Composable +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.draw.drawWithCache @@ -27,6 +29,8 @@ import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.BlendMode import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.graphics.drawOutline +import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.layer.CompositingStrategy import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.LayoutDirection @@ -62,6 +66,8 @@ fun MessageEventBubble( onClick: () -> Unit, onLongClick: () -> Unit, modifier: Modifier = Modifier, + customBackgroundColor: Color? = null, + borderColor: Color? = null, content: @Composable BoxScope.() -> Unit = {}, ) { val clickableModifier = if (isTalkbackActive()) { @@ -79,10 +85,12 @@ fun MessageEventBubble( val cutTopStart = state.cutTopStart // Ignore state.isHighlighted for now, we need a design decision on it. - val backgroundBubbleColor = MessageEventBubbleDefaults.backgroundBubbleColor(state.isMine) + val backgroundBubbleColor by rememberUpdatedState(customBackgroundColor ?: MessageEventBubbleDefaults.backgroundBubbleColor(state.isMine)) val bubbleShape = remember(state) { MessageEventBubbleDefaults.shape(state.cutTopStart, state.groupPosition, state.isMine) } val radiusPx = (avatarRadius + SENDER_AVATAR_BORDER_WIDTH).toPx() val yOffsetPx = -(NEGATIVE_MARGIN_FOR_BUBBLE + avatarRadius).toPx() + + val updatedBorderColor by rememberUpdatedState(borderColor) BoxWithConstraints( modifier = modifier .drawWithCache { @@ -103,6 +111,9 @@ fun MessageEventBubble( // Then draw the content on top of it drawContent() + // Draw border color, if any + updatedBorderColor?.let { drawOutline(outline, it, style = Stroke(width = 1.dp.toPx())) } + // And then clip the top start corner if needed to make room for the avatar if (cutTopStart) { drawCircle( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemContentScannerPreviews.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemContentScannerPreviews.kt new file mode 100644 index 0000000000..5c5414646d --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemContentScannerPreviews.kt @@ -0,0 +1,320 @@ +/* + * 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 + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.remember +import androidx.compose.ui.unit.dp +import io.element.android.features.messages.impl.timeline.aTimelineItemEvent +import io.element.android.features.messages.impl.timeline.components.event.ElementTimelineItemPreview +import io.element.android.features.messages.impl.timeline.components.event.aGalleryItem +import io.element.android.features.messages.impl.timeline.components.event.aTimelineItemGalleryContent +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.model.event.aTimelineItemAttachmentsContent +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 +import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStickerContent +import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent +import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVideoContent +import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVoiceContent +import io.element.android.features.messages.impl.timeline.model.event.anAttachmentItem +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +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 +import io.element.android.libraries.matrix.api.timeline.item.event.ImageMessageType +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.ui.media.contentvalidation.ContentValidationValue +import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.InMemoryEventContentValidationCache +import io.element.android.libraries.matrix.ui.media.contentvalidation.LocalEventContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState +import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails + +private val AN_EVENT_ID = EventId($$"$eventId") + +@PreviewsDayNight +@Composable +internal fun TimelineItemImageViewScanningContentPreview() = ElementPreview { + val cache = remember { + InMemoryEventContentValidationCache(initial = mapOf(AN_EVENT_ID to NoopContentValidationState(ContentValidationValue.Loading))) + } + CompositionLocalProvider(LocalEventContentValidationState provides cache) { + ATimelineItemEventRow( + event = aTimelineItemEvent(eventId = AN_EVENT_ID, content = aTimelineItemImageContent()), + ) + } +} + +@PreviewsDayNight +@Composable +internal fun TimelineItemStickerViewScanningContentPreview() = ElementPreview { + val cache = remember { + InMemoryEventContentValidationCache(initial = mapOf(AN_EVENT_ID to NoopContentValidationState(ContentValidationValue.Loading))) + } + CompositionLocalProvider(LocalEventContentValidationState provides cache) { + ATimelineItemEventRow( + event = aTimelineItemEvent(eventId = AN_EVENT_ID, content = aTimelineItemStickerContent(aspectRatio = 1.5f)), + ) + } +} + +@PreviewsDayNight +@Composable +internal fun TimelineItemVideoViewScanningContentPreview() = ElementPreview { + val cache = remember { + InMemoryEventContentValidationCache(initial = mapOf(AN_EVENT_ID to NoopContentValidationState(ContentValidationValue.Loading))) + } + CompositionLocalProvider(LocalEventContentValidationState provides cache) { + ATimelineItemEventRow( + event = aTimelineItemEvent(eventId = AN_EVENT_ID, content = aTimelineItemVideoContent()), + ) + } +} + +@PreviewsDayNight +@Composable +internal fun TimelineItemFileViewScanningContentPreview() { + ElementTimelineItemPreview { + val cache = remember { + InMemoryEventContentValidationCache(initial = mapOf(AN_EVENT_ID to NoopContentValidationState(ContentValidationValue.Loading))) + } + CompositionLocalProvider( + LocalEventContentValidationState provides cache + ) { + ATimelineItemEventRow(event = aTimelineItemEvent(eventId = AN_EVENT_ID, content = aTimelineItemFileContent())) + } + } +} + +@PreviewsDayNight +@Composable +internal fun TimelineItemAudioViewScanningContentPreview() { + ElementTimelineItemPreview { + val cache = remember { + InMemoryEventContentValidationCache(initial = mapOf(AN_EVENT_ID to NoopContentValidationState(ContentValidationValue.Loading))) + } + CompositionLocalProvider( + LocalEventContentValidationState provides cache + ) { + ATimelineItemEventRow(event = aTimelineItemEvent(eventId = AN_EVENT_ID, content = aTimelineItemAudioContent())) + } + } +} + +@PreviewsDayNight +@Composable +internal fun TimelineItemVoiceViewScanningContentPreview() = ElementPreview { + val cache = remember { + InMemoryEventContentValidationCache(initial = mapOf(AN_EVENT_ID to NoopContentValidationState(ContentValidationValue.Loading))) + } + ElementTimelineItemPreview { + CompositionLocalProvider( + LocalEventContentValidationState provides cache, + LocalTimelineItemPresenterFactories provides aFakeTimelineItemPresenterFactories(), + ) { + ATimelineItemEventRow( + event = aTimelineItemEvent(eventId = AN_EVENT_ID, content = aTimelineItemVoiceContent()), + ) + } + } +} + +@PreviewsDayNight +@Composable +internal fun TimelineItemScanningContentFailedPreview() = ElementPreview { + val cache = remember { + InMemoryEventContentValidationCache(initial = mapOf(AN_EVENT_ID to NoopContentValidationState(ContentValidationValue.Invalid))) + } + CompositionLocalProvider(LocalEventContentValidationState provides cache) { + Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { + ATimelineItemEventRow(event = aTimelineItemEvent(eventId = AN_EVENT_ID, content = aTimelineItemImageContent())) + ATimelineItemEventRow(event = aTimelineItemEvent(eventId = AN_EVENT_ID, content = aTimelineItemImageContent(caption = "A caption"))) + } + } +} + +@PreviewsDayNight +@Composable +internal fun TimelineItemScanningContentWithInvalidRepliesPreview() = ElementPreview { + val cache = remember { + InMemoryEventContentValidationCache(initial = mapOf(AN_EVENT_ID to NoopContentValidationState(ContentValidationValue.Invalid))) + } + CompositionLocalProvider(LocalEventContentValidationState provides cache) { + Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { + ATimelineItemEventRow( + event = aTimelineItemEvent( + content = aTimelineItemTextContent(), + inReplyTo = inReplyToInvalidContent(), + ) + ) + ATimelineItemEventRow( + event = aTimelineItemEvent( + eventId = AN_EVENT_ID, + content = aTimelineItemImageContent(), + inReplyTo = inReplyToInvalidContent(), + ) + ) + ATimelineItemEventRow( + event = aTimelineItemEvent( + eventId = AN_EVENT_ID, + content = aTimelineItemImageContent(), + inReplyTo = inReplyToTextContent(), + ) + ) + } + } +} + +@PreviewsDayNight +@Composable +internal fun TimelineItemScanningContentWithRepliesFailedPreview() = ElementPreview { + val cache = remember { + InMemoryEventContentValidationCache( + initial = mapOf(AN_EVENT_ID to NoopContentValidationState(ContentValidationValue.UnrecoverableError(IllegalStateException("BOOM")))) + ) + } + CompositionLocalProvider(LocalEventContentValidationState provides cache) { + Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { + ATimelineItemEventRow( + event = aTimelineItemEvent( + content = aTimelineItemTextContent(), + inReplyTo = inReplyToInvalidContent(), + ) + ) + ATimelineItemEventRow( + event = aTimelineItemEvent( + eventId = AN_EVENT_ID, + content = aTimelineItemImageContent(), + inReplyTo = inReplyToInvalidContent(), + ) + ) + ATimelineItemEventRow( + event = aTimelineItemEvent( + eventId = AN_EVENT_ID, + content = aTimelineItemImageContent(), + inReplyTo = inReplyToTextContent(), + ) + ) + } + } +} + +@PreviewsDayNight +@Composable +internal fun TimelineItemGalleryViewScanningContentFailedPreview() = ElementPreview { + val cache = remember { + InMemoryEventContentValidationCache( + initial = + mapOf( + AN_EVENT_ID to DefaultContentValidationState(mapOf( + "invalid" to ContentValidationValue.Invalid, + "error" to ContentValidationValue.UnrecoverableError(IllegalStateException("BOOM")), + "" to ContentValidationValue.Valid + )) + ) + ) + } + CompositionLocalProvider(LocalEventContentValidationState provides cache) { + ATimelineItemEventRow( + event = aTimelineItemEvent( + eventId = AN_EVENT_ID, + content = aTimelineItemGalleryContent( + items = listOf( + aGalleryItem(), + aGalleryItem(mediaSource = MediaSource("invalid", "{}")), + aGalleryItem(), + aGalleryItem(mediaSource = MediaSource("invalid", "{}")), + aGalleryItem(mediaSource = MediaSource("error", "{}")), + aGalleryItem(mediaSource = MediaSource("invalid", "{}")), + aGalleryItem(), + ) + ) + ) + ) + } +} + +@PreviewsDayNight +@Composable +internal fun TimelineItemAttachmentsViewScanningContentFailedPreview() = ElementPreview { + val cache = remember { + InMemoryEventContentValidationCache( + initial = + mapOf( + AN_EVENT_ID to DefaultContentValidationState(mapOf( + "invalid" to ContentValidationValue.Invalid, + "error" to ContentValidationValue.UnrecoverableError(IllegalStateException("BOOM")), + "" to ContentValidationValue.Valid + )) + ) + ) + } + CompositionLocalProvider(LocalEventContentValidationState provides cache) { + ATimelineItemEventRow( + event = aTimelineItemEvent( + eventId = AN_EVENT_ID, + content = aTimelineItemAttachmentsContent( + attachments = listOf( + anAttachmentItem(), + anAttachmentItem(mediaSource = MediaSource("invalid", "{}")), + anAttachmentItem(), + anAttachmentItem(), + anAttachmentItem(mediaSource = MediaSource("error", "{}")), + anAttachmentItem(mediaSource = MediaSource("invalid", "{}")), + ) + ) + ) + ) + } +} + +private fun inReplyToInvalidContent(): InReplyToDetails.Ready = InReplyToDetails.Ready( + eventId = AN_EVENT_ID, + senderId = UserId("@sender:matrix.org"), + eventContent = MessageContent( + body = "A body", + inReplyTo = null, + isEdited = false, + threadInfo = null, + type = ImageMessageType( + filename = "A file", + caption = "A caption", + formattedCaption = null, + source = MediaSource("", ""), + info = null, + ) + ), + textContent = "A text content", + senderProfile = ProfileDetails.Ready(displayName = "Sender", displayNameAmbiguous = false, avatarUrl = null) +) + +private fun inReplyToTextContent(): InReplyToDetails.Ready = InReplyToDetails.Ready( + eventId = EventId($$"$text_eventId"), + senderId = UserId("@sender:matrix.org"), + eventContent = MessageContent( + body = "A body", + inReplyTo = null, + isEdited = false, + threadInfo = null, + type = TextMessageType( + body = "A body", + formatted = null, + ) + ), + textContent = "A text content", + senderProfile = ProfileDetails.Ready(displayName = "Sender", 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 c73248af53..30053294da 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 @@ -33,9 +33,12 @@ 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 +import androidx.compose.runtime.getValue import androidx.compose.runtime.movableContentOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -88,7 +91,6 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt 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 import io.element.android.libraries.architecture.AsyncData @@ -122,9 +124,13 @@ import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageTy 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.matrix.api.timeline.item.event.getDisplayName +import io.element.android.libraries.matrix.api.timeline.item.event.mediaSources import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.ui.media.contentvalidation.collectOverallState +import io.element.android.libraries.matrix.ui.media.contentvalidation.rememberEventContentValidationState import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails import io.element.android.libraries.matrix.ui.messages.reply.InReplyToView +import io.element.android.libraries.matrix.ui.messages.reply.content import io.element.android.libraries.matrix.ui.messages.reply.eventId import io.element.android.libraries.matrix.ui.messages.sender.SenderName import io.element.android.libraries.matrix.ui.messages.sender.SenderNameMode @@ -176,12 +182,12 @@ fun TimelineItemEventRow( val onContentClick = onEventClick.takeUnless { event.isWholeContentClickable } TimelineItemEventContentView( + eventId = event.eventId, content = event.content, - hideMediaContent = timelineProtectionState.hideMediaContent(event.eventId), + timelineProtectionState = timelineProtectionState, onContentClick = onContentClick, onGalleryItemClick = onGalleryItemClick, onLongClick = onLongClick, - onShowContentClick = { timelineProtectionState.eventSink(TimelineProtectionEvent.ShowContent(event.eventId)) }, onLinkClick = onLinkClick, onLinkLongClick = onLinkLongClick, eventSink = eventSink, @@ -468,6 +474,23 @@ private fun TimelineItemEventRowContent( ) } + val currentContentValidationState by rememberEventContentValidationState(eventId = event.eventId, needsValidation = event.content.isMedia) + .collectOverallState() + val needsInvalidContentCustomisations = + // Gallery events should not apply the custom bubble color, instead each item will apply some custom color if needed + event.content !is TimelineItemGalleryContent && + event.content !is TimelineItemAttachmentsContent && + currentContentValidationState.hasError() && + event.content.isMedia + + // If the event has a dangerous media content we need to set custom message bubble background and border colors + val themeColors = ElementTheme.colors + val (dangerousContentBubbleColor, borderColor) = remember(themeColors.isLight, needsInvalidContentCustomisations, event.content.type) { + val background = themeColors.bgCriticalSubtle.takeIf { needsInvalidContentCustomisations } + val border = themeColors.borderCriticalSubtle.takeIf { needsInvalidContentCustomisations } + background to border + } + // Message bubble val bubbleState = BubbleState( groupPosition = event.groupPosition, @@ -494,6 +517,8 @@ private fun TimelineItemEventRowContent( interactionSource = interactionSource, onClick = onContentClick, onLongClick = onLongClick, + customBackgroundColor = dangerousContentBubbleColor, + borderColor = borderColor, ) { MessageEventBubbleContent( event = event, @@ -747,6 +772,7 @@ private fun MessageEventBubbleContent( } ContentPadding.CaptionedMedia -> Modifier.padding(start = 8.dp, end = 8.dp, top = topPadding, bottom = 8.dp) + ContentPadding.InvalidContent -> Modifier.padding(top = topPadding, bottom = 8.dp) } val threadDecoration = @Composable { @@ -770,10 +796,13 @@ private fun MessageEventBubbleContent( } val inReplyTo = @Composable { inReplyTo: InReplyToDetails -> + val currentContentValidationState by rememberEventContentValidationState(eventId = inReplyTo.eventId(), eventContent = inReplyTo.content()) + .collectOverallState() val topPadding = if (showThreadDecoration) 0.dp else 8.dp + val shape = RoundedCornerShape(6.dp) val inReplyToModifier = Modifier .padding(top = topPadding, start = 8.dp, end = 8.dp) - .clip(RoundedCornerShape(6.dp)) + .clip(shape) val talkbackCompatModifier = if (isTalkbackActive()) { // Use z-index to make the replied to text being read after the message @@ -782,14 +811,25 @@ private fun MessageEventBubbleContent( } else { inReplyToModifier.clickable(onClick = inReplyToClick) } + + val contentHasError = currentContentValidationState.hasError() + val borderColor = if (contentHasError) ElementTheme.colors.borderCriticalSubtle else ElementTheme.colors.separatorPrimary + val backgroundColor = if (contentHasError) ElementTheme.colors.bgCriticalSubtle else ElementTheme.colors.bgCanvasDefault Box( modifier = talkbackCompatModifier - .border(1.dp, ElementTheme.colors.separatorPrimary, RoundedCornerShape(6.dp)) - .background(ElementTheme.colors.bgCanvasDefault, RoundedCornerShape(6.dp)) + .border(1.dp, borderColor, shape) + .background(backgroundColor, shape) .padding(4.dp) ) { + val contentValidationState = rememberEventContentValidationState(eventId = inReplyTo.eventId(), eventContent = inReplyTo.content()) + val updatedEventSink by rememberUpdatedState(eventSink) + LaunchedEffect(inReplyTo) { + val mediaSources = inReplyTo.content()?.mediaSources() ?: return@LaunchedEffect + updatedEventSink(TimelineEvent.ValidateMedia(inReplyTo.eventId(), mediaSources, contentValidationState)) + } InReplyToView( inReplyTo = inReplyTo, + contentValidationValue = currentContentValidationState, hideImage = timelineProtectionState.hideMediaContent(inReplyTo.eventId()), ) } @@ -809,30 +849,47 @@ private fun MessageEventBubbleContent( } } - 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 TimelineItemGalleryContent -> if (content.showCaption) TimestampPosition.Aligned else TimestampPosition.Below - is TimelineItemAttachmentsContent -> TimestampPosition.Below - is TimelineItemStickerContent -> TimestampPosition.Overlay - is TimelineItemLocationContent -> { - val content = content.ensureActiveLiveLocation() - val shouldHide = content.mode is TimelineItemLocationContent.Mode.Live && - content.mode.isActive && - content.mode.isOwnUser - if (shouldHide) TimestampPosition.Hidden else TimestampPosition.Overlay + val contentValidationState by rememberEventContentValidationState(eventId = event.eventId, needsValidation = event.content.isMedia).collectOverallState() + val needsInvalidContentLayout = + // Gallery events should not apply custom paddings or layout dispositions + event.content !is TimelineItemGalleryContent && + event.content !is TimelineItemAttachmentsContent && + contentValidationState.hasError() + + val timestampPosition = if (needsInvalidContentLayout) { + // The invalid content view will be displayed in all these cases, independent of the event content + TimestampPosition.Aligned + } else { + 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 TimelineItemGalleryContent -> if (content.showCaption) TimestampPosition.Aligned else TimestampPosition.Below + is TimelineItemAttachmentsContent -> if (content.showCaption) TimestampPosition.Aligned else TimestampPosition.Below + is TimelineItemStickerContent -> TimestampPosition.Overlay + is TimelineItemLocationContent -> { + val content = content.ensureActiveLiveLocation() + val shouldHide = content.mode is TimelineItemLocationContent.Mode.Live && + content.mode.isActive && + content.mode.isOwnUser + if (shouldHide) TimestampPosition.Hidden else TimestampPosition.Overlay + } + is TimelineItemPollContent -> TimestampPosition.Below + else -> TimestampPosition.Default } - is TimelineItemPollContent -> TimestampPosition.Below - else -> TimestampPosition.Default } - val paddingBehaviour = when (event.content) { - is TimelineItemImageContent -> if (event.content.showCaption) ContentPadding.CaptionedMedia else ContentPadding.Media - is TimelineItemVideoContent -> if (event.content.showCaption) ContentPadding.CaptionedMedia else ContentPadding.Media - is TimelineItemGalleryContent -> ContentPadding.CaptionedMedia - is TimelineItemAttachmentsContent -> ContentPadding.CaptionedMedia - is TimelineItemStickerContent, - is TimelineItemLocationContent -> ContentPadding.Media - else -> ContentPadding.Textual + + val paddingBehaviour = if (needsInvalidContentLayout) { + ContentPadding.InvalidContent + } else { + when (event.content) { + is TimelineItemImageContent -> if (event.content.showCaption) ContentPadding.CaptionedMedia else ContentPadding.Media + is TimelineItemVideoContent -> if (event.content.showCaption) ContentPadding.CaptionedMedia else ContentPadding.Media + is TimelineItemGalleryContent -> ContentPadding.CaptionedMedia + is TimelineItemAttachmentsContent -> ContentPadding.CaptionedMedia + is TimelineItemStickerContent, + is TimelineItemLocationContent -> ContentPadding.Media + else -> ContentPadding.Textual + } } CommonLayout( showThreadDecoration = timelineMode !is Timeline.Mode.Thread && event.threadInfo is TimelineItemThreadInfo.ThreadResponse, 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 a49952b272..024169b00a 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 @@ -28,7 +28,6 @@ import io.element.android.features.messages.impl.timeline.components.receipt.Rea import io.element.android.features.messages.impl.timeline.components.receipt.TimelineItemReadReceiptView import io.element.android.features.messages.impl.timeline.groups.isRedactedMessagesGroup import io.element.android.features.messages.impl.timeline.model.TimelineItem -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.aTimelineProtectionState import io.element.android.libraries.designsystem.preview.ElementPreview @@ -62,9 +61,9 @@ fun TimelineItemGroupedEventsRow( eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { event, contentModifier, onContentLayoutChange -> TimelineItemEventContentView( + eventId = event.eventId, content = event.content, - hideMediaContent = timelineProtectionState.hideMediaContent(event.eventId, event.isMine), - onShowContentClick = { timelineProtectionState.eventSink(TimelineProtectionEvent.ShowContent(event.eventId)) }, + timelineProtectionState = timelineProtectionState, onLinkClick = onLinkClick, onLinkLongClick = onLinkLongClick, eventSink = eventSink, @@ -134,9 +133,9 @@ private fun TimelineItemGroupedEventsRowContent( eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { event, contentModifier, onContentLayoutChange -> TimelineItemEventContentView( + eventId = event.eventId, content = event.content, - hideMediaContent = timelineProtectionState.hideMediaContent(event.eventId, event.isMine), - onShowContentClick = { timelineProtectionState.eventSink(TimelineProtectionEvent.ShowContent(event.eventId)) }, + timelineProtectionState = timelineProtectionState, onLinkClick = onLinkClick, onLinkLongClick = onLinkLongClick, eventSink = eventSink, 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 6a5cbfd9dd..20444903ad 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 @@ -36,7 +36,6 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent -import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionEvent import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionState import io.element.android.libraries.designsystem.colors.gradientSubtleColors import io.element.android.libraries.designsystem.modifiers.onKeyboardContextMenuAction @@ -77,9 +76,9 @@ internal fun TimelineItemRow( eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = { event, contentModifier, onContentLayoutChange -> TimelineItemEventContentView( + eventId = event.eventId, content = event.content, - hideMediaContent = timelineProtectionState.hideMediaContent(event.eventId, event.isMine), - onShowContentClick = { timelineProtectionState.eventSink(TimelineProtectionEvent.ShowContent(event.eventId)) }, + timelineProtectionState = timelineProtectionState, onContentClick = { onContentClick(event) }, onGalleryItemClick = { index -> onGalleryItemClick(event, index) }, onLongClick = { onLongClick(event) }, @@ -119,6 +118,7 @@ internal fun TimelineItemRow( onClick = { onContentClick(timelineItem) }, onReadReceiptsClick = onReadReceiptClick, onLongClick = { onLongClick(timelineItem) }, + timelineProtectionState = timelineProtectionState, eventSink = eventSink, ) } 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 a6015758fc..eb27134065 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 @@ -31,6 +31,8 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition import io.element.android.features.messages.impl.timeline.model.TimelineItemReadReceipts import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemStateEventContent +import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionState +import io.element.android.features.messages.impl.timeline.protection.aTimelineProtectionState import io.element.android.features.messages.impl.timeline.util.defaultTimelineContentPadding import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -43,6 +45,7 @@ fun TimelineItemStateEventRow( onClick: () -> Unit, onLongClick: () -> Unit, onReadReceiptsClick: (event: TimelineItem.Event) -> Unit, + timelineProtectionState: TimelineProtectionState, eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, modifier: Modifier = Modifier ) { @@ -67,11 +70,11 @@ fun TimelineItemStateEventRow( .widthIn(max = 320.dp) ) { TimelineItemEventContentView( + eventId = event.eventId, content = event.content, onLinkClick = {}, onLinkLongClick = {}, - hideMediaContent = false, - onShowContentClick = {}, + timelineProtectionState = timelineProtectionState, eventSink = eventSink, onContentClick = null, onGalleryItemClick = {}, @@ -107,6 +110,7 @@ internal fun TimelineItemStateEventRowPreview() = ElementPreview { onClick = {}, onLongClick = {}, onReadReceiptsClick = {}, + timelineProtectionState = aTimelineProtectionState(), eventSink = {} ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAttachmentView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAttachmentView.kt index 4aa41a472b..38d575718f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAttachmentView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAttachmentView.kt @@ -13,7 +13,6 @@ 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.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable @@ -25,8 +24,10 @@ import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayout import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData +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.matrix.ui.media.contentvalidation.ContentValidationValue /** * package-private, you should only use TimelineItemFileView and TimelineItemAudioView. @@ -38,9 +39,9 @@ fun TimelineItemAttachmentView( iconContentDescription: String?, filename: String, fileExtensionAndSize: String, - caption: String?, onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit, modifier: Modifier = Modifier, + contentValidationValue: ContentValidationValue = ContentValidationValue.Valid, ) { Column( modifier = modifier, @@ -50,16 +51,9 @@ fun TimelineItemAttachmentView( iconContentDescription = iconContentDescription, filename = filename, fileExtensionAndSize = fileExtensionAndSize, - hasCaption = caption != null, + isLoading = !contentValidationValue.isValidated(), onContentLayoutChange = onContentLayoutChange, ) - if (caption != null) { - TimelineItemAttachmentCaptionView( - modifier = Modifier.padding(top = 4.dp), - caption = caption, - onContentLayoutChange = onContentLayoutChange, - ) - } } } @@ -69,7 +63,7 @@ private fun TimelineItemAttachmentHeaderView( iconContentDescription: String?, filename: String, fileExtensionAndSize: String, - hasCaption: Boolean, + isLoading: Boolean, onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit, modifier: Modifier = Modifier, ) { @@ -86,12 +80,19 @@ private fun TimelineItemAttachmentHeaderView( .background(ElementTheme.colors.bgCanvasDefault, RoundedCornerShape(4.dp)), contentAlignment = Alignment.Center, ) { - Icon( - imageVector = icon, - contentDescription = iconContentDescription, - tint = ElementTheme.colors.iconPrimary, - modifier = Modifier.size(24.dp), - ) + if (isLoading) { + CircularProgressIndicator( + modifier = Modifier.size(24.dp), + color = ElementTheme.colors.iconPrimary, + ) + } else { + Icon( + imageVector = icon, + contentDescription = iconContentDescription, + tint = ElementTheme.colors.iconPrimary, + modifier = Modifier.size(24.dp), + ) + } } Column { Text( @@ -107,32 +108,11 @@ private fun TimelineItemAttachmentHeaderView( style = ElementTheme.typography.fontBodySmRegular, maxLines = 1, overflow = TextOverflow.Ellipsis, - onTextLayout = if (hasCaption) { - {} - } else { - ContentAvoidingLayout.measureLastTextLine( - onContentLayoutChange = onContentLayoutChange, - extraWidth = iconSize + spacing - ) - }, + onTextLayout = ContentAvoidingLayout.measureLastTextLine( + onContentLayoutChange = onContentLayoutChange, + extraWidth = iconSize + spacing + ), ) } } } - -@Composable -private fun TimelineItemAttachmentCaptionView( - caption: String, - onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit, - modifier: Modifier = Modifier, -) { - Text( - modifier = modifier, - text = caption, - color = ElementTheme.colors.textPrimary, - style = ElementTheme.typography.fontBodyLgRegular, - onTextLayout = ContentAvoidingLayout.measureLastTextLine( - onContentLayoutChange = onContentLayoutChange, - ) - ) -} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAttachmentsContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAttachmentsContentProvider.kt index 9bc554057f..c63d68e062 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAttachmentsContentProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAttachmentsContentProvider.kt @@ -38,7 +38,6 @@ class TimelineItemAttachmentsContentProvider : PreviewParameterProvider Unit, - onLinkClick: (Link) -> Unit, - onLinkLongClick: (Link) -> Unit, - onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit, modifier: Modifier = Modifier, ) { - Column(modifier = modifier) { - Column( - modifier = Modifier.fillMaxWidth(), - ) { - content.attachments.forEachIndexed { index, attachment -> - Column { - if (index > 0) { - HorizontalDivider( - color = ElementTheme.colors.borderInteractiveSecondary, + val contentValidationState = rememberEventContentValidationState( + eventId = eventId, + needsValidation = content.isMedia, + ) + + Column(modifier = modifier.fillMaxWidth()) { + val validationStates = remember(content.attachments) { + buildList { + for (attachment in content.attachments) { + add(validationStateForAttachment(attachment, contentValidationState)) + } + }.toMutableStateList() + } + content.attachments.forEachIndexed { index, attachment -> + Column(modifier = Modifier.fillMaxWidth()) { + val thumbnailContentValidationState by contentValidationState.collectMediaState(attachment.thumbnailSource?.safeUrl) + val mediaContentValidationState by contentValidationState.collectMediaState(attachment.mediaSource.safeUrl) + + val itemContentValidationState = remember(thumbnailContentValidationState, mediaContentValidationState) { + validationStateForAttachment(attachment, contentValidationState) + } + + LaunchedEffect(itemContentValidationState) { + validationStates[index] = itemContentValidationState + } + + val needsSeparator = index in 1..max(1, content.attachments.lastIndex) + val isPreviousItemInvalid = validationStates.getOrNull(index - 1)?.hasError() == true + if (needsSeparator && !itemContentValidationState.hasError() && !isPreviousItemInvalid) { + HorizontalDivider( + color = ElementTheme.colors.borderInteractiveSecondary, + ) + } + + when (itemContentValidationState) { + ContentValidationValue.Invalid -> { + val shape = RoundedCornerShape(6.dp) + InvalidContentView( + modifier = Modifier + .padding(vertical = 6.dp) + .border(width = 1.dp, color = ElementTheme.colors.borderCriticalSubtle, shape = shape) + .clip(shape), + contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp), ) } - AttachmentListItem( - attachment = attachment, - onClick = { onGalleryItemClick(index) }, + is ContentValidationValue.UnrecoverableError -> { + val shape = RoundedCornerShape(6.dp) + NotFoundContentView( + modifier = Modifier + .padding(vertical = 6.dp) + .border(width = 1.dp, color = ElementTheme.colors.borderCriticalSubtle, shape = shape) + .clip(shape), + contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp), + ) + } + ContentValidationValue.Loading -> { + CircularProgressIndicator(modifier = Modifier.padding(8.dp).align(Alignment.CenterHorizontally)) + } + ContentValidationValue.Valid -> { + AttachmentListItem( + attachment = attachment, + onClick = { onGalleryItemClick(index) }, + ) + } + else -> { + // TODO handle cases where either the content hasn't started validation or it failed to do so + } + } + + if (index == content.attachments.lastIndex && content.showCaption && !itemContentValidationState.isInvalid()) { + HorizontalDivider( + color = ElementTheme.colors.borderInteractiveSecondary, ) } } } - if (content.showCaption) { - HorizontalDivider( - color = ElementTheme.colors.borderInteractiveSecondary, - ) - Spacer(modifier = Modifier.height(8.dp)) - val caption = if (LocalInspectionMode.current) { - SpannedString(content.caption) - } else { - content.formattedCaption ?: SpannedString(content.caption) - } - CompositionLocalProvider( - LocalContentColor provides ElementTheme.colors.textPrimary, - LocalTextStyle provides ElementTheme.typography.fontBodyLgRegular - ) { - EditorStyledText( - modifier = Modifier - .padding(horizontal = 4.dp) - .widthIn(min = 120.dp), - text = caption, - style = ElementRichTextEditorStyle.textStyle(), - onLinkClickedListener = onLinkClick, - onLinkLongClickedListener = onLinkLongClick, - releaseOnDetach = false, - onTextLayout = ContentAvoidingLayout.measureLegacyLastTextLine(onContentLayoutChange = onContentLayoutChange), - ) - } - } + } +} + +private fun validationStateForAttachment( + attachment: AttachmentItem, + contentValidationState: ContentValidationState, +): ContentValidationValue { + val thumbnailValue = attachment.thumbnailSource?.safeUrl?.let { contentValidationState.getCurrentMediaState(it) } ?: ContentValidationValue.Unknown + val mediaValue = contentValidationState.getCurrentMediaState(attachment.mediaSource.safeUrl) + return validationStateForAttachment(thumbnailValue, mediaValue) +} + +private fun validationStateForAttachment( + thumbnailValue: ContentValidationValue, + mediaValue: ContentValidationValue, +): ContentValidationValue { + return if (thumbnailValue.isInvalid() || mediaValue.isInvalid()) { + ContentValidationValue.Invalid + } else if (thumbnailValue.hasUnrecoverableError() || mediaValue.hasUnrecoverableError()) { + listOf(thumbnailValue, mediaValue).first { it.hasUnrecoverableError() } + } else if (thumbnailValue.isLoading() || mediaValue.isLoading()) { + ContentValidationValue.Loading + } else { + mediaValue } } @@ -213,10 +268,8 @@ internal fun TimelineItemAttachmentsListViewPreview( @PreviewParameter(TimelineItemAttachmentsContentProvider::class) content: TimelineItemAttachmentsContent ) = ElementPreview { TimelineItemAttachmentsListView( + eventId = EventId("\$eventId"), content = content, onGalleryItemClick = {}, - onLinkClick = {}, - onLinkLongClick = {}, - onContentLayoutChange = {}, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAudioView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAudioView.kt index d5a07194cf..1f10a97eda 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAudioView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAudioView.kt @@ -16,21 +16,23 @@ import io.element.android.features.messages.impl.timeline.components.layout.Cont import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContentProvider import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue @Composable fun TimelineItemAudioView( content: TimelineItemAudioContent, onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit, modifier: Modifier = Modifier, + contentValidationValue: ContentValidationValue = ContentValidationValue.Valid, ) { TimelineItemAttachmentView( icon = CompoundIcons.Audio(), iconContentDescription = null, filename = content.filename, fileExtensionAndSize = content.fileExtensionAndSize, - caption = content.caption, onContentLayoutChange = onContentLayoutChange, modifier = modifier, + contentValidationValue = contentValidationValue, ) } 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 2951d13d65..c622a3044a 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 @@ -8,9 +8,23 @@ package io.element.android.features.messages.impl.timeline.components.event +import android.text.SpannedString +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.LocalTextStyle import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalInspectionMode +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme import io.element.android.features.messages.impl.timeline.TimelineEvent +import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayout import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.di.rememberPresenter @@ -32,132 +46,265 @@ 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.captionOrNull import io.element.android.features.messages.impl.timeline.model.event.ensureActiveLiveLocation +import io.element.android.features.messages.impl.timeline.model.event.formattedCaptionOrNull +import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionEvent +import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionState import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.designsystem.components.EqualWidthColumn +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.InvalidContentView +import io.element.android.libraries.matrix.ui.media.contentvalidation.NotFoundContentView +import io.element.android.libraries.matrix.ui.media.contentvalidation.collectOverallState +import io.element.android.libraries.matrix.ui.media.contentvalidation.rememberEventContentValidationState +import io.element.android.libraries.textcomposer.ElementRichTextEditorStyle import io.element.android.libraries.voiceplayer.api.VoiceMessageState +import io.element.android.wysiwyg.compose.EditorStyledText import io.element.android.wysiwyg.link.Link @Composable fun TimelineItemEventContentView( + eventId: EventId?, content: TimelineItemEventContent, - hideMediaContent: Boolean, onContentClick: (() -> Unit)?, onGalleryItemClick: ((Int) -> Unit), + timelineProtectionState: TimelineProtectionState, onLongClick: (() -> Unit)?, - onShowContentClick: () -> Unit, onLinkClick: (Link) -> Unit, onLinkLongClick: (Link) -> Unit, eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, modifier: Modifier = Modifier, onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit = {}, ) { - val presenterFactories = LocalTimelineItemPresenterFactories.current - when (content) { - is TimelineItemEncryptedContent -> TimelineItemEncryptedView( - content = content, - onContentLayoutChange = onContentLayoutChange, - modifier = modifier - ) - is TimelineItemRedactedContent -> TimelineItemRedactedView( - content = content, - onContentLayoutChange = onContentLayoutChange, - modifier = modifier - ) - is TimelineItemTextBasedContent -> TimelineItemTextView( - content = content, - modifier = modifier, - onLinkClick = onLinkClick, - onLinkLongClick = onLinkLongClick, - onContentLayoutChange = onContentLayoutChange - ) - is TimelineItemUnknownContent -> TimelineItemUnknownView( - content = content, - onContentLayoutChange = onContentLayoutChange, - modifier = modifier - ) - is TimelineItemLocationContent -> { - TimelineItemLocationView( - content = content.ensureActiveLiveLocation(), - onStopLiveLocationClick = { eventSink(TimelineEvent.StopLiveLocationShare) }, - modifier = modifier - ) + val hideMediaContent = remember(eventId, timelineProtectionState.protectionState) { + timelineProtectionState.hideMediaContent(eventId) + } + + val onShowContentClick = remember(timelineProtectionState.eventSink) { + { + timelineProtectionState.eventSink(TimelineProtectionEvent.ShowContent(eventId)) } - is TimelineItemImageContent -> TimelineItemImageView( - content = content, - hideMediaContent = hideMediaContent, - onContentClick = onContentClick, - onLongClick = onLongClick, - onShowContentClick = onShowContentClick, - onLinkClick = onLinkClick, - onLinkLongClick = onLinkLongClick, - onContentLayoutChange = onContentLayoutChange, - modifier = modifier, - ) - is TimelineItemGalleryContent -> TimelineItemGalleryView( - content = content, - onGalleryItemClick = { index -> onGalleryItemClick(index) }, - onLongClick = onLongClick, - onLinkClick = onLinkClick, - onLinkLongClick = onLinkLongClick, - onContentLayoutChange = onContentLayoutChange, - modifier = modifier, - ) - is TimelineItemAttachmentsContent -> TimelineItemAttachmentsListView( - content = content, - onGalleryItemClick = { index -> onGalleryItemClick(index) }, - onLinkClick = onLinkClick, - onLinkLongClick = onLinkLongClick, - onContentLayoutChange = {}, - modifier = modifier, - ) - is TimelineItemStickerContent -> TimelineItemStickerView( - content = content, - hideMediaContent = hideMediaContent, - onContentClick = onContentClick, - onLongClick = onLongClick, - onShowClick = onShowContentClick, - modifier = modifier, - ) - is TimelineItemVideoContent -> TimelineItemVideoView( - content = content, - hideMediaContent = hideMediaContent, - onContentClick = onContentClick, - onLongClick = onLongClick, - onShowContentClick = onShowContentClick, - onLinkClick = onLinkClick, - onLinkLongClick = onLinkLongClick, - onContentLayoutChange = onContentLayoutChange, - modifier = modifier - ) - is TimelineItemFileContent -> TimelineItemFileView( - content = content, - onContentLayoutChange = onContentLayoutChange, - modifier = modifier - ) - is TimelineItemAudioContent -> TimelineItemAudioView( - content = content, - onContentLayoutChange = onContentLayoutChange, - modifier = modifier - ) - is TimelineItemLegacyCallInviteContent -> TimelineItemLegacyCallInviteView(modifier = modifier) - is TimelineItemStateContent -> TimelineItemStateView( - content = content, - modifier = modifier - ) - is TimelineItemPollContent -> TimelineItemPollView( - content = content, - eventSink = eventSink, - modifier = modifier, - ) - is TimelineItemVoiceContent -> { - val presenter: Presenter = presenterFactories.rememberPresenter(content) - TimelineItemVoiceView( - state = presenter.present(), - content = content, + } + + val contentValidationState = rememberEventContentValidationState(eventId = eventId, needsValidation = content.isMedia) + val overallValidationState by contentValidationState.collectOverallState() + val needsContentValidationPerItem = remember(content) { content is TimelineItemGalleryContent || content is TimelineItemAttachmentsContent } + + if (eventId != null) { + ValidateMediaHelper(eventId, content, contentValidationState, eventSink) + } + + val caption = content.captionOrNull() + val showCaption = caption != null && content !is TimelineItemStickerContent && content !is TimelineItemVoiceContent + // If a caption is added, it will be used to get the free space for the overlay, so we don't need to add onContentLayoutChange to the actual content + val calculatedOnContentLayoutChange = remember(onContentLayoutChange, showCaption) { + if (showCaption) { + {} + } else { + onContentLayoutChange + } + } + + val displayInvalidContent = overallValidationState.isInvalid() && !needsContentValidationPerItem + val displayContentNotFound = overallValidationState.hasUnrecoverableError() && !needsContentValidationPerItem + EqualWidthColumn(modifier = modifier) { + if (displayInvalidContent) { + InvalidContentView( + contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp), + onTextLayout = ContentAvoidingLayout.measureLastTextLine( + onContentLayoutChange = calculatedOnContentLayoutChange, + // Icon + horizontal paddings + extraWidth = 24.dp + 20.dp, + ) + ) + } else if (displayContentNotFound) { + NotFoundContentView( + contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp), + onTextLayout = ContentAvoidingLayout.measureLastTextLine( + onContentLayoutChange = calculatedOnContentLayoutChange, + // Icon + horizontal paddings + extraWidth = 24.dp + 20.dp, + ) + ) + } else { + val presenterFactories = LocalTimelineItemPresenterFactories.current + when (content) { + is TimelineItemEncryptedContent -> TimelineItemEncryptedView( + content = content, + onContentLayoutChange = calculatedOnContentLayoutChange, + ) + is TimelineItemRedactedContent -> TimelineItemRedactedView( + content = content, + onContentLayoutChange = calculatedOnContentLayoutChange, + ) + is TimelineItemTextBasedContent -> TimelineItemTextView( + content = content, + onLinkClick = onLinkClick, + onLinkLongClick = onLinkLongClick, + onContentLayoutChange = calculatedOnContentLayoutChange, + ) + is TimelineItemUnknownContent -> TimelineItemUnknownView( + content = content, + onContentLayoutChange = calculatedOnContentLayoutChange, + ) + is TimelineItemLocationContent -> { + TimelineItemLocationView( + content = content.ensureActiveLiveLocation(), + onStopLiveLocationClick = { eventSink(TimelineEvent.StopLiveLocationShare) }, + ) + } + is TimelineItemImageContent -> { + TimelineItemImageView( + content = content, + hideMediaContent = hideMediaContent, + onContentClick = onContentClick, + onLongClick = onLongClick, + onShowContentClick = onShowContentClick, + contentValidationState = contentValidationState, + ) + } + is TimelineItemStickerContent -> { + TimelineItemStickerView( + content = content, + hideMediaContent = hideMediaContent, + onContentClick = onContentClick, + onLongClick = onLongClick, + onShowClick = onShowContentClick, + contentValidationState = contentValidationState, + ) + } + is TimelineItemVideoContent -> { + TimelineItemVideoView( + content = content, + hideMediaContent = hideMediaContent, + onContentClick = onContentClick, + onLongClick = onLongClick, + onShowContentClick = onShowContentClick, + contentValidationState = contentValidationState, + ) + } + is TimelineItemGalleryContent -> TimelineItemGalleryView( + eventId = eventId, + content = content, + onGalleryItemClick = { index -> onGalleryItemClick(index) }, + onLongClick = onLongClick, + ) + is TimelineItemAttachmentsContent -> TimelineItemAttachmentsListView( + eventId = eventId, + content = content, + onGalleryItemClick = { index -> onGalleryItemClick(index) }, + ) + is TimelineItemFileContent -> { + TimelineItemFileView( + content = content, + onContentLayoutChange = calculatedOnContentLayoutChange, + contentValidationValue = overallValidationState, + ) + } + is TimelineItemAudioContent -> { + TimelineItemAudioView( + content = content, + onContentLayoutChange = calculatedOnContentLayoutChange, + contentValidationValue = overallValidationState, + ) + } + is TimelineItemLegacyCallInviteContent -> TimelineItemLegacyCallInviteView() + is TimelineItemStateContent -> TimelineItemStateView( + content = content, + ) + is TimelineItemPollContent -> TimelineItemPollView( + content = content, + eventSink = eventSink, + ) + is TimelineItemVoiceContent -> { + val presenter: Presenter = presenterFactories.rememberPresenter(content) + TimelineItemVoiceView( + state = presenter.present(), + content = content, + onContentLayoutChange = calculatedOnContentLayoutChange, + contentValidationValue = overallValidationState, + ) + } + is TimelineItemRtcNotificationContent -> error("This shouldn't be rendered as the content of a bubble") + } + } + + if (showCaption) { + val padding = if (displayInvalidContent) { + PaddingValues(start = 12.dp, end = 12.dp, top = 4.dp, bottom = 0.dp) + } else { + when (content) { + is TimelineItemImageContent, + is TimelineItemVideoContent, + is TimelineItemGalleryContent, + is TimelineItemAttachmentsContent -> PaddingValues(start = 4.dp, end = 4.dp, top = 8.dp, bottom = 0.dp) + else -> PaddingValues(horizontal = 12.dp, vertical = 8.dp) + } + } + CaptionView( + modifier = Modifier.padding(padding), + caption = caption, + formattedCaption = content.formattedCaptionOrNull(), + onLinkClick = onLinkClick, + onLinkLongClick = onLinkLongClick, onContentLayoutChange = onContentLayoutChange, - modifier = modifier ) } - is TimelineItemRtcNotificationContent -> error("This shouldn't be rendered as the content of a bubble") + } +} + +@Composable +private fun CaptionView( + caption: String, + formattedCaption: CharSequence?, + onLinkClick: (Link) -> Unit, + onLinkLongClick: (Link) -> Unit, + onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit, + modifier: Modifier = Modifier, +) { + val caption = if (LocalInspectionMode.current) { + SpannedString(caption) + } else { + formattedCaption ?: SpannedString(caption) + } + CompositionLocalProvider( + LocalContentColor provides ElementTheme.colors.textPrimary, + LocalTextStyle provides ElementTheme.typography.fontBodyLgRegular + ) { + EditorStyledText( + modifier = modifier, + text = caption, + style = ElementRichTextEditorStyle.textStyle(), + onLinkClickedListener = onLinkClick, + onLinkLongClickedListener = onLinkLongClick, + releaseOnDetach = false, + onTextLayout = ContentAvoidingLayout.measureLegacyLastTextLine(onContentLayoutChange = onContentLayoutChange), + ) + } +} + +@Composable +private fun ValidateMediaHelper( + eventId: EventId, + content: TimelineItemEventContent, + contentValidationState: ContentValidationState, + eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, +) { + val mediaSources = when (content) { + is TimelineItemImageContent -> listOfNotNull(content.thumbnailSource, content.mediaSource) + is TimelineItemStickerContent -> listOfNotNull(content.thumbnailSource, content.mediaSource) + is TimelineItemVideoContent -> listOfNotNull(content.thumbnailSource, content.mediaSource) + is TimelineItemFileContent -> listOfNotNull(content.thumbnailSource, content.mediaSource) + is TimelineItemAudioContent -> listOf(content.mediaSource) + is TimelineItemVoiceContent -> listOf(content.mediaSource) + is TimelineItemGalleryContent -> content.items.flatMap { listOfNotNull(it.thumbnailSource, it.mediaSource) } + is TimelineItemAttachmentsContent -> content.attachments.flatMap { listOfNotNull(it.thumbnailSource, it.mediaSource) } + else -> return + } + val updatedEventSink by rememberUpdatedState(eventSink) + LaunchedEffect(eventId, mediaSources) { + updatedEventSink(TimelineEvent.ValidateMedia(eventId, mediaSources, contentValidationState)) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemFileView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemFileView.kt index 7f8be6e60a..a0deec6d84 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemFileView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemFileView.kt @@ -17,6 +17,7 @@ import io.element.android.features.messages.impl.timeline.components.layout.Cont import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContentProvider import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue import io.element.android.libraries.ui.strings.CommonStrings /** @@ -27,15 +28,16 @@ fun TimelineItemFileView( content: TimelineItemFileContent, onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit, modifier: Modifier = Modifier, + contentValidationValue: ContentValidationValue = ContentValidationValue.Valid, ) { TimelineItemAttachmentView( icon = CompoundIcons.Attachment(), iconContentDescription = stringResource(CommonStrings.common_file), filename = content.filename, fileExtensionAndSize = content.fileExtensionAndSize, - caption = content.caption, onContentLayoutChange = onContentLayoutChange, modifier = modifier, + contentValidationValue = contentValidationValue, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryContentProvider.kt index fe7de6a7f6..9d88d8c0fb 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryContentProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryContentProvider.kt @@ -116,6 +116,7 @@ fun aGalleryItem( width: Int = 400, height: Int = 300, duration: Duration = Duration.ZERO, + mediaSource: MediaSource = MediaSource(url = "", json = ""), ): GalleryItem { return GalleryItem( filename = filename, @@ -125,7 +126,7 @@ fun aGalleryItem( GalleryItem.Type.File -> "application/pdf" GalleryItem.Type.Image -> "image/jpeg" }, - mediaSource = MediaSource(url = "", json = ""), + mediaSource = mediaSource, thumbnailSource = null, width = width, height = height, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryView.kt index c51055da92..8c4244a651 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryView.kt @@ -7,7 +7,6 @@ package io.element.android.features.messages.impl.timeline.components.event -import android.text.SpannedString import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement @@ -21,28 +20,24 @@ 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.layout.widthIn import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.LocalTextStyle +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider +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.clip import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalInspectionMode 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 import io.element.android.compound.tokens.generated.CompoundIcons -import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayout -import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData import io.element.android.features.messages.impl.timeline.model.event.GalleryItem import io.element.android.features.messages.impl.timeline.model.event.TimelineItemGalleryContent import io.element.android.libraries.designsystem.components.blurhash.blurHashBackground @@ -50,10 +45,11 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.bgSubtleTertiary import io.element.android.libraries.designsystem.theme.components.Icon -import io.element.android.libraries.textcomposer.ElementRichTextEditorStyle +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue +import io.element.android.libraries.matrix.ui.media.contentvalidation.collectMediaState +import io.element.android.libraries.matrix.ui.media.contentvalidation.rememberEventContentValidationState import io.element.android.libraries.ui.utils.time.formatShort -import io.element.android.wysiwyg.compose.EditorStyledText -import io.element.android.wysiwyg.link.Link import kotlinx.collections.immutable.ImmutableList private const val MAX_TILES = 5 @@ -67,12 +63,10 @@ private val THREE_IMAGE_ROW_HEIGHT = 85.dp @Composable fun TimelineItemGalleryView( + eventId: EventId?, content: TimelineItemGalleryContent, onGalleryItemClick: (Int) -> Unit, onLongClick: (() -> Unit)?, - onLinkClick: (Link) -> Unit, - onLinkLongClick: (Link) -> Unit, - onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit, modifier: Modifier = Modifier, ) { val totalItems = content.items.size @@ -87,21 +81,25 @@ fun TimelineItemGalleryView( when (totalItems) { 0 -> Unit 1 -> SingleItemLayout( + eventId = eventId, item = content.items[0], onClick = { onGalleryItemClick(0) }, onLongClick = onLongClick, ) 2 -> TwoItemLayout( + eventId = eventId, items = content.items, onItemClick = onGalleryItemClick, onLongClick = onLongClick, ) 3 -> ThreeItemLayout( + eventId = eventId, items = content.items, onItemClick = onGalleryItemClick, onLongClick = onLongClick, ) else -> FourPlusItemLayout( + eventId = eventId, items = content.items, showOverflow = showOverflow, overflowCount = overflowCount, @@ -110,40 +108,18 @@ fun TimelineItemGalleryView( ) } } - if (content.showCaption) { - Spacer(modifier = Modifier.height(8.dp)) - val caption = if (LocalInspectionMode.current) { - SpannedString(content.caption) - } else { - content.formattedCaption ?: SpannedString(content.caption) - } - CompositionLocalProvider( - LocalContentColor provides ElementTheme.colors.textPrimary, - LocalTextStyle provides ElementTheme.typography.fontBodyLgRegular - ) { - EditorStyledText( - modifier = Modifier - .padding(horizontal = 4.dp) - .widthIn(min = 120.dp), - text = caption, - style = ElementRichTextEditorStyle.textStyle(), - onLinkClickedListener = onLinkClick, - onLinkLongClickedListener = onLinkLongClick, - releaseOnDetach = false, - onTextLayout = ContentAvoidingLayout.measureLegacyLastTextLine(onContentLayoutChange = onContentLayoutChange), - ) - } - } } } @Composable private fun SingleItemLayout( + eventId: EventId?, item: GalleryItem, onClick: () -> Unit, onLongClick: (() -> Unit)?, ) { GalleryItemCell( + eventId = eventId, item = item, isLast = false, remainingCount = 0, @@ -157,6 +133,7 @@ private fun SingleItemLayout( @Composable private fun TwoItemLayout( + eventId: EventId?, items: ImmutableList, onItemClick: (Int) -> Unit, onLongClick: (() -> Unit)?, @@ -167,6 +144,7 @@ private fun TwoItemLayout( ) { items.forEachIndexed { index, item -> GalleryItemCell( + eventId = eventId, item = item, isLast = false, remainingCount = 0, @@ -182,6 +160,7 @@ private fun TwoItemLayout( @Composable private fun ThreeItemLayout( + eventId: EventId?, items: ImmutableList, onItemClick: (Int) -> Unit, onLongClick: (() -> Unit)?, @@ -191,6 +170,7 @@ private fun ThreeItemLayout( verticalArrangement = Arrangement.spacedBy(GRID_SPACING), ) { GalleryItemCell( + eventId = eventId, item = items[0], isLast = false, remainingCount = 0, @@ -206,6 +186,7 @@ private fun ThreeItemLayout( ) { for (it in 1..2) { GalleryItemCell( + eventId = eventId, item = items[it], isLast = false, remainingCount = 0, @@ -222,6 +203,7 @@ private fun ThreeItemLayout( @Composable private fun FourPlusItemLayout( + eventId: EventId?, items: ImmutableList, showOverflow: Boolean, overflowCount: Int, @@ -238,6 +220,7 @@ private fun FourPlusItemLayout( ) { for (it in 0..1) { GalleryItemCell( + eventId = eventId, item = items[it], isLast = false, remainingCount = 0, @@ -260,6 +243,7 @@ private fun FourPlusItemLayout( if (itemIndex < items.size) { val isOverflowItem = showOverflow && i == bottomRowItems - 1 GalleryItemCell( + eventId = eventId, item = items[itemIndex], isLast = isOverflowItem, remainingCount = if (isOverflowItem) overflowCount else 0, @@ -277,6 +261,7 @@ private fun FourPlusItemLayout( @Composable private fun GalleryItemCell( + eventId: EventId?, item: GalleryItem, isLast: Boolean, remainingCount: Int, @@ -284,6 +269,22 @@ private fun GalleryItemCell( onLongClick: (() -> Unit)?, modifier: Modifier = Modifier, ) { + val eventContentValidationState = rememberEventContentValidationState(eventId, needsValidation = true) + val thumbnailContentValidationState by eventContentValidationState.collectMediaState(item.thumbnailSource?.safeUrl) + val mediaContentValidationState by eventContentValidationState.collectMediaState(item.mediaSource.safeUrl) + + val itemContentValidationState = remember(thumbnailContentValidationState, mediaContentValidationState) { + if (thumbnailContentValidationState.isInvalid() || mediaContentValidationState.isInvalid()) { + ContentValidationValue.Invalid + } else if (thumbnailContentValidationState.hasUnrecoverableError() || mediaContentValidationState.hasUnrecoverableError()) { + listOf(thumbnailContentValidationState, mediaContentValidationState).first { it is ContentValidationValue.UnrecoverableError } + } else if (thumbnailContentValidationState.isLoading() || mediaContentValidationState.isLoading()) { + ContentValidationValue.Loading + } else { + mediaContentValidationState + } + } + Box( modifier = modifier .blurHashBackground(item.blurhash, alpha = 0.9f) @@ -305,7 +306,20 @@ private fun GalleryItemCell( VideoOverlay(duration = item.duration) } - if (isLast && remainingCount > 0) { + if (itemContentValidationState.isLoading()) { + CircularProgressIndicator() + } else if (itemContentValidationState.hasError()) { + Box( + modifier = Modifier.fillMaxSize().background(ElementTheme.colors.bgCriticalSubtle) + ) { + Icon( + modifier = Modifier.align(Alignment.Center), + imageVector = CompoundIcons.Error(), + tint = ElementTheme.colors.iconCriticalPrimary, + contentDescription = null, + ) + } + } else if (isLast && remainingCount > 0) { RemainingCountOverlay(count = remainingCount) } } @@ -374,11 +388,9 @@ internal fun TimelineItemGalleryViewPreview( @PreviewParameter(TimelineItemGalleryContentProvider::class) content: TimelineItemGalleryContent, ) = ElementPreview { TimelineItemGalleryView( + eventId = null, content = content, onGalleryItemClick = {}, onLongClick = {}, - onLinkClick = {}, - onLinkLongClick = {}, - onContentLayoutChange = {}, ) } 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 0e0a98a96c..eb5c507779 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 @@ -8,20 +8,13 @@ package io.element.android.features.messages.impl.timeline.components.event -import android.text.SpannedString import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Column -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.widthIn +import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.LocalTextStyle import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -31,118 +24,97 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage -import coil3.compose.AsyncImagePainter -import io.element.android.compound.theme.ElementTheme import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.components.ATimelineItemEventRow -import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayout -import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContentProvider import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.protection.ProtectedView import io.element.android.features.messages.impl.timeline.protection.coerceRatioWhenHidingContent +import io.element.android.features.messages.impl.timeline.util.handleAsyncImageStateChange import io.element.android.libraries.designsystem.components.blurhash.blurHashBackground 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.textcomposer.ElementRichTextEditorStyle +import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.collectOverallState import io.element.android.libraries.ui.strings.CommonStrings 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, hideMediaContent: Boolean, onContentClick: (() -> Unit)?, onLongClick: (() -> Unit)?, - onLinkClick: (Link) -> Unit, - onLinkLongClick: (Link) -> Unit, onShowContentClick: () -> Unit, - onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit, modifier: Modifier = Modifier, + contentValidationState: ContentValidationState = remember { DefaultContentValidationState() }, ) { val a11yLabel = stringResource(CommonStrings.common_image) val description = content.caption?.let { "$a11yLabel: $it" } ?: a11yLabel - Column(modifier = modifier) { + Column(modifier = modifier.wrapContentWidth(Alignment.CenterHorizontally)) { val containerModifier = if (content.showCaption) { Modifier.clip(RoundedCornerShape(10.dp)) } else { Modifier } + + val eventContentValidation by contentValidationState.collectOverallState() + val isContentBeingValidated = !eventContentValidation.isValidated() TimelineItemAspectRatioBox( - modifier = containerModifier.blurHashBackground(content.blurhash, alpha = 0.9f).align(Alignment.CenterHorizontally), + modifier = containerModifier + .blurHashBackground(content.blurhash, alpha = 0.9f) + .align(Alignment.CenterHorizontally), aspectRatio = coerceRatioWhenHidingContent(content.aspectRatio, hideMediaContent), ) { - ProtectedView( - hideContent = hideMediaContent, - onShowClick = onShowContentClick, - ) { - var isLoaded by remember { mutableStateOf(false) } - AsyncImage( - modifier = Modifier - .fillMaxWidth() - .then(if (isLoaded) Modifier.background(Color.White) else Modifier) - .then( - if (!isTalkbackActive() && onContentClick != null) { - Modifier - .combinedClickable( - onClick = onContentClick, - onLongClick = onLongClick, - ) - .onKeyboardContextMenuAction(onLongClick) - } else { - Modifier - } - ), - model = content.thumbnailMediaRequestData, - contentScale = ContentScale.Crop, - alignment = Alignment.Center, - contentDescription = description, - onState = { isLoaded = it is AsyncImagePainter.State.Success }, - ) - } - } - - if (content.showCaption) { - Spacer(modifier = Modifier.height(8.dp)) - val caption = if (LocalInspectionMode.current) { - SpannedString(content.caption) + if (isContentBeingValidated) { + CircularProgressIndicator(modifier = Modifier.align(Alignment.Center)) } else { - content.formattedCaption ?: SpannedString(content.caption) - } - CompositionLocalProvider( - LocalContentColor provides ElementTheme.colors.textPrimary, - LocalTextStyle provides ElementTheme.typography.fontBodyLgRegular - ) { - 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 + ProtectedView( + hideContent = hideMediaContent, + onShowClick = onShowContentClick, + ) { + var isLoaded by remember { mutableStateOf(false) } + AsyncImage( + modifier = Modifier + .fillMaxWidth() + .then(if (isLoaded) Modifier.background(Color.White) else Modifier) + .then( + if (!isTalkbackActive() && onContentClick != null) { + Modifier + .combinedClickable( + onClick = onContentClick, + onLongClick = onLongClick, + ) + .onKeyboardContextMenuAction(onLongClick) + } else { + Modifier + } + ), + model = content.thumbnailMediaRequestData, + contentScale = ContentScale.Crop, + alignment = Alignment.Center, + contentDescription = description, + onState = { state -> + val url = content.thumbnailMediaRequestData.source?.safeUrl + if (url != null) { + handleAsyncImageStateChange( + state = state, + onLoaded = { isLoaded = true }, + updateContentValidationState = { contentValidationState.update(url, it) }, + ) + } + }, + ) } - EditorStyledText( - modifier = Modifier - .padding(horizontal = 4.dp) // This is (12.dp - 8.dp) contentPadding from CommonLayout - .widthIn(min = MIN_HEIGHT_IN_DP.dp * aspectRatio, max = MAX_HEIGHT_IN_DP.dp * aspectRatio), - text = caption, - style = ElementRichTextEditorStyle.textStyle(), - onLinkClickedListener = onLinkClick, - onLinkLongClickedListener = onLinkLongClick, - releaseOnDetach = false, - onTextLayout = ContentAvoidingLayout.measureLegacyLastTextLine(onContentLayoutChange = onContentLayoutChange), - ) } } } @@ -157,9 +129,6 @@ internal fun TimelineItemImageViewPreview(@PreviewParameter(TimelineItemImageCon onShowContentClick = {}, onContentClick = {}, onLongClick = {}, - onLinkClick = {}, - onLinkLongClick = {}, - onContentLayoutChange = {}, ) } @@ -172,43 +141,9 @@ internal fun TimelineItemImageViewHideMediaContentPreview() = ElementPreview { onShowContentClick = {}, onContentClick = {}, onLongClick = {}, - onLinkClick = {}, - onLinkLongClick = {}, - onContentLayoutChange = {}, ) } -@PreviewsDayNight -@Composable -internal fun TimelineImageWithCaptionRowPreview() = 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", - aspectRatio = 2.5f, - ), - groupPosition = TimelineItemGroupPosition.Last, - ), - ) - } - ATimelineItemEventRow( - event = aTimelineItemEvent( - isMine = false, - content = aTimelineItemImageContent( - filename = "image.jpg", - caption = "Image with null aspectRatio", - aspectRatio = null, - ), - groupPosition = TimelineItemGroupPosition.Last, - ), - ) - } -} - @PreviewsDayNight @Composable internal fun ATimelineItemEventRowPreview() = ElementPreview { @@ -220,9 +155,9 @@ internal fun ATimelineItemEventRowPreview() = ElementPreview { content = aTimelineItemImageContent( filename = "image.jpg", caption = "A long caption that may wrap into several lines", - width = 80, - height = 300, - aspectRatio = 80f / 300f, + width = 40, + height = 20, + aspectRatio = 40f / 20f, ), groupPosition = TimelineItemGroupPosition.Last, ), @@ -235,7 +170,7 @@ internal fun ATimelineItemEventRowPreview() = ElementPreview { filename = "image.jpg", caption = "Narrow image with null aspectRatio", width = 80, - height = 300, + height = 150, aspectRatio = null, ), groupPosition = TimelineItemGroupPosition.Last, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemStickerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemStickerView.kt index 104e420d51..76ffda2a15 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemStickerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemStickerView.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -26,16 +27,20 @@ import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.PreviewParameter import coil3.compose.AsyncImage -import coil3.compose.AsyncImagePainter import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStickerContentProvider import io.element.android.features.messages.impl.timeline.protection.ProtectedView import io.element.android.features.messages.impl.timeline.protection.coerceRatioWhenHidingContent +import io.element.android.features.messages.impl.timeline.util.handleAsyncImageStateChange import io.element.android.libraries.designsystem.components.blurhash.blurHashBackground 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.theme.components.CircularProgressIndicator import io.element.android.libraries.matrix.ui.media.MediaRequestData +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.collectOverallState import io.element.android.libraries.ui.strings.CommonStrings private const val STICKER_SIZE_IN_DP = 128 @@ -48,10 +53,14 @@ fun TimelineItemStickerView( onLongClick: (() -> Unit)?, onShowClick: () -> Unit, modifier: Modifier = Modifier, + contentValidationState: ContentValidationState = remember { DefaultContentValidationState() }, ) { val description = content.bestDescription.takeIf { it.isNotEmpty() } ?: stringResource(CommonStrings.common_image) + + val eventContentValidation by contentValidationState.collectOverallState() + val isContentBeingValidated = !eventContentValidation.isValidated() Column( - modifier = modifier.semantics { contentDescription = description }, + modifier = modifier.semantics { contentDescription = description }.wrapContentWidth(Alignment.CenterHorizontally), ) { TimelineItemAspectRatioBox( modifier = Modifier.blurHashBackground(content.blurhash, alpha = 0.9f), @@ -63,11 +72,12 @@ fun TimelineItemStickerView( hideContent = hideMediaContent, onShowClick = onShowClick, ) { - var isLoaded by remember { mutableStateOf(false) } + var isThumbnailLoaded by remember { mutableStateOf(false) } + AsyncImage( modifier = Modifier .fillMaxSize() - .then(if (isLoaded) Modifier.background(Color.White) else Modifier) + .then(if (isThumbnailLoaded) Modifier.background(Color.White) else Modifier) .then( if (onContentClick != null) { Modifier @@ -91,9 +101,22 @@ fun TimelineItemStickerView( contentScale = ContentScale.Crop, alignment = Alignment.Center, contentDescription = description, - onState = { isLoaded = it is AsyncImagePainter.State.Success }, + onState = { state -> + val url = content.preferredMediaSource?.safeUrl + if (url != null) { + handleAsyncImageStateChange( + state = state, + onLoaded = { isThumbnailLoaded = true }, + updateContentValidationState = { contentValidationState.update(url, it) }, + ) + } + }, ) } + + if (isContentBeingValidated) { + CircularProgressIndicator(modifier = Modifier.align(Alignment.Center)) + } } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemTextView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemTextView.kt index 0449ef26f0..1a4be5d2e5 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemTextView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemTextView.kt @@ -30,6 +30,7 @@ import io.element.android.features.messages.impl.utils.containsOnlyEmojis import io.element.android.libraries.androidutils.text.LinkifyHelper import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.utils.LocalUiTestMode import io.element.android.libraries.textcomposer.ElementRichTextEditorStyle import io.element.android.libraries.textcomposer.mentions.LocalMentionSpanUpdater import io.element.android.wysiwyg.compose.EditorStyledText @@ -43,6 +44,9 @@ fun TimelineItemTextView( modifier: Modifier = Modifier, onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit = {}, ) { + // The View <-> Compose interop is not working well with Compose UI tests (it loops indefinitely), so we skip it in the UI test mode. + if (LocalUiTestMode.current) return + val emojiOnly = content.formattedBody.toString() == content.body && content.body.replace(" ", "").containsOnlyEmojis() val textStyle = when { 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 8d1ef18f39..ce97ecc775 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 @@ -8,22 +8,17 @@ package io.element.android.features.messages.impl.timeline.components.event -import android.text.SpannedString import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -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.widthIn +import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.LocalTextStyle +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -34,26 +29,19 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.hideFromAccessibility import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp 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.timeline.aTimelineItemEvent -import io.element.android.features.messages.impl.timeline.components.ATimelineItemEventRow -import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayout -import io.element.android.features.messages.impl.timeline.components.layout.ContentAvoidingLayoutData -import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContentProvider import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVideoContent import io.element.android.features.messages.impl.timeline.protection.ProtectedView import io.element.android.features.messages.impl.timeline.protection.coerceRatioWhenHidingContent +import io.element.android.features.messages.impl.timeline.util.handleAsyncImageStateChange import io.element.android.libraries.designsystem.components.blurhash.blurHashBackground import io.element.android.libraries.designsystem.modifiers.onKeyboardContextMenuAction import io.element.android.libraries.designsystem.modifiers.roundedBackground @@ -62,11 +50,11 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.matrix.ui.media.MAX_THUMBNAIL_HEIGHT 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.matrix.ui.media.contentvalidation.ContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.collectOverallState import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.utils.a11y.isTalkbackActive -import io.element.android.wysiwyg.compose.EditorStyledText -import io.element.android.wysiwyg.link.Link @Composable fun TimelineItemVideoView( @@ -75,15 +63,13 @@ fun TimelineItemVideoView( onContentClick: (() -> Unit)?, onLongClick: (() -> Unit)?, onShowContentClick: () -> Unit, - onLinkClick: (Link) -> Unit, - onLinkLongClick: (Link) -> Unit, - onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit, modifier: Modifier = Modifier, + contentValidationState: ContentValidationState = remember { DefaultContentValidationState() }, ) { val isTalkbackActive = isTalkbackActive() val a11yLabel = stringResource(CommonStrings.common_video) val description = content.caption?.let { "$a11yLabel: $it" } ?: a11yLabel - Column(modifier = modifier) { + Column(modifier = modifier.wrapContentWidth(Alignment.CenterHorizontally)) { val containerModifier = if (content.showCaption) { Modifier .padding(top = 6.dp) @@ -91,6 +77,9 @@ fun TimelineItemVideoView( } else { Modifier } + + val eventContentValidation by contentValidationState.collectOverallState() + val isContentBeingValidated = !eventContentValidation.isValidated() TimelineItemAspectRatioBox( modifier = containerModifier.blurHashBackground(content.blurHash, alpha = 0.9f), aspectRatio = coerceRatioWhenHidingContent(content.aspectRatio, hideMediaContent), @@ -127,48 +116,35 @@ fun TimelineItemVideoView( contentScale = ContentScale.Crop, alignment = Alignment.Center, contentDescription = description, - onState = { isLoaded = it is AsyncImagePainter.State.Success }, + onState = { state -> + val url = content.thumbnailSource?.safeUrl + if (url != null) { + handleAsyncImageStateChange( + state = state, + onLoaded = { isLoaded = true }, + updateContentValidationState = { contentValidationState.update(url, it) }, + ) + } + }, ) - Box( - modifier = Modifier.roundedBackground(), - contentAlignment = Alignment.Center, - ) { - Image( - imageVector = CompoundIcons.PlaySolid(), - contentDescription = stringResource(id = CommonStrings.a11y_play), - colorFilter = ColorFilter.tint(Color.White), - modifier = Modifier.semantics { hideFromAccessibility() } - ) + if (!isContentBeingValidated) { + Box( + modifier = Modifier.roundedBackground(), + contentAlignment = Alignment.Center, + ) { + Image( + imageVector = CompoundIcons.PlaySolid(), + contentDescription = stringResource(id = CommonStrings.a11y_play), + colorFilter = ColorFilter.tint(Color.White), + modifier = Modifier.semantics { hideFromAccessibility() } + ) + } + } else { + CircularProgressIndicator() } } } - - if (content.showCaption) { - Spacer(modifier = Modifier.height(8.dp)) - val caption = if (LocalInspectionMode.current) { - SpannedString(content.caption) - } else { - content.formattedCaption ?: SpannedString(content.caption) - } - CompositionLocalProvider( - LocalContentColor provides ElementTheme.colors.textPrimary, - LocalTextStyle provides ElementTheme.typography.fontBodyLgRegular, - ) { - val aspectRatio = content.aspectRatio ?: DEFAULT_ASPECT_RATIO - EditorStyledText( - modifier = Modifier - .padding(horizontal = 4.dp) // This is (12.dp - 8.dp) contentPadding from CommonLayout - .widthIn(min = MIN_HEIGHT_IN_DP.dp * aspectRatio, max = MAX_HEIGHT_IN_DP.dp * aspectRatio), - text = caption, - onLinkClickedListener = onLinkClick, - onLinkLongClickedListener = onLinkLongClick, - style = ElementRichTextEditorStyle.textStyle(), - releaseOnDetach = false, - onTextLayout = ContentAvoidingLayout.measureLegacyLastTextLine(onContentLayoutChange = onContentLayoutChange), - ) - } - } } } @@ -181,9 +157,6 @@ internal fun TimelineItemVideoViewPreview(@PreviewParameter(TimelineItemVideoCon onShowContentClick = {}, onContentClick = {}, onLongClick = {}, - onLinkClick = {}, - onLinkLongClick = {}, - onContentLayoutChange = {}, ) } @@ -196,39 +169,5 @@ internal fun TimelineItemVideoViewHideMediaContentPreview() = ElementPreview { onShowContentClick = {}, onContentClick = {}, onLongClick = {}, - onLinkClick = {}, - onLinkLongClick = {}, - onContentLayoutChange = {}, ) } - -@PreviewsDayNight -@Composable -internal fun TimelineVideoWithCaptionRowPreview() = ElementPreview { - Column { - sequenceOf(false, true).forEach { isMine -> - ATimelineItemEventRow( - event = aTimelineItemEvent( - isMine = isMine, - content = aTimelineItemVideoContent().copy( - filename = "video.mp4", - caption = "A long caption that may wrap into several lines", - aspectRatio = 2.5f, - ), - groupPosition = TimelineItemGroupPosition.Last, - ), - ) - } - ATimelineItemEventRow( - event = aTimelineItemEvent( - isMine = false, - content = aTimelineItemVideoContent().copy( - filename = "video.mp4", - caption = "Video with null aspect ratio", - aspectRatio = null, - ), - groupPosition = TimelineItemGroupPosition.Last, - ), - ) - } -} 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 86e3f1c849..67f1cbfa96 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 @@ -51,6 +51,7 @@ import io.element.android.libraries.designsystem.theme.components.CircularProgre 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.matrix.ui.media.contentvalidation.ContentValidationValue import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import io.element.android.libraries.voiceplayer.api.VoiceMessageEvent @@ -64,6 +65,7 @@ fun TimelineItemVoiceView( content: TimelineItemVoiceContent, onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit, modifier: Modifier = Modifier, + contentValidationValue: ContentValidationValue = ContentValidationValue.Valid, ) { fun playPause() { state.eventSink(VoiceMessageEvent.PlayPause) @@ -103,12 +105,16 @@ fun TimelineItemVoiceView( verticalAlignment = Alignment.CenterVertically, ) { if (!isTalkbackActive()) { - when (state.buttonType) { - VoiceMessageState.ButtonType.Play -> PlayButton(onClick = ::playPause) - VoiceMessageState.ButtonType.Pause -> PauseButton(onClick = ::playPause) - VoiceMessageState.ButtonType.Downloading -> ProgressButton() - VoiceMessageState.ButtonType.Retry -> RetryButton(onClick = ::playPause) - VoiceMessageState.ButtonType.Disabled -> PlayButton(onClick = {}, enabled = false) + if (contentValidationValue.isValid()) { + when (state.buttonType) { + VoiceMessageState.ButtonType.Play -> PlayButton(onClick = ::playPause) + VoiceMessageState.ButtonType.Pause -> PauseButton(onClick = ::playPause) + VoiceMessageState.ButtonType.Downloading -> ProgressButton() + VoiceMessageState.ButtonType.Retry -> RetryButton(onClick = ::playPause) + VoiceMessageState.ButtonType.Disabled -> PlayButton(onClick = {}, enabled = false) + } + } else { + ProgressButton(displayImmediately = true) } } Spacer(Modifier.width(8.dp)) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/layout/ContentAvoidingLayout.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/layout/ContentAvoidingLayout.kt index a299d2f1ce..cebe7f93b2 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/layout/ContentAvoidingLayout.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/layout/ContentAvoidingLayout.kt @@ -9,6 +9,7 @@ package io.element.android.features.messages.impl.timeline.components.layout import android.text.Layout +import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf @@ -23,6 +24,7 @@ import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp import io.element.android.libraries.core.data.tryOrNull import io.element.android.libraries.designsystem.text.roundToPx +import io.element.android.libraries.designsystem.utils.LocalUiTestMode import io.element.android.wysiwyg.compose.EditorStyledText import kotlin.math.max import kotlin.math.min @@ -41,6 +43,7 @@ import kotlin.math.roundToInt * @param shrinkContent Whether the content should be shrunk to fit the available width or not. Defaults to `false`. * @param content The 'content' component of the layout. */ +@Suppress("ContentSlotReused") // Since we added an exception for `LocalUiTestMode`, detekt thinks the layout can change in runtime: it won't @Composable fun ContentAvoidingLayout( overlay: @Composable () -> Unit, @@ -52,6 +55,15 @@ fun ContentAvoidingLayout( ) { val scope = remember { ContentAvoidingLayoutScopeInstance() } + // Custom layouts don't seem to work well with Compose UI tests (they crash), so we use a Column instead when running in test mode. + if (LocalUiTestMode.current) { + Column { + scope.content() + overlay() + } + return + } + Layout( modifier = modifier, content = { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemAudioContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemAudioContentProvider.kt index 9fddfa98ff..3b60a48c78 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemAudioContentProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemAudioContentProvider.kt @@ -19,8 +19,6 @@ open class TimelineItemAudioContentProvider : PreviewParameterProvider null } +fun TimelineItemEventContent.formattedCaptionOrNull(): CharSequence? = when (this) { + is TimelineItemEventContentWithAttachment -> formattedCaption + is TimelineItemGalleryContent -> formattedCaption + is TimelineItemAttachmentsContent -> formattedCaption + else -> null +} + fun TimelineItemEventContentWithAttachment.duration(): Duration? { return when (this) { is TimelineItemAudioContent -> duration @@ -123,3 +133,12 @@ fun TimelineItemEventContentWithAttachment.duration(): Duration? { else -> null } } + +fun TimelineItemEventContentWithAttachment.blurHash(): String? { + return when (this) { + is TimelineItemImageContent -> blurhash + is TimelineItemVideoContent -> blurHash + is TimelineItemStickerContent -> blurhash + else -> null + } +} 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 76502b2975..1d4c7c04ec 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 @@ -135,6 +135,7 @@ fun anAttachmentItem( fileSize: Long? = 1_000_000L, formattedFileSize: String = "1MB", mimeType: String? = null, + mediaSource: MediaSource = MediaSource(url = "", json = ""), thumbnailSource: MediaSource? = null, hasThumbnail: Boolean = false, ) = AttachmentItem( @@ -143,7 +144,7 @@ fun anAttachmentItem( hasThumbnail -> "image/jpeg" else -> "application/$fileExtension" }, - mediaSource = MediaSource(url = "", json = ""), + mediaSource = mediaSource, thumbnailSource = thumbnailSource ?: if (hasThumbnail) MediaSource(url = "", json = "") else null, fileSize = fileSize, formattedFileSize = formattedFileSize, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemFileContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemFileContentProvider.kt index 58e25e5dcd..e2021e9646 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemFileContentProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemFileContentProvider.kt @@ -18,8 +18,6 @@ open class TimelineItemFileContentProvider : PreviewParameterProvider, + val validationState: ContentValidationState, + ) : TimelineProtectionEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenter.kt index b2ea1d6bd8..dc70b63f32 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenter.kt @@ -12,23 +12,28 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.mutableStateSetOf import androidx.compose.runtime.remember import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.SingleIn +import io.element.android.features.contentscanner.api.ContentScannerService import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.mapState +import io.element.android.libraries.di.RoomScope import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.media.MediaPreviewService import io.element.android.libraries.matrix.api.media.isPreviewEnabled import io.element.android.libraries.matrix.api.room.BaseRoom import kotlinx.collections.immutable.toImmutableSet +@SingleIn(RoomScope::class) @Inject class TimelineProtectionPresenter( private val mediaPreviewService: MediaPreviewService, private val room: BaseRoom, + private val contentScannerService: ContentScannerService, ) : Presenter { - private val allowedEvents = mutableStateOf>(setOf()) + private val allowedEvents = mutableStateSetOf() @Composable override fun present(): TimelineProtectionState { @@ -36,13 +41,14 @@ class TimelineProtectionPresenter( mediaPreviewService.mediaPreviewConfigFlow.mapState { config -> config.mediaPreviewValue } }.collectAsState() val roomInfo = room.roomInfoFlow.collectAsState() + val protectionState by remember { derivedStateOf { val isPreviewEnabled = mediaPreviewValue.value.isPreviewEnabled(roomInfo.value.joinRule) if (isPreviewEnabled) { ProtectionState.RenderAll } else { - ProtectionState.RenderOnly(eventIds = allowedEvents.value.toImmutableSet()) + ProtectionState.RenderOnly(eventIds = allowedEvents.toImmutableSet()) } } } @@ -50,7 +56,10 @@ class TimelineProtectionPresenter( fun handleEvent(event: TimelineProtectionEvent) { when (event) { is TimelineProtectionEvent.ShowContent -> { - allowedEvents.value = allowedEvents.value + setOfNotNull(event.eventId) + allowedEvents += setOfNotNull(event.eventId) + } + is TimelineProtectionEvent.ValidateContent -> { + contentScannerService.scan(event.eventId, event.mediaSources, event.validationState) } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/util/AsyncImageStateHandler.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/util/AsyncImageStateHandler.kt new file mode 100644 index 0000000000..546d37de3d --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/util/AsyncImageStateHandler.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.messages.impl.timeline.util + +import coil3.compose.AsyncImagePainter +import io.element.android.libraries.matrix.api.exception.ClientException +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue +import okio.IOException + +fun handleAsyncImageStateChange( + state: AsyncImagePainter.State, + onLoaded: () -> Unit, + updateContentValidationState: ((ContentValidationValue) -> Unit)?, +) { + if (state is AsyncImagePainter.State.Success) { + onLoaded() + } + + val updatedContentValidationValue = when (state) { + is AsyncImagePainter.State.Empty -> ContentValidationValue.Unknown + is AsyncImagePainter.State.Loading -> ContentValidationValue.Loading + is AsyncImagePainter.State.Success -> ContentValidationValue.Valid + is AsyncImagePainter.State.Error -> { + when (val cause = state.result.throwable) { + is ClientException.ContentScanner if cause.reason.isDangerous() -> ContentValidationValue.Invalid + is IOException -> { + // Use `Unknown` instead of `Invalid` to allow retrying the download later + ContentValidationValue.Unknown + } + else -> ContentValidationValue.UnrecoverableError(cause) + } + } + } + + updateContentValidationState?.invoke(updatedContentValidationValue) +} 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 61b1fc8d26..0ac8c3be1f 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 @@ -37,6 +37,7 @@ 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.matrix.ui.media.contentvalidation.InMemoryEventContentValidationCache import io.element.android.libraries.mediapickers.api.PickerProvider import io.element.android.libraries.mediapickers.test.FakePickerProvider import io.element.android.libraries.mediaupload.api.MediaOptimizationConfig @@ -315,6 +316,8 @@ class MessageComposerPresenterSlashCommandTest { notificationConversationService = notificationConversationService, slashCommandService = slashCommandService, featureFlagService = featureFlagService, + contentScannerService = { _, _, _ -> }, + contentValidationCache = InMemoryEventContentValidationCache(), ).apply { isTesting = true showTextFormatting = isRichTextEditorEnabled 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 499e4bf91a..c164a30160 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 @@ -75,6 +75,7 @@ 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 +import io.element.android.libraries.matrix.ui.media.contentvalidation.InMemoryEventContentValidationCache import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails import io.element.android.libraries.mediapickers.api.PickerProvider import io.element.android.libraries.mediapickers.test.FakePickerProvider @@ -1649,6 +1650,8 @@ class MessageComposerPresenterTest : RobolectricTest() { notificationConversationService = notificationConversationService, slashCommandService = slashCommandService, featureFlagService = featureFlagService, + contentScannerService = { _, _, _ -> }, + contentValidationCache = InMemoryEventContentValidationCache(), ).apply { isTesting = true showTextFormatting = isRichTextEditorEnabled 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 a8be3f3836..3b0794305f 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 @@ -19,6 +19,8 @@ import io.element.android.features.messages.impl.timeline.components.MessageShie import io.element.android.features.messages.impl.timeline.components.aCriticalShield 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.protection.TimelineProtectionState +import io.element.android.features.messages.impl.timeline.protection.aTimelineProtectionState import io.element.android.features.messages.impl.typing.aTypingNotificationState import io.element.android.features.messages.impl.voicemessages.timeline.FakeRedactedVoiceMessageManager import io.element.android.features.messages.impl.voicemessages.timeline.RedactedVoiceMessageManager @@ -28,6 +30,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.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.core.EventId @@ -1585,6 +1588,7 @@ class TimelinePresenterTest { featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService(), liveLocationShareManager: FakeActiveLiveLocationShareManager = FakeActiveLiveLocationShareManager(), markAsFullyRead: MarkAsFullyRead = FakeMarkAsFullyRead { _, _ -> }, + timelineProtectionPresenter: Presenter = { aTimelineProtectionState() }, ): TimelinePresenter { return TimelinePresenter( timelineItemsFactoryCreator = aTimelineItemsFactoryCreator(), @@ -1605,6 +1609,7 @@ class TimelinePresenterTest { analyticsService = FakeAnalyticsService(), liveLocationShareManager = liveLocationShareManager, markAsFullyRead = markAsFullyRead, + timelineProtectionPresenter = timelineProtectionPresenter, ) } } 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 dc63817e99..6348d9b115 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 @@ -21,7 +21,7 @@ import androidx.compose.ui.test.v2.runAndroidComposeUiTest 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.TimelineItem -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.aTimelineItemUnknownContent import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemLoadingIndicatorModel import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionState @@ -67,7 +67,7 @@ class TimelineViewTest : RobolectricTest() { val eventsRecorder = EventsRecorder() setTimelineView( state = aTimelineState( - timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemImageContent())), + timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemTextContent())), eventSink = eventsRecorder, ), ) @@ -79,7 +79,7 @@ class TimelineViewTest : RobolectricTest() { val eventsRecorder = EventsRecorder() setTimelineView( state = aTimelineState( - timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemImageContent())), + timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemTextContent())), isLive = true, eventSink = eventsRecorder, ), @@ -98,7 +98,7 @@ class TimelineViewTest : RobolectricTest() { val eventsRecorder = EventsRecorder() setTimelineView( state = aTimelineState( - timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemImageContent())), + timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemTextContent())), isLive = false, eventSink = eventsRecorder, ), @@ -133,7 +133,7 @@ class TimelineViewTest : RobolectricTest() { timelineItems = persistentListOf( aTimelineItemEvent( // Do not use a Text because EditorStyledText cannot be used in UI test. - content = aTimelineItemImageContent(), + content = aTimelineItemTextContent(), messageShield = MessageShield.UnverifiedIdentity(true), ), ), @@ -155,7 +155,7 @@ class TimelineViewTest : RobolectricTest() { val eventsRecorder = EventsRecorder() setTimelineView( state = aTimelineState( - timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemImageContent())), + timelineItems = persistentListOf(aTimelineItemEvent(content = aTimelineItemTextContent())), isLive = false, eventSink = eventsRecorder, messageShield = aCriticalShield(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenterTest.kt index d6af8ebd68..11093bd74f 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenterTest.kt @@ -9,19 +9,28 @@ package io.element.android.features.messages.impl.timeline.protection import com.google.common.truth.Truth.assertThat +import io.element.android.features.contentscanner.api.ContentScannerService +import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.media.MediaPreviewConfig import io.element.android.libraries.matrix.api.media.MediaPreviewService import io.element.android.libraries.matrix.api.media.MediaPreviewValue +import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.media.FakeMediaPreviewService import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.aRoomInfo +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue +import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.test import kotlinx.collections.immutable.persistentSetOf +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -87,11 +96,49 @@ class TimelineProtectionPresenterTest { } } + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `present - validate media scans the media source`() = runTest { + val url = "https://example.com/media" + + val mediaPreviewConfig = MediaPreviewConfig(mediaPreviewValue = MediaPreviewValue.Private, hideInviteAvatar = false) + val mediaPreviewService = FakeMediaPreviewService(mediaPreviewConfigFlow = MutableStateFlow(mediaPreviewConfig)) + val room = FakeBaseRoom(initialRoomInfo = aRoomInfo(joinRule = JoinRule.Invite), roomCoroutineScope = backgroundScope) + val contentScannerService = lambdaRecorder { _: EventId, _: List, state: ContentValidationState -> + state.update(url, ContentValidationValue.Valid) + } + val presenter = createPresenter( + mediaPreviewService = mediaPreviewService, + room = room, + contentScannerService = contentScannerService, + ) + presenter.test { + val validationState = DefaultContentValidationState(initial = mapOf(url to ContentValidationValue.Unknown)) + assertThat(validationState.getCurrentOverallState().isValid()).isFalse() + + val initialState = awaitItem() + initialState.eventSink( + TimelineProtectionEvent.ValidateContent( + eventId = AN_EVENT_ID, + mediaSources = listOf(MediaSource(url)), + validationState = validationState + ) + ) + + runCurrent() + + contentScannerService.assertions().isCalledOnce() + assertThat(validationState.getCurrentOverallState().isValid()).isTrue() + } + } + private fun createPresenter( room: BaseRoom = FakeBaseRoom(), mediaPreviewService: MediaPreviewService = FakeMediaPreviewService(), + contentScannerService: ContentScannerService = ContentScannerService { _: EventId, _: List, _: ContentValidationState -> }, ) = TimelineProtectionPresenter( mediaPreviewService = mediaPreviewService, room = room, + contentScannerService = contentScannerService, ) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/util/AsyncImageStateHandlerTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/util/AsyncImageStateHandlerTest.kt new file mode 100644 index 0000000000..c4861ba57b --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/util/AsyncImageStateHandlerTest.kt @@ -0,0 +1,104 @@ +/* + * 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.util + +import androidx.compose.ui.graphics.painter.Painter +import coil3.compose.AsyncImagePainter +import coil3.request.ErrorResult +import coil3.request.SuccessResult +import io.element.android.libraries.matrix.api.exception.ClientException +import io.element.android.libraries.matrix.api.exception.ContentScannerErrorReason +import io.element.android.libraries.matrix.api.exception.ContentScannerErrorReason.MCS_MEDIA_NOT_CLEAN +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.lambda.value +import io.mockk.mockk +import org.junit.Test +import java.io.FileNotFoundException + +class AsyncImageStateHandlerTest { + @Test + fun `test Empty state sets the content validation state to Unknown`() { + val updateContentValidationState = lambdaRecorder {} + handleAsyncImageStateChange( + state = AsyncImagePainter.State.Empty, + onLoaded = {}, + updateContentValidationState = updateContentValidationState, + ) + + updateContentValidationState.assertions().isCalledOnce().with(value(ContentValidationValue.Unknown)) + } + + @Test + fun `test Loading state sets the content validation state to Loading`() { + val updateContentValidationState = lambdaRecorder {} + handleAsyncImageStateChange( + state = AsyncImagePainter.State.Loading(null), + onLoaded = {}, + updateContentValidationState = updateContentValidationState, + ) + + updateContentValidationState.assertions().isCalledOnce().with(value(ContentValidationValue.Loading)) + } + + @Test + fun `test Success state sets the content validation state to Valid and triggers onLoaded callback`() { + val updateContentValidationState = lambdaRecorder {} + val onLoaded = lambdaRecorder {} + handleAsyncImageStateChange( + state = AsyncImagePainter.State.Success(mockk(), SuccessResult(mockk(), mockk())), + onLoaded = onLoaded, + updateContentValidationState = updateContentValidationState, + ) + + onLoaded.assertions().isCalledOnce() + updateContentValidationState.assertions().isCalledOnce().with(value(ContentValidationValue.Valid)) + } + + @Test + fun `test Failure state sets the content validation state to Invalid if the error matches`() { + val updateContentValidationState = lambdaRecorder {} + val onLoaded = lambdaRecorder {} + val mediaNotCleanError = ClientException.ContentScanner("dangerous", MCS_MEDIA_NOT_CLEAN) + val forbiddenMimeTypeError = ClientException.ContentScanner("dangerous", ContentScannerErrorReason.MCS_MIME_TYPE_FORBIDDEN) + handleAsyncImageStateChange( + state = AsyncImagePainter.State.Error(null, ErrorResult(null, mockk(), mediaNotCleanError)), + onLoaded = onLoaded, + updateContentValidationState = updateContentValidationState, + ) + + handleAsyncImageStateChange( + state = AsyncImagePainter.State.Error(null, ErrorResult(null, mockk(), forbiddenMimeTypeError)), + onLoaded = onLoaded, + updateContentValidationState = updateContentValidationState, + ) + + onLoaded.assertions().isNeverCalled() + updateContentValidationState.assertions() + .isCalledExactly(2) + .withSequence( + listOf(value(ContentValidationValue.Invalid)), + listOf(value(ContentValidationValue.Invalid)) + ) + } + + @Test + fun `test Failure state sets the content validation state to Uknown if the error does not match a content scanner one`() { + val updateContentValidationState = lambdaRecorder {} + val onLoaded = lambdaRecorder {} + val error = FileNotFoundException("File not found") + handleAsyncImageStateChange( + state = AsyncImagePainter.State.Error(null, ErrorResult(null, mockk(), error)), + onLoaded = onLoaded, + updateContentValidationState = updateContentValidationState, + ) + + onLoaded.assertions().isNeverCalled() + updateContentValidationState.assertions().isCalledOnce().with(value(ContentValidationValue.Unknown)) + } +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/EqualWidthColumn.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/EqualWidthColumn.kt index 14fd284067..576ab07532 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/EqualWidthColumn.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/EqualWidthColumn.kt @@ -29,21 +29,32 @@ fun EqualWidthColumn( ) { SubcomposeLayout(modifier = modifier) { constraints -> val measurables = subcompose(0, content).map { it.measure(constraints) } - val maxWidth = measurables.maxOf { it.width } - val newConstraints = constraints.copy(minWidth = maxWidth) - val newMeasurables = if (measurables.all { it.width == maxWidth }) { - // Skip re-measuring if all children have the same width - measurables + if (measurables.isEmpty()) { + // No children, so just return a layout with 0 width and height + layout(0, 0) {} + } else if (measurables.size == 1) { + // No need to re-measure if there's only one child + val measurable = measurables.first() + layout(measurable.width, measurable.height) { + measurable.placeRelative(0, 0) + } } else { - // Re-measure with the largest width as the minWidth to have all children constrained to the same width - subcompose(1, content).map { it.measure(newConstraints) } - } - val totalHeight = (newMeasurables.sumOf { it.height } + spacing.toPx() * (newMeasurables.size - 1)).roundToInt() - layout(maxWidth, totalHeight) { - var yPosition = 0 - newMeasurables.forEach { measurable -> - measurable.placeRelative(0, yPosition) - yPosition += measurable.height + spacing.roundToPx() + val maxWidth = measurables.maxOf { it.width } + val newConstraints = constraints.copy(minWidth = maxWidth) + val newMeasurables = if (measurables.all { it.width == maxWidth }) { + // Skip re-measuring if all children have the same width + measurables + } else { + // Re-measure with the largest width as the minWidth to have all children constrained to the same width + subcompose(1, content).map { it.measure(newConstraints) } + } + val totalHeight = (newMeasurables.sumOf { it.height } + spacing.toPx() * (newMeasurables.size - 1)).roundToInt() + layout(maxWidth, totalHeight) { + var yPosition = 0 + newMeasurables.forEach { measurable -> + measurable.placeRelative(0, yPosition) + yPosition += measurable.height + spacing.roundToPx() + } } } } 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 f323b316f7..b1501601d9 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 @@ -124,3 +124,34 @@ data class CallNotifyContent( ) : EventContent data object UnknownContent : EventContent + +fun EventContent.isMediaContent(): Boolean { + return when (this) { + is MessageContent -> type is MessageTypeWithAttachment || type is GalleryMessageType + is StickerContent -> true + else -> false + } +} + +fun EventContent.mediaSources(): List { + return when (this) { + is MessageContent -> mediaSources() + is StickerContent -> listOfNotNull(source, info.thumbnailSource) + else -> emptyList() + } +} + +fun MessageContent.mediaSources(): List { + return when (val messageType = type) { + is MessageTypeWithAttachment -> when (messageType) { + is ImageMessageType -> listOfNotNull(messageType.source, messageType.info?.thumbnailSource) + is VideoMessageType -> listOfNotNull(messageType.source, messageType.info?.thumbnailSource) + is AudioMessageType -> listOf(messageType.source) + is VoiceMessageType -> listOf(messageType.source) + is FileMessageType -> listOfNotNull(messageType.source, messageType.info?.thumbnailSource) + else -> emptyList() + } + is GalleryMessageType -> messageType.items.flatMap { it.mediaSources() } + else -> emptyList() + } +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageType.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageType.kt index fdc538ec44..2f61b8f58a 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageType.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/MessageType.kt @@ -115,6 +115,14 @@ sealed interface GalleryItemType { data class Video(val content: VideoMessageType) : GalleryItemType data class File(val content: FileMessageType) : GalleryItemType data class Other(val itemType: String, val body: String) : GalleryItemType + + fun mediaSources(): List = when (this) { + is Image -> listOfNotNull(content.source, content.info?.thumbnailSource) + is Audio -> listOf(content.source) + is Video -> listOfNotNull(content.source, content.info?.thumbnailSource) + is File -> listOfNotNull(content.source, content.info?.thumbnailSource) + is Other -> emptyList() + } } data class OtherMessageType( diff --git a/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt b/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt index 713057ecda..d31b5671eb 100644 --- a/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt +++ b/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/CoilMediaFetcher.kt @@ -40,7 +40,7 @@ internal class CoilMediaFetcher( onSuccess = { it }, onFailure = { error -> if (error.isNetworkError()) { - null + throw error } else { fetchContent(mediaSource) } @@ -73,7 +73,7 @@ internal class CoilMediaFetcher( .onFailure { Timber.e(it) } - .getOrNull() + .getOrThrow() } private suspend fun fetchContent(mediaSource: MediaSource): FetchResult? { @@ -83,7 +83,7 @@ internal class CoilMediaFetcher( byteArray.asSourceResult() }.onFailure { Timber.e(it) - }.getOrNull() + }.getOrThrow() } private suspend fun fetchThumbnail(mediaSource: MediaSource, kind: MediaRequestData.Kind.Thumbnail): Result { diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentErrorView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentErrorView.kt new file mode 100644 index 0000000000..85753246d3 --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentErrorView.kt @@ -0,0 +1,93 @@ +/* + * 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.ui.media.contentvalidation + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +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.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.movableContentOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.TextLayoutResult +import androidx.compose.ui.text.rememberTextMeasurer +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 + +@Composable +internal fun ContentErrorView( + title: String, + message: String, + modifier: Modifier = Modifier, + contentPadding: PaddingValues = PaddingValues.Zero, + onTextLayout: ((TextLayoutResult) -> Unit)? = null, +) { + val updatedOnTextLayout by rememberUpdatedState(onTextLayout) + Row( + modifier = modifier + .background(color = ElementTheme.colors.bgCriticalSubtle) + .padding(contentPadding), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier.size(24.dp), + imageVector = CompoundIcons.Error(), + contentDescription = null, + tint = ElementTheme.colors.iconCriticalPrimary + ) + Column(Modifier.weight(1f)) { + Text( + text = title, + color = ElementTheme.colors.textCriticalPrimary, + style = ElementTheme.typography.fontBodyMdMedium, + ) + val textMeasurer = rememberTextMeasurer() + val textContent = remember(message) { + movableContentOf( + @Composable { + Text( + text = message, + color = ElementTheme.colors.textSecondary, + style = ElementTheme.typography.fontBodySmRegular, + ) + } + ) + } + + // BoxWithConstraints is needed to be able to calculate the text layout in the current constraints, so we can pass it to the onTextLayout callback. + // However, this can't be used inside a SubComposeLayout (like the one in the text composer), so we only use it when the onTextLayout callback + // is provided. + if (updatedOnTextLayout != null) { + BoxWithConstraints(modifier = Modifier.fillMaxWidth()) { + LaunchedEffect(message) { + updatedOnTextLayout?.invoke(textMeasurer.measure(message, overflow = TextOverflow.Visible, constraints = constraints)) + } + + textContent() + } + } else { + textContent() + } + } + } +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentValidationState.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentValidationState.kt new file mode 100644 index 0000000000..c0afa69d1a --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentValidationState.kt @@ -0,0 +1,197 @@ +/* + * 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.ui.media.contentvalidation + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.State +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.produceState +import androidx.compose.runtime.remember +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.mapLatest +import kotlinx.coroutines.flow.update + +/** + * Wrapper for the content validation state of an event. + * + * It can be used to check the overall validation state of the event, as well as the validation state of each media item in it. + */ +@Immutable +interface ContentValidationState { + /** + * A flow that emits the overall validation state of the event, which is an aggregation of the different media values. + */ + val overallStateFlow: Flow + + /** + * Returns a flow that emits the validation state of a specific media item, identified by its URL. + */ + fun getMediaStateFlow(url: String): Flow + + /** + * Returns the current overall validation state of the event. + */ + fun getCurrentOverallState(): ContentValidationValue + + /** + * Returns the current validation state of a specific media item, identified by its URL. + */ + fun getCurrentMediaState(url: String): ContentValidationValue + + /** + * Updates the validation state of a specific media item, identified by its URL, with a new [ContentValidationValue]. + */ + fun update(url: String, newValue: ContentValidationValue) +} + +/** + * A no-op implementation of [ContentValidationState] that always returns a fixed validation state. + * By default, this is [ContentValidationValue.Valid]. + */ +@Immutable +class NoopContentValidationState( + private val initial: ContentValidationValue = ContentValidationValue.Valid, +) : ContentValidationState { + override val overallStateFlow: Flow = MutableStateFlow(initial) + override fun getMediaStateFlow(url: String): Flow = MutableStateFlow(initial) + override fun getCurrentOverallState(): ContentValidationValue = initial + override fun getCurrentMediaState(url: String): ContentValidationValue = initial + override fun update(url: String, newValue: ContentValidationValue) {} +} + +/** + * A default implementation of [ContentValidationState] that tracks the validation state of media items in a mutable map. + * It calculates the overall validation state based on the individual media states. + */ +@Immutable +class DefaultContentValidationState( + private val states: MutableStateFlow>, +) : ContentValidationState { + @OptIn(ExperimentalCoroutinesApi::class) + override val overallStateFlow: Flow = states + .mapLatest { states -> calculateOverallState(states) } + .distinctUntilChanged() + + constructor() : this(states = MutableStateFlow(emptyMap())) + + constructor(initial: Map) : this(states = MutableStateFlow(initial)) + + @OptIn(ExperimentalCoroutinesApi::class) + override fun getMediaStateFlow(url: String): Flow { + return states.map { states -> + states[url] ?: ContentValidationValue.Unknown + }.distinctUntilChanged() + } + + override fun getCurrentOverallState(): ContentValidationValue { + return calculateOverallState(states.value) + } + + override fun getCurrentMediaState(url: String): ContentValidationValue { + return states.value[url] ?: ContentValidationValue.Unknown + } + + override fun update(url: String, newValue: ContentValidationValue) { + states.update { current -> + if (current[url]?.isValidated() == true && newValue.isLoading()) { + // If the current state is already validated and the new value is loading, we keep the current validated state + current + } else { + // Otherwise, we update the state for the given URL with the new value + current + (url to newValue) + } + } + } +} + +private fun calculateOverallState(states: Map): ContentValidationValue { + return when { + states.values.any { it is ContentValidationValue.Invalid } -> ContentValidationValue.Invalid + states.values.any { it is ContentValidationValue.Loading } -> ContentValidationValue.Loading + states.values.any { it is ContentValidationValue.UnrecoverableError } -> states.values.first { it is ContentValidationValue.UnrecoverableError } + states.values.all { it is ContentValidationValue.Valid } -> ContentValidationValue.Valid + else -> ContentValidationValue.Unknown + } +} + +/** + * Represents the validation state of a media item or an event. + */ +@Immutable +sealed interface ContentValidationValue { + /** Indicates that the content is valid. */ + data object Valid : ContentValidationValue + + /** Indicates that the content is invalid/unsafe. */ + data object Invalid : ContentValidationValue + + /** Indicates that the content is currently being validated. */ + data object Loading : ContentValidationValue + + /** Indicates that an unrecoverable error occurred during validation, and it should not be retried. */ + data class UnrecoverableError(val error: Throwable) : ContentValidationValue + + /** Indicates that the validation state is unknown and should be checked. Recoverable errors are also represented with this. */ + data object Unknown : ContentValidationValue + + /** + * Returns true if the validation state is either [Valid], [Invalid], or [UnrecoverableError], meaning that the validation process has completed + * and a definitive result is available. + */ + fun isValidated(): Boolean = when (this) { + is Valid -> true + is Invalid -> true + is Loading -> false + is UnrecoverableError -> true + is Unknown -> false + } + + /** Returns true if the validation state is [Valid]. */ + fun isValid(): Boolean = this is Valid + + /** Returns true if the validation state is [Invalid]. */ + fun isInvalid(): Boolean = this is Invalid + + /** Returns true if the validation state is [Loading]. */ + fun isLoading(): Boolean = this is Loading + + /** Returns true if the validation state is [UnrecoverableError]. */ + fun hasUnrecoverableError(): Boolean = this is UnrecoverableError + + /** Returns true if the validation state is either [Invalid] or [UnrecoverableError]. */ + fun hasError(): Boolean = this is Invalid || this is UnrecoverableError +} + +/** + * Collects the overall validation state of the [ContentValidationState] as a [State] in a Composable context. + */ +@Composable +fun ContentValidationState.collectOverallState(): State { + return produceState(getCurrentOverallState()) { + overallStateFlow.collect { value = it } + } +} + +/** + * Collects the validation state of a specific media item, identified by its URL, as a [State] in a Composable context. + */ +@Composable +fun ContentValidationState.collectMediaState(url: String?): State { + if (url == null) { + return remember { mutableStateOf(ContentValidationValue.Unknown) } + } + + return produceState(getCurrentMediaState(url), key1 = url) { + getMediaStateFlow(url).collect { value = it } + } +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/EventContentValidationCache.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/EventContentValidationCache.kt new file mode 100644 index 0000000000..df7737e5fb --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/EventContentValidationCache.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.ui.media.contentvalidation + +import io.element.android.libraries.matrix.api.core.EventId + +/** + * A cache that holds the validation state of event contents, based on their [EventId]. + */ +interface EventContentValidationCache { + /** + * Returns the [ContentValidationState] for the given [eventId]. If none exists, it creates a new one with [ContentValidationValue.Unknown]. + */ + operator fun get(eventId: EventId): ContentValidationState +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/InMemoryEventContentValidationCache.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/InMemoryEventContentValidationCache.kt new file mode 100644 index 0000000000..999558898a --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/InMemoryEventContentValidationCache.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.matrix.ui.media.contentvalidation + +import io.element.android.libraries.matrix.api.core.EventId + +/** + * In-memory variant of [EventContentValidationCache] that holds the validation state of event contents, based on their [EventId]. + * + * Note: this is intended to be used in tests. + */ +class InMemoryEventContentValidationCache( + initial: Map = emptyMap(), +) : EventContentValidationCache { + private val cache = initial.toMutableMap() + + override operator fun get(eventId: EventId): ContentValidationState { + return cache[eventId] ?: DefaultContentValidationState() + } + + fun put(eventId: EventId, state: ContentValidationState) { + cache[eventId] = state + } +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/InvalidContentView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/InvalidContentView.kt new file mode 100644 index 0000000000..b1e4ffc02a --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/InvalidContentView.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.libraries.matrix.ui.media.contentvalidation + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextLayoutResult +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.ui.strings.CommonStrings + +/** + * A view to display when the media content is invalid or dangerous. + */ +@Composable +fun InvalidContentView( + modifier: Modifier = Modifier, + contentPadding: PaddingValues = PaddingValues.Zero, + onTextLayout: ((TextLayoutResult) -> Unit)? = null, +) { + ContentErrorView( + title = stringResource(CommonStrings.content_scanner_unsafe_title), + message = stringResource(CommonStrings.content_scanner_unsafe_message), + modifier = modifier, + contentPadding = contentPadding, + onTextLayout = onTextLayout, + ) +} + +@PreviewsDayNight +@Composable +internal fun InvalidContentViewPreview() = ElementPreview { + Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { + InvalidContentView() + } +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/LocalEventContentValidationState.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/LocalEventContentValidationState.kt new file mode 100644 index 0000000000..ab7f6da042 --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/LocalEventContentValidationState.kt @@ -0,0 +1,72 @@ +/* + * 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.ui.media.contentvalidation + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.runtime.staticCompositionLocalOf +import io.element.android.libraries.matrix.api.core.EventId +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.StickerContent +import io.element.android.libraries.matrix.api.timeline.item.event.isMediaContent + +private val noopValue = NoopContentValidationState() + +/** + * A composition local that provides an [EventContentValidationCache] instance, so we can check if a given event content has been validated or not. + */ +val LocalEventContentValidationState = staticCompositionLocalOf { NoopEventContentValidationCache() } + +/** + * A noop implementation of the [EventContentValidationCache] that immediately returns a successful validation state. This will be used in FOSS. + */ +class NoopEventContentValidationCache : EventContentValidationCache { + override operator fun get(eventId: EventId): ContentValidationState = noopValue +} + +/** + * A helper to remember the validation state of an event content, based on its [EventId] and [EventContent], if known. + */ +@Composable +fun rememberEventContentValidationState(eventId: EventId?, eventContent: EventContent?): ContentValidationState { + val needsValidation = remember(eventContent) { + when (eventContent) { + is MessageContent -> eventContent.isMediaContent() + is StickerContent -> true + // If the event content is not known or not a media content, we don't need to validate it. + else -> false + } + } + + return rememberEventContentValidationState(eventId, needsValidation) +} + +/** + * A helper to remember the validation state of an event content, based on its [EventId] and whether it needs validation or not. + */ +@Composable +fun rememberEventContentValidationState(eventId: EventId?, needsValidation: Boolean): ContentValidationState { + if (!needsValidation) { + return noopValue + } + + return rememberEventContentValidationStateInternal(eventId) +} + +@Composable +private fun rememberEventContentValidationStateInternal(eventId: EventId?): ContentValidationState { + val cache = LocalEventContentValidationState.current + return remember(eventId) { + if (eventId != null) { + cache[eventId] + } else { + noopValue + } + } +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/NotFoundContentView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/NotFoundContentView.kt new file mode 100644 index 0000000000..019465965c --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/NotFoundContentView.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.libraries.matrix.ui.media.contentvalidation + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextLayoutResult +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.ui.strings.CommonStrings + +/** + * A view to display when the media content can't be fetched. + */ +@Composable +fun NotFoundContentView( + modifier: Modifier = Modifier, + contentPadding: PaddingValues = PaddingValues.Zero, + onTextLayout: ((TextLayoutResult) -> Unit)? = null, +) { + ContentErrorView( + title = stringResource(CommonStrings.content_scanner_not_found_title), + message = stringResource(CommonStrings.content_scanner_not_found), + modifier = modifier, + contentPadding = contentPadding, + onTextLayout = onTextLayout, + ) +} + +@PreviewsDayNight +@Composable +internal fun NotFoundContentViewPreview() = ElementPreview { + Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { + NotFoundContentView() + } +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetails.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetails.kt index 3179c748ea..2105655b01 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetails.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/messages/reply/InReplyToDetails.kt @@ -40,6 +40,12 @@ fun InReplyToDetails.eventId() = when (this) { is InReplyToDetails.Error -> eventId } +fun InReplyToDetails.content() = when (this) { + is InReplyToDetails.Ready -> eventContent + is InReplyToDetails.Loading -> null + is InReplyToDetails.Error -> null +} + fun InReplyTo.map( permalinkParser: PermalinkParser, ) = when (this) { 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 4d0e02aa6f..7ff41abcd3 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 @@ -19,6 +19,7 @@ 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.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -44,6 +45,9 @@ import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails import io.element.android.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue +import io.element.android.libraries.matrix.ui.media.contentvalidation.InvalidContentView +import io.element.android.libraries.matrix.ui.media.contentvalidation.NotFoundContentView import io.element.android.libraries.matrix.ui.messages.sender.SenderName import io.element.android.libraries.matrix.ui.messages.sender.SenderNameMode import io.element.android.libraries.ui.strings.CommonStrings @@ -55,18 +59,22 @@ import io.element.android.libraries.ui.strings.CommonStrings fun InReplyToView( inReplyTo: InReplyToDetails, hideImage: Boolean, + contentValidationValue: ContentValidationValue, modifier: Modifier = Modifier, maxLines: Int = 2, ) { when (inReplyTo) { - is InReplyToDetails.Ready -> { - ReplyToReadyContent( + is InReplyToDetails.Ready -> when (contentValidationValue) { + ContentValidationValue.Valid -> ReplyToReadyContent( senderId = inReplyTo.senderId, senderProfile = inReplyTo.senderProfile, metadata = inReplyTo.metadata(hideImage), maxLines = maxLines, modifier = modifier, ) + ContentValidationValue.Invalid -> ReplyToInvalidContent() + is ContentValidationValue.UnrecoverableError -> ReplyToNotFoundContent() + else -> ReplyToLoadingContent(modifier = modifier) } is InReplyToDetails.Error -> ReplyToErrorContent(data = inReplyTo, maxLines = maxLines, modifier = modifier) @@ -86,7 +94,7 @@ private fun ReplyToReadyContent( val paddings = if (metadata is InReplyToMetadata.Thumbnail) { PaddingValues(end = 8.dp) } else { - PaddingValues(start = 8.dp, end = 8.dp) + PaddingValues(horizontal = 8.dp) } Row( modifier @@ -213,11 +221,50 @@ private fun ReplyToContentText( } } +@Composable +private fun ReplyToInvalidContent( + modifier: Modifier = Modifier +) { + InvalidContentView( + modifier = modifier, + contentPadding = PaddingValues(horizontal = 8.dp), + onTextLayout = null, + ) +} + +@Composable +private fun ReplyToNotFoundContent( + modifier: Modifier = Modifier +) { + NotFoundContentView( + modifier = modifier, + contentPadding = PaddingValues(horizontal = 8.dp), + onTextLayout = null, + ) +} + @PreviewsDayNight @Composable internal fun InReplyToViewPreview(@PreviewParameter(provider = InReplyToDetailsProvider::class) inReplyTo: InReplyToDetails) = ElementPreview { InReplyToView( inReplyTo = inReplyTo, hideImage = false, + contentValidationValue = ContentValidationValue.Valid, ) } + +@PreviewsDayNight +@Composable +internal fun ReplyToInvalidContentPreview() { + ElementPreview { + ReplyToInvalidContent(modifier = Modifier.padding(10.dp)) + } +} + +@PreviewsDayNight +@Composable +internal fun ReplyToNotFoundContentPreview() { + ElementPreview { + ReplyToNotFoundContent(modifier = Modifier.padding(10.dp)) + } +} diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/GalleryItemData.kt b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/GalleryItemData.kt index 3a2f2321db..fb60a7488c 100644 --- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/GalleryItemData.kt +++ b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/GalleryItemData.kt @@ -18,6 +18,7 @@ data class GalleryItemData( val mediaSource: MediaSource, val thumbnailSource: MediaSource?, val type: Type, + val blurHash: String?, ) : Parcelable { enum class Type { Image, diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaViewerEntryPoint.kt b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaViewerEntryPoint.kt index f6de6cf839..7b9f65e60e 100644 --- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaViewerEntryPoint.kt +++ b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaViewerEntryPoint.kt @@ -42,6 +42,7 @@ interface MediaViewerEntryPoint : FeatureEntryPoint { val mediaInfo: MediaInfo, val mediaSource: MediaSource, val thumbnailSource: MediaSource?, + val blurHash: String?, ) : Params data class EventGallery( @@ -55,6 +56,7 @@ interface MediaViewerEntryPoint : FeatureEntryPoint { val avatarInfo: AvatarInfo, val mediaSource: MediaSource, val thumbnailSource: MediaSource?, + val blurHash: String?, ) : Params } 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 10858c76c8..4cbcd75a5e 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 @@ -27,6 +27,8 @@ class DefaultMediaViewerEntryPoint : MediaViewerEntryPoint { ), mediaSource = MediaSource(url = avatarUrl), thumbnailSource = null, + // Maybe add avatar blurhash if available? + blurHash = null, ) } 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 05d5dd4022..f489186ade 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 @@ -116,6 +116,7 @@ class EventItemFactory( ), mediaSource = c.source, thumbnailSource = c.info?.thumbnailSource, + blurHash = c.info?.blurhash, ) } is GalleryItemType.Video -> { @@ -136,6 +137,7 @@ class EventItemFactory( ), mediaSource = c.source, thumbnailSource = c.info?.thumbnailSource, + blurHash = c.info?.blurhash, ) } is GalleryItemType.Audio -> { @@ -242,6 +244,7 @@ class EventItemFactory( ), mediaSource = type.source, thumbnailSource = type.info?.thumbnailSource, + blurHash = type.info?.blurhash, )) is StickerMessageType -> listOf(MediaItem.Image( id = currentTimelineItem.uniqueId, @@ -264,6 +267,7 @@ class EventItemFactory( ), mediaSource = type.source, thumbnailSource = type.info?.thumbnailSource, + blurHash = type.info?.blurhash, )) is VideoMessageType -> listOf(MediaItem.Video( id = currentTimelineItem.uniqueId, @@ -286,6 +290,7 @@ class EventItemFactory( ), mediaSource = type.source, thumbnailSource = type.info?.thumbnailSource, + blurHash = type.info?.blurhash, )) is VoiceMessageType -> listOf(MediaItem.Voice( id = currentTimelineItem.uniqueId, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/root/MediaGalleryFlowNode.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/root/MediaGalleryFlowNode.kt index 611d619d52..957f0011d3 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/root/MediaGalleryFlowNode.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/root/MediaGalleryFlowNode.kt @@ -34,6 +34,7 @@ import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint import io.element.android.libraries.mediaviewer.impl.gallery.MediaGalleryNode import io.element.android.libraries.mediaviewer.impl.model.MediaItem +import io.element.android.libraries.mediaviewer.impl.model.blurHash import io.element.android.libraries.mediaviewer.impl.model.eventId import io.element.android.libraries.mediaviewer.impl.model.mediaInfo import io.element.android.libraries.mediaviewer.impl.model.mediaSource @@ -68,6 +69,7 @@ class MediaGalleryFlowNode( val mediaInfo: MediaInfo, val mediaSource: MediaSource, val thumbnailSource: MediaSource?, + val blurHash: String?, ) : NavTarget } @@ -104,6 +106,7 @@ class MediaGalleryFlowNode( mediaInfo = item.mediaInfo(), mediaSource = item.mediaSource(), thumbnailSource = item.thumbnailSource(), + blurHash = item.blurHash(), ) ) } @@ -134,6 +137,7 @@ class MediaGalleryFlowNode( mediaInfo = navTarget.mediaInfo, mediaSource = navTarget.mediaSource, thumbnailSource = navTarget.thumbnailSource, + blurHash = navTarget.blurHash, ), callback = callback, ) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/VideoItemView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/VideoItemView.kt index 7d9e634687..3aad3f1061 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/VideoItemView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/VideoItemView.kt @@ -34,6 +34,7 @@ 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.libraries.designsystem.components.blurhash.blurHashBackground import io.element.android.libraries.designsystem.modifiers.onKeyboardContextMenuAction import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -51,6 +52,7 @@ fun VideoItemView( ) { Box( modifier = modifier + .blurHashBackground(blurHash = video.blurHash) .aspectRatio(1f) .combinedClickable( onClick = onClick, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItem.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItem.kt index 90708db802..5a0b56a9b7 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItem.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItem.kt @@ -35,6 +35,7 @@ sealed interface MediaItem { val mediaInfo: MediaInfo, val mediaSource: MediaSource, val thumbnailSource: MediaSource?, + val blurHash: String?, ) : Event { val thumbnailMediaRequestData: MediaRequestData get() = MediaRequestData(thumbnailSource ?: mediaSource, MediaRequestData.Kind.Thumbnail(100)) @@ -46,6 +47,7 @@ sealed interface MediaItem { val mediaInfo: MediaInfo, val mediaSource: MediaSource, val thumbnailSource: MediaSource?, + val blurHash: String?, ) : Event { val thumbnailMediaRequestData: MediaRequestData get() = MediaRequestData(thumbnailSource ?: mediaSource, MediaRequestData.Kind.Thumbnail(100)) @@ -124,3 +126,11 @@ fun MediaItem.Event.thumbnailSource(): MediaSource? { is MediaItem.Voice -> null } } + +fun MediaItem.Event.blurHash(): String? { + return when (this) { + is MediaItem.Image -> blurHash + is MediaItem.Video -> blurHash + else -> null + } +} diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItemFactories.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItemFactories.kt index be73787828..96059cfd1f 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItemFactories.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItemFactories.kt @@ -34,6 +34,7 @@ fun aMediaItemImage( ), mediaSource = MediaSource(mediaSourceUrl), thumbnailSource = null, + blurHash = null, ) } @@ -50,6 +51,7 @@ fun aMediaItemVideo( ), mediaSource = mediaSource, thumbnailSource = null, + blurHash = null, ) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSource.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSource.kt index 2dfb11a89f..d254985ebf 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSource.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSource.kt @@ -63,6 +63,7 @@ class GalleryMediaGalleryDataSource( mediaInfo = itemMediaInfo, mediaSource = galleryItem.mediaSource, thumbnailSource = galleryItem.thumbnailSource, + blurHash = galleryItem.blurHash, ) GalleryItemData.Type.Audio -> MediaItem.Audio( id = id, @@ -82,6 +83,7 @@ class GalleryMediaGalleryDataSource( mediaInfo = itemMediaInfo, mediaSource = galleryItem.mediaSource, thumbnailSource = galleryItem.thumbnailSource, + blurHash = galleryItem.blurHash, ) } mixedItems.add(mediaItem) 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 6809f6b685..f347e8181f 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 @@ -63,6 +63,7 @@ class SingleMediaGalleryDataSource( ), mediaSource = params.mediaSource, thumbnailSource = params.thumbnailSource, + blurHash = params.blurHash, ) ), fileItems = persistentListOf(), @@ -79,6 +80,7 @@ fun MediaViewerEntryPoint.Params.RoomMedia.toMediaItem() = when { mediaInfo = mediaInfo, mediaSource = mediaSource, thumbnailSource = thumbnailSource, + blurHash = blurHash, ) } mediaInfo.mimeType.isMimeTypeVideo() -> { @@ -88,6 +90,7 @@ fun MediaViewerEntryPoint.Params.RoomMedia.toMediaItem() = when { mediaInfo = mediaInfo, mediaSource = mediaSource, thumbnailSource = thumbnailSource, + blurHash = blurHash, ) } mediaInfo.mimeType.isMimeTypeAudio() -> { 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 9cd134b843..0c2e36903c 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 @@ -141,6 +141,7 @@ class DefaultMediaViewerEntryPointTest { avatarInfo = AvatarInfo(filename = "avatar.png"), mediaSource = MediaSource(url = "avatarUrl"), thumbnailSource = null, + blurHash = null, ) ) assertThat(result.plugins).contains(callback) diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactoryTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactoryTest.kt index 7d0018f120..7147e74e72 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactoryTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactoryTest.kt @@ -226,6 +226,7 @@ class EventItemFactoryTest { ), mediaSource = MediaSource(""), thumbnailSource = null, + blurHash = null, ) ) } @@ -326,6 +327,7 @@ class EventItemFactoryTest { ), mediaSource = MediaSource(""), thumbnailSource = null, + blurHash = null, ) ) } @@ -437,6 +439,7 @@ class EventItemFactoryTest { ), mediaSource = MediaSource("image_url"), thumbnailSource = MediaSource("thumbnail_url"), + blurHash = null, ) ) } @@ -498,6 +501,7 @@ class EventItemFactoryTest { ), mediaSource = MediaSource("video_url"), thumbnailSource = MediaSource("thumbnail_url"), + blurHash = null, ) ) } @@ -744,6 +748,7 @@ class EventItemFactoryTest { ), mediaSource = MediaSource(""), thumbnailSource = null, + blurHash = null, ) ) } 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 88aefb842c..a5151f3b68 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 @@ -249,6 +249,7 @@ class TimelineMediaGalleryDataSourceTest { ), mediaSource = MediaSource("url"), thumbnailSource = MediaSource("url_thumbnail"), + blurHash = A_BLUR_HASH, ) ), fileItems = persistentListOf() diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSourceTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSourceTest.kt index 710aaff1ab..670dfd6242 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSourceTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSourceTest.kt @@ -91,6 +91,7 @@ class GalleryMediaGalleryDataSourceTest { mediaSource = MediaSource("image_url"), thumbnailSource = MediaSource("thumbnail_url"), type = GalleryItemData.Type.Image, + blurHash = null, ) ), galleryInfo = aGalleryInfo(), @@ -104,6 +105,7 @@ class GalleryMediaGalleryDataSourceTest { mediaInfo = expectedMediaInfo("image.jpg", MimeTypes.Jpeg), mediaSource = MediaSource("image_url"), thumbnailSource = MediaSource("thumbnail_url"), + blurHash = null, ) ) } @@ -119,6 +121,7 @@ class GalleryMediaGalleryDataSourceTest { mediaSource = MediaSource("video_url"), thumbnailSource = MediaSource("thumbnail_url"), type = GalleryItemData.Type.Video, + blurHash = null, ) ), galleryInfo = aGalleryInfo(), @@ -132,6 +135,7 @@ class GalleryMediaGalleryDataSourceTest { mediaInfo = expectedMediaInfo("video.mp4", MimeTypes.Mp4), mediaSource = MediaSource("video_url"), thumbnailSource = MediaSource("thumbnail_url"), + blurHash = null, ) ) } @@ -147,6 +151,7 @@ class GalleryMediaGalleryDataSourceTest { mediaSource = MediaSource("audio_url"), thumbnailSource = null, type = GalleryItemData.Type.Audio, + blurHash = null, ) ), galleryInfo = aGalleryInfo(), @@ -174,6 +179,7 @@ class GalleryMediaGalleryDataSourceTest { mediaSource = MediaSource("file_url"), thumbnailSource = null, type = GalleryItemData.Type.File, + blurHash = null, ) ), galleryInfo = aGalleryInfo(), @@ -201,6 +207,7 @@ class GalleryMediaGalleryDataSourceTest { mediaSource = MediaSource("image_url"), thumbnailSource = null, type = GalleryItemData.Type.Image, + blurHash = null, ) ), galleryInfo = aGalleryInfo(), @@ -222,6 +229,7 @@ class GalleryMediaGalleryDataSourceTest { mediaSource = MediaSource("image_url"), thumbnailSource = null, type = GalleryItemData.Type.Image, + blurHash = null, ), GalleryItemData( filename = "document.pdf", @@ -229,6 +237,7 @@ class GalleryMediaGalleryDataSourceTest { mediaSource = MediaSource("file_url"), thumbnailSource = null, type = GalleryItemData.Type.File, + blurHash = null, ), GalleryItemData( filename = "video.mp4", @@ -236,6 +245,7 @@ class GalleryMediaGalleryDataSourceTest { mediaSource = MediaSource("video_url"), thumbnailSource = null, type = GalleryItemData.Type.Video, + blurHash = null, ), ), galleryInfo = aGalleryInfo(), 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 f917e8e0d1..b25b8577ee 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 @@ -114,6 +114,7 @@ class MediaViewerPresenterTest { avatarInfo = AvatarInfo(filename = "avatar.png"), mediaSource = aMediaSource(), thumbnailSource = null, + blurHash = null, ), room = FakeJoinedRoom( baseRoom = FakeBaseRoom( @@ -983,4 +984,5 @@ internal fun createMediaViewerEntryPointParams( mediaInfo = TESTED_MEDIA_INFO, mediaSource = aMediaSource(), thumbnailSource = null, + blurHash = null, ) 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 a869690907..ad44d1b372 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 @@ -89,6 +89,7 @@ class SingleMediaGalleryDataSourceTest { mediaInfo = params.mediaInfo, mediaSource = params.mediaSource, thumbnailSource = params.thumbnailSource, + blurHash = null, ) } ) @@ -105,6 +106,7 @@ class SingleMediaGalleryDataSourceTest { mediaInfo = params.mediaInfo, mediaSource = params.mediaSource, thumbnailSource = params.thumbnailSource, + blurHash = null, ) } ) @@ -175,5 +177,6 @@ class SingleMediaGalleryDataSourceTest { mediaInfo = mediaInfo, mediaSource = aMediaSource(url = "aUrl"), thumbnailSource = aMediaSource(url = "aThumbnailUrl"), + blurHash = null, ) } 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 039f516547..9b2260d441 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 @@ -13,6 +13,7 @@ import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -20,6 +21,7 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ripple import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -35,8 +37,11 @@ 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.Text +import io.element.android.libraries.matrix.ui.media.contentvalidation.collectOverallState +import io.element.android.libraries.matrix.ui.media.contentvalidation.rememberEventContentValidationState import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails import io.element.android.libraries.matrix.ui.messages.reply.InReplyToView +import io.element.android.libraries.matrix.ui.messages.reply.eventId import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.libraries.ui.strings.CommonStrings @@ -134,28 +139,44 @@ private fun ReplyToModeView( onResetComposerMode: () -> Unit, modifier: Modifier = Modifier, ) { - Row( + val shape = RoundedCornerShape(6.dp) + val contentValidationState = rememberEventContentValidationState(replyToDetails.eventId(), (replyToDetails as? InReplyToDetails.Ready)?.eventContent) + val currentValidationState by contentValidationState.collectOverallState() + + val contentHasErrors = currentValidationState.hasError() + + Box( modifier - .clip(RoundedCornerShape(6.dp)) - .background(ElementTheme.colors.bgCanvasDefault) - .border(1.dp, ElementTheme.colors.separatorPrimary, RoundedCornerShape(6.dp)) + .clip(shape) + .background( + color = if (contentHasErrors) ElementTheme.colors.bgCriticalSubtle else ElementTheme.colors.bgCanvasDefault, + shape = shape, + ) + .border( + width = 1.dp, + color = if (contentHasErrors) ElementTheme.colors.borderCriticalSubtle else ElementTheme.colors.separatorPrimary, + shape = shape, + ) .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, + contentValidationValue = currentValidationState, maxLines = maxReplyContentLines, - modifier = Modifier.weight(1f), + modifier = Modifier.fillMaxWidth(), ) Icon( imageVector = CompoundIcons.Close(), contentDescription = stringResource(CommonStrings.action_close), - tint = ElementTheme.colors.iconSecondary, + tint = if (contentHasErrors) ElementTheme.colors.iconCriticalPrimary else ElementTheme.colors.iconSecondary, modifier = Modifier + .align(Alignment.TopEnd) .padding(end = 4.dp, top = 4.dp, start = 8.dp, bottom = 16.dp) .size(16.dp) .clickable( diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistArchitectureTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistArchitectureTest.kt index fe303f360c..c0e62482fa 100644 --- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistArchitectureTest.kt +++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistArchitectureTest.kt @@ -34,6 +34,7 @@ class KonsistArchitectureTest { .classes() .withNameEndingWith("State") .withoutName( + "NoopContentValidationState", "CameraPositionState", "CustomSheetState", ) 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 8a088e8e93..97def07130 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 @@ -145,7 +145,8 @@ class KonsistPreviewTest { "TextComposerVoiceNotEncryptedPreview", "TextComposerVoicePreview", "TextFieldDialogWithErrorPreview", - "TimelineImageWithCaptionRowPreview", + "TimelineItemAttachmentsViewScanningContentFailedPreview", + "TimelineItemAudioViewScanningContentPreview", "TimelineItemEventRowForDirectRoomPreview", "TimelineItemEventRowShieldPreview", "TimelineItemEventRowTimestampPreview", @@ -155,13 +156,21 @@ class KonsistPreviewTest { "TimelineItemEventRowWithRRPreview", "TimelineItemEventRowWithReplyPreview", "TimelineItemEventRowWithThreadSummaryPreview", + "TimelineItemFileViewScanningContentPreview", + "TimelineItemGalleryViewScanningContentFailedPreview", "TimelineItemGroupedEventsRowContentCollapsePreview", "TimelineItemGroupedEventsRowContentExpandedPreview", "TimelineItemImageViewHideMediaContentPreview", + "TimelineItemImageViewScanningContentPreview", "TimelineItemRedactedMessagesGroupPreview", + "TimelineItemScanningContentFailedPreview", + "TimelineItemScanningContentWithInvalidRepliesPreview", + "TimelineItemScanningContentWithRepliesFailedPreview", + "TimelineItemStickerViewScanningContentPreview", "TimelineItemVideoViewHideMediaContentPreview", + "TimelineItemVideoViewScanningContentPreview", + "TimelineItemVoiceViewScanningContentPreview", "TimelineItemVoiceViewUnifiedPreview", - "TimelineVideoWithCaptionRowPreview", "TimelineViewMessageShieldPreview", "TimelineViewWithReadMarkerBothIndicatorsPreview", "TimelineViewWithReadMarkerJumpToUnreadIndicatorOnlyPreview", diff --git a/tests/uitests/src/test/kotlin/base/ScreenshotTest.kt b/tests/uitests/src/test/kotlin/base/ScreenshotTest.kt index e9bd34d10e..971783cd63 100644 --- a/tests/uitests/src/test/kotlin/base/ScreenshotTest.kt +++ b/tests/uitests/src/test/kotlin/base/ScreenshotTest.kt @@ -26,6 +26,8 @@ import com.android.resources.Density.DEFAULT_DENSITY import com.android.resources.NightMode import com.android.resources.ScreenOrientation import io.element.android.compound.theme.ElementTheme +import io.element.android.libraries.matrix.ui.media.contentvalidation.LocalEventContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopEventContentValidationCache import sergio.sastre.composable.preview.scanner.android.AndroidPreviewInfo import sergio.sastre.composable.preview.scanner.core.preview.ComposablePreview import java.util.Locale @@ -55,6 +57,7 @@ object ScreenshotTest { setLocales(LocaleList(locale)) uiMode = preview.previewInfo.uiMode }, + LocalEventContentValidationState provides NoopEventContentValidationCache(), ) { ElementTheme { Box( diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png index 912b90b537..a2b35f18ca 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4746d11c30648f7c517b0880021e5a1dc6ed2819af6c800b081b0d842ac2c384 -size 5325 +oid sha256:c5572491b675a16724cd9e33ebb477c82edf285fa07d57ebef09c670fcaaddf1 +size 21285 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png index 45011fea4d..9c425cec6e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eede6f990a7a1dbddee1cd9e722b30600160d475ad2ae72faebcb773f52aaa7b -size 20793 +oid sha256:290a2be6838445739b0181006f9fea87337a85cfed3573c153e9f503c66624a6 +size 4994 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 index 08169845d5..12bd190dd1 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86eac241e9084cc830ff13d231908da2eb0dff246aa5cac64dddaac68a5d5f13 -size 295298 +oid sha256:ce15ca9f89274620728715e3448ce671e2253f4fed22a44035460e9a3709ca0b +size 647404 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 index 3f12875a5b..0ccdcbb603 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7076c9a44a433cd9eeca536365ae262d39b4ad99a8f854faadec272cb1b82031 -size 294992 +oid sha256:d0424685437a433b35b589668b409d55f26ab41bcae01af0121a54033c56a8c2 +size 646194 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en.png deleted file mode 100644 index 29e7582971..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d6441c572f64d99bc119d649e5e6422fe516b9d097f310ccbd99a9ddded9609f -size 612494 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en.png deleted file mode 100644 index 176ebfa36b..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5a867dda82242d2b13bd4bc84a9f1c9b8b7b99c030e19a6cce39b2f828b517f3 -size 611488 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Day_1_en.png index aa00f45355..7577f6934f 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa4034a06aa6e8d24806b640d9c6604bf4cffc5ec5664d2b9b189e6c39850ce0 -size 42543 +oid sha256:9e8d673869b3fd1d6be2b95c79c8a12e94732f74f28b51a38e40c166a9eae4f6 +size 39466 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Night_1_en.png index 29714c40b3..6db39b19c9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b777363de123a6de81360e4ee9c5066c8953ac103c52349979e4c3fdca1e20c -size 41699 +oid sha256:99672a8ee0d4d22f0d15a74d4e3c8923b762116ecd2e741fd09c184963737e11 +size 38609 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 deleted file mode 100644 index faf7f18e65..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_3_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -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 deleted file mode 100644 index f8f7b243b3..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_4_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c836c0a00fb5697138349028540d5e1cb4f1fddd2fd50d388cb5a1b55ccaa8f4 -size 21023 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 deleted file mode 100644 index f5db366e09..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_3_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -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 deleted file mode 100644 index 2ed11e26e2..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_4_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5735813e0f9c40e5d861ba0c35ba73689ff7ee41224829289ce017746323922c -size 20150 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 deleted file mode 100644 index c65619f05d..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_3_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -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 deleted file mode 100644 index d68ac1725c..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Day_4_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:085310083c4150fb70e48087881e529f17005df69cc01dd53807a06266f4f4bb -size 20317 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 deleted file mode 100644 index 48242a7b75..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_3_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -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 deleted file mode 100644 index 3146070439..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemFileView_Night_4_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:983620627af06dc1937b040fe21b3e12920e84116cc584fe76a7ef799473540c -size 19547 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_0_en.png index b06744a137..1cedae7a21 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a649c1213f7577e41c8fb847694a433fb8296008b020ce9c11b9f19e4daf2362 -size 366552 +oid sha256:3055caaede7c8a66712d4b91f82924e8ce360aba73c65b0174eaf5c881182ed6 +size 362018 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_6_en.png index 4d6c2f9914..0bc2983ce1 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a45bc7d128c477a017d3f64a1e7ae14b4de888873fce20e5b8f146871f52d08c -size 372020 +oid sha256:0141d829cc2e45571ab9d83b4bb186d4ec98c8d190bf133ff81846b94208e029 +size 367771 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_7_en.png index 5bf7ad4ca9..0bc2983ce1 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f46ed316ce20fdec7c2a8ab834cc68c0db8f1cf5dab05a3835133274bdf74968 -size 372000 +oid sha256:0141d829cc2e45571ab9d83b4bb186d4ec98c8d190bf133ff81846b94208e029 +size 367771 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_9_en.png index 14393b4454..6182255ade 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1cb42c166ced625581718e7f0f11fe9a6a04a0fc9ccd907addd368c44884069 -size 309093 +oid sha256:2515f92e88a09887126a4c479a9ce803d8ead7e6d01b1bee196b0354e06df836 +size 305941 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_0_en.png index 36cd635ba6..2fa6580120 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f4a12a0fc4ad8f9d5b64a30e3d7ba8c678dfd8582c98b668d292594dba7b2742 -size 361947 +oid sha256:960a42eae929b92bfe78c8efa697a42f05457ec3ec8ef7fedfc97d09187a7795 +size 357766 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_6_en.png index d2eafbba35..50c642af70 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e813d8530f1083a960a30cda348e7b68ec54b02f62773fd83788054d9b78a8c -size 371473 +oid sha256:6dd15a5434b1282d154bf10b74e8b4cab4671845f5e1a6111d86629a554f93bd +size 367628 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_7_en.png index c4f9b5ac91..50c642af70 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f8c6615f0b06c1e1a358622e0598aa89bc7c7e2b5bdf7daad269c92434e124d -size 371473 +oid sha256:6dd15a5434b1282d154bf10b74e8b4cab4671845f5e1a6111d86629a554f93bd +size 367628 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_9_en.png index 146e3a9211..cf02780154 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c144e259fa322bd899a047ade06c7105a6d5f41732193baa9e1437067d7b47f -size 302873 +oid sha256:460ad18856a9b9afefb8e8d8544f7362396a3755d0d51622c1449f2b4f62812d +size 299907 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_4_en.png new file mode 100644 index 0000000000..9238837c39 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb6b6a0c8d9891776097e0e5448c017dd9a943fe30b99735300d5107ff29ff47 +size 274673 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_4_en.png new file mode 100644 index 0000000000..9238837c39 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb6b6a0c8d9891776097e0e5448c017dd9a943fe30b99735300d5107ff29ff47 +size 274673 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en.png deleted file mode 100644 index f792a1663a..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e3bb005a88e9a4d2bb850478ee8ac2c4f31d32625bd6d2abf455fade461cd399 -size 607806 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en.png deleted file mode 100644 index 18319e718f..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4a2a57f5547f98b9ac2d8bf7195a1e4b49e03834e8866c6cc76660a6a3b16e74 -size 606823 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Day_0_en.png new file mode 100644 index 0000000000..04c37256d4 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e801fb628e90136e1a2c83c2ec8e9ad9b75febd0fb0566a3c66aa13f42799912 +size 48113 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Night_0_en.png new file mode 100644 index 0000000000..5925416c47 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:accb6fd85427c220b02c271316568e09f00e7307c861d75bdcd43456c7c9d892 +size 47680 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAudioViewScanningContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAudioViewScanningContent_Day_0_en.png new file mode 100644 index 0000000000..4cefab49f4 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAudioViewScanningContent_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:86e1ca5c57fe2522dde2ac9037b1eb808cd2afff4e83bbc6def1c5cec6eb1208 +size 16510 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAudioViewScanningContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAudioViewScanningContent_Night_0_en.png new file mode 100644 index 0000000000..48b2f2b047 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAudioViewScanningContent_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad421c54c0bd3e25ebf07d9a005cb050ed62fef9c19e1a5c01f54f0f3cf2931b +size 16818 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 ab6392a424..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:94f89a37549a3f198442db467bc7d8539f0b5649d97927bfe731f090d6dfb03d -size 379505 +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 9cbd5c1d95..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:d0e170b4bea262de612bf3374d475fcd25470ff91b7554d20809c51857a78cec -size 377963 +oid sha256:04ea6c2947a21d3d4a3d43e9c4750c4f2a49056536a4da3f34c95df8353e9de3 +size 377990 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_5_en.png index 23ce668685..632aee5c4e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:620849b893491d33f5b0a2a0f2d0814c40d111026aee52e299b893909b08afb8 -size 48309 +oid sha256:0782326696849e56e4fde44a2cd36197f3d1d3e08ca1f942f2ed00a4b41da400 +size 48247 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_6_en.png index 7521205f85..a736afce19 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:50ee16d8894cb50860bbe0dafb7f1e6002ba18336070875699409c1ffd1b7de0 -size 103322 +oid sha256:9f84c2d5963f9fc81c10f53f336c2edc1ed5b176b9c294ef22548ec17c3e0fab +size 103104 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_7_en.png index 829dabebd5..ab7e249fae 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7381b146b64c1281d8e3032539c38270b086d2173d635d969dce3e1f24e07081 -size 76539 +oid sha256:df2867676c67b8c9db0a96de915886444242313ae1333a4a1fcc6a5d11a39050 +size 76255 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_8_en.png index dee2a3b025..8657eb4117 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d737d3c634a812cd2338be8c372de94a5f0a959e56be9b5acd6a4a2d83b57879 -size 39262 +oid sha256:41d765ad4383ab40232716a22e202fc8a2fcd59b9a3a44f417631f4d880806b4 +size 38890 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_5_en.png index 8857763fe8..a11cab2edc 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a89c2d2ece84f2bd9a4613c84ee7a4090cd00e79de88bbdb0dc3b82f6f867b1e -size 47837 +oid sha256:25b3cbef7e304a3135bd8a49af18465fa79f35ebfdcf4de867163874b31887e8 +size 47739 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_6_en.png index ac841eead4..81218bc9e5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e2cccbfba9adf2c1aa799e98410f32fc3895a28552577ae5a49860cd04e9d9e -size 102247 +oid sha256:e6605daf6c22d2461e82df7e37bd25a70e5c2728047fc4dd971107f977c44525 +size 102080 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_7_en.png index b6c5b1a006..baf457824d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b98b6d69d157f84bae3dcd9f8cfba2f98d1f8dbd923b9d8ec803dffa18f7d92a -size 75860 +oid sha256:2b7f7fa2ac9f05d539033679c63e5ea242d4b943ac3259371b4591757ea1c68b +size 75647 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_8_en.png index 14597ddb08..c4d02de93e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9da51e0ce86a07b09548161e60b0bf76cae5dc7fa53929ea23f81f416347de6d -size 38627 +oid sha256:2ff7894525ac8a1582baec5a5466912dfc32a627e58ed969b7acb881fcfee087 +size 38346 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 3ac59caeea..1f0fdabe6d 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:1a94d5198e27338675c0e15df5874ba3272ee315b8d77291dc7ccc7c754ed1f4 -size 365082 +oid sha256:b8bb5a6de6601da8d7fe59f110a054577e2e25dae4bb449f60c04e7d7a1b9551 +size 365073 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 86018764ac..195aa04fe2 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:8344427a0fe87cbf0883ff53a9ee4dcf90976a7011f6618d85961df48b2c53a9 -size 370228 +oid sha256:76e5ae44362792d570cd82f3910c8bd0acde509b8418c5892e0385e7d636f042 +size 370223 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 29771235f0..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:60b9f2b920cd2a2a414805d1f0f77925232d9ae60bd607fa18d4395cda2dd73d -size 363291 +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 c6d4541184..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:c00e504593d8eb61b598f05f46ee4d591757975a80c0b4227b240847d2cd4868 -size 368510 +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 94428abb56..84d9d4e5c3 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:36d7cf2510d546d2b330b1d1b1674ce58df0558c547e443794a1e7b2222add87 -size 347897 +oid sha256:7c609a633ab23eae5729ecb57a17a385bac65e81cbf0180c01e0847f1028039e +size 347890 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 7ddac02717..73b7e674e2 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:a4ac79f3b8fb4e231244bd96b244a4f2526d6ed28d558f9d50734d83bbb74992 -size 363909 +oid sha256:991deacdfb7bc371a2df960a2364ae3b2187e588aa5afe7f39409e367040dd9c +size 363893 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 22ff4965d1..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:787151f8f242a8794a804bf14831f6ca680814d617e85feb3652103e8a0f20cd -size 346565 +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 4e17de6908..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:c1e15400fa2c5ee6087316501445c551a3932b65e16de31e68acc5efbd16a559 -size 361603 +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 67490ba700..01d4dca84b 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:f4431e2d9f30123949ea5676ce60f642234adcf9b5a33f2acc3f80ebf6609a66 -size 369730 +oid sha256:ef2bf449671b652cb152b3baab92ab100eab77a54229ab49daeab156f2f484d0 +size 369724 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 1600afff71..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:273351cc9c533b2424859a0de00a8a3786628abc3a88175705c4205dedf7e9aa -size 354737 +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 e38cf03ad6..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:41a0e404dea7f52359b24b3ec3926b1405429b165cfed44c63b3922ea6d3cb46 -size 368114 +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 68f8148879..b5dac8434c 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:6ca8cf82aa8ab1bdad56a27584b27789402aeb7ad8fadd038280a376fb75a72c -size 345094 +oid sha256:1a92f8af94682facac66d4aacb6e49f345561c15be2f8b689041b78aeaaae831 +size 345062 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 1b99468924..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:3a9509411777f342261cab58b92a022b3c9f8f0f7a9e4d0527120a91976575f0 -size 357733 +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 b5032c29b3..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:dce23463c335d01eb67293cfcede5d85e96ab2ba035cc9a188d42e8e6866bc63 -size 356831 +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 14a40a5676..a332744358 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:a11044fe90227f1f316a1ade8587e545bb620e11cca76865fc2eb83cdb817fc5 -size 364655 +oid sha256:588967869cbd25ed8b82aff5618175660a8a9e45a5a861b1c7867cf1913f575b +size 364646 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 133fd3903f..d7b969fd5b 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:426d1c844a8c88281c5fa4c61916d93278fdfd38f8cdf2dc54bf1a821f2de3eb -size 397167 +oid sha256:2528df873713755f542f61cd794080929586c1bd5f316c0378ce9e837c21d50b +size 397145 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 63bd9c3f6d..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:a6cd94664f89bdad2a9761ea8b20acb83fed3ed7cb5be41af8fe4852643c0bfc -size 356175 +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 f67906a37c..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:ffa68c8398d789444151855496e5df4ffa03218a383db6ea46fd4f979829b823 -size 355831 +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 d235670def..6e83d6491d 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:a00bd766a00b7e7c6615fc53bf469b3ca5056a6c514c096431ae38d99d604306 -size 364845 +oid sha256:34152c742abc486a48234e22101833bc163cf11979890d06aac41e68e3c404d0 +size 364846 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 b10f9741b9..0021619c44 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:3ec1b0244dab22414c6719b3309426e13128d0c70fb67dc66cd8a60d42521fd0 -size 355411 +oid sha256:7b23d3a37774283067a8919b8c332b1bb5a79e90dceb7216b484b985491282e5 +size 355389 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 422c324695..77abe20982 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:a1df8d22766981fc76d6d767dc3f40d98cadc7c51be20417b067b91af604232b -size 367884 +oid sha256:5c3d87862c6d7fc88d0f23cd54c5b9f77028992fdd7c282a195b964dd17e85ac +size 367855 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 448bcec677..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:fe0daf9161bc2da194992a2fc9505bf2009c5dbed78cdb35d2eb7ed1380a7df5 -size 353037 +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 5243218ae3..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:9a85db2f5958db867578663533f204b2e803372d470da890fd8056ffed0cf46c -size 366254 +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 b6d1f07279..47a9a6b630 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:4bee12a6bdb18fea5ac6997671bfcb903296da7278cf69b2456330066ca31dfb -size 342870 +oid sha256:54372845e922d047408dd960d048b9b5eae2263d589117d8e7d197741aa34f32 +size 342827 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 5560c21967..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:af4a48ee80535f2c0a226c4ffa4344054fb63b7b0a88ea2c030a4eb8dd5e9644 -size 356078 +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 5cdad1df92..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:9e2d8caf5aaae7d3406c703288e491f328552f0acd18e56afd5265b4ceaf1cd1 -size 355272 +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 e9d85990e8..a431a9429a 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:66d4b6ea4a697735bbb0fac936b89cde99c5077973ba828894bf50b5dae233b3 -size 362848 +oid sha256:93c2df04d65f6078ce3f7067fbae8a7317ec42ed0fc013dee962a3953269f3b7 +size 362813 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 0eb106f4a9..b51a89586b 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:217ac95bf476c53d2dc6d3d0143b21312bf38b8ab86c8dfd4f9360582b584f9d -size 395476 +oid sha256:e642229c58169775fe702769a306bbef22698516ae6f7ac75a761213c3f195fa +size 395446 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 aa322fc2e4..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:5fae87094ea13b14e2dc7c16ca96e4f8096ff39e962799468fb4ead4c666620f -size 354381 +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 9d617f6688..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:dabad9dcd5b8f0d4bb964a0187ad7c94b023b04552dacd29a077daddfd48d550 -size 354052 +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 0cfd1dc985..1a8ea3e4e9 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:545c9e8933e420cc3f8fbba0fbd5162c946c65a20721faeb77c568596ca720cd -size 363045 +oid sha256:66aba7b4271a990fac85b0bbc7cbdc371fa1e38a4da5bb4e2f62a80b21cb3a8f +size 363012 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 c8306263a0..c9227ebf94 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:756f0cff90ddd61adce2f467c0384d74d430f6d51c091e4980e45bcc9ee6f0fd -size 353705 +oid sha256:e614f4a8657637c584a283d69124236d00fe1251c2b8d739c5688a57a6fd152e +size 353693 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemFileViewScanningContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemFileViewScanningContent_Day_0_en.png new file mode 100644 index 0000000000..ddbd585aa4 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemFileViewScanningContent_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:659b376f3030142fe61bd95e62c312b2272179fbed3d5fe07d9446c8d5b07594 +size 15423 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemFileViewScanningContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemFileViewScanningContent_Night_0_en.png new file mode 100644 index 0000000000..3584a58631 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemFileViewScanningContent_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a352a0d80264a2998ffe5c08665e752ef34b96a92430eb047badd786c0a8b7be +size 15754 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemGalleryViewScanningContentFailed_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemGalleryViewScanningContentFailed_Day_0_en.png new file mode 100644 index 0000000000..3618ebc14e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemGalleryViewScanningContentFailed_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:59fe552df2e412f3850c248c9837e789e6b9cae2b659d3d9e53fb5abef187a16 +size 164976 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemGalleryViewScanningContentFailed_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemGalleryViewScanningContentFailed_Night_0_en.png new file mode 100644 index 0000000000..a6531edce0 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemGalleryViewScanningContentFailed_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b7942cb8112895b177dcef36a2ad9824bd5b380a6442f8bfd6d1bdf2f88b8b95 +size 164488 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemImageViewScanningContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemImageViewScanningContent_Day_0_en.png new file mode 100644 index 0000000000..930a0ecf82 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemImageViewScanningContent_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9888d8f9f8b3ded76f601c7300c33c8d111aa926ed7bc0793fe3212710786656 +size 119693 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemImageViewScanningContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemImageViewScanningContent_Night_0_en.png new file mode 100644 index 0000000000..e52ec14d2e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemImageViewScanningContent_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c90a542bf2c396ec844e1e8b1763a94078f0139cbfdd1cd8ec7ab7e4e21f2b91 +size 120861 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentFailed_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentFailed_Day_0_en.png new file mode 100644 index 0000000000..282f372040 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentFailed_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9252417e89d51f89041e42a43a6685a8278832fa976b85bdc024e6cc5281857 +size 37983 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentFailed_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentFailed_Night_0_en.png new file mode 100644 index 0000000000..c065368538 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentFailed_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:40441524640785b0a1ec20fef0c083fbd69105f48142e30a05ca7e1eae4b6c1e +size 38889 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Day_0_en.png new file mode 100644 index 0000000000..8f65bb19fd --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:020f44e2c54b1449ea4b4f3608073433133ebb3d3cae3be20dab121a103d2f65 +size 66749 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Night_0_en.png new file mode 100644 index 0000000000..cc10efcb15 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75b14fa771f05ebd3ab6a6d57068c59259ac6a7c3891e9cbdb96d4a025e6491a +size 66992 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Day_0_en.png new file mode 100644 index 0000000000..6a78894774 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d56fc7f2007ec4679281452b42591c0e125bcb6efe15739fd1d1d3709a5d4a2 +size 53534 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Night_0_en.png new file mode 100644 index 0000000000..a834e8e7d2 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3fc62d83354b76e3844818a63a97cac0afbf04a2992f8acb150c1976003e057 +size 54679 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemStickerViewScanningContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemStickerViewScanningContent_Day_0_en.png new file mode 100644 index 0000000000..c867853a06 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemStickerViewScanningContent_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:09774478b8279b1603e5669eb20ff0eaffbcb055fa6c650f0a9beb15a0576c94 +size 146145 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemStickerViewScanningContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemStickerViewScanningContent_Night_0_en.png new file mode 100644 index 0000000000..e87bb6e271 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemStickerViewScanningContent_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b28e20d5b38ef952a949c1dd464d7eca42dd3d9b39e5afd6a91ad36e188676c +size 145737 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVideoViewScanningContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVideoViewScanningContent_Day_0_en.png new file mode 100644 index 0000000000..b683d83582 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVideoViewScanningContent_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:710c36047d9e1ca7c3d242cd53ac9232c536c36b3706ae22f49ab62e05e57a23 +size 284681 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVideoViewScanningContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVideoViewScanningContent_Night_0_en.png new file mode 100644 index 0000000000..34d69603dc --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVideoViewScanningContent_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:380a80cb0cfdd1c0ed2bb90793e640552323c9719b1914e10ca6be0abc8c9929 +size 283849 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVoiceViewScanningContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVoiceViewScanningContent_Day_0_en.png new file mode 100644 index 0000000000..2bfb17b0e1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVoiceViewScanningContent_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9088ebdc55620f1829aa78d2b46aaa57413ed6925fdbf5c6f60bb2a1d7e4a062 +size 14265 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVoiceViewScanningContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVoiceViewScanningContent_Night_0_en.png new file mode 100644 index 0000000000..ac4ac1435f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemVoiceViewScanningContent_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:158974ba9eae0d43ac7a75702254dca08a081999a3f89dd1a53152aeb02636b0 +size 14739 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_InvalidContentView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_InvalidContentView_Day_0_en.png new file mode 100644 index 0000000000..5fc8a42dda --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_InvalidContentView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cdd3a8df3a9decf6e84d8deb8bbca28f844dc812a238d89f34239e546df9635e +size 13015 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_InvalidContentView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_InvalidContentView_Night_0_en.png new file mode 100644 index 0000000000..6223b491cd --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_InvalidContentView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e475efcf0d4e56d6519007e6b6e7d671f4bb8c283c2b69336877aac3540eb284 +size 12679 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Day_0_en.png new file mode 100644 index 0000000000..db17a4bb83 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a0a59033bbc70903db2251e44c92248a3d5a574a4fe0a5347f74b4ba0b065fee +size 10002 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Night_0_en.png new file mode 100644 index 0000000000..49914a6484 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d963d8b910b34a552636f4bf9a5657acef2a1507469acf136074a88cf3ff7c4 +size 9819 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Day_0_en.png new file mode 100644 index 0000000000..7a941824b1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:779d234f352bcd163ad792b858dc832c0e01c0598766c5cd636e2767ce10b30f +size 13153 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Night_0_en.png new file mode 100644 index 0000000000..b79f27aaae --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:12a4056aeda90fbe1d54cc6d5fb7c01b54c5c97eb9aab2d49b665da49860f3e3 +size 12540 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Day_0_en.png new file mode 100644 index 0000000000..a4e8be33e0 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a0d67a139c137d80f642f7a00b16c1e3ac916f7b82cd780cfe5ca93759ec8e96 +size 10170 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Night_0_en.png new file mode 100644 index 0000000000..616e0cf151 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27303f65c849be3fed38b005cb1cf8abc6fa037e2cc9475de7c3eca53a1c6c1e +size 9791 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 4caec79857..e5602cc913 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:5aa13d38c3c677dc552e1ad6ffdc19caa37c96287945b877804584e418e4acbc -size 10915 +oid sha256:c9e491bd12948a77b277e16594ce6aea80e7eddf0e2a2efb27e87546f156525b +size 10909 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 6482d7322b..bdf129ee4a 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:416b0ee79cd8c07fed42739309059895f8c36c20d3838be4a5a4afbfbd0b5394 -size 18548 +oid sha256:63f992f8496bac188c746dfc000f3d62d9f88c08131110d5977159b72d61169a +size 19669 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 6f42ac691e..679685e936 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:c82fdba61809fce17e2eb7e9a79857a260e5598a2a9db88f481db69e2c7f79fa -size 7745 +oid sha256:ee086e521812765d474d094157c0311f48e2a3feff3bf6756be06974114c020f +size 7734 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 fddd092e48..e26ea57b89 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:36aad99f720579ad309c01591f2d4e765925aefd60bec2f66a28c14d5748b855 -size 10551 +oid sha256:4532dceab59523019eb7e0ca944c3c50278ef91eea6d6dc194bda743b9511fdf +size 10528 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 92b79113e1..60a8334d91 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:1d527056f8cc0ae149aed408898cfc47cfdaba91cc7367e4cbf10fa49df44f9b -size 17781 +oid sha256:f644d1b6798c3761b0a16924a697cc653f31a090bab723177e40ec48131789a3 +size 19008 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 f59422b33e..9ddb94878d 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:c9042bb2175fb555c005faa1f69bffd1640c91a3c109a18d4759d802d1540350 -size 7485 +oid sha256:bd1cd65b9fa83f0dc89331eee859ce08a3ac9444c815b4ddc572fd2953d38085 +size 7459 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 4a6e665500..bdd255116a 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:ead7c23c723cbaf116629cfc502f4696454a1da1bdcb4aeaac29605d937d2605 -size 71610 +oid sha256:01d65375670bd50fdd58c2b105fecae6efb572df1a23e4d883361fba4ebd32af +size 71628 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 3ee771684a..e3d68e573f 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:4e9d1d7021b65b18e7038e6551495b6d391381e85484827c005594fef3a038c7 -size 57984 +oid sha256:b0477ab88d07880dfef518acbeb6a020122797b4d1833bdf58f7a9a4342d93ad +size 58002 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 846a262c57..1c308dc42c 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:68ef756dd45911d9a06f5ceb2ce4917d0d35ed0c9f1b6aa559fccef662672e38 -size 71118 +oid sha256:dd47b5f29485ade1aa9bbf1ef9f13b0be0b829f4b60f047bcdd616daa5044925 +size 71141 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 c56359f7e4..e5feb7324d 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:63eb5bc48de34efb71ffa644e78f18e0596c709f153b35fb6b7aec49dbdaab78 -size 79800 +oid sha256:1affca1d77e8929fe3abe279ae3bde06856313ef8dbcbe335905d50afc6493ac +size 81821 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 4551d86254..7df51fb255 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:fe419a00799214722644f17edb94aa4dda3bb7c3b4f19dad689c490bf05d550d -size 60676 +oid sha256:658ff95ae679d89fcb1b093617a46f3555bf242d44781a15c2a34c9f5a1a0c81 +size 60697 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 0beaf993fb..b566c6f449 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:864b6a01fbcd041a2cb5fee1602fceed5f311a1d73bab6fb7b10a3acf279f47f -size 59579 +oid sha256:5238f56c1cf3437ea6a8cae67497c3a80acdfd0842e6ab970bf398b422b40ba6 +size 59601 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 326f3948ed..acd556e96e 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:59a644589a3eb4ef7d791994caf7c6aae6b23a8964405db4d8e9ebba4fc26459 -size 66594 +oid sha256:de7995760d329c8425771d2d2fe461b817ae9b9e305275ca379cf95c1997d583 +size 66622 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 f583680c90..a65ca8b35c 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:7185c0bbb80d40e3da31df878f5127947e5944dcf3ed81b8266342dea94a585d -size 88177 +oid sha256:4cf390d9a439b6df56e0ba58bef71fb7cc7abd4cd0a96f06307ea8d169ea9709 +size 88195 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 2de8f41575..cec8a0b12a 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:957b3b1896978c725e03d8d8a22afb767fe032b8c10e499a70f0395eface7d12 -size 58909 +oid sha256:4112021940576375c6c32c2a5fb04f165368cfc7eb6ebdd2abdb3aabeb1cb707 +size 58930 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 f97044e8b6..26bbc77e27 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:faa3cf430f066965686bf11dc9dcedd7a7161e18f6a96be566b8f9be615ee164 -size 58974 +oid sha256:91daf1d41634ff04960ca66a0acfcf2a337dd8e470c7d1f8f4aeea5df11685ab +size 58996 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 a2a9d84eca..a2bc71b494 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:f21ce912bf7ec69db5cbb024c09d385cee117e0698b28432a54fb3c330d4b44c -size 66110 +oid sha256:236a64de0e67f91d2e3bc7e7442f99fd83f472a4be46c5f449d2e808ce4b6c43 +size 66132 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 cdd4983e85..738e779bad 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:47521fcbb94b38913cdffa41faef1a0af40289576a892df84fb166b855a77cec -size 58441 +oid sha256:f7b9c8b0404e420411f22cab257c707ad1b0b50d9c42a35ff1253bcf753fd527 +size 58466 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 f89f4b12b7..5236db62bf 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:82904fd6abba5122b5b243e88e58bbf9a5c128128999afb4b536e689f114b967 -size 68610 +oid sha256:9e664f8e6f1e135c0243001e46e41a38ad72a9628c4960445f334ef87498715d +size 68511 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 4ccf9c5917..bc81f67b2b 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:06e63017d3636a943f015652d90089c6ded569930067dd8d6020df4053d98d3c -size 55340 +oid sha256:0043d71f6d17e9aa6392ff4ef28367e4f3cc9a5c637254b72adfd9c72cbfe3ad +size 55233 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 aebee6a41b..fc16867249 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:b4564c1019c830ef0bbed284bd9c8ac8dd1c8082dc76f89e394ae82a1756fa17 -size 68119 +oid sha256:0e24b826fa1fa408e6820078f0bb47fede7cf5d2a2bfae55978739e47084c249 +size 68028 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 42f7ea79a3..08e8504449 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:713af5b3d329a98e75e9587b8b228e1c017a342dc5bc4663df5d0aebf4951637 -size 76948 +oid sha256:15120e28f72ffbc1b035509b747d0137d56b6b0520341baad7f8ba090fb700b9 +size 78666 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 7313e32cf0..df3b32b8d2 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:0bf814a838410e92a932373b39aa91deb53b18857055770ffa2c1687d6128e37 -size 57989 +oid sha256:a55a88cef50cbfd1357f51e572093a84e056d0a93a12bd33fb25ba5f370e4615 +size 57901 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 a372614326..d460968d64 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:728842933007c366c10e0293a22b0722bf2436c43e3ced69bb78838fef4e4aac -size 56944 +oid sha256:6531f685230484610a5e12fade57ad8266c431b5a19f7b3eee77c15b75c96e38 +size 56848 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 639cfeee1f..6dc48a0630 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:55c8b429bfc0d518cde9b16127adf05fb23a29f70df2572a6212c3f837f36133 -size 63826 +oid sha256:d193184265e4d575a34a6820bc77482a126aac0c43cfd0bc09152906ef6fa601 +size 63732 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 bdf1ea5885..d0b1d953ff 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:bb8e8cf4624d8b6a75db331dd43fb4b51df2723f98eccdc4d87bc1d4df80c3a8 -size 84918 +oid sha256:62e37482c9ace9e4332df8aa650d12c7300a2cab05194b825184dc39dd926772 +size 84860 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 465d5a5c11..c86ff3c07e 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:9c3c802c57eeb15b14ab02677a84b422238aa08515b9151d9e01c8aefc0327b5 -size 56322 +oid sha256:6c5edf80cef291b62f4c3f125e3c2e1073e5e6db40de4b826f83aece9ff55af8 +size 56221 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 3ba841381f..dab20f0c93 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:7995253a70c47aca2215d475549c5da8a5ecd6331f8e1d2268df6979cd5fbc01 -size 56276 +oid sha256:5787b8a8b31173fae71bd513d84d02467d154917d4a2d2825424ca868c8bd101 +size 56171 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 ee775246b6..523ffd0d50 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:8b3868e61ecafeb234c4e3438c138ac420192a569949fc8f4f8e4c946ba42f14 -size 63243 +oid sha256:acf87ea3c8f6db07c1758861d3e4849295538c741393fda18759d7f66225cea0 +size 63155 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 861384a18e..8b1d78f601 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:1912b608b35257618b42d8abb602f031b67fcbc9810e59e6b20bc86075002b5d -size 55847 +oid sha256:25f1ebd9f70c477df9b1159fd92becf0d5ec9139c36c081faa6af862b388e42e +size 55735 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 b78d36fdd4..a7d1026e41 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:745714bf11601a9abedc9526d3ddfcbfebc1ed8d73872ebd33f10cc638119c19 -size 72647 +oid sha256:3ac4707a32f7680319d1026d9dd6f56de74a95c4a4f990b0c1adf5280fa1a1c7 +size 72582 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 5ef7a3ecaa..319cf76ebc 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:3a55cd98bc72c250706402bfac0706da3adc60a23010ab3a634290f2115f8543 -size 56527 +oid sha256:621b28e55b2a2a6894c4eed975c4aafccf25e77ece0db90621e639c9718adbfb +size 56478 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 94488a8118..be729307b0 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:5f4ec0a26c52319ec4c0e3468115c977bf3d4be116fa29d5f234758978b518cc -size 70973 +oid sha256:1f56ca941457d2e53a3659e516a7a27da56071820b221c251ff89a231185320a +size 70911 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 31cf97c9c4..568ba4e7b7 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:a34d90d08ce5cd10a239c3accb0a92abeeb5309ac73a079700ded09ed1ee1697 -size 82282 +oid sha256:c718cd9d08c6ff483a2567ff6795803574a873091c5a1b984a08e1873e691c65 +size 84530 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 7cb03f9aac..9a40df428f 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:3d2c24321d4e7e827aa56ec9715d591b0f47091dab02b13c1dc045a175a70154 -size 59640 +oid sha256:7aa00fb0b59a871158c44cb67a4536aa2318e215add4fabf221726406e9f2781 +size 59617 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 e008b3ee4e..a55b92e8b8 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:c7727ad7b23e98365dbf7b30f2375500cdbff8062d17a1909b166040e07281a0 -size 58638 +oid sha256:3f4d668e7f9fa7d294cb1de945dd70bfd1b394f14159705ad37c0f55cae2c6e7 +size 58611 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 ba46e2e270..35f2d39b79 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:b514f0f3c246531c3bab262d9b85f60eb737b960c0f1401c0c8d684d75a4f1d9 -size 66694 +oid sha256:22d2ab3ba2f9e04510e7ea7d185baaf305d12a3548956a695fd72c3d7e181d57 +size 66671 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 0c23280443..437e1acae5 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:1a84a52cd5320adfa2bc77781d7d5b996b21a4dcc94d2800c66e636a06f40a40 -size 101578 +oid sha256:890b7338df518463862560114113d64504383c01c2e6db6800c85c082637f496 +size 101548 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 5b5b142b81..7562d7090b 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:795ab6fd6386131a124707e96d38a916dca88fa081562cbaef269f6831fc55ca -size 57855 +oid sha256:5c30ee7afcc5cb4c1a405a026a4ce3b36e645b5b720b39531c1b8b979e6961ec +size 57801 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 9de8ba3f72..883800c68f 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:cae668f5a1adfbe42e44ea472dbf7dc5079ec1c3826507859d3e0536766fdb39 -size 57700 +oid sha256:1f1e64891abde888d1ad06bfb24ad4ba1aafcc2eb7c9a573a1deb116761b4080 +size 57688 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 e7784793c4..a5ed775376 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:4e704bc61a2ae26cfdc30262a4e43122f24faa2a546ae7f16ad15560fc615327 -size 66960 +oid sha256:dc00781c5eafbbc1f574506b7948eb64d9784f6c69f8c0e29be5d120f39b366d +size 66942 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 5b56c20157..4eac81e304 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:919a9159a4a6b82d65e2f0a59cf55031620f32fe4066aca9440ffdd9f97ccd01 -size 57246 +oid sha256:be145b0f36fb88eb76a15d90ebdd2edf89ec99c84112216ffdfd2bdae9a850af +size 57204 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 b18545b512..06ba9eb873 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:758cd0c11cb3d951b7c6db787bbaf66dc87252758c6bc9b36e0d1b479fd495e8 -size 69281 +oid sha256:9ddb88b02eaed6c732e11dd26e3f45506d037d4e113db171c9283a2fab4f9bd7 +size 69203 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 6ec2ca88f6..d9e77e9bd4 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:56711e24449f15fa13b6147d1087180bc18f9a873eb0a96d19acfbaae66f74fa -size 53284 +oid sha256:1d456410474fb03e3a0bfcd2d737b2f0333e56d26c3eddd3515bcf8031a17d59 +size 53155 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 638136ddda..5c44befebb 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:b598d4cb370923b7aa28287247c08131b773aee20467dd5d3ce95d0506e26ec6 -size 67706 +oid sha256:ebd0a8984dc9ced8ea84180862034c531bd2713dba6e35729d2686921a01b3d8 +size 67634 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 ccab6d1cc6..f3f6ee2ee8 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:3d0300a4ba4a025b29e37cf01e29d9cd77ac411fe00642c64a9c14ff80ee4149 -size 79018 +oid sha256:eb3bb205e9cf382961dc003ee33248a3dc87089060dffaadee6d2af3c842dd1a +size 80952 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 c2a4773ab4..a438c1fdfe 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:3224a33cd9db2adf69479e8acfbaacaabd0d8ba00d4d862f1b38fc8e360539bf -size 56546 +oid sha256:ee8618bb0da86007b0e50f957f7d941bd5f31332a021e36e7641f95d32dc2108 +size 56440 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 a01a166e95..132c4d7b5f 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:a2cbbf5adf4d45fa65aa176b55216f8dff89114ef1a5b4de57bc86a53a22f012 -size 55584 +oid sha256:b912c22474b75a78b951a071b9217e1fc25e2f2d49916a4724399fb898c4a4ef +size 55462 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 d9592ab2d0..9da26c1c14 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:c49ee949c20152ff3c9ecef1bd361b223fc4eff62a420740d9b708343f5c6121 -size 63442 +oid sha256:99e13306414846ce38775a5b681562f6e79d2e8d860310e4dda1d1fb3aaac60f +size 63341 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 e6f0772abc..dab02cddf2 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:46c32f65a5071767b8603f93711f8c3c6150bfc9f6c0f6fd61317aafdebb2e83 -size 97701 +oid sha256:92d0ab372ab8efb76da83c9e28fb5f2d6a4d202285f9fe0644d378d02f8e11ba +size 97602 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 f18f28fa0f..e9c013be92 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:b2baad13bfc9fd755108365a9b0f7251f60cc8f9bf335115ab5c02b2d0f19f74 -size 54660 +oid sha256:1579ecd04cfde9b62d85287014e519fbb04745d9253140e2cd9936f4a23dbe56 +size 54540 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 381119052c..9e0186982d 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:0a735f4a7003f631c230c29e4248d186d86111ada2c4c4cfc8e6e4fe9897b224 -size 54424 +oid sha256:e11143794228c270b85db674577948d52161fe1c16c8ae8ff04870636ee58e4d +size 54317 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 16da419a33..a53692356b 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:c109f03989aaa14873823c230bb262add95099b44031512ee29b9f8c8e7d180f -size 63642 +oid sha256:8c51275bdbf340dafbeac16ba6c946c5ea8fbd829a8b1ad45f9c2d1da0a28df9 +size 63540 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 dfa1308111..41f97a0155 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:bbe7caa3bd8b8788befae4c4febbcd1bb02bd2ea9d6feb00bffb962d0f2885d6 -size 54080 +oid sha256:a99c944c69b41ce89be07fb0c183ef0588b4b0540c747dd40a1135ffcf8d1216 +size 53962 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 index 3806b4217c..cb6393e72b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerScaledDensityWithReply_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.textcomposer_TextComposerScaledDensityWithReply_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d35ab62460942f4f14edc87aab84f4d659b18763c4cf8a1c353f99085c1c164d -size 16727 +oid sha256:2508c7785b3dc7f2d2e0abd45c2556c8bbd9a3905179f1082fe66b296d7b4752 +size 17282 diff --git a/tools/detekt/detekt.yml b/tools/detekt/detekt.yml index cc99ecab5a..79bfeb7250 100644 --- a/tools/detekt/detekt.yml +++ b/tools/detekt/detekt.yml @@ -227,6 +227,7 @@ Compose: # You can optionally define a list of CompositionLocals that are allowed here allowedCompositionLocals: - LocalCompoundColors + - LocalEventContentValidationState - LocalSnackbarDispatcher - LocalCameraPositionState - LocalMediaItemPresenterFactories From 4cb9d272f43cd5afe22a80df5d2e1ed3b1336060 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Jul 2026 10:05:43 +0200 Subject: [PATCH 139/383] Update dependency io.sentry:sentry-android to v8.48.0 (#7217) 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 52f59e898c..76e384ddd1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -230,7 +230,7 @@ color_picker = "io.mhssn:colorpicker:1.0.0" # Analytics posthog = "com.posthog:posthog-android:3.51.1" -sentry = "io.sentry:sentry-android:8.47.0" +sentry = "io.sentry:sentry-android:8.48.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.37.0" From 3854caa8f121bbbce05a4135beedf1a0a3a0e0d2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 16 Jul 2026 10:27:20 +0200 Subject: [PATCH 140/383] Fix test compilation issue. --- .../screens/qrcode/scan/QrCodeScanPresenterTest.kt | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenterTest.kt index b0b83f8c24..d4f23a452c 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/qrcode/scan/QrCodeScanPresenterTest.kt @@ -9,17 +9,12 @@ package io.element.android.features.login.impl.screens.qrcode.scan 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.login.impl.accesscontrol.DefaultAccountProviderAccessControl import io.element.android.features.login.impl.qrcode.FakeQrCodeLoginManager -import io.element.android.features.wellknown.test.FakeWellknownRetriever import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep import io.element.android.libraries.matrix.api.auth.qrlogin.QrLoginException import io.element.android.libraries.matrix.test.auth.qrlogin.FakeMatrixQrCodeLoginData import io.element.android.libraries.matrix.test.auth.qrlogin.FakeMatrixQrCodeLoginDataFactory -import io.element.android.libraries.wellknown.api.WellknownRetriever import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.test import io.element.android.tests.testutils.testCoroutineDispatchers @@ -52,9 +47,6 @@ class QrCodeScanPresenterTest { ) val presenter = createQrCodeScanPresenter( qrCodeLoginDataFactory = qrCodeLoginDataFactory, - enterpriseService = FakeEnterpriseService( - isAllowedToConnectToHomeserverResult = { true }, - ) ) presenter.test { val initialState = awaitItem() @@ -114,15 +106,9 @@ class QrCodeScanPresenterTest { qrCodeLoginDataFactory: FakeMatrixQrCodeLoginDataFactory = FakeMatrixQrCodeLoginDataFactory(), coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(), qrCodeLoginManager: FakeQrCodeLoginManager = FakeQrCodeLoginManager(), - enterpriseService: EnterpriseService = FakeEnterpriseService(), - wellknownRetriever: WellknownRetriever = FakeWellknownRetriever(), ) = QrCodeScanPresenter( qrCodeLoginDataFactory = qrCodeLoginDataFactory, qrCodeLoginManager = qrCodeLoginManager, coroutineDispatchers = coroutineDispatchers, - defaultAccountProviderAccessControl = DefaultAccountProviderAccessControl( - enterpriseService = enterpriseService, - wellknownRetriever = wellknownRetriever, - ), ) } From 2112e1bf04704a6e9e7f7632d21d427b94b9a629 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 16 Jul 2026 12:19:40 +0000 Subject: [PATCH 141/383] Update screenshots --- ...omponents.customreaction_EmojiItemWithPopup_Night_0_en.png | 4 ++-- ...line.components.event_ATimelineItemEventRow_Night_0_en.png | 4 ++-- ...imeline.components_ActiveCallTimelineItemView_Day_0_en.png | 3 +++ ...eline.components_ActiveCallTimelineItemView_Night_0_en.png | 3 +++ ...impl.timeline.components_ActiveCallTimelineItemView_en.png | 3 +++ ....components_TimelineItemEventRowDisambiguated_Day_0_en.png | 4 ++-- ...ents_TimelineItemEventRowWithReplyInformative_Day_0_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReplyInformative_Night_0_en.png | 4 ++-- ...components_TimelineItemEventRowWithReplyOther_Day_0_en.png | 4 ++-- ...mponents_TimelineItemEventRowWithReplyOther_Night_0_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_0_en.png | 4 ++-- ...ine.components_TimelineItemEventRowWithReply_Day_10_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_2_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_4_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_6_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_8_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_0_en.png | 4 ++-- ...e.components_TimelineItemEventRowWithReply_Night_10_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_2_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_4_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_6_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_8_en.png | 4 ++-- ...references.impl.blockedusers_BlockedUsersView_Day_4_en.png | 4 ++-- ...ferences.impl.blockedusers_BlockedUsersView_Night_5_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_6_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_5_en.png | 4 ++-- ...eme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png | 4 ++-- ...em.theme.components_HorizontalFloatingToolbar_Day_0_en.png | 4 ++-- 28 files changed, 59 insertions(+), 50 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ActiveCallTimelineItemView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ActiveCallTimelineItemView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ActiveCallTimelineItemView_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png index 9c425cec6e..45011fea4d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:290a2be6838445739b0181006f9fea87337a85cfed3573c153e9f503c66624a6 -size 4994 +oid sha256:eede6f990a7a1dbddee1cd9e722b30600160d475ad2ae72faebcb773f52aaa7b +size 20793 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 index 0ccdcbb603..160d58f9ec 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0424685437a433b35b589668b409d55f26ab41bcae01af0121a54033c56a8c2 -size 646194 +oid sha256:c4e7b28b78cfbcbb6abf00317eea945859ac6465cecf81a3ad15801b0de721e4 +size 646216 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ActiveCallTimelineItemView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ActiveCallTimelineItemView_Day_0_en.png new file mode 100644 index 0000000000..947dc86c51 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ActiveCallTimelineItemView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c24d5387bfc751396e258d4c53ac84547fb9f18f00d12e506fb747b1867aa4b +size 59223 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ActiveCallTimelineItemView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ActiveCallTimelineItemView_Night_0_en.png new file mode 100644 index 0000000000..c19b613595 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ActiveCallTimelineItemView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da8763d8164555fb531238f70df3565831fca93208b44e737b8da13711bda1c3 +size 59450 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ActiveCallTimelineItemView_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ActiveCallTimelineItemView_en.png new file mode 100644 index 0000000000..38d7dcda9e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_ActiveCallTimelineItemView_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:757bf94f152cd24e33871165b57f3bd5c0e5e3d0666009b0be8a344c3b24599f +size 50275 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 0435f55de6..ab6392a424 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:ff839731834d7d0c94fa9a2c412014ddbaeaa053c5af1c8cbd00a3f3a583f364 -size 379511 +oid sha256:94f89a37549a3f198442db467bc7d8539f0b5649d97927bfe731f090d6dfb03d +size 379505 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 1f0fdabe6d..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:b8bb5a6de6601da8d7fe59f110a054577e2e25dae4bb449f60c04e7d7a1b9551 -size 365073 +oid sha256:1a94d5198e27338675c0e15df5874ba3272ee315b8d77291dc7ccc7c754ed1f4 +size 365082 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 058a3992c3..29771235f0 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:00fe1e676086766a3eac3e4457eff52c989789fc5d8d0df2624c019ed25ce9af -size 363322 +oid sha256:60b9f2b920cd2a2a414805d1f0f77925232d9ae60bd607fa18d4395cda2dd73d +size 363291 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 84d9d4e5c3..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:7c609a633ab23eae5729ecb57a17a385bac65e81cbf0180c01e0847f1028039e -size 347890 +oid sha256:36d7cf2510d546d2b330b1d1b1674ce58df0558c547e443794a1e7b2222add87 +size 347897 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 bac23aab98..22ff4965d1 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:e30686c7c037ef102717e0316543faf4d3ed2671c21eca96a667150daab380d6 -size 346614 +oid sha256:787151f8f242a8794a804bf14831f6ca680814d617e85feb3652103e8a0f20cd +size 346565 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 01d4dca84b..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:ef2bf449671b652cb152b3baab92ab100eab77a54229ab49daeab156f2f484d0 -size 369724 +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 f0dfbc3321..1600afff71 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:f7a6302320bd1e4258e03487539bf46b0b12781dfc8a22b3f9f267017a6146fa -size 354751 +oid sha256:273351cc9c533b2424859a0de00a8a3786628abc3a88175705c4205dedf7e9aa +size 354737 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 8aa2cca147..1b99468924 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:02ecb903124273e24151ea2088f6b99144f7dcadba00a582b6210dd23835b5c9 -size 357743 +oid sha256:3a9509411777f342261cab58b92a022b3c9f8f0f7a9e4d0527120a91976575f0 +size 357733 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 a332744358..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:588967869cbd25ed8b82aff5618175660a8a9e45a5a861b1c7867cf1913f575b -size 364646 +oid sha256:a11044fe90227f1f316a1ade8587e545bb620e11cca76865fc2eb83cdb817fc5 +size 364655 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 0041a870b9..63bd9c3f6d 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:a2bd77c08be705c66225f16c29fd6826decd92b41922d0f8ffc0d1a63d8c59d2 -size 356193 +oid sha256:a6cd94664f89bdad2a9761ea8b20acb83fed3ed7cb5be41af8fe4852643c0bfc +size 356175 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 6e83d6491d..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:34152c742abc486a48234e22101833bc163cf11979890d06aac41e68e3c404d0 -size 364846 +oid sha256:a00bd766a00b7e7c6615fc53bf469b3ca5056a6c514c096431ae38d99d604306 +size 364845 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 77abe20982..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:5c3d87862c6d7fc88d0f23cd54c5b9f77028992fdd7c282a195b964dd17e85ac -size 367855 +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 1d34761a9b..448bcec677 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:f7d9b5fc0ff5d7828ad6f4dc0c9bd9520b4920553da97ed7b4e030ee844c0208 -size 353054 +oid sha256:fe0daf9161bc2da194992a2fc9505bf2009c5dbed78cdb35d2eb7ed1380a7df5 +size 353037 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 ceca184bd7..5560c21967 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:8e82011a72f36889c53ab61ed2b9947c7fb5f868c9b7010904fc10f4ca587082 -size 356082 +oid sha256:af4a48ee80535f2c0a226c4ffa4344054fb63b7b0a88ea2c030a4eb8dd5e9644 +size 356078 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 a431a9429a..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:93c2df04d65f6078ce3f7067fbae8a7317ec42ed0fc013dee962a3953269f3b7 -size 362813 +oid sha256:66d4b6ea4a697735bbb0fac936b89cde99c5077973ba828894bf50b5dae233b3 +size 362848 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 ae8495618a..aa322fc2e4 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:08057fdc1e1184720b438ddd2a8753f00791baf2456cc30b45de8e6bdeb57e8e -size 354404 +oid sha256:5fae87094ea13b14e2dc7c16ca96e4f8096ff39e962799468fb4ead4c666620f +size 354381 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 1a8ea3e4e9..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:66aba7b4271a990fac85b0bbc7cbdc371fa1e38a4da5bb4e2f62a80b21cb3a8f -size 363012 +oid sha256:545c9e8933e420cc3f8fbba0fbd5162c946c65a20721faeb77c568596ca720cd +size 363045 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png index 7cca911c45..074820e157 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26e14b77fa3c3aeaea58782309e6de8b9047e07945009322990ebf5f4c283309 -size 52770 +oid sha256:7caacb336793b8ae4b83e9a10a82325e25e8b3c036f881898ed28688250eb6e0 +size 55744 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png index 616c06bf46..36d19c6b72 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ce2519906f1aaf34700ca9ba4bdeaa72030f1f5aff3f7e24352a1435ac67d98 -size 53966 +oid sha256:7dfa2767c55a81d3f121b8fa55443b7b05f9369e91639b80e0be349863799ad7 +size 55438 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png index 0ca6f66438..f831ed92a2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5896eb5df6f5398bdb94e74280d0d5c04b6a5a53c2378b7377c60fa58eef544b -size 12013 +oid sha256:7fe1f51d385bba8821dfc0f0da84990cf0d148e991d765484b343d8764abd47d +size 11724 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index fb72cafe03..1e04c3e7d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ef1b643a16b5a94c75f8bb845c36d3cbc7f7ed96a0cac32fdb9f0b09d26b4d1 -size 11747 +oid sha256:6bbc8c05e6f6818d00282228f52424ebe93e6e3dca3431d742e8c652d56460d6 +size 11712 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png index 58546b8522..ee5c582240 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30357bf18792db5ab20085010251170a724ffe8c00313facd04ee704e806af64 -size 10982 +oid sha256:75de341f705bb22955f9399180519b65ad59c2e1917317d56e50ea4db78f35bc +size 12102 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png index 83302d6ba4..38ad0e4b56 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:16dee1dfe746cd40dac9fe8f0af3ecb42cd14bab5cc490917b589beed065ed1b -size 14686 +oid sha256:326d59cf768b2dbd96eb7964d54c8eda509a5cd57c6e62087625e3314da0bb4d +size 13658 From f005693874c541dcfeb16e9451c28a311bfce46d Mon Sep 17 00:00:00 2001 From: Thirumani Vihaan Date: Thu, 16 Jul 2026 20:20:58 +0530 Subject: [PATCH 142/383] Fix #7181: Remove back arrow from device verified screen and use 'Done' text (#7222) * Fix #7181: Remove back arrow from device verified screen and use 'Done' text * Update screenshots * Fix failing Maestro test by tapping 'Done' instead of 'Continue' --------- Co-authored-by: ElementBot Co-authored-by: thirumani-vihaan --- .maestro/tests/account/verifySession.yaml | 2 +- .../impl/outgoing/OutgoingVerificationView.kt | 15 +++++++++------ .../impl/outgoing/OutgoingVerificationViewTest.kt | 8 ++++---- ...utgoing_OutgoingVerificationView_Day_10_en.png | 4 ++-- ...utgoing_OutgoingVerificationView_Day_11_en.png | 4 ++-- ...going_OutgoingVerificationView_Night_10_en.png | 4 ++-- ...going_OutgoingVerificationView_Night_11_en.png | 4 ++-- 7 files changed, 22 insertions(+), 19 deletions(-) diff --git a/.maestro/tests/account/verifySession.yaml b/.maestro/tests/account/verifySession.yaml index 20b3d1b8ac..456627f742 100644 --- a/.maestro/tests/account/verifySession.yaml +++ b/.maestro/tests/account/verifySession.yaml @@ -16,4 +16,4 @@ appId: ${MAESTRO_APP_ID} - extendedWaitUntil: visible: "Device verified" timeout: 30000 -- tapOn: "Continue" +- tapOn: "Done" 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 1c199f8826..9131ad63fb 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 @@ -66,7 +66,8 @@ fun OutgoingVerificationView( fun cancelOrResetFlow() { when (step) { is Step.Canceled -> state.eventSink(OutgoingVerificationViewEvents.Reset) - Step.Initial, Step.Completed -> onBack() + Step.Initial -> onBack() + Step.Completed -> onFinish() Step.Ready, is Step.AwaitingOtherDeviceResponse -> state.eventSink(OutgoingVerificationViewEvents.Cancel) is Step.Verifying -> { if (!step.state.isLoading()) { @@ -96,7 +97,9 @@ fun OutgoingVerificationView( TopAppBar( title = {}, navigationIcon = { - BackButton(onClick = ::cancelOrResetFlow) + if (step !is Step.Completed) { + BackButton(onClick = ::cancelOrResetFlow) + } }, colors = topAppBarColors(containerColor = Color.Transparent), ) @@ -108,7 +111,7 @@ fun OutgoingVerificationView( OutgoingVerificationBottomMenu( state = state, onCancelClick = ::cancelOrResetFlow, - onContinueClick = onFinish, + onDoneClick = onFinish, ) }, isScrollable = true, @@ -244,7 +247,7 @@ private fun ContentInitial( private fun OutgoingVerificationBottomMenu( state: OutgoingVerificationState, onCancelClick: () -> Unit, - onContinueClick: () -> Unit, + onDoneClick: () -> Unit, ) { val eventSink = state.eventSink when (val step = state.step) { @@ -313,8 +316,8 @@ private fun OutgoingVerificationBottomMenu( VerificationBottomMenu { Button( modifier = Modifier.fillMaxWidth(), - text = stringResource(CommonStrings.action_continue), - onClick = onContinueClick, + text = stringResource(CommonStrings.action_done), + onClick = onDoneClick, ) InvisibleButton() } 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 311b9c795e..2b5ec63ced 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 @@ -99,10 +99,10 @@ class OutgoingVerificationViewTest : RobolectricTest() { } @Test - fun `back key pressed - on Completed exits the flow`() = runAndroidComposeUiTest { + fun `back key pressed - on Completed finishes the flow`() = runAndroidComposeUiTest { ensureCalledOnce { callback -> setOutgoingVerificationView( - onBack = callback, + onFinished = callback, state = anOutgoingVerificationState( step = OutgoingVerificationState.Step.Completed, ), @@ -112,7 +112,7 @@ class OutgoingVerificationViewTest : RobolectricTest() { } @Test - fun `when flow is completed and the user clicks on the continue button, the expected callback is invoked`() = runAndroidComposeUiTest { + fun `when flow is completed and the user clicks on the done button, the expected callback is invoked`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { callback -> setOutgoingVerificationView( @@ -122,7 +122,7 @@ class OutgoingVerificationViewTest : RobolectricTest() { ), onFinished = callback, ) - clickOn(CommonStrings.action_continue) + clickOn(CommonStrings.action_done) } } diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en.png index 985c931a4c..9d1a89e07b 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c41e73e5672477877ad2fdf17f54373ccac938fe71b2d9b3e53a191b6c658ab -size 26697 +oid sha256:917a2f98fd8feef075587d4176020e98aa6834d39423e29ddaf5f10244a6ffed +size 25647 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en.png index f2ee878314..ab703510df 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd79cc12515daa43485e6b412e0e98dd3bb9f90882d173c6b48a85de36977afe -size 26164 +oid sha256:dddee8fbcb6e9ddead24c66b0e15b4e9fb1b5d8b56eba4dda369755769c2b92e +size 25128 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en.png index ffb648a554..4ca95f531b 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c8f9b413f870e28b65528fefcdd879f687ff6b485e57ffa3b53fac9dc5b8724d -size 26036 +oid sha256:b1a4e54a3f7154294b772f647d9bebdb3a8ec149996a308fe7e6b610c0854a80 +size 25072 diff --git a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en.png index a826b396ca..54a166cff5 100644 --- a/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1721ac66d58b99333061ee6148d5b242eea75eda7137076c4632a52a11720252 -size 25422 +oid sha256:d13b603195be9d91383818fbc0fa79ec533256305092c6c7433c4cc8e17d1fe5 +size 24446 From 9c99b020de46978f33d8a7bf02e62ef2bb98b264 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 Jul 2026 10:52:40 +0200 Subject: [PATCH 143/383] Update dependency com.google.crypto.tink:tink-android to v1.23.0 (#7229) 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 76e384ddd1..fac8c2b40d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -88,7 +88,7 @@ google_firebase_bom = "com.google.firebase:firebase-bom:34.15.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.22.0" +google_tink = "com.google.crypto.tink:tink-android:1.23.0" jna = "net.java.dev.jna:jna:5.19.1" # AndroidX From 87890ea30b30757b28c29f824bc2147bb99ec872 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 Jul 2026 11:42:14 +0200 Subject: [PATCH 144/383] Update kotlin to v2.3.10 (#7234) 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 fac8c2b40d..45599f5061 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ android_gradle_plugin = "9.2.1" # When updating this, please also update the version in the file ./idea/kotlinc.xml kotlin = "2.4.0" kotlinpoet = "2.3.0" -ksp = "2.3.9" +ksp = "2.3.10" firebaseAppDistribution = "5.3.0" # AndroidX From 584e5097fd368cba1a746c6cd36caa5b0d1c7b52 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 17 Jul 2026 14:15:15 +0200 Subject: [PATCH 145/383] Group Element Pro changes into a dedicated release notes section Pro-only PRs (labelled pr-element-pro) leaked into Element X release notes, causing confusion. They now group into a single Element Pro section instead of scattering through Features/Bugfixes. Granularity is dropped on purpose for these changes. --- .github/release.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/release.yml b/.github/release.yml index 17090ec328..8f1d04ac9d 100644 --- a/.github/release.yml +++ b/.github/release.yml @@ -28,6 +28,10 @@ changelog: labels: - PR-Dependencies + - title: 💼 Element Pro + labels: + - PR-Element-Pro + - title: Others labels: - PR-misc From 2705efad15a2051e56f4fdd7fea005c9371897e6 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 17 Jul 2026 15:26:13 +0200 Subject: [PATCH 146/383] Add content scanner support to media gallery and viewer (Element Pro) (#7233) * Add content scanner support to media gallery and viewer * Improve UI and previews * Remove default content validation state in media content views * Disable click for invalid media items in the gallery events * Update screenshots --------- Co-authored-by: ElementBot --- .../impl/DefaultContentScannerService.kt | 4 +- .../impl/DefaultContentScannerServiceTest.kt | 4 +- .../components/event/TimelineItemAudioView.kt | 3 +- .../components/event/TimelineItemFileView.kt | 3 +- .../event/TimelineItemGalleryView.kt | 12 +- .../components/event/TimelineItemImageView.kt | 65 ++++---- .../event/TimelineItemStickerView.kt | 5 +- .../components/event/TimelineItemVideoView.kt | 6 +- .../components/event/TimelineItemVoiceView.kt | 4 +- .../ContentValidationState.kt | 1 + .../LocalEventContentValidationState.kt | 6 +- libraries/mediaviewer/impl/build.gradle.kts | 2 + .../impl/datasource/EventItemFactory.kt | 15 ++ .../impl/gallery/MediaGalleryPresenter.kt | 32 ++++ .../impl/gallery/MediaGalleryStateProvider.kt | 30 +++- .../impl/gallery/MediaGalleryView.kt | 83 ++++++++-- .../impl/gallery/ui/AudioItemView.kt | 126 ++++----------- .../impl/gallery/ui/FileItemView.kt | 126 ++++----------- .../impl/gallery/ui/GalleryFileListItem.kt | 152 ++++++++++++++++++ .../impl/gallery/ui/MediaItemAudioProvider.kt | 2 +- .../impl/gallery/ui/MediaItemFileProvider.kt | 2 +- .../impl/gallery/ui/MediaItemVoiceProvider.kt | 2 +- .../impl/gallery/ui/VoiceItemView.kt | 92 +++++++---- .../impl/local/video/MediaVideoView.kt | 48 +++--- .../mediaviewer/impl/model/MediaItem.kt | 16 +- .../impl/model/MediaItemFactories.kt | 15 +- .../viewer/GalleryMediaGalleryDataSource.kt | 6 + .../impl/viewer/MediaViewerDataSource.kt | 27 ++++ .../impl/viewer/MediaViewerEvent.kt | 2 + .../impl/viewer/MediaViewerNode.kt | 14 +- .../impl/viewer/MediaViewerPresenter.kt | 6 +- .../impl/viewer/MediaViewerState.kt | 2 + .../impl/viewer/MediaViewerStateProvider.kt | 33 ++++ .../impl/viewer/MediaViewerView.kt | 117 ++++++++++---- .../viewer/SingleMediaGalleryDataSource.kt | 26 ++- .../impl/DefaultMediaViewerEntryPointTest.kt | 6 + .../impl/datasource/EventItemFactoryTest.kt | 14 ++ .../TimelineMediaGalleryDataSourceTest.kt | 8 +- .../impl/gallery/MediaGalleryPresenterTest.kt | 1 + .../GalleryMediaGalleryDataSourceTest.kt | 13 ++ .../impl/viewer/MediaViewerDataSourceTest.kt | 3 + .../impl/viewer/MediaViewerPresenterTest.kt | 3 + .../SingleMediaGalleryDataSourceTest.kt | 20 ++- ...impl.gallery.ui_AudioItemView_Day_0_en.png | 4 +- ...impl.gallery.ui_AudioItemView_Day_1_en.png | 4 +- ...impl.gallery.ui_AudioItemView_Day_2_en.png | 4 +- ...pl.gallery.ui_AudioItemView_Night_0_en.png | 4 +- ...pl.gallery.ui_AudioItemView_Night_1_en.png | 4 +- ...pl.gallery.ui_AudioItemView_Night_2_en.png | 4 +- ....impl.gallery.ui_FileItemView_Day_0_en.png | 4 +- ....impl.gallery.ui_FileItemView_Day_1_en.png | 4 +- ....impl.gallery.ui_FileItemView_Day_2_en.png | 4 +- ...mpl.gallery.ui_FileItemView_Night_0_en.png | 4 +- ...mpl.gallery.ui_FileItemView_Night_1_en.png | 4 +- ...mpl.gallery.ui_FileItemView_Night_2_en.png | 4 +- ....gallery.ui_VoiceItemViewPlay_Day_0_en.png | 4 +- ....gallery.ui_VoiceItemViewPlay_Day_1_en.png | 4 +- ....gallery.ui_VoiceItemViewPlay_Day_2_en.png | 4 +- ....gallery.ui_VoiceItemViewPlay_Day_3_en.png | 4 +- ....gallery.ui_VoiceItemViewPlay_Day_4_en.png | 4 +- ...allery.ui_VoiceItemViewPlay_Night_0_en.png | 4 +- ...allery.ui_VoiceItemViewPlay_Night_1_en.png | 4 +- ...allery.ui_VoiceItemViewPlay_Night_2_en.png | 4 +- ...allery.ui_VoiceItemViewPlay_Night_3_en.png | 4 +- ...allery.ui_VoiceItemViewPlay_Night_4_en.png | 4 +- ...impl.gallery.ui_VoiceItemView_Day_0_en.png | 4 +- ...impl.gallery.ui_VoiceItemView_Day_1_en.png | 4 +- ...impl.gallery.ui_VoiceItemView_Day_2_en.png | 4 +- ...impl.gallery.ui_VoiceItemView_Day_3_en.png | 4 +- ...pl.gallery.ui_VoiceItemView_Night_0_en.png | 4 +- ...pl.gallery.ui_VoiceItemView_Night_1_en.png | 4 +- ...pl.gallery.ui_VoiceItemView_Night_2_en.png | 4 +- ...pl.gallery.ui_VoiceItemView_Night_3_en.png | 4 +- ...impl.gallery_MediaGalleryView_Day_3_en.png | 4 +- ...impl.gallery_MediaGalleryView_Day_7_en.png | 4 +- ...pl.gallery_MediaGalleryView_Night_3_en.png | 4 +- ...pl.gallery_MediaGalleryView_Night_7_en.png | 4 +- ...pl.local.video_MediaVideoView_Day_0_en.png | 4 +- ....local.video_MediaVideoView_Night_0_en.png | 4 +- ....viewer_MediaViewerViewLandscape_16_en.png | 4 +- ...l.viewer_MediaViewerViewLandscape_1_en.png | 4 +- ....viewer_MediaViewerViewLandscape_23_en.png | 3 + ....viewer_MediaViewerViewLandscape_24_en.png | 3 + ...l.viewer_MediaViewerViewLandscape_6_en.png | 4 +- ...l.viewer_MediaViewerViewLandscape_8_en.png | 4 +- ...ewer.impl.viewer_MediaViewerView_23_en.png | 3 + ...ewer.impl.viewer_MediaViewerView_24_en.png | 3 + ...iewer.impl.viewer_MediaViewerView_8_en.png | 4 +- 88 files changed, 892 insertions(+), 441 deletions(-) create mode 100644 libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/GalleryFileListItem.kt create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_23_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_24_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_23_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_24_en.png diff --git a/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.kt b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.kt index 5cc8b9e315..2765686f9d 100644 --- a/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.kt +++ b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.kt @@ -26,7 +26,7 @@ class DefaultContentScannerService( private val coroutineScope: CoroutineScope, coroutineDispatchers: CoroutineDispatchers, ) : ContentScannerService { - private val context = coroutineDispatchers.io.limitedParallelism(4) + private val dispatcher = coroutineDispatchers.io.limitedParallelism(4) override fun scan(eventId: EventId, mediaSources: List, contentValidationState: ContentValidationState) { for (mediaSource in mediaSources) { @@ -35,7 +35,7 @@ class DefaultContentScannerService( if (currentState != ContentValidationValue.Unknown) continue contentValidationState.update(url, ContentValidationValue.Loading) - coroutineScope.launch(context) { + coroutineScope.launch(dispatcher) { contentScanner.scan(mediaSource) .onSuccess { isValid -> val contentValidationValue = if (isValid) ContentValidationValue.Valid else ContentValidationValue.Invalid diff --git a/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerServiceTest.kt b/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerServiceTest.kt index accdf0ff37..4bd20ebaf8 100644 --- a/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerServiceTest.kt +++ b/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerServiceTest.kt @@ -32,7 +32,7 @@ import java.io.FileNotFoundException @OptIn(ExperimentalCoroutinesApi::class) class DefaultContentScannerServiceTest { @Test - fun `scan with no media sources returns valid`() = runTest { + fun `scan with no media sources returns unknown`() = runTest { val scanLambda = lambdaRecorder> { Result.success(true) } val scanner = FakeContentScanner(scan = scanLambda) val contentValidationState = DefaultContentValidationState() @@ -45,7 +45,7 @@ class DefaultContentScannerServiceTest { ) scanLambda.assertions().isNeverCalled() - assertThat(contentValidationState.getCurrentOverallState()).isEqualTo(ContentValidationValue.Valid) + assertThat(contentValidationState.getCurrentOverallState()).isEqualTo(ContentValidationValue.Unknown) } @Test diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAudioView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAudioView.kt index 1f10a97eda..221ba2ca6f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAudioView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemAudioView.kt @@ -22,8 +22,8 @@ import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentVal fun TimelineItemAudioView( content: TimelineItemAudioContent, onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit, + contentValidationValue: ContentValidationValue, modifier: Modifier = Modifier, - contentValidationValue: ContentValidationValue = ContentValidationValue.Valid, ) { TimelineItemAttachmentView( icon = CompoundIcons.Audio(), @@ -43,5 +43,6 @@ internal fun TimelineItemAudioViewPreview(@PreviewParameter(TimelineItemAudioCon TimelineItemAudioView( content, onContentLayoutChange = {}, + contentValidationValue = ContentValidationValue.Valid, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemFileView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemFileView.kt index a0deec6d84..cd0632282e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemFileView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemFileView.kt @@ -27,8 +27,8 @@ import io.element.android.libraries.ui.strings.CommonStrings fun TimelineItemFileView( content: TimelineItemFileContent, onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit, + contentValidationValue: ContentValidationValue, modifier: Modifier = Modifier, - contentValidationValue: ContentValidationValue = ContentValidationValue.Valid, ) { TimelineItemAttachmentView( icon = CompoundIcons.Attachment(), @@ -48,6 +48,7 @@ internal fun TimelineItemFileViewPreview(@PreviewParameter(TimelineItemFileConte TimelineItemFileView( content, onContentLayoutChange = {}, + contentValidationValue = ContentValidationValue.Valid, ) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryView.kt index 8c4244a651..c7426f6f8d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryView.kt @@ -288,9 +288,15 @@ private fun GalleryItemCell( Box( modifier = modifier .blurHashBackground(item.blurhash, alpha = 0.9f) - .combinedClickable( - onClick = onClick, - onLongClick = onLongClick, + .then( + if (itemContentValidationState.isValid()) { + Modifier.combinedClickable( + onClick = onClick, + onLongClick = onLongClick, + ) + } else { + Modifier + } ), contentAlignment = Alignment.Center, ) { 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 eb5c507779..3e79fd6fd9 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 @@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -43,7 +44,9 @@ 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.matrix.ui.media.contentvalidation.ContentValidationState -import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.LocalEventContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopEventContentValidationCache import io.element.android.libraries.matrix.ui.media.contentvalidation.collectOverallState import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.utils.a11y.isTalkbackActive @@ -55,8 +58,8 @@ fun TimelineItemImageView( onContentClick: (() -> Unit)?, onLongClick: (() -> Unit)?, onShowContentClick: () -> Unit, + contentValidationState: ContentValidationState, modifier: Modifier = Modifier, - contentValidationState: ContentValidationState = remember { DefaultContentValidationState() }, ) { val a11yLabel = stringResource(CommonStrings.common_image) val description = content.caption?.let { "$a11yLabel: $it" } ?: a11yLabel @@ -129,52 +132,56 @@ internal fun TimelineItemImageViewPreview(@PreviewParameter(TimelineItemImageCon onShowContentClick = {}, onContentClick = {}, onLongClick = {}, + contentValidationState = NoopContentValidationState(), ) } @PreviewsDayNight @Composable internal fun TimelineItemImageViewHideMediaContentPreview() = ElementPreview { - TimelineItemImageView( - content = aTimelineItemImageContent(), - hideMediaContent = true, - onShowContentClick = {}, - onContentClick = {}, - onLongClick = {}, - ) + TimelineItemImageView( + content = aTimelineItemImageContent(), + hideMediaContent = true, + onShowContentClick = {}, + onContentClick = {}, + onLongClick = {}, + contentValidationState = NoopContentValidationState(), + ) } @PreviewsDayNight @Composable internal fun ATimelineItemEventRowPreview() = ElementPreview { - Column { - sequenceOf(false, true).forEach { isMine -> + CompositionLocalProvider(LocalEventContentValidationState provides NoopEventContentValidationCache()) { + 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 = 40, + height = 20, + aspectRatio = 40f / 20f, + ), + groupPosition = TimelineItemGroupPosition.Last, + ), + ) + } ATimelineItemEventRow( event = aTimelineItemEvent( - isMine = isMine, + isMine = false, content = aTimelineItemImageContent( filename = "image.jpg", - caption = "A long caption that may wrap into several lines", - width = 40, - height = 20, - aspectRatio = 40f / 20f, + caption = "Narrow image with null aspectRatio", + width = 80, + height = 150, + aspectRatio = null, ), groupPosition = TimelineItemGroupPosition.Last, ), ) } - ATimelineItemEventRow( - event = aTimelineItemEvent( - isMine = false, - content = aTimelineItemImageContent( - filename = "image.jpg", - caption = "Narrow image with null aspectRatio", - width = 80, - height = 150, - aspectRatio = null, - ), - groupPosition = TimelineItemGroupPosition.Last, - ), - ) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemStickerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemStickerView.kt index 76ffda2a15..7e240f8b51 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemStickerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemStickerView.kt @@ -39,7 +39,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.matrix.ui.media.MediaRequestData import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState -import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState import io.element.android.libraries.matrix.ui.media.contentvalidation.collectOverallState import io.element.android.libraries.ui.strings.CommonStrings @@ -52,8 +52,8 @@ fun TimelineItemStickerView( onContentClick: (() -> Unit)?, onLongClick: (() -> Unit)?, onShowClick: () -> Unit, + contentValidationState: ContentValidationState, modifier: Modifier = Modifier, - contentValidationState: ContentValidationState = remember { DefaultContentValidationState() }, ) { val description = content.bestDescription.takeIf { it.isNotEmpty() } ?: stringResource(CommonStrings.common_image) @@ -130,5 +130,6 @@ internal fun TimelineItemStickerViewPreview(@PreviewParameter(TimelineItemSticke onContentClick = {}, onLongClick = {}, onShowClick = {}, + contentValidationState = NoopContentValidationState(), ) } 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 ce97ecc775..b47220fa5e 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 @@ -51,7 +51,7 @@ import io.element.android.libraries.matrix.ui.media.MAX_THUMBNAIL_HEIGHT 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.matrix.ui.media.contentvalidation.ContentValidationState -import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState import io.element.android.libraries.matrix.ui.media.contentvalidation.collectOverallState import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.utils.a11y.isTalkbackActive @@ -63,8 +63,8 @@ fun TimelineItemVideoView( onContentClick: (() -> Unit)?, onLongClick: (() -> Unit)?, onShowContentClick: () -> Unit, + contentValidationState: ContentValidationState, modifier: Modifier = Modifier, - contentValidationState: ContentValidationState = remember { DefaultContentValidationState() }, ) { val isTalkbackActive = isTalkbackActive() val a11yLabel = stringResource(CommonStrings.common_video) @@ -157,6 +157,7 @@ internal fun TimelineItemVideoViewPreview(@PreviewParameter(TimelineItemVideoCon onShowContentClick = {}, onContentClick = {}, onLongClick = {}, + contentValidationState = NoopContentValidationState(), ) } @@ -169,5 +170,6 @@ internal fun TimelineItemVideoViewHideMediaContentPreview() = ElementPreview { onShowContentClick = {}, onContentClick = {}, onLongClick = {}, + contentValidationState = NoopContentValidationState(), ) } 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 67f1cbfa96..15387f51c0 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 @@ -64,8 +64,8 @@ fun TimelineItemVoiceView( state: VoiceMessageState, content: TimelineItemVoiceContent, onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit, + contentValidationValue: ContentValidationValue, modifier: Modifier = Modifier, - contentValidationValue: ContentValidationValue = ContentValidationValue.Valid, ) { fun playPause() { state.eventSink(VoiceMessageEvent.PlayPause) @@ -289,6 +289,7 @@ internal fun TimelineItemVoiceViewPreview( state = timelineItemVoiceViewParameters.state, content = timelineItemVoiceViewParameters.content, onContentLayoutChange = {}, + contentValidationValue = ContentValidationValue.Valid, ) } @@ -302,6 +303,7 @@ internal fun TimelineItemVoiceViewUnifiedPreview() = ElementPreview { state = it.state, content = it.content, onContentLayoutChange = {}, + contentValidationValue = ContentValidationValue.Valid, ) } } diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentValidationState.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentValidationState.kt index c0afa69d1a..bbaf52f5b0 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentValidationState.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentValidationState.kt @@ -116,6 +116,7 @@ class DefaultContentValidationState( private fun calculateOverallState(states: Map): ContentValidationValue { return when { + states.values.isEmpty() -> ContentValidationValue.Unknown states.values.any { it is ContentValidationValue.Invalid } -> ContentValidationValue.Invalid states.values.any { it is ContentValidationValue.Loading } -> ContentValidationValue.Loading states.values.any { it is ContentValidationValue.UnrecoverableError } -> states.values.first { it is ContentValidationValue.UnrecoverableError } diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/LocalEventContentValidationState.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/LocalEventContentValidationState.kt index ab7f6da042..f5277a3537 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/LocalEventContentValidationState.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/LocalEventContentValidationState.kt @@ -26,8 +26,10 @@ val LocalEventContentValidationState = staticCompositionLocalOf { @@ -138,6 +144,7 @@ class EventItemFactory( mediaSource = c.source, thumbnailSource = c.info?.thumbnailSource, blurHash = c.info?.blurhash, + validationState = validationState, ) } is GalleryItemType.Audio -> { @@ -156,6 +163,7 @@ class EventItemFactory( dateSentFull = dateSentFull, ), mediaSource = c.source, + validationState = validationState, ) } is GalleryItemType.File -> { @@ -174,6 +182,7 @@ class EventItemFactory( dateSentFull = dateSentFull, ), mediaSource = c.source, + validationState = validationState, ) } is GalleryItemType.Other -> null @@ -200,6 +209,7 @@ class EventItemFactory( duration = null, ), mediaSource = type.source, + validationState = validationState, )) is FileMessageType -> listOf(MediaItem.File( id = currentTimelineItem.uniqueId, @@ -221,6 +231,7 @@ class EventItemFactory( duration = null, ), mediaSource = type.source, + validationState = validationState, // TODO We may want to add a thumbnailSource and set it to type.info?.thumbnailSource )) is ImageMessageType -> listOf(MediaItem.Image( @@ -245,6 +256,7 @@ class EventItemFactory( mediaSource = type.source, thumbnailSource = type.info?.thumbnailSource, blurHash = type.info?.blurhash, + validationState = validationState, )) is StickerMessageType -> listOf(MediaItem.Image( id = currentTimelineItem.uniqueId, @@ -268,6 +280,7 @@ class EventItemFactory( mediaSource = type.source, thumbnailSource = type.info?.thumbnailSource, blurHash = type.info?.blurhash, + validationState = validationState, )) is VideoMessageType -> listOf(MediaItem.Video( id = currentTimelineItem.uniqueId, @@ -291,6 +304,7 @@ class EventItemFactory( mediaSource = type.source, thumbnailSource = type.info?.thumbnailSource, blurHash = type.info?.blurhash, + validationState = validationState, )) is VoiceMessageType -> listOf(MediaItem.Voice( id = currentTimelineItem.uniqueId, @@ -312,6 +326,7 @@ class EventItemFactory( duration = type.info?.duration?.inWholeMilliseconds?.toHumanReadableDuration(), ), mediaSource = type.source, + validationState = validationState, )) } } 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 25e27330b4..2add4630e7 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 @@ -20,6 +20,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.contentscanner.api.ContentScannerService import io.element.android.libraries.androidutils.R import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter @@ -43,7 +44,11 @@ import io.element.android.libraries.mediaviewer.impl.model.eventId import io.element.android.libraries.mediaviewer.impl.model.mediaInfo import io.element.android.libraries.mediaviewer.impl.model.mediaPermissions import io.element.android.libraries.mediaviewer.impl.model.mediaSource +import io.element.android.libraries.mediaviewer.impl.model.thumbnailSource import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @AssistedInject @@ -55,6 +60,7 @@ class MediaGalleryPresenter( private val mediaLoader: MatrixMediaLoader, private val localMediaActions: LocalMediaActions, private val snackbarDispatcher: SnackbarDispatcher, + private val contentScannerService: ContentScannerService, ) : Presenter { @AssistedFactory interface Factory { @@ -74,6 +80,17 @@ class MediaGalleryPresenter( val groupedMediaItems by remember { mediaGalleryDataSource.groupedMediaItemsFlow() + .onEach { groupedItems -> + if (groupedItems is AsyncData.Success) { + val items = groupedItems.data.getItems(mode) + items.forEach { item -> + if (item is MediaItem.Event) { + val eventId = item.eventId() ?: return@forEach + coroutineScope.validateMedia(eventId, item) + } + } + } + } } .collectAsState(AsyncData.Uninitialized) @@ -220,6 +237,21 @@ class MediaGalleryPresenter( } } + private fun CoroutineScope.validateMedia(eventId: EventId, mediaItem: MediaItem.Event) { + launch { + val thumbnailSource = mediaItem.thumbnailSource() + val mediaSource = mediaItem.mediaSource() + val contentValidationState = mediaItem.validationState + val currentState = contentValidationState.overallStateFlow.first() + + if (currentState.isLoading() || currentState.isValid()) { + return@launch + } + + contentScannerService.scan(eventId, listOfNotNull(thumbnailSource, mediaSource).distinct(), contentValidationState) + } + } + 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/MediaGalleryStateProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/MediaGalleryStateProvider.kt index 75b849cd0c..43a361ac29 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,6 +13,8 @@ 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.matrix.ui.media.contentvalidation.ContentValidationValue +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState import io.element.android.libraries.mediaviewer.impl.details.aMediaBottomSheetStateDetails import io.element.android.libraries.mediaviewer.impl.model.GroupedMediaItems @@ -47,9 +49,20 @@ open class MediaGalleryStateProvider : PreviewParameterProvider + val contentValidationState = remember(item is MediaItem.Event) { + if (item is MediaItem.Event) { + item.validationState + } else { + NoopContentValidationState() + } + } + val contentValidationValue by contentValidationState.collectOverallState() when (item) { is MediaItem.File -> FileItemView( modifier = Modifier.animateItem(), @@ -323,6 +342,7 @@ private fun MediaGalleryFilesList( onLongClick = { eventSink(MediaGalleryEvent.OpenInfo(item)) }, + contentValidationState = contentValidationValue, ) is MediaItem.Audio -> AudioItemView( modifier = Modifier.animateItem(), @@ -331,6 +351,7 @@ private fun MediaGalleryFilesList( onLongClick = { eventSink(MediaGalleryEvent.OpenInfo(item)) }, + contentValidationValue = contentValidationValue, ) is MediaItem.Voice -> { val presenter: Presenter = presenterFactories.rememberPresenter(item) @@ -341,16 +362,17 @@ private fun MediaGalleryFilesList( onLongClick = { eventSink(MediaGalleryEvent.OpenInfo(item)) }, + contentValidationValue = contentValidationValue, ) } + is MediaItem.Image, + is MediaItem.Video -> { + // Should not happen + } is MediaItem.DateSeparator -> DateItemView( modifier = Modifier.animateItem(), item = item ) - is MediaItem.Image, - is MediaItem.Video -> { - // Should not happen - } is MediaItem.LoadingIndicator -> LoadingMoreIndicator( modifier = Modifier.animateItem(), item = item, @@ -387,11 +409,48 @@ private fun MediaGalleryImageGrid( key = { it.id() }, contentType = { it::class.java }, ) { item -> + val blurHash = when (item) { + is MediaItem.Image -> item.blurHash + is MediaItem.Video -> item.blurHash + else -> null + } + + val blurHashBackgroundModifier = if (blurHash != null) { + Modifier.blurHashBackground(blurHash) + } else { + Modifier + } + + val currentValidationState by when (item) { + is MediaItem.Event -> item.validationState.collectOverallState() + else -> remember { mutableStateOf(ContentValidationValue.Unknown) } + } + when (item) { - is MediaItem.DateSeparator -> DateItemView( - modifier = Modifier.animateItem(), - item = item, - ) + is MediaItem.Event if !currentValidationState.isValidated() -> { + Box(modifier = blurHashBackgroundModifier.aspectRatio(1f), contentAlignment = Alignment.Center) { + CircularProgressIndicator( + modifier = Modifier.size(24.dp), + strokeWidth = 2.dp, + ) + } + } + is MediaItem.Event if currentValidationState.isInvalid() -> { + Box( + modifier = Modifier + .clickable { onItemClick(item) } + .background(ElementTheme.colors.bgCriticalSubtle) + .aspectRatio(1f), + contentAlignment = Alignment.Center, + ) { + Icon( + modifier = Modifier.size(24.dp), + imageVector = CompoundIcons.Error(), + tint = ElementTheme.colors.iconCriticalPrimary, + contentDescription = null, + ) + } + } is MediaItem.Audio -> { // Should not happen } @@ -402,7 +461,7 @@ private fun MediaGalleryImageGrid( // Should not happen } is MediaItem.Image -> ImageItemView( - modifier = Modifier.animateItem(), + modifier = blurHashBackgroundModifier.animateItem(), image = item, onClick = { onItemClick(item) }, onLongClick = { @@ -410,13 +469,17 @@ private fun MediaGalleryImageGrid( }, ) is MediaItem.Video -> VideoItemView( - modifier = Modifier.animateItem(), + modifier = blurHashBackgroundModifier.animateItem(), video = item, onClick = { onItemClick(item) }, onLongClick = { eventSink(MediaGalleryEvent.OpenInfo(item)) }, ) + is MediaItem.DateSeparator -> DateItemView( + modifier = Modifier.animateItem(), + item = item, + ) is MediaItem.LoadingIndicator -> LoadingMoreIndicator( modifier = Modifier.animateItem(), item = item, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/AudioItemView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/AudioItemView.kt index ed4e59d631..cda8422e33 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/AudioItemView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/AudioItemView.kt @@ -8,117 +8,38 @@ package io.element.android.libraries.mediaviewer.impl.gallery.ui -import androidx.compose.foundation.background -import androidx.compose.foundation.combinedClickable 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.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -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 -import io.element.android.libraries.core.extensions.withBrackets -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.theme.components.HorizontalDivider -import io.element.android.libraries.designsystem.theme.components.Icon -import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue import io.element.android.libraries.mediaviewer.impl.model.MediaItem -import io.element.android.libraries.ui.strings.CommonStrings @Composable fun AudioItemView( audio: MediaItem.Audio, onClick: () -> Unit, onLongClick: () -> Unit, + contentValidationValue: ContentValidationValue, modifier: Modifier = Modifier, ) { - Column( - modifier = modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), + GalleryFileListItem( + modifier = modifier, + contentValidationValue = contentValidationValue, + caption = audio.mediaInfo.caption, ) { - Spacer(modifier = Modifier.height(20.dp)) - FilenameRow( - audio = audio, + GalleryFileListItemContent( + name = audio.mediaInfo.filename, + formattedSize = audio.mediaInfo.formattedFileSize, + icon = CompoundIcons.Audio(), + isValidating = contentValidationValue.isLoading(), onClick = onClick, onLongClick = onLongClick, ) - val caption = audio.mediaInfo.caption - if (caption != null) { - CaptionView(caption) - } else { - Spacer(modifier = Modifier.height(20.dp)) - } - HorizontalDivider() - } -} - -@Composable -private fun FilenameRow( - audio: MediaItem.Audio, - onClick: () -> Unit, - onLongClick: () -> Unit, -) { - Row( - modifier = Modifier - .clip(RoundedCornerShape(12.dp)) - .background( - color = ElementTheme.colors.bgSubtleSecondary, - shape = RoundedCornerShape(12.dp), - ) - .combinedClickable( - onClick = onClick, - onLongClick = onLongClick, - onLongClickLabel = stringResource(CommonStrings.action_open_context_menu), - ) - .onKeyboardContextMenuAction(onLongClick) - .fillMaxWidth() - .padding(start = 12.dp, end = 36.dp, top = 8.dp, bottom = 8.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Icon( - modifier = Modifier - .background( - color = ElementTheme.colors.bgActionSecondaryRest, - shape = CircleShape, - ) - .size(32.dp) - .padding(6.dp), - imageVector = CompoundIcons.Audio(), - contentDescription = null, - ) - Spacer(modifier = Modifier.width(8.dp)) - Text( - text = audio.mediaInfo.filename, - modifier = Modifier.weight(1f), - style = ElementTheme.typography.fontBodyLgRegular, - color = ElementTheme.colors.textPrimary, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - val formattedSize = audio.mediaInfo.formattedFileSize - if (formattedSize.isNotEmpty()) { - Text( - text = formattedSize.withBrackets(), - style = ElementTheme.typography.fontBodyLgRegular, - color = ElementTheme.colors.textPrimary, - ) - } } } @@ -127,9 +48,22 @@ private fun FilenameRow( internal fun AudioItemViewPreview( @PreviewParameter(MediaItemAudioProvider::class) audio: MediaItem.Audio, ) = ElementPreview { - AudioItemView( - audio = audio, - onClick = {}, - onLongClick = {}, - ) + val states = remember { + listOf( + ContentValidationValue.Valid, + ContentValidationValue.Loading, + ContentValidationValue.Invalid, + ContentValidationValue.UnrecoverableError(Throwable("Unrecoverable error")), + ) + } + Column { + for (state in states) { + AudioItemView( + contentValidationValue = state, + audio = audio, + onClick = {}, + onLongClick = {}, + ) + } + } } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/FileItemView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/FileItemView.kt index 7738e4c1e4..b552c374b9 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/FileItemView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/FileItemView.kt @@ -8,117 +8,38 @@ package io.element.android.libraries.mediaviewer.impl.gallery.ui -import androidx.compose.foundation.background -import androidx.compose.foundation.combinedClickable 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.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -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 -import io.element.android.libraries.core.extensions.withBrackets -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.theme.components.HorizontalDivider -import io.element.android.libraries.designsystem.theme.components.Icon -import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue import io.element.android.libraries.mediaviewer.impl.model.MediaItem -import io.element.android.libraries.ui.strings.CommonStrings @Composable fun FileItemView( file: MediaItem.File, onClick: () -> Unit, onLongClick: () -> Unit, + contentValidationState: ContentValidationValue, modifier: Modifier = Modifier, ) { - Column( - modifier = modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), + GalleryFileListItem( + modifier = modifier, + contentValidationValue = contentValidationState, + caption = file.mediaInfo.caption ) { - Spacer(modifier = Modifier.height(20.dp)) - FilenameRow( - file = file, + GalleryFileListItemContent( + name = file.mediaInfo.filename, + formattedSize = file.mediaInfo.formattedFileSize, + icon = CompoundIcons.Attachment(), onClick = onClick, + isValidating = contentValidationState.isLoading(), onLongClick = onLongClick, ) - val caption = file.mediaInfo.caption - if (caption != null) { - CaptionView(caption) - } else { - Spacer(modifier = Modifier.height(20.dp)) - } - HorizontalDivider() - } -} - -@Composable -private fun FilenameRow( - file: MediaItem.File, - onClick: () -> Unit, - onLongClick: () -> Unit, -) { - Row( - modifier = Modifier - .clip(RoundedCornerShape(12.dp)) - .background( - color = ElementTheme.colors.bgSubtleSecondary, - shape = RoundedCornerShape(12.dp), - ) - .combinedClickable( - onClick = onClick, - onLongClick = onLongClick, - onLongClickLabel = stringResource(CommonStrings.action_open_context_menu), - ) - .onKeyboardContextMenuAction(onLongClick) - .fillMaxWidth() - .padding(start = 12.dp, end = 36.dp, top = 8.dp, bottom = 8.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Icon( - modifier = Modifier - .background( - color = ElementTheme.colors.bgActionSecondaryRest, - shape = CircleShape, - ) - .size(32.dp) - .padding(6.dp), - imageVector = CompoundIcons.Attachment(), - contentDescription = null, - ) - Spacer(modifier = Modifier.width(8.dp)) - Text( - text = file.mediaInfo.filename, - modifier = Modifier.weight(1f), - style = ElementTheme.typography.fontBodyLgRegular, - color = ElementTheme.colors.textPrimary, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - val formattedSize = file.mediaInfo.formattedFileSize - if (formattedSize.isNotEmpty()) { - Text( - text = formattedSize.withBrackets(), - style = ElementTheme.typography.fontBodyLgRegular, - color = ElementTheme.colors.textPrimary, - ) - } } } @@ -127,9 +48,22 @@ private fun FilenameRow( internal fun FileItemViewPreview( @PreviewParameter(MediaItemFileProvider::class) file: MediaItem.File, ) = ElementPreview { - FileItemView( - file = file, - onClick = {}, - onLongClick = {}, - ) + val states = remember { + listOf( + ContentValidationValue.Valid, + ContentValidationValue.Loading, + ContentValidationValue.Invalid, + ContentValidationValue.UnrecoverableError(Throwable("Unrecoverable error")), + ) + } + Column { + for (state in states) { + FileItemView( + file = file, + onClick = {}, + onLongClick = {}, + contentValidationState = state, + ) + } + } } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/GalleryFileListItem.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/GalleryFileListItem.kt new file mode 100644 index 0000000000..383f32653e --- /dev/null +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/GalleryFileListItem.kt @@ -0,0 +1,152 @@ +/* + * 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.gallery.ui + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.combinedClickable +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.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.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.graphics.vector.ImageVector +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.libraries.core.extensions.withBrackets +import io.element.android.libraries.designsystem.modifiers.onKeyboardContextMenuAction +import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator +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 +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue +import io.element.android.libraries.matrix.ui.media.contentvalidation.InvalidContentView +import io.element.android.libraries.matrix.ui.media.contentvalidation.NotFoundContentView +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +internal fun GalleryFileListItem( + contentValidationValue: ContentValidationValue, + caption: String?, + modifier: Modifier = Modifier, + content: @Composable () -> Unit, +) { + Column( + modifier = modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + ) { + Spacer(modifier = Modifier.height(20.dp)) + + when (contentValidationValue) { + ContentValidationValue.Invalid -> InvalidContentView( + modifier = invalidContentModifier(), + contentPadding = PaddingValues(horizontal = 12.dp, vertical = 8.dp), + ) + is ContentValidationValue.UnrecoverableError -> NotFoundContentView( + modifier = invalidContentModifier(), + contentPadding = PaddingValues(horizontal = 12.dp, vertical = 8.dp), + ) + else -> { + content() + } + } + + if (caption != null) { + CaptionView(caption) + } else { + Spacer(modifier = Modifier.height(20.dp)) + } + HorizontalDivider() + } +} + +@Composable +private fun invalidContentModifier(): Modifier { + return Modifier + .border(width = 1.dp, color = ElementTheme.colors.borderCriticalSubtle, shape = RoundedCornerShape(12.dp)) + .clip(RoundedCornerShape(12.dp)) + .background(ElementTheme.colors.bgCriticalSubtle) +} + +@Composable +internal fun GalleryFileListItemContent( + name: String, + formattedSize: String, + icon: ImageVector, + isValidating: Boolean, + onClick: () -> Unit, + onLongClick: () -> Unit, +) { + Row( + modifier = Modifier + .clip(RoundedCornerShape(12.dp)) + .background( + color = ElementTheme.colors.bgSubtleSecondary, + shape = RoundedCornerShape(12.dp), + ) + .combinedClickable( + onClick = onClick.takeIf { !isValidating } ?: {}, + onLongClick = onLongClick.takeIf { !isValidating } ?: {}, + onLongClickLabel = stringResource(CommonStrings.action_open_context_menu), + ) + .onKeyboardContextMenuAction(onLongClick) + .fillMaxWidth() + .padding(start = 12.dp, end = 36.dp, top = 8.dp, bottom = 8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + val iconModifier = Modifier + .background( + color = ElementTheme.colors.bgActionSecondaryRest, + shape = CircleShape, + ) + .size(32.dp) + .padding(6.dp) + + if (isValidating) { + CircularProgressIndicator( + modifier = iconModifier, + strokeWidth = 2.dp, + ) + } else { + Icon( + modifier = iconModifier, + imageVector = icon, + contentDescription = null, + ) + } + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = name, + modifier = Modifier.weight(1f), + style = ElementTheme.typography.fontBodyLgRegular, + color = ElementTheme.colors.textPrimary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + if (formattedSize.isNotEmpty()) { + Text( + text = formattedSize.withBrackets(), + style = ElementTheme.typography.fontBodyLgRegular, + color = ElementTheme.colors.textPrimary, + ) + } + } +} diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/MediaItemAudioProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/MediaItemAudioProvider.kt index 25e8a88dfe..4dfd1c18c8 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/MediaItemAudioProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/MediaItemAudioProvider.kt @@ -22,7 +22,7 @@ class MediaItemAudioProvider : PreviewParameterProvider { caption = "A caption", ), aMediaItemAudio( - caption = loremIpsum, + caption = loremIpsum.take(80), ), ) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/MediaItemFileProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/MediaItemFileProvider.kt index 7419ae3d44..e64b10adb4 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/MediaItemFileProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/MediaItemFileProvider.kt @@ -22,7 +22,7 @@ class MediaItemFileProvider : PreviewParameterProvider { caption = "A caption", ), aMediaItemFile( - caption = loremIpsum, + caption = loremIpsum.take(80), ), ) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/MediaItemVoiceProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/MediaItemVoiceProvider.kt index 4b23d28795..56c1c4bb32 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/MediaItemVoiceProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/MediaItemVoiceProvider.kt @@ -22,7 +22,7 @@ class MediaItemVoiceProvider : PreviewParameterProvider { caption = "A caption", ), aMediaItemVoice( - caption = loremIpsum, + caption = loremIpsum.take(80), ), aMediaItemVoice( waveform = emptyList(), diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/VoiceItemView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/VoiceItemView.kt index dbbeb28b80..6c9df5fc48 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/VoiceItemView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/gallery/ui/VoiceItemView.kt @@ -45,10 +45,10 @@ import io.element.android.libraries.designsystem.modifiers.onKeyboardContextMenu 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.HorizontalDivider 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.matrix.ui.media.contentvalidation.ContentValidationValue import io.element.android.libraries.mediaviewer.impl.model.MediaItem import io.element.android.libraries.mediaviewer.impl.model.aMediaItemVoice import io.element.android.libraries.ui.strings.CommonStrings @@ -64,26 +64,20 @@ fun VoiceItemView( state: VoiceMessageState, voice: MediaItem.Voice, onLongClick: () -> Unit, + contentValidationValue: ContentValidationValue, modifier: Modifier = Modifier, ) { - Column( - modifier = modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), + GalleryFileListItem( + modifier = modifier, + contentValidationValue = contentValidationValue, + caption = voice.mediaInfo.caption, ) { - Spacer(modifier = Modifier.height(20.dp)) VoiceInfoRow( state = state, voice = voice, + isValidating = contentValidationValue.isLoading(), onLongClick = onLongClick, ) - val caption = voice.mediaInfo.caption - if (caption != null) { - CaptionView(caption) - } else { - Spacer(modifier = Modifier.height(16.dp)) - } - HorizontalDivider() } } @@ -91,6 +85,7 @@ fun VoiceItemView( private fun VoiceInfoRow( state: VoiceMessageState, voice: MediaItem.Voice, + isValidating: Boolean, onLongClick: () -> Unit, ) { fun playPause() { @@ -114,12 +109,21 @@ private fun VoiceInfoRow( .padding(start = 12.dp, end = 36.dp, top = 8.dp, bottom = 8.dp), verticalAlignment = Alignment.CenterVertically, ) { - when (state.buttonType) { - VoiceMessageState.ButtonType.Play -> PlayButton(onClick = ::playPause) - VoiceMessageState.ButtonType.Pause -> PauseButton(onClick = ::playPause) - VoiceMessageState.ButtonType.Downloading -> ProgressButton() - VoiceMessageState.ButtonType.Retry -> RetryButton(onClick = ::playPause) - VoiceMessageState.ButtonType.Disabled -> PlayButton(onClick = {}, enabled = false) + if (isValidating) { + CustomIconButton(onClick = {}, enabled = false) { + CircularProgressIndicator( + strokeWidth = 2.dp, + modifier = Modifier.size(16.dp) + ) + } + } else { + when (state.buttonType) { + VoiceMessageState.ButtonType.Play -> PlayButton(onClick = ::playPause) + VoiceMessageState.ButtonType.Pause -> PauseButton(onClick = ::playPause) + VoiceMessageState.ButtonType.Downloading -> ProgressButton() + VoiceMessageState.ButtonType.Retry -> RetryButton(onClick = ::playPause) + VoiceMessageState.ButtonType.Disabled -> PlayButton(onClick = {}, enabled = false) + } } Spacer(Modifier.width(8.dp)) Column( @@ -128,7 +132,7 @@ private fun VoiceInfoRow( ) { PlaybackSpeedButton( speed = state.playbackSpeed, - onClick = { state.eventSink(VoiceMessageEvent.ChangePlaybackSpeed) }, + onClick = { state.eventSink(VoiceMessageEvent.ChangePlaybackSpeed) }.takeIf { !isValidating } ?: {}, ) Text( text = if (state.progress > 0f) state.time else voice.mediaInfo.duration ?: state.time, @@ -149,7 +153,7 @@ private fun VoiceInfoRow( onSeek = { state.eventSink(VoiceMessageEvent.Seek(it)) }, - seekEnabled = true, + seekEnabled = !isValidating, ) } } @@ -277,11 +281,24 @@ private fun CustomIconButton( internal fun VoiceItemViewPreview( @PreviewParameter(MediaItemVoiceProvider::class) voice: MediaItem.Voice, ) = ElementPreview { - VoiceItemView( - state = aVoiceMessageState(), - voice = voice, - onLongClick = {}, - ) + val states = remember { + listOf( + ContentValidationValue.Valid, + ContentValidationValue.Loading, + ContentValidationValue.Invalid, + ContentValidationValue.UnrecoverableError(Throwable("Unrecoverable error")), + ) + } + Column { + for (state in states) { + VoiceItemView( + state = aVoiceMessageState(), + voice = voice, + onLongClick = {}, + contentValidationValue = state, + ) + } + } } @PreviewsDayNight @@ -289,9 +306,22 @@ internal fun VoiceItemViewPreview( internal fun VoiceItemViewPlayPreview( @PreviewParameter(VoiceMessageStateProvider::class) state: VoiceMessageState, ) = ElementPreview { - VoiceItemView( - state = state, - voice = aMediaItemVoice(), - onLongClick = {}, - ) + val validationState = remember { + listOf( + ContentValidationValue.Valid, + ContentValidationValue.Loading, + ContentValidationValue.Invalid, + ContentValidationValue.UnrecoverableError(Throwable("Unrecoverable error")), + ) + } + Column { + for (validationState in validationState) { + VoiceItemView( + state = state, + voice = aMediaItemVoice(), + onLongClick = {}, + contentValidationValue = validationState, + ) + } + } } 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 d6484cd5a4..b5c65fa609 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 @@ -254,29 +254,31 @@ private fun ExoPlayerMediaVideoView( }, ) } - MediaPlayerControllerView( - state = mediaPlayerControllerState, - onTogglePlay = { - autoHideController++ - exoPlayer.togglePlay() - }, - onSeekChange = { - autoHideController++ - mediaPlayerControllerState = mediaPlayerControllerState.copy( - seekingToMillis = it.toLong(), - ) - exoPlayer.seekToEnsurePlaying(it.toLong()) - }, - onToggleMute = { - autoHideController++ - exoPlayer.volume = if (exoPlayer.volume == 1f) 0f else 1f - }, - audioFocus = audioFocus, - modifier = Modifier - .fillMaxWidth() - .align(Alignment.BottomCenter) - .padding(bottom = bottomPaddingInPixels.toDp()), - ) + if (localMedia != null) { + MediaPlayerControllerView( + state = mediaPlayerControllerState, + onTogglePlay = { + autoHideController++ + exoPlayer.togglePlay() + }, + onSeekChange = { + autoHideController++ + mediaPlayerControllerState = mediaPlayerControllerState.copy( + seekingToMillis = it.toLong(), + ) + exoPlayer.seekToEnsurePlaying(it.toLong()) + }, + onToggleMute = { + autoHideController++ + exoPlayer.volume = if (exoPlayer.volume == 1f) 0f else 1f + }, + audioFocus = audioFocus, + modifier = Modifier + .fillMaxWidth() + .align(Alignment.BottomCenter) + .padding(bottom = bottomPaddingInPixels.toDp()), + ) + } } LaunchedEffect(exoPlayer.isPlaying) { diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItem.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItem.kt index 5a0b56a9b7..5367751a19 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItem.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItem.kt @@ -13,6 +13,8 @@ import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.ui.media.MediaRequestData +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue import io.element.android.libraries.mediaviewer.api.MediaInfo sealed interface MediaItem { @@ -27,7 +29,9 @@ sealed interface MediaItem { val timestamp: Long, ) : MediaItem - sealed interface Event : MediaItem + sealed interface Event : MediaItem { + val validationState: ContentValidationState + } data class Image( val id: UniqueId, @@ -36,6 +40,7 @@ sealed interface MediaItem { val mediaSource: MediaSource, val thumbnailSource: MediaSource?, val blurHash: String?, + override val validationState: ContentValidationState, ) : Event { val thumbnailMediaRequestData: MediaRequestData get() = MediaRequestData(thumbnailSource ?: mediaSource, MediaRequestData.Kind.Thumbnail(100)) @@ -48,6 +53,7 @@ sealed interface MediaItem { val mediaSource: MediaSource, val thumbnailSource: MediaSource?, val blurHash: String?, + override val validationState: ContentValidationState, ) : Event { val thumbnailMediaRequestData: MediaRequestData get() = MediaRequestData(thumbnailSource ?: mediaSource, MediaRequestData.Kind.Thumbnail(100)) @@ -58,6 +64,7 @@ sealed interface MediaItem { val eventId: EventId?, val mediaInfo: MediaInfo, val mediaSource: MediaSource, + override val validationState: ContentValidationState, ) : Event data class Voice( @@ -65,6 +72,7 @@ sealed interface MediaItem { val eventId: EventId?, val mediaInfo: MediaInfo, val mediaSource: MediaSource, + override val validationState: ContentValidationState, ) : Event data class File( @@ -72,6 +80,7 @@ sealed interface MediaItem { val eventId: EventId?, val mediaInfo: MediaInfo, val mediaSource: MediaSource, + override val validationState: ContentValidationState, ) : Event } @@ -134,3 +143,8 @@ fun MediaItem.Event.blurHash(): String? { else -> null } } + +fun MediaItem.isMediaValid(): Boolean? = when (this) { + is MediaItem.Event -> validationState.getCurrentOverallState() == ContentValidationValue.Valid + else -> null +} diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItemFactories.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItemFactories.kt index 96059cfd1f..d625ebe398 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItemFactories.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/model/MediaItemFactories.kt @@ -14,6 +14,8 @@ import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState import io.element.android.libraries.mediaviewer.api.aPdfMediaInfo import io.element.android.libraries.mediaviewer.api.aVideoMediaInfo import io.element.android.libraries.mediaviewer.api.aVoiceMediaInfo @@ -25,6 +27,8 @@ fun aMediaItemImage( eventId: EventId? = null, senderId: UserId? = null, mediaSourceUrl: String = "", + validationState: ContentValidationState = NoopContentValidationState(), + blurHash: String? = null, ): MediaItem.Image { return MediaItem.Image( id = id, @@ -34,7 +38,8 @@ fun aMediaItemImage( ), mediaSource = MediaSource(mediaSourceUrl), thumbnailSource = null, - blurHash = null, + blurHash = blurHash, + validationState = validationState, ) } @@ -42,6 +47,7 @@ fun aMediaItemVideo( id: UniqueId = UniqueId("videoId"), mediaSource: MediaSource = MediaSource(""), duration: String? = "1:23", + validationState: ContentValidationState = NoopContentValidationState(), ): MediaItem.Video { return MediaItem.Video( id = id, @@ -52,6 +58,7 @@ fun aMediaItemVideo( mediaSource = mediaSource, thumbnailSource = null, blurHash = null, + validationState = validationState, ) } @@ -60,6 +67,7 @@ fun aMediaItemFile( eventId: EventId? = null, filename: String = "filename", caption: String? = null, + validationState: ContentValidationState = NoopContentValidationState(), ): MediaItem.File { return MediaItem.File( id = id, @@ -69,6 +77,7 @@ fun aMediaItemFile( caption = caption, ), mediaSource = MediaSource(""), + validationState = validationState, ) } @@ -77,6 +86,7 @@ fun aMediaItemAudio( eventId: EventId? = null, filename: String = "filename", caption: String? = null, + validationState: ContentValidationState = NoopContentValidationState(), ): MediaItem.Audio { return MediaItem.Audio( id = id, @@ -86,6 +96,7 @@ fun aMediaItemAudio( caption = caption, ), mediaSource = MediaSource(""), + validationState = validationState, ) } @@ -95,6 +106,7 @@ fun aMediaItemVoice( caption: String? = null, duration: String? = "1:23", waveform: List = WaveFormSamples.realisticWaveForm, + validationState: ContentValidationState = NoopContentValidationState(), ): MediaItem.Voice { return MediaItem.Voice( id = id, @@ -106,6 +118,7 @@ fun aMediaItemVoice( waveForm = waveform, ), mediaSource = MediaSource(""), + validationState = validationState, ) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSource.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSource.kt index d254985ebf..c8b1de07aa 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSource.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSource.kt @@ -11,6 +11,7 @@ import io.element.android.libraries.architecture.AsyncData 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.timeline.Timeline +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState import io.element.android.libraries.mediaviewer.api.GalleryInfo import io.element.android.libraries.mediaviewer.api.GalleryItemData import io.element.android.libraries.mediaviewer.api.MediaInfo @@ -37,6 +38,7 @@ class GalleryMediaGalleryDataSource( eventId: EventId?, galleryItems: List, galleryInfo: GalleryInfo, + contentValidationState: ContentValidationState, ): GalleryMediaGalleryDataSource { val mixedItems = mutableListOf() galleryItems.forEachIndexed { index, galleryItem -> @@ -64,18 +66,21 @@ class GalleryMediaGalleryDataSource( mediaSource = galleryItem.mediaSource, thumbnailSource = galleryItem.thumbnailSource, blurHash = galleryItem.blurHash, + validationState = contentValidationState, ) GalleryItemData.Type.Audio -> MediaItem.Audio( id = id, eventId = eventId, mediaInfo = itemMediaInfo, mediaSource = galleryItem.mediaSource, + validationState = contentValidationState, ) GalleryItemData.Type.File -> MediaItem.File( id = id, eventId = eventId, mediaInfo = itemMediaInfo, mediaSource = galleryItem.mediaSource, + validationState = contentValidationState, ) GalleryItemData.Type.Image -> MediaItem.Image( id = id, @@ -84,6 +89,7 @@ class GalleryMediaGalleryDataSource( mediaSource = galleryItem.mediaSource, thumbnailSource = galleryItem.thumbnailSource, blurHash = galleryItem.blurHash, + validationState = contentValidationState, ) } mixedItems.add(mediaItem) 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 7cbeafa0b2..8b48955502 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 @@ -17,6 +17,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.produceState import androidx.compose.runtime.rememberUpdatedState +import io.element.android.features.contentscanner.api.ContentScannerService import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.core.extensions.mapCatchingExceptions import io.element.android.libraries.matrix.api.core.EventId @@ -24,6 +25,9 @@ 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.matrix.ui.media.contentvalidation.ContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.EventContentValidationCache import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint.MediaViewerMode import io.element.android.libraries.mediaviewer.api.local.LocalMedia import io.element.android.libraries.mediaviewer.api.local.LocalMediaFactory @@ -57,6 +61,8 @@ class MediaViewerDataSource( private val localMediaFactory: LocalMediaFactory, private val systemClock: SystemClock, private val pagerKeysHandler: PagerKeysHandler, + private val contentScannerService: ContentScannerService, + private val contentValidationCache: EventContentValidationCache, ) { // List of media files that are currently being loaded private val mediaFiles: ConcurrentHashMap = ConcurrentHashMap() @@ -71,6 +77,9 @@ class MediaViewerDataSource( private val localMediaStates: MutableMap>> = mutableMapOf() + private val mediaValidationState: MutableMap = + mutableMapOf() + fun setup(coroutineScope: CoroutineScope) { galleryDataSource.start(coroutineScope) } @@ -162,6 +171,9 @@ class MediaViewerDataSource( val localMedia = localMediaStates.getOrPut(sourceUrl) { mutableStateOf(AsyncData.Uninitialized) } + val validationState = mediaValidationState.getOrPut(sourceUrl) { + mediaItem.eventId()?.let { contentValidationCache[it] } ?: DefaultContentValidationState() + } add( MediaViewerPageData.MediaViewerData( eventId = mediaItem.eventId(), @@ -170,6 +182,7 @@ class MediaViewerDataSource( thumbnailSource = mediaItem.thumbnailSource(), downloadedMedia = localMedia, pagerKey = pagerKeysHandler.getKey(mediaItem), + validationState = validationState, ) ) } @@ -229,6 +242,20 @@ class MediaViewerDataSource( } } + fun validateMedia( + eventId: EventId, + mediaSource: MediaSource, + ) { + val validationState = mediaValidationState[mediaSource.safeUrl] ?: return + val currentState = validationState.getCurrentMediaState(mediaSource.safeUrl) + + if (currentState.isLoading() || currentState.isValid()) { + return + } + + contentScannerService.scan(eventId, listOf(mediaSource), validationState) + } + fun cancelLoadingMedia(data: MediaViewerPageData.MediaViewerData) { if (localMediaStates[data.mediaSource.safeUrl]?.value?.isLoading() == true) { Timber.d("cancelLoadingMedia for ${data.eventId}") 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 53d287075d..21769f81be 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 @@ -9,6 +9,7 @@ package io.element.android.libraries.mediaviewer.impl.viewer 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 sealed interface MediaViewerEvent { @@ -30,4 +31,5 @@ sealed interface MediaViewerEvent { data class OnNavigateTo(val index: Int) : MediaViewerEvent data class LoadMore(val direction: Timeline.PaginationDirection) : MediaViewerEvent data class CancelLoadingMedia(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvent + data class ValidateMedia(val eventId: EventId, val mediaSource: MediaSource) : MediaViewerEvent } 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 2298981543..e53153ce19 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 @@ -22,6 +22,7 @@ import dev.zacsweers.metro.AssistedInject import io.element.android.annotations.ContributesNode import io.element.android.compound.colors.SemanticColorsLightDark import io.element.android.compound.theme.ForcedDarkElementTheme +import io.element.android.features.contentscanner.api.ContentScannerService import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.features.viewfolder.api.TextFileViewer import io.element.android.libraries.architecture.callback @@ -33,6 +34,8 @@ 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.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.ui.media.contentvalidation.EventContentValidationCache +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint import io.element.android.libraries.mediaviewer.api.local.LocalMediaFactory import io.element.android.libraries.mediaviewer.impl.datasource.FocusedTimelineMediaGalleryDataSourceFactory @@ -57,6 +60,8 @@ class MediaViewerNode( private val audioFocus: AudioFocus, private val sessionId: SessionId, private val enterpriseService: EnterpriseService, + private val contentScannerService: ContentScannerService, + private val contentValidationCache: EventContentValidationCache, ) : Node(buildContext, plugins = plugins), MediaViewerNavigator { private val callback: MediaViewerEntryPoint.Callback = callback() @@ -76,12 +81,13 @@ class MediaViewerNode( private val mediaGallerySource = when (inputs) { is MediaViewerEntryPoint.Params.Avatar -> - SingleMediaGalleryDataSource.createFrom(inputs) + SingleMediaGalleryDataSource.createFrom(inputs, contentValidationCache) is MediaViewerEntryPoint.Params.EventGallery -> GalleryMediaGalleryDataSource.createFrom( eventId = inputs.eventId, galleryItems = inputs.galleryItems, galleryInfo = inputs.galleryInfo, + contentValidationState = inputs.eventId?.let { contentValidationCache[it] } ?: NoopContentValidationState(), ) is MediaViewerEntryPoint.Params.RoomMedia -> { val eventId = inputs.eventId @@ -103,7 +109,7 @@ class MediaViewerNode( } else { focusedTimelineMediaGalleryDataSourceFactory.createFor( eventId = eventId, - mediaItem = inputs.toMediaItem(), + mediaItem = inputs.toMediaItem(contentValidationCache[eventId]), onlyPinnedEvents = false, ) } @@ -111,7 +117,7 @@ class MediaViewerNode( Timeline.Mode.PinnedEvents -> { focusedTimelineMediaGalleryDataSourceFactory.createFor( eventId = eventId, - mediaItem = inputs.toMediaItem(), + mediaItem = inputs.toMediaItem(contentValidationCache[eventId]), onlyPinnedEvents = true, ) } @@ -142,6 +148,8 @@ class MediaViewerNode( localMediaFactory = localMediaFactory, systemClock = systemClock, pagerKeysHandler = pagerKeysHandler, + contentScannerService = contentScannerService, + contentValidationCache = contentValidationCache, ) ) 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 eaea61b5a5..60c14f562e 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 @@ -42,7 +42,9 @@ import io.element.android.libraries.mediaviewer.impl.model.MediaPermissions import io.element.android.libraries.mediaviewer.impl.model.mediaPermissions import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import io.element.android.libraries.androidutils.R as UtilsR @@ -70,6 +72,7 @@ class MediaViewerPresenter( private val eventId = inputs.eventId() private val mediaSource = inputs.mediaSource() + @OptIn(ExperimentalCoroutinesApi::class) @Composable override fun present(): MediaViewerState { val coroutineScope = rememberCoroutineScope() @@ -93,7 +96,7 @@ class MediaViewerPresenter( // Restore index based on the eventId after the initial items have been loaded currentIndex.intValue = dataSource.findEventIndex(eventId, mediaSource) ?: 0 } - value = new + value = new.toImmutableList() } } @@ -191,6 +194,7 @@ class MediaViewerPresenter( is MediaViewerEvent.LoadMore -> coroutineScope.launch { dataSource.loadMore(event.direction) } + is MediaViewerEvent.ValidateMedia -> dataSource.validateMedia(event.eventId, event.mediaSource) } } 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 a51d3c44e9..03803708af 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 @@ -15,6 +15,7 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage 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 +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.api.local.LocalMedia import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState @@ -51,6 +52,7 @@ sealed interface MediaViewerPageData { val mediaSource: MediaSource, val thumbnailSource: MediaSource?, val downloadedMedia: State>, + val validationState: ContentValidationState, override val pagerKey: Long, ) : 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 8cc14d6445..440d366c30 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 @@ -17,6 +17,9 @@ 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 +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.api.aPdfMediaInfo import io.element.android.libraries.mediaviewer.api.aTxtMediaInfo @@ -275,6 +278,34 @@ open class MediaViewerStateProvider : PreviewParameterProvider ) ) }, + anImageMediaInfo( + senderName = "Frank", + dateSent = "26 NOV, 2024", + ).let { + aMediaViewerState( + listOf( + aMediaViewerPageData( + downloadedMedia = AsyncData.Uninitialized, + validationState = NoopContentValidationState(ContentValidationValue.Loading), + mediaInfo = it, + ) + ) + ) + }, + anImageMediaInfo( + senderName = "Frank", + dateSent = "26 NOV, 2024", + ).let { + aMediaViewerState( + listOf( + aMediaViewerPageData( + downloadedMedia = AsyncData.Uninitialized, + validationState = NoopContentValidationState(ContentValidationValue.Invalid), + mediaInfo = it, + ) + ) + ) + }, ) } @@ -293,6 +324,7 @@ fun aMediaViewerPageData( downloadedMedia: AsyncData = AsyncData.Uninitialized, mediaInfo: MediaInfo = anImageMediaInfo(), mediaSource: MediaSource = MediaSource(""), + validationState: ContentValidationState = NoopContentValidationState(), ): MediaViewerPageData.MediaViewerData = MediaViewerPageData.MediaViewerData( eventId = null, mediaInfo = mediaInfo, @@ -300,6 +332,7 @@ fun aMediaViewerPageData( thumbnailSource = null, downloadedMedia = mutableStateOf(downloadedMedia), pagerKey = 0L, + validationState = validationState, ) fun aMediaViewerState( 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 c981132b48..c05bcb6bf6 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 @@ -12,11 +12,14 @@ package io.element.android.libraries.mediaviewer.impl.viewer import androidx.activity.compose.BackHandler import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.spring import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -73,7 +76,10 @@ 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 +import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule +import io.element.android.libraries.designsystem.components.BigIcon import io.element.android.libraries.designsystem.components.async.AsyncFailure +import io.element.android.libraries.designsystem.components.async.AsyncIndicator import io.element.android.libraries.designsystem.components.async.AsyncLoading import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.dialogs.RetryDialog @@ -176,7 +182,7 @@ fun MediaViewerView( } }, snackbarHost = { SnackbarHost(snackbarHostState) }, - ) { + ) { padding -> val pagerState = rememberPagerState(state.currentIndex, 0f) { state.listData.size } @@ -211,17 +217,33 @@ fun MediaViewerView( ) } is MediaViewerPageData.MediaViewerData -> { + val eventId = dataForPage.eventId + + val isMediaValid = dataForPage.validationState.getCurrentMediaState(dataForPage.mediaSource.safeUrl).isValid() + + // Check if the media to display is valid or dangerous + LaunchedEffect(eventId) { + if (eventId != null) { + state.eventSink(MediaViewerEvent.ValidateMedia(eventId, dataForPage.mediaSource)) + } + } + var bottomPaddingInPixels by remember { mutableIntStateOf(defaultBottomPaddingInPixels) } - Box( - modifier = Modifier - .onVisibilityChanged(minDurationMs = 200L) { isVisible -> + val loadMediaOnVisibilityChangedModifier = remember(isMediaValid) { + if (isMediaValid == true) { + Modifier.onVisibilityChanged(minDurationMs = 200L) { isVisible -> if (isVisible) { state.eventSink(MediaViewerEvent.LoadMedia(dataForPage)) } else { state.eventSink(MediaViewerEvent.CancelLoadingMedia(dataForPage)) } } - .fillMaxSize() + } else { + Modifier + } + } + Box( + modifier = loadMediaOnVisibilityChangedModifier.fillMaxSize() ) { val isDisplayed = remember(pagerState.settledPage) { // This 'item provider' lambda will be called when the data source changes with an outdated `settlePage` value @@ -232,6 +254,7 @@ fun MediaViewerView( MediaViewerPage( isDisplayed = isDisplayed, showOverlay = showOverlay, + containerPadding = padding, bottomPaddingInPixels = (bottomPaddingInPixels - navigationBarPadding).coerceAtLeast(0), data = dataForPage, textFileViewer = textFileViewer, @@ -333,6 +356,7 @@ private fun MediaViewerPage( isDisplayed: Boolean, showOverlay: Boolean, bottomPaddingInPixels: Int, + containerPadding: PaddingValues, data: MediaViewerPageData.MediaViewerData, textFileViewer: TextFileViewer, isUserSelected: Boolean, @@ -365,6 +389,25 @@ private fun MediaViewerPage( .fillMaxSize() .navigationBarsPadding() ) { + AnimatedVisibility( + visible = data.validationState.getCurrentMediaState(data.mediaSource.safeUrl).isLoading(), + modifier = Modifier.padding(top = containerPadding.calculateTopPadding()).align(Alignment.TopCenter), + enter = fadeIn(spring(stiffness = 500F)), + exit = fadeOut(spring(stiffness = 500F)), + ) { + AsyncIndicator.Loading( + text = stringResource(CommonStrings.content_scanner_scanning), + ) + } + + if (showProgress) { + LinearProgressIndicator( + modifier = Modifier + .fillMaxWidth() + .height(2.dp) + ) + } + Box(contentAlignment = Alignment.Center) { val zoomableState = rememberZoomableState( zoomSpec = ZoomSpec(maxZoomFactor = 4f, overzoomEffect = OverzoomEffect.NoLimits) @@ -380,29 +423,44 @@ private fun MediaViewerPage( } } - LocalMediaView( - modifier = Modifier.fillMaxSize(), - isDisplayed = isDisplayed, - bottomPaddingInPixels = bottomPaddingInPixels, - localMediaViewState = localMediaViewState, - localMedia = downloadedMedia.dataOrNull(), - mediaInfo = data.mediaInfo, - textFileViewer = textFileViewer, - onClick = { - if (playableState is PlayableState.NotPlayable) { - currentOnShowOverlayChange(!currentShowOverlay) - } - }, - onOpenWith = onOpenWith, - isUserSelected = isUserSelected, - audioFocus = audioFocus, - forPreview = false, - ) - if (showThumbnail) { - ThumbnailView( + val isMediaValid = data.validationState.getCurrentMediaState(data.mediaSource.safeUrl).isValid() + + if (isMediaValid == false) { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + ) { + IconTitleSubtitleMolecule( + iconStyle = BigIcon.Style.AlertSolid, + title = "The file is not safe", + subTitle = "Preview and download have been disabled.", + ) + } + } else { + LocalMediaView( + modifier = Modifier.fillMaxSize(), + isDisplayed = isDisplayed, + bottomPaddingInPixels = bottomPaddingInPixels, + localMediaViewState = localMediaViewState, + localMedia = downloadedMedia.dataOrNull(), mediaInfo = data.mediaInfo, - thumbnailSource = data.thumbnailSource, + textFileViewer = textFileViewer, + onClick = { + if (playableState is PlayableState.NotPlayable) { + currentOnShowOverlayChange(!currentShowOverlay) + } + }, + onOpenWith = onOpenWith, + isUserSelected = isUserSelected, + audioFocus = audioFocus, + forPreview = false, ) + if (showThumbnail) { + ThumbnailView( + mediaInfo = data.mediaInfo, + thumbnailSource = data.thumbnailSource, + ) + } } if (showError) { ErrorView( @@ -412,13 +470,6 @@ private fun MediaViewerPage( ) } } - if (showProgress) { - LinearProgressIndicator( - modifier = Modifier - .fillMaxWidth() - .height(2.dp) - ) - } } } } 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 f347e8181f..1f21252d9f 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 @@ -16,6 +16,9 @@ import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeVideo 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.timeline.Timeline +import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.DefaultContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.EventContentValidationCache import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint import io.element.android.libraries.mediaviewer.impl.datasource.MediaGalleryDataSource @@ -27,6 +30,7 @@ import kotlinx.coroutines.flow.flowOf class SingleMediaGalleryDataSource( private val data: GroupedMediaItems, + private val contentValidationCache: EventContentValidationCache, ) : MediaGalleryDataSource { override fun start(coroutineScope: CoroutineScope) = Unit override fun groupedMediaItemsFlow() = flowOf(AsyncData.Success(data)) @@ -38,7 +42,10 @@ class SingleMediaGalleryDataSource( override suspend fun deleteItem(eventId: EventId) = Unit companion object { - fun createFrom(params: MediaViewerEntryPoint.Params.Avatar) = SingleMediaGalleryDataSource( + fun createFrom( + params: MediaViewerEntryPoint.Params.Avatar, + contentValidationCache: EventContentValidationCache, + ) = SingleMediaGalleryDataSource( data = GroupedMediaItems( // Always use imageAndVideoItems, in Single mode, this is the data that will be used imageAndVideoItems = persistentListOf( @@ -64,15 +71,19 @@ class SingleMediaGalleryDataSource( mediaSource = params.mediaSource, thumbnailSource = params.thumbnailSource, blurHash = params.blurHash, + validationState = DefaultContentValidationState(), ) ), fileItems = persistentListOf(), - ) + ), + contentValidationCache = contentValidationCache, ) } } -fun MediaViewerEntryPoint.Params.RoomMedia.toMediaItem() = when { +fun MediaViewerEntryPoint.Params.RoomMedia.toMediaItem( + contentValidationState: ContentValidationState, +) = when { mediaInfo.mimeType.isMimeTypeImage() -> { MediaItem.Image( id = UniqueId("dummy"), @@ -80,7 +91,8 @@ fun MediaViewerEntryPoint.Params.RoomMedia.toMediaItem() = when { mediaInfo = mediaInfo, mediaSource = mediaSource, thumbnailSource = thumbnailSource, - blurHash = blurHash, + blurHash = null, + validationState = contentValidationState, ) } mediaInfo.mimeType.isMimeTypeVideo() -> { @@ -90,7 +102,8 @@ fun MediaViewerEntryPoint.Params.RoomMedia.toMediaItem() = when { mediaInfo = mediaInfo, mediaSource = mediaSource, thumbnailSource = thumbnailSource, - blurHash = blurHash, + blurHash = null, + validationState = contentValidationState, ) } mediaInfo.mimeType.isMimeTypeAudio() -> { @@ -100,6 +113,7 @@ fun MediaViewerEntryPoint.Params.RoomMedia.toMediaItem() = when { eventId = eventId, mediaInfo = mediaInfo, mediaSource = mediaSource, + validationState = contentValidationState, ) } else { MediaItem.Voice( @@ -107,6 +121,7 @@ fun MediaViewerEntryPoint.Params.RoomMedia.toMediaItem() = when { eventId = eventId, mediaInfo = mediaInfo, mediaSource = mediaSource, + validationState = contentValidationState, ) } } @@ -116,6 +131,7 @@ fun MediaViewerEntryPoint.Params.RoomMedia.toMediaItem() = when { eventId = eventId, mediaInfo = mediaInfo, mediaSource = mediaSource, + validationState = contentValidationState, ) } } 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 0c2e36903c..1691ed9995 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 @@ -12,11 +12,13 @@ import android.net.Uri 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.contentscanner.api.ContentScannerService import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.media.FakeMatrixMediaLoader +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopEventContentValidationCache import io.element.android.libraries.mediaplayer.test.FakeAudioFocus import io.element.android.libraries.mediaviewer.api.AvatarInfo import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint @@ -71,6 +73,8 @@ class DefaultMediaViewerEntryPointTest { audioFocus = FakeAudioFocus(), sessionId = A_SESSION_ID, enterpriseService = FakeEnterpriseService(), + contentValidationCache = NoopEventContentValidationCache(), + contentScannerService = ContentScannerService { _, _, _ -> }, ) } val callback = object : MediaViewerEntryPoint.Callback { @@ -118,6 +122,8 @@ class DefaultMediaViewerEntryPointTest { audioFocus = FakeAudioFocus(), sessionId = A_SESSION_ID, enterpriseService = FakeEnterpriseService(), + contentValidationCache = NoopEventContentValidationCache(), + contentScannerService = ContentScannerService { _, _, _ -> }, ) } val callback = object : MediaViewerEntryPoint.Callback { diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactoryTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactoryTest.kt index 7147e74e72..d00f5a3eb2 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactoryTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactoryTest.kt @@ -52,6 +52,8 @@ import io.element.android.libraries.matrix.test.timeline.aProfileChangeMessageCo import io.element.android.libraries.matrix.test.timeline.aStickerContent 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.media.contentvalidation.NoopContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopEventContentValidationCache import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.impl.model.MediaItem import io.element.android.libraries.mediaviewer.test.util.FileExtensionExtractorWithoutValidation @@ -174,6 +176,7 @@ class EventItemFactoryTest { duration = null, ), mediaSource = MediaSource(""), + validationState = noopValidationState, ) ) } @@ -227,6 +230,7 @@ class EventItemFactoryTest { mediaSource = MediaSource(""), thumbnailSource = null, blurHash = null, + validationState = noopValidationState, ) ) } @@ -274,6 +278,7 @@ class EventItemFactoryTest { duration = null, ), mediaSource = MediaSource(""), + validationState = noopValidationState, ) ) } @@ -328,6 +333,7 @@ class EventItemFactoryTest { mediaSource = MediaSource(""), thumbnailSource = null, blurHash = null, + validationState = noopValidationState, ) ) } @@ -379,6 +385,7 @@ class EventItemFactoryTest { duration = "7:36", ), mediaSource = MediaSource(""), + validationState = noopValidationState, ) ) } @@ -440,6 +447,7 @@ class EventItemFactoryTest { mediaSource = MediaSource("image_url"), thumbnailSource = MediaSource("thumbnail_url"), blurHash = null, + validationState = noopValidationState, ) ) } @@ -502,6 +510,7 @@ class EventItemFactoryTest { mediaSource = MediaSource("video_url"), thumbnailSource = MediaSource("thumbnail_url"), blurHash = null, + validationState = noopValidationState, ) ) } @@ -557,6 +566,7 @@ class EventItemFactoryTest { duration = null, ), mediaSource = MediaSource("audio_url"), + validationState = noopValidationState, ) ) } @@ -613,6 +623,7 @@ class EventItemFactoryTest { duration = null, ), mediaSource = MediaSource("file_url"), + validationState = noopValidationState, ) ) } @@ -749,13 +760,16 @@ class EventItemFactoryTest { mediaSource = MediaSource(""), thumbnailSource = null, blurHash = null, + validationState = noopValidationState, ) ) } } +private val noopValidationState = NoopContentValidationState() private fun createEventItemFactory() = EventItemFactory( fileSizeFormatter = FakeFileSizeFormatter(), fileExtensionExtractor = FileExtensionExtractorWithoutValidation(), dateFormatter = FakeDateFormatter(), + contentValidationCache = NoopEventContentValidationCache(noopValidationState), ) 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 a5151f3b68..81bb23d73c 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 @@ -34,6 +34,8 @@ 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.ui.components.A_BLUR_HASH +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopEventContentValidationCache import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.impl.model.GroupedMediaItems import io.element.android.libraries.mediaviewer.impl.model.MediaItem @@ -250,6 +252,7 @@ class TimelineMediaGalleryDataSourceTest { mediaSource = MediaSource("url"), thumbnailSource = MediaSource("url_thumbnail"), blurHash = A_BLUR_HASH, + validationState = noopValidationState, ) ), fileItems = persistentListOf() @@ -260,6 +263,8 @@ class TimelineMediaGalleryDataSourceTest { } } +private val noopValidationState = NoopContentValidationState() + internal fun TestScope.createTimelineMediaGalleryDataSource( room: JoinedRoom = FakeJoinedRoom( liveTimeline = FakeTimeline(), @@ -282,5 +287,6 @@ fun TestScope.createTimelineMediaItemsFactory() = TimelineMediaItemsFactory( fileSizeFormatter = FakeFileSizeFormatter(), fileExtensionExtractor = FileExtensionExtractorWithoutValidation(), dateFormatter = FakeDateFormatter(), - ), + contentValidationCache = NoopEventContentValidationCache(noopValidationState), + ) ) 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 3ab95f2703..1ce9b6ff19 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 @@ -534,6 +534,7 @@ class MediaGalleryPresenterTest { mediaLoader = matrixMediaLoader, localMediaActions = localMediaActions, snackbarDispatcher = snackbarDispatcher, + contentScannerService = { _, _, _ -> }, ) } } diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSourceTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSourceTest.kt index 670dfd6242..38f59f48cc 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSourceTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/GalleryMediaGalleryDataSourceTest.kt @@ -16,6 +16,7 @@ import io.element.android.libraries.matrix.api.media.MediaSource 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_USER_ID +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopContentValidationState import io.element.android.libraries.mediaviewer.api.GalleryInfo import io.element.android.libraries.mediaviewer.api.GalleryItemData import io.element.android.libraries.mediaviewer.api.MediaInfo @@ -95,6 +96,7 @@ class GalleryMediaGalleryDataSourceTest { ) ), galleryInfo = aGalleryInfo(), + contentValidationState = noopValidationState, ) val data = (result.getLastData() as AsyncData.Success).data assertThat(data.fileItems).isEmpty() @@ -106,6 +108,7 @@ class GalleryMediaGalleryDataSourceTest { mediaSource = MediaSource("image_url"), thumbnailSource = MediaSource("thumbnail_url"), blurHash = null, + validationState = noopValidationState, ) ) } @@ -125,6 +128,7 @@ class GalleryMediaGalleryDataSourceTest { ) ), galleryInfo = aGalleryInfo(), + contentValidationState = noopValidationState, ) val data = (result.getLastData() as AsyncData.Success).data assertThat(data.fileItems).isEmpty() @@ -136,6 +140,7 @@ class GalleryMediaGalleryDataSourceTest { mediaSource = MediaSource("video_url"), thumbnailSource = MediaSource("thumbnail_url"), blurHash = null, + validationState = noopValidationState, ) ) } @@ -155,6 +160,7 @@ class GalleryMediaGalleryDataSourceTest { ) ), galleryInfo = aGalleryInfo(), + contentValidationState = noopValidationState, ) val data = (result.getLastData() as AsyncData.Success).data assertThat(data.fileItems).isEmpty() @@ -164,6 +170,7 @@ class GalleryMediaGalleryDataSourceTest { eventId = AN_EVENT_ID, mediaInfo = expectedMediaInfo("audio.mp3", MimeTypes.Mp3), mediaSource = MediaSource("audio_url"), + validationState = noopValidationState, ) ) } @@ -183,6 +190,7 @@ class GalleryMediaGalleryDataSourceTest { ) ), galleryInfo = aGalleryInfo(), + contentValidationState = noopValidationState, ) val data = (result.getLastData() as AsyncData.Success).data assertThat(data.fileItems).isEmpty() @@ -192,6 +200,7 @@ class GalleryMediaGalleryDataSourceTest { eventId = AN_EVENT_ID, mediaInfo = expectedMediaInfo("document.pdf", MimeTypes.Pdf), mediaSource = MediaSource("file_url"), + validationState = noopValidationState, ) ) } @@ -211,6 +220,7 @@ class GalleryMediaGalleryDataSourceTest { ) ), galleryInfo = aGalleryInfo(), + contentValidationState = noopValidationState, ) val data = (result.getLastData() as AsyncData.Success).data val item = data.imageAndVideoItems.single() as MediaItem.Image @@ -249,6 +259,7 @@ class GalleryMediaGalleryDataSourceTest { ), ), galleryInfo = aGalleryInfo(), + contentValidationState = noopValidationState, ) val data = (result.getLastData() as AsyncData.Success).data assertThat(data.fileItems).isEmpty() @@ -258,6 +269,8 @@ class GalleryMediaGalleryDataSourceTest { assertThat((data.imageAndVideoItems[2] as MediaItem.Video).id).isEqualTo(UniqueId("${AN_EVENT_ID.value}_2")) } + private val noopValidationState = NoopContentValidationState() + private fun aGalleryInfo() = GalleryInfo( caption = "A caption", formattedCaption = null, 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 d7ba547ee4..95052e29a0 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 @@ -18,6 +18,7 @@ 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.AN_EXCEPTION import io.element.android.libraries.matrix.test.media.FakeMatrixMediaLoader +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopEventContentValidationCache import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint.MediaViewerMode import io.element.android.libraries.mediaviewer.api.local.LocalMediaFactory import io.element.android.libraries.mediaviewer.impl.datasource.FakeMediaGalleryDataSource @@ -290,5 +291,7 @@ class MediaViewerDataSourceTest { localMediaFactory = localMediaFactory, systemClock = FakeSystemClock(), pagerKeysHandler = PagerKeysHandler(), + contentScannerService = { _, _, _ -> }, + contentValidationCache = NoopEventContentValidationCache(), ) } 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 b25b8577ee..0ca6534a6c 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 @@ -30,6 +30,7 @@ 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.matrix.ui.media.contentvalidation.NoopEventContentValidationCache import io.element.android.libraries.mediaviewer.api.AvatarInfo import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint import io.element.android.libraries.mediaviewer.api.anApkMediaInfo @@ -969,6 +970,8 @@ internal fun TestScope.createMediaViewerPresenter( localMediaFactory = localMediaFactory, systemClock = FakeSystemClock(), pagerKeysHandler = PagerKeysHandler(), + contentScannerService = { _, _, _ -> }, + contentValidationCache = NoopEventContentValidationCache(), ), room = room, localMediaActions = localMediaActions, 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 ad44d1b372..ebd722f25c 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 @@ -16,6 +16,7 @@ import io.element.android.libraries.matrix.api.core.UniqueId 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.aMediaSource +import io.element.android.libraries.matrix.ui.media.contentvalidation.NoopEventContentValidationCache import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint import io.element.android.libraries.mediaviewer.api.aVideoMediaInfo @@ -36,22 +37,24 @@ class SingleMediaGalleryDataSourceTest { @get:Rule val warmUpRule = WarmUpRule() + private val contentValidationCache = NoopEventContentValidationCache() + @Test fun `function start is no op`() = runTest { - val sut = SingleMediaGalleryDataSource(aGroupedMediaItems()) + val sut = SingleMediaGalleryDataSource(aGroupedMediaItems(), contentValidationCache) sut.start(backgroundScope) } @Test fun `function loadMore is no op`() = runTest { - val sut = SingleMediaGalleryDataSource(aGroupedMediaItems()) + val sut = SingleMediaGalleryDataSource(aGroupedMediaItems(), contentValidationCache) sut.loadMore(Timeline.PaginationDirection.BACKWARDS) sut.loadMore(Timeline.PaginationDirection.FORWARDS) } @Test fun `function deleteItem is no op`() = runTest { - val sut = SingleMediaGalleryDataSource(aGroupedMediaItems()) + val sut = SingleMediaGalleryDataSource(aGroupedMediaItems(), contentValidationCache) sut.deleteItem(AN_EVENT_ID) } @@ -61,7 +64,7 @@ class SingleMediaGalleryDataSourceTest { imageAndVideoItems = listOf(aMediaItemImage()), fileItems = listOf(aMediaItemFile()), ) - val sut = SingleMediaGalleryDataSource(data) + val sut = SingleMediaGalleryDataSource(data, contentValidationCache) assertThat(sut.getLastData()).isEqualTo(AsyncData.Success(data)) } @@ -71,7 +74,7 @@ class SingleMediaGalleryDataSourceTest { imageAndVideoItems = listOf(aMediaItemImage()), fileItems = listOf(aMediaItemFile()), ) - val sut = SingleMediaGalleryDataSource(data) + val sut = SingleMediaGalleryDataSource(data, contentValidationCache) sut.groupedMediaItemsFlow().test { assertThat(awaitItem()).isEqualTo(AsyncData.Success(data)) awaitComplete() @@ -90,6 +93,7 @@ class SingleMediaGalleryDataSourceTest { mediaSource = params.mediaSource, thumbnailSource = params.thumbnailSource, blurHash = null, + validationState = contentValidationCache[AN_EVENT_ID], ) } ) @@ -107,6 +111,7 @@ class SingleMediaGalleryDataSourceTest { mediaSource = params.mediaSource, thumbnailSource = params.thumbnailSource, blurHash = null, + validationState = contentValidationCache[AN_EVENT_ID], ) } ) @@ -122,6 +127,7 @@ class SingleMediaGalleryDataSourceTest { eventId = params.eventId, mediaInfo = params.mediaInfo, mediaSource = params.mediaSource, + validationState = contentValidationCache[AN_EVENT_ID], ) } ) @@ -140,6 +146,7 @@ class SingleMediaGalleryDataSourceTest { eventId = params.eventId, mediaInfo = params.mediaInfo, mediaSource = params.mediaSource, + validationState = contentValidationCache[AN_EVENT_ID], ) } ) @@ -155,6 +162,7 @@ class SingleMediaGalleryDataSourceTest { eventId = params.eventId, mediaInfo = params.mediaInfo, mediaSource = params.mediaSource, + validationState = contentValidationCache[AN_EVENT_ID], ) } ) @@ -165,7 +173,7 @@ class SingleMediaGalleryDataSourceTest { expectedResult: (MediaViewerEntryPoint.Params.RoomMedia) -> MediaItem, ) { val params = aMediaViewerEntryPointParams(mediaInfo) - val result = params.toMediaItem() + val result = params.toMediaItem(contentValidationCache[AN_EVENT_ID],) assertThat(result).isEqualTo(expectedResult(params)) } diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_0_en.png index d9f1bfbc09..b74ae6d0fe 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de447e1f21d51bd3e21a0fe4de6817c375a408beb8225a6ad5deb85025801e4f -size 8293 +oid sha256:fbcb3345c0486059b8a446e0a9b904345b899e398d07f3363449e577d2c0e9fb +size 30369 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_1_en.png index ca71909e7f..8d6179571f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6c7e6ecb02d33e3849ebd2624dfd1e994d77b9f7f43e7ffe9afcf33e8436d44 -size 13041 +oid sha256:d149cbbffd2698eba03f4d89de3af98fb1ad7bc37849598b95dd3f02e66965a8 +size 43742 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_2_en.png index 037395a7f8..d14753f755 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75f5d30bc99d5b09a69b77d544aaafaf665b1c377405f7ccb04092ac0da0a114 -size 35334 +oid sha256:f1abb765bc08c172adefb0ebd4c78d65b5b52791f54c15d72257b7b5a7192f0e +size 79970 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_0_en.png index 93cbbae2f8..8ead5cf497 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b3105694519d42956dc164a04b7642dfff4a303d7b96cfd2967ea3ad1bc19cd -size 8071 +oid sha256:63449813a8ca880d291113834561224e2547546580cb10a1c4dd7e35a142c638 +size 29089 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_1_en.png index 6c89e912be..a08b41cdef 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8fd9f5dfc87d0a6e65e9c10c67f4359abde2ce85265770f8a47e3329f2f64a2d -size 12443 +oid sha256:a5efe93f94bd3f0c68adaa21043cbbf02ef1e6aebbbdd137e8e2a8e99f2f6193 +size 41850 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_2_en.png index 1fb003e7b3..72b4781c79 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97f49b6969c5a852624558077f9fc9b0add39a12e76e744a385c85785d4489ec -size 34405 +oid sha256:7c488147fde94e3c74660141125279b12435b9f037359256d70555afcd239a18 +size 77333 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_0_en.png index ca864249bd..8681053839 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:31283735c33057ede4d2ba20024b00ae4a4f45510cfbb47c21f980f7151c3858 -size 8931 +oid sha256:70aa1b155531b531ae7f7e7ac1a5123fd065a3c9080c6319435f63f8c315c4e4 +size 31421 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_1_en.png index e4eb34aaac..b6eda3a2ad 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0a2decb05c73655390dd2cfb3d88d209b17ded46d5d6c40cc8672e5781b48348 -size 13334 +oid sha256:a5e462fa9302567a3ac90a4493e71ccb08ba8b924af686b251791c24c8b8553a +size 44108 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_2_en.png index d2199b862f..f377ff83a8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21803c66fce41f53cd7796321fb9f3fc774e0c4fc99cd3683a3a8b22e00e2615 -size 35966 +oid sha256:5ecc879f8b304ffd4b95f54d1aeda7208238352af1570be23bc9d8de4fe84677 +size 80846 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_0_en.png index c9a00ed743..1314bb6c3d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:11300a4c85f2e8daa06ddb4a3f8d6f72432dc581dca279366b1229450d3b973c -size 8634 +oid sha256:447a27ce5bcd769a8efda39c39ef3494eaf648cbd0fa4939b6089e58b3f31ea3 +size 30107 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_1_en.png index e1090265d0..f867981bb1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1c8a1759a613527cfe5912f6e811121e29611ed05b8a8cecb95391ffb1bc5be2 -size 12710 +oid sha256:3946799c8c3faba3bfef028f6adba46919bda464b73d83d3dcee95383fec491b +size 42288 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_2_en.png index e73cf16f0c..914059d9f1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c53798a077d020700ae58aa93aa507dd7ce88984c48aaabf11ba863e8b1773ed -size 34944 +oid sha256:99a5e5fa3f4e014fd1a2b127646e88d848802d24f3150c45b1fb8e4b405d45d1 +size 78217 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_0_en.png index ecb8160d12..0394b633bb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ef97e6e11a66c49ed5ba1863567f24097fe8121ea34f7de5fc5cdda3f0c7a0b -size 9279 +oid sha256:42a0dbb630480cda58746522b69f6368c9cc7295f98a865a3caa4535a8f024f3 +size 32081 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_1_en.png index 2ee1097de9..fbc23c84c8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49bec9adfef9cf1637c722f5c96e0fec677c21a4ea3f89fd4555a9c894090be0 -size 9833 +oid sha256:d325f7de3a1c8517e7a924de415ab8da043ae3b44eec5e46c5150b1f58f01a50 +size 32799 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_2_en.png index 793b579aab..8756055e70 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a010f16ec1221a43ba2bd5266da05f3de48d354b98dfc087974ff605d32d095d -size 9576 +oid sha256:ff893a90f760818bd9c4f5befabf67c90d2ecc30ce26e1f613420ec32285c588 +size 32630 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_3_en.png index 08a42124fa..23d8c4a18e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c91316c96e75ba29e3d1bae38cb8b0abf255d7316ff3a616fdbddafc550c744f -size 9715 +oid sha256:458bca1df07c79811b4deb874bb71bb822ae21cf85eb76ecf92c69f8ea10e84d +size 32949 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_4_en.png index 7250c6af6e..1272ba5775 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f8945f66443988d9b36084868241079e22e61605f21cad055d8e21e8e063c0c -size 9819 +oid sha256:c107c8d928bb50527a24032697dee9427dd1dde5987c0c536c52163ce3b8e2a6 +size 33164 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_0_en.png index f6828af0c8..8f214b76c7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2cc4cb7aca28fba19e6e5d9398ca7d26c9c361298137552789024f84a78a7f70 -size 8713 +oid sha256:0cd6406db1a8309e2f524d4de88ceed6062ac0902622d16fa73d6d8ca64f780e +size 30306 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_1_en.png index 2639fb33e1..43098d2d33 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:48a1a38461c9d2f0bb66878b977673531808eafc0aba53f17beff779a575707e -size 9337 +oid sha256:8b63323a128da29de0ebee9104ce6473136e5e3e8a11394c61116c683c3d51a7 +size 31109 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_2_en.png index a68f3fd1af..239aea7dc1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:98990600b7b05b8fe64404ef1f463bf5be99f48b90b6d6aab64f799d5b03f737 -size 9095 +oid sha256:8008dfe4f3a135203766b8107751960f159a1bb3350e1d43ede376075db8d61d +size 30978 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_3_en.png index de56ab0f99..4b9fe06e2c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c662180e91e10974f7709364a07fa54194df0061425565e08644e731f5922dfa -size 9196 +oid sha256:f642dd641bf49c51d09fcbbc6a644cf280efaf2e88d3c8f4f85ee51b37eeac2a +size 31190 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_4_en.png index fc138d7153..165d682461 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c08ae126aab643824bd431aa4449a855e382e65840ebd980d4849e19ed17152 -size 9310 +oid sha256:e383090f2f0f06d902b220e05434045ebdd5be781d8f076e21bdc434a83c5bde +size 31393 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_0_en.png index eb40570d60..6815b035e0 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a3c0e76d07f250735fd75061fb076732180b254d8e8bc145887e0d307272de0 -size 9340 +oid sha256:cf406dbc78412e6c4e457dfbcbabf05248f2578e938016c4a5a6b5cccf1b0c29 +size 32157 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_1_en.png index 508eb5b48e..a478fb4e7d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:08357309dca3a8a3cd8a38f0928522eeefd3a0cdd91990fcc590929e187b162a -size 11676 +oid sha256:2506e19dfcd975a69fa533973ead95ea7923dbc67545553bad0b09ca87b3f6e9 +size 40834 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_2_en.png index 3f7c6715b7..f62505f562 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d03f232373aa8cb3f0f6fceeecbd4b1ef86f8703ac6b887683cbfa5c5e5af4e4 -size 36831 +oid sha256:1a6bc629fad6fdd5e1285cc9ac4484683b111498f989c5fe43f0b037b5619b36 +size 82000 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_3_en.png index 2cc97641ec..37f6d667a9 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:886dff267c22e2ba300b81f13e3071756483c5938e9d1cfb357f633357f5ff06 -size 7634 +oid sha256:745ea9fca0277511ef197608025135387a985082367e52d52b780ba94498b7aa +size 28992 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_0_en.png index b83e6823b5..ff3c7036a6 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c11e7b79420af53a8b934b3ad6dbe9c68d8ea5635322389663b55f62160eade -size 8775 +oid sha256:e20e92f594ead4e2d5a0beb2f290077506322ec11eb75f8d16c1374ddb217456 +size 30375 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_1_en.png index a0ee911211..166d22f9b0 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22f76d8fbeaca8d0b986b4ac17a28c16e5f757e2022466200215fca333f69ede -size 10929 +oid sha256:dd0e274dc81bf5bfa6498922cb3a75721bb98af8fbeaf558d67b127248755543 +size 38543 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_2_en.png index 6f77d72e3f..cb4cec9dda 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:73cc7f1b0f8b9bff2b2e6c9a88b833baaeb9f39923c2113a006399c6a877634a -size 35118 +oid sha256:e54d39cc93385c85ae9c1f8b9f5dd459811c28878f788d0e05562bfb62dfff6d +size 78927 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_3_en.png index c82f55de11..1474d94884 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d4d538dd90a36eefd2f9c8f8f66847cce6bc17f60e503513bf1890e6b5403d12 -size 7244 +oid sha256:4485fe9b2310bde15485f78d7dd556df6453e2567f859ab3268e36d5ec901f4f +size 27453 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en.png index 68a850744e..d9f30b5a5e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5832d2a257dcf613420352d10c42e058ca9df0afa323f2a6bd91ab6596240e5a -size 528252 +oid sha256:b5bb8fe5d28d0df28c25c633d5e37aa6245d69e754e3ec543d855fd4a64517fb +size 448654 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en.png index be668fb03c..e1fb7f49bf 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:691c6ffd759b01f216128c1f7d59e7cae76e1f1a83c95a8b89e6f2f55dce3b9c -size 33009 +oid sha256:a7f75b9cad16c26fdca283a79b871be4b4c41d8c15b1d4ea96c82dd37015761e +size 48065 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en.png index c6267965cd..63afe83d3c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a5fbccba6548b6101f50f3842310e591507321817b048ec9a7310203dcd868d9 -size 524645 +oid sha256:ece2446eaa8417ce67a32589fa2901a8e2c73b6475b46b1bfb895ee3aacb6937 +size 445037 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en.png index 341dc6115f..09dc2830bb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e218343a909a15b66c6c00f46c6bbdd783ad1365aa380ed576a9e66c6dc3c09f -size 31646 +oid sha256:a4d6f6ad2d759fd2383eed4d051880851cd3b46a03812e6ce43a372dd4542be8 +size 46007 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 12f6ba7c36..7d18f051ef 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:f10ca2d461e4078e46455e007eca2d1e9c9a20dbb6bc24c681fa5164e5f50efd -size 13531 +oid sha256:d5c4ad66332bc73642009c013cf99b4b67dfe22d34dfe9db5d30e18dbafa2f10 +size 8905 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 6273b591af..ecef82ecca 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:da386980ce6a45e102727715b5d50f219e39dcb40a513abdfaab9fa725b8ea41 -size 13260 +oid sha256:921ac0d2d3ced6fc6c21c3fa82c49a783bf1c1ecababbac8d07364c5ee5a2573 +size 8727 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 a737f60d1b..f9fb733b8f 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:348a194ad17a0a0dffda47c7387edde99436d543e9bff1726608946e92558830 -size 185553 +oid sha256:be416c0da077b81dbbe3c61c750bcaa3398150ac3444f1f9a365709d2ef647d0 +size 185717 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 312b19a389..806a046288 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:b23ef4fb29f51e308b74681017fcee257308edbd1e218e4daf5736501c70e0de -size 699637 +oid sha256:06735917160f8f210909922ccf765b806c64586853fad685634a006fe59af974 +size 700189 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_23_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_23_en.png new file mode 100644 index 0000000000..704d3432cf --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_23_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:47779722cc50bb7181d300e5738d10c32824c87122faef5939c4774e1b6530d8 +size 23583 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_24_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_24_en.png new file mode 100644 index 0000000000..3620fdacf9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_24_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c23fdfa983bc6032756dfb80149f8f39643215eab97ddb8d9c843401262bfc6 +size 20022 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 3afa92e837..7510665188 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:515d5a47d530117ff21cb922d1cb2cb81b22d02c083c51bbff69964f92260bbe -size 197095 +oid sha256:d3403da236e7e9e8a28001adcb0f5c188d79bdf83146b69e8094b37e02627b28 +size 197245 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 6ac98e0150..698903e181 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:2871bd26b6c21d31ca251761eb5a203468406b4d18c13662fa815c53f015b5e1 -size 210297 +oid sha256:3454f97fd3811411ea5cd941b3d1e37a0f5ab98b9ef7475fa2c903c2b6b089d1 +size 210375 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_23_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_23_en.png new file mode 100644 index 0000000000..98cca36417 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_23_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc42702e3ee2b646b4763fef985568f03d3d1ad971fd426328a1d9820045cbb8 +size 24235 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_24_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_24_en.png new file mode 100644 index 0000000000..0193d6c61f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_24_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e2d3fd5b70d90864b581d71b064a684f1dfbaa368464c32d259dc418a4ab77f5 +size 20821 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 53aafed48f..0f87d86340 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:cc65f284ec05a8ed7ea496c49c52afae585f09d26986d8582c00385459823393 -size 136782 +oid sha256:9f3f46de75cee217874e2c57b390998136a19d32613ea33a2e303541a4fd165b +size 136770 From c2d90ed87061f4427710e8766efca8166330d5a0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 Jul 2026 15:26:24 +0200 Subject: [PATCH 147/383] Update dependency net.zetetic:sqlcipher-android to v4.17.0 (#7218) 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 45599f5061..07f6098a34 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -208,7 +208,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.16.0" +sqlcipher = "net.zetetic:sqlcipher-android:4.17.0" sqlite = "androidx.sqlite:sqlite-ktx:2.7.0" unifiedpush = "org.unifiedpush.android:connector:3.3.3" vanniktech_blurhash = "com.vanniktech:blurhash:0.3.0" From 01823852fdc23a4fb6fbc78656c40aeed1207a61 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 Jul 2026 13:28:32 +0000 Subject: [PATCH 148/383] Update dependency com.google.firebase:firebase-bom to v34.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 07f6098a34..cdc77980a6 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.15.0" +google_firebase_bom = "com.google.firebase:firebase-bom:34.16.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 8109290650ea41f5ae7ad94ae9fe1f76e5d36d0e Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 17 Jul 2026 15:33:28 +0200 Subject: [PATCH 149/383] code review --- .../components/ActiveCallTimelineItemView.kt | 47 ++++++++++++++----- .../event/TimelineItemContentFactory.kt | 35 +++++++------- .../TimelineItemRtcNotificationContent.kt | 2 +- .../api/timeline/item/event/EventContent.kt | 2 +- .../item/event/TimelineEventContentMapper.kt | 2 +- 5 files changed, 57 insertions(+), 31 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt index fd2364316d..34e17f8ab6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt @@ -25,6 +25,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableLongStateOf +import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment @@ -92,9 +93,6 @@ internal fun ActiveCallTimelineItemView( } } - val elapsedMillis = (currentTime - state.callStartTsMillis).coerceAtLeast(0) - val formattedDuration = elapsedMillis.toHumanReadableDuration() - Column(modifier = modifier) { Row( modifier = Modifier @@ -142,18 +140,16 @@ internal fun ActiveCallTimelineItemView( ) { if (!state.isJoined) { Button( - text = "Join", + text = stringResource(CommonStrings.action_join), size = ButtonSize.Small, onClick = { onJoinCallClick(state.callIntent == CallIntent.AUDIO) } ) } - Text( - text = "($formattedDuration)", - style = ElementTheme.typography.fontBodyXsRegular, - color = ElementTheme.colors.textSecondary, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) + if (state.callStartTsMillis != null) { + CallDurationText( + state.callStartTsMillis, + ) + } } } @@ -188,7 +184,7 @@ private fun DirectMessageCallBody(state: RtcNotificationState.Active, modifier: ) Text( modifier = Modifier.padding(start = 6.dp), - text = "${caller.displayName ?: caller.userId} started a call", + text = stringResource(CommonStrings.common_user_started_a_call, caller.displayName ?: caller.userId), style = ElementTheme.typography.fontBodyMdMedium, color = ElementTheme.colors.textPrimary, ) @@ -283,6 +279,33 @@ private fun GroupCallBody(event: TimelineItem.Event, state: RtcNotificationState } } +@Composable +private fun CallDurationText( + startTsMillis: Long, + modifier: Modifier = Modifier, +) { + val duration by produceState( + initialValue = formatElapsed(startTsMillis), + startTsMillis, + ) { + while (true) { + delay(1.seconds) + value = formatElapsed(startTsMillis) + } + } + Text( + modifier = modifier, + text = "($duration)", + style = ElementTheme.typography.fontBodyXsRegular, + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) +} + +private fun formatElapsed(startTsMillis: Long): String = + (System.currentTimeMillis() - startTsMillis).coerceAtLeast(0).toHumanReadableDuration() + @PreviewsDayNight @PreviewWithLargeHeight @Composable 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 d5367c872d..3bc7f9f070 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,22 +111,25 @@ class TimelineItemContentFactory( is UnableToDecryptContent -> utdFactory.create(itemContent) is CallNotifyContent -> TimelineItemRtcNotificationContent( callIntent = itemContent.callIntent, - state = if (itemContent.activeMembers.isNotEmpty()) { - RtcNotificationState.Active( - joinedMembers = itemContent.activeMembers.map { active -> - roomMembers.find { - it.userId == active - }?.toMatrixUser() ?: MatrixUser(active) - }, - isJoined = itemContent.isJoined, - callStartTsMillis = itemContent.callStartTsMillis, - callIntent = itemContent.callIntent - ) - } else { - if (itemContent.declinedBy.isEmpty()) { - RtcNotificationState.Started - } else { - RtcNotificationState.Declined(itemContent.declinedBy.any { it == sessionId }) + state = when { + itemContent.activeMembers.isNotEmpty() -> { + RtcNotificationState.Active( + joinedMembers = itemContent.activeMembers.map { active -> + roomMembers.find { + it.userId == active + }?.toMatrixUser() ?: MatrixUser(active) + }, + isJoined = itemContent.isJoined, + callStartTsMillis = itemContent.callStartTsMillis, + callIntent = itemContent.callIntent + ) + } + else -> { + if (itemContent.declinedBy.isEmpty()) { + RtcNotificationState.Started + } else { + RtcNotificationState.Declined(itemContent.declinedBy.any { it == sessionId }) + } } } ) 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 c48641982f..c0db3a7547 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 @@ -18,7 +18,7 @@ sealed interface RtcNotificationState { data class Active( val joinedMembers: List, val isJoined: Boolean, - val callStartTsMillis: Long, + val callStartTsMillis: Long?, val callIntent: CallIntent, ) : RtcNotificationState 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 f60312e1d1..c2d388ecb0 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 @@ -123,7 +123,7 @@ data class CallNotifyContent( val declinedBy: List, val activeMembers: List, val isJoined: Boolean, - val callStartTsMillis: Long, + val callStartTsMillis: Long?, ) : 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 93f7c608d7..98efa505d0 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 @@ -156,7 +156,7 @@ class TimelineEventContentMapper( }, declinedBy = it.declinedBy.map(::UserId), activeMembers = it.activeMembers.map(::UserId), - callStartTsMillis = it.callStartTsMillis?.toLong() ?: 0, + callStartTsMillis = it.callStartTsMillis?.toLong(), isJoined = it.isJoined ) } From 7f27f4d697afd1c0729aec72ff7c9164c3deb8ac Mon Sep 17 00:00:00 2001 From: gradle-update-robot Date: Fri, 17 Jul 2026 13:59:33 +0000 Subject: [PATCH 150/383] Update Gradle Wrapper from 9.5.1 to 9.6.1 Signed-off-by: gradle-update-robot --- gradle/wrapper/gradle-wrapper.jar | Bin 46175 -> 48462 bytes gradle/wrapper/gradle-wrapper.properties | 6 ++-- gradlew | 6 ++-- gradlew.bat | 35 ++++++++--------------- 4 files changed, 19 insertions(+), 28 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 61285a659d17295f1de7c53e24fdf13ad755c379..b1b8ef56b44f16b14dc800fa8103a6d89abb526f 100644 GIT binary patch delta 39773 zcmYg%Q(&F{^K{xcIpK+I+fHNKwr%G$I>y3d?eJZ-{;_a&V0^jVH&W5P*0u*u2;6Eysbq*sftrzs#7h zyJjsc-5kUV*s<3cBn|}eFuus>N1={WPH50L>>Y-&e0dYlO2qUjuELG5Dk_j3J5S#I zl&}Gyna~z4P8_6oMi}x-T;K)d8w^p0?2|;Q>ffJmvB2c`X!=IBZjgi+9&1#0Nh6Ic zoO&ne(A(?tmB_3breYbm+|#huT{((`^zVmgN3X$^9q61PINav#n9p@BDPn5@kmE{0 zD?TbY9xnc?VO;iJ`Ot(gvG5;X{OTp@5hP{kmYE6y%2mE{DET_o-@hJ~tJR2n;490) z!X3h%OOt+qfN)N32qsLzR1Xku zMOBBizxF@7t_j+s*n4GdGtT3@5Wm9uYmlRJunN8LzXN+Bej=u#8_rDq_^|BZ-JSY; zeY=GHuEW66wY%wO7+B=s8X&a>=Bhi>(-m3FkyO*&N{=(J=K<%p(KGZ5iV%a&x9ER+ z6kL1PfXk+xTqc3gH8xoIT{*w6Cz0e*+~v}+awJ1GB~$5YI6^Ej z#c^R;UYMA5wz%Zzvo=MaFx^4yG>Q>7I51VD`M>0<9zy*dGjHetbY9b%Vr!qj>O zD$6vm7_WSwWbg(S4RBXXq`gRN18-1+hZI(AI9E%ItWFIRS{{f|O& zz5%jN8nLK8NBNx-#|45A;OX5<=RHDQ+-W0di;+I}=$e&BKJb7C7&?+%X=M-b-!gFE z-=g0k|HEpHPjGIsKhP4isEiTFgrDMJ_8sn-Ni(5a8A~D=egsNJUK)#~5a-$SYNNBZ zy4%2!KLzK7^bDR`BU5kGK~?Ks;!FaesgE z4z_5b2At5+V6V+-)?fd%_smzo71HK4h|$^zUg<_zxqe1$u@Vtfh1T*ur(Ns9jDaY* z$QrQ2vCR{XibBMA%VwhS5^7}UL*x+Z;kXk|y5LfRI+2Qed4-6n%DBPI%*2?cpm%{! z9Nv%fP?KN6aJ%&g6@p7sc0}XoS7`3zXv26Dz;uaV;oGl4vvgt0h;I867ZHV%0vGF5 zmCus?AaRamD4_+UND7err60_-C6sI#W^x)yzkNzOs9!5A&^w(lRddqHK9@LOU_udM zQml$IL^GH%i&7bUR9=2h3`lODAlf~ljF&5G!WUwsy`th#-lL1(y@ zukb6*A*A#>Qc-nuWxo({!`uUN7HY;GWvgUwL!$5{>2bFPE-@TU!6t>U-$MEm_F4iQ zA-Jmi2BNGX*fNH*<2u`Z|@DDgvJ(DOPQ;PtOYjw`+eUz{q*Ut+|uX!`5% zj4U%>X8P!ckCkpd*6sVItDkC4V|hlngz^txXMo%$=4tt)1EU!1%80)mF#iWL$PCjV z-LDW3Ey?*5gvpU;*bX-@x^Lpsmyn+lMVB44R&D0P`fow zQSQ+5dBad_s=I$&O2@SXn_~=c9k=P|XtT@+Hra5oYtNjlDjhp3P1JK|h~8YbxO30y z%ykaO9?CpK-+X*m1^rymO;0e+h-~g&hI^QCa%~Mu@xMZZCj<}%Zr^}G#>(l3TNsf6 z^Yuu7*#;jQyk7$);k3MNqYj@i+zYD^jlQXn9EJkmsc}09v&h^(XdJ=I4Zq&}Lr&x! zS6wNEr5$cb*og2|>Crk}zhyR==}L4;pIS*1GUxgQl`>lZKzkTsY>xQwMywA!`-VFM zd5J)9(3s02_tX~p({K7N74;j=p0fdx9*a}{dWL;|@Sn^ZTuCoj-zrz5Q=yVGh~hnh zB(@pT(=nbR0qN)5!h_N?`%lxl&6!fdeIiIb4VK_}l17X{dwbKTwd=Df7clTu>XY=+ zr#=hAJmInsguH+=WP%y>h`Rf&Q;)jRNl_BdJ&-N0CCAH7L2m7HS=fDEb{|9R`jbtX zXO?AYLZ-3AkbPW)?RS*9?U0;;yQy#dZFmpE+-)(MiA&|%1?e3~ume+<0osjbB4bzr ztQPJaDQ=XOI2u2SE66RRvgZTtJ+vCjE%H+LA=|M6(cKotK^;Ei_b~j%NMSqo?jx4;D6Xb{`+p%%`cK{oFUSjxgHz2TQzQ;zQFdE zp>(@TRR5g|g8KMO+v)%IV%f*{0ky5Y_X)-61NNbOK%KBsTGuj^Mr z1Ufea45+{1){5XQ&Ra}Vc(hsZLg@rD%s8m3e2V~Ui5VGlwT>TXalx1Kh_5L-nJ!2_ zn;%|^W0UwMaD`P*zu|M^AS31V!3&Fh$Uskfr7;xm9hJ0=jh3Ht#k0dNg}8Z^3n!8-Hi(bAXu5_!e9!tIU2qKMoC-r(Ny&Ud2)Y=_khmZ zo&Bn0iKX6gM#|tl^xKq9XJpwW-fI4miv`&X=D<;e0$Y*dH?9(^Zc>7Css^`mSf@hk zHT*~7%NnB1TBVgm3@W+=5e+<-X(qoZmHFt=MWooj@#7RlL4`JPkMye->Z;doR_a$d zFWcKO=m=x8(57Z^^cMW6CZn{%%K_CV81g%;Oc`Oe1T(h7@o%$3tLsHyA(T24Dk%X| zqUAXW=K6I-B)K%ES}v~JvW5j;boaz zwnyc$q5H#4+!pRz@u-EY-h$j-6Uj_Gelbx$rnk|(>?kV>I_mv+faBL3Y}O|LHJ7?~ zX@73Sw^ByYt;BovvP!htFzfsF_B(xeWAvI`I3zZe;>>s*89Z?9JkotjLWc}HvT%dX zNj~YS@)z_kVN1+bx|K=0ND!hU&ek&zc(h6?8u&v~{wu8b?oz*>kQjupwLD=J+290BJn~n zbL8NDC%>_#YcKX_5K{O4+9;_JTpJ*M+w>~KU|o}X9hqI)hy_xm`$DN%ZDWmlnM^uD zt?SiOCn{NH1XKC`L&OO72llOd^>*ubtHy}Y4f@ZROc*1vVSy2;OtXDyd#w;BqVaxz z3NcnHb5P2Gj{ZfFJID=dao?xwMyPgcDE&G1F--bRmm)gdai8A;=a$94jy?L?ZT+MA znojqQ8Pb;s5!{Lpyje4ewbtj?gxCHT6yLT*3QCc3nNc)p}N41KAE))cM6U zL(6{NS{#aYII$_Ukfh*wqsaPfdcV%BX8Vcq3+T&#()-PKq}LD@0)h_(0zz315()zX z4i4_05?_<*fRY`Q{%u;Lf7AOrQps2(hNzo@Jy9$W$`Ns5(G}!TW7u(gyjFKSQvZ0` z@S~d@g*@Z>7evksVFyA8r`$HV!yv(nW<6}>e$HNJ=lWgE8tsB0w87&yCQjE9hdDb3 zD{%=eJ%xG>-KBa#yB>l>ok1KQeON~*VbtCfr)J?&pweZu6~(1{@_>@*Zt10mTC>+K zyAF7NT8tfN*L^(vHMXb)(x34%M z8vx$|%G|bG<2GQZ;x>HyWn{;%_Q&SFr}n1R$cOCkM7WdOb`|llX-C!9!8w}|0W1VC zuC3Gv=qihWY&HQ!6=Cr1HL>9h9tBmC_A{4$`&nqv;E>|`9oAs|ZBti?NLZ<8e+Kw# zltheiw#mSWlU{JKN!O2MUW@A9{m!l{m$RiTmxaycJFXB@fryD?(dO@q7*BQL{TMR- zM2oqSc%>?;E?6fxBVS*z1K&{JN#T`Ns)rAyK(uYr_h`~do`PtL{#zWMWyLv{>scwE;sobj#^KwAqr@$jK#VQzSt0+hZp)Q(}WADbE}m z+23-m{ZH7e0{_0;BKA>W;R@wtSCQrFE?zSd?cKNbcU>u#|}$5~?E2RqX; z^c#qbeD&h&CV2>GHShd=!PKgssEh)bK8DRavx8$5;_O!&O0A&(yPaf#wujZmb*x4( z=pLF-YKH1dQ!Lj2rxYt6Q``jV;!zjo3}OxCilVHDUM;1>DUDu`#!EV3Ok84QZ&z<} zxH{63p`9$DKib;}%5!^#Oiv#Jj|vv#=aQ-{zGO;~i~an}8_2KSL8V!|*I;u4#2WUy z!%AHn?;@Q1JW&{Zz{1%Pw_CIekMBk#4?QNqbB-?%>NtQjX$s3HL6-ypgL^7M3Z{=o zc}2ox>lRqRwWq&{gpXvR`6XQk?`JKT{^W{8GIg*zQ0#=h9eE`e=BLweJy{cNu@L3+ zhYCHYokuB_p6W;TcF1*E4lkdGOyiYn^ag(c`yGrW3oyneF%ry{4A2$G<=Rj#s@@%H zEIu9&DBp5KP~(`NwuON5_i)9&pWJiv{Y={gc1Y#GlSgU8&9eIQ|I|yRkyg%VzBr!H zwWLlC?CeTbaB^g-v%>MMT1Xy1l~PYXfj?7@BA13KFnQ2Dq{pSfv9e|hZ8djEue^vD zscd8jp}qq@#*W3d#=_>u!s{y;bI0Bi21(5~~6 za{J7nyFcMse+}Xjek?ra}AwcP!OEU@TiEVmyf{Kq&C$*AUqDDb>$}7Cb5W967YE_(nB{b7J z$=G>~{Bdc*W?)SFc`jTcv|yVbkl?Q;U67n~PHLV{K(5S0eS`fUV1Xi7smuSo09ojN zn+ZWOER8hC3CM~{$ZbUFuz07!^VoQhknf0vo}kGn8Y~+jtD=Xt1lc-%Wq!DFZm_;n zt||e7`x~rQLiGIQy*$bV&ejQz_|b=vmFWar?i~m62=1SSR1_Hhl;cVU_I6c z{;kQ=lw~!s!s)rASlg?q~r#5?GK0f@cCl05b4sog?fod9+ut0yM!Gy=bpo(S- zsVJmTVdJB@Bk_#^q({?HKeO+c)my=g** z{|j+PQK#d`472gyUP6A{b|vd;eV@>}==ioq^&@YcM@Yl2?+Q+?>c4<&M$Uy1tMhxT zA2z`^YWLmKb>T6=4Yvn)D}mktlauFiKH)CR7PL;@I(>^Ju%j0nK?>RoSvdki!J~-& z2R<{Ex7}ZxcmJzf=b|sL;GeA>@b!On%LP&<3(ygPoX|xu1l1Bs+N6Utn>4C6ZG#$7 zYp9Ajh1Q13Y-2O<{8w~$j5$?R5Ff=@F) z-abatogl7?W^VSMpC#^VR`y2{ojW&LEFYROExqHM)&-gbw7j}%NemJ6ZobV~DTSe(B)bdFwrTjJPVBD^}+EG8Z5hSlqmX=wDx-Nj$yLKDe5_bNhNZPF(#{*^g| z90n-Ix}AR2?5^+{R`yGWF&k^@3gQ?7PGSK%sHefSKC4(rgDrTSxrffJol>&1?SN4I z-KU~lJ(J=plJR=yvG6Vvw^jQKFXS*ZI%yCqMH>e$f?qH5C@nvLmN|{&X3n+d25nH% zhtDyyf*`@Z-8KJ!tPz){t(YwK#Yev{IBE(96KA1-d&XFsLCeyErR>~B|Fi1x9@cm%br8BWi42^zrcwfP zie%d-(WFtsMr{vm%1nMvKF>f78uJ9PO6J_M@R^d!8Q!JNRLzHYBC6V$RnE7l;!%3E zaLT~{%|u^1@bO6hHN9nW5Rfprh(QE2tBB8vIx-qc!I6NT-xoPq8D2cmc#zi=TnUSs zN+z6YW+TxH2(R%=#5+2d?y(Q@Mj7)ERX2gGVZnFgKHzhmNcjE34F#gJ zo@wvu&mV#JeF+?+WW}xk<|`iuX0G*bbPUDwftKh89h4Fo!03Rfk2a-S51}cLt5a_{ zU0Dma^alX8#~o03*-Z#ow;Mcp>@HB%AA37>;*C};p=wku(sZ{NB=Flb|b)0o{<)pE%C8Boi)UW$o5ToG04a7hK6gpYIYz4#4=$ z!4q3c!&Iq^ru@Rt%+Lcz!>I?tMr47#wp9+x{JwtNx*~xz!Q^D_4MZ!lcj0r+L9O4o zct7z#^m-0iDf!+pU+15$=C7vdxzjZRycsS*hMK|;Fnze!3}1|U;Ckk4G>N~ulqXS5jU!l%jkkZFqs!P_|9C$o!!OBlE}?7BY)J9 z3|*~&lg<7p$T0BSpK)}+RvlwN{CTNNJo`et$jf-k16d;VU;D3o%1KrwCo+YC@aS=X z6s&mo|Ly`2k?q^v42W;@Tib;rVB-mA^HpgT?LGDt@Eq*B5z|xFM^L(vR(8#j0yi^O zZu6!^eTH0NtQlaAT;Yhdp3Qltq z&>joD+c}Kr@LSdvg`d8&ny(CWGz|e)fdCZIvy8Z-7HauPx9MMVPd>(45ogfpi3y8! zA=@PW#MLV)4@GObQ)Y>hNhY=A?*M&nF*;Qyv5JMne58)CguMk5oazhEji95ifb&$d zwt{?x&^gp(ex9Y{-I~KY)LGyujN^NR$kC_Og}k%S?TZK4{7NU#Kunm)GC@*P3?`sk z+C(}8j5vWmKNn*7E0*VRS;+t^lF!p55x2(SNXF@|nys>@7atMRJ7O@~ zW{gZ5ZuK#O3)m4B#wtKVEs^;K@3tON+P9{GYGPm5agS7rC$&qxhFJ2&tCv116Y9K| zfny7F3lEvVqj`gbbd9H_CU-e=HIiYRe5Xi7HFw1%LMHnzg?IbDy{RwYXjmLhWR_1t z>jS2J*Q$;@2J+3+_l*gIesTJAhhM5;V)}0@vP%2DdL8HPzIVj0LbRHv4Fe;RkVUij z#pOYp*T^PaHpcp2aHdK_p<>07ft$*}6y@NAXT<-&W_i}_;QEg)M*nv&$YvD*m2+TO zWXZw@CD7@TKVy<>B2Y*xlH=`{YCeF zk}OSLgO;|+=%zxuvuvFjS204$QWwYdfh1IO9`C%_`=*&#*A5mpBbqo+Xg8oH>~?%# zG>|Wk5I>V>R#6dI;Rx5Xh^Xz#+IIupq9KFmB#xZHEWtB-kISWlY)y+ZYxY#s!q^K3 zIfHZ7*P`OIjho~GEBAb>Hs&^Svd?2%zs+U}_c&PP=85G(unsrVEs-?gvF{~6krGuo~Zocb-<{c3G%mXg_%eu2Cn0B$ibPrCUMa#V&0 zO_PeV?LNM0S?{M6Nq#yMZj${?3yPGZbH+Vcpr;LB1yqY&^PB~JF)~>Q$TP)5UIqAx zGq4iu{7%V33#mn?eP}-@r7f*MRs5uOd0(V>P=nb(ZY6kYIaY6Rsp%Bgx4Lo3K={oN zsqzb1BYb$S7c;BMxr&BpDXbs@CMo76OFGF7$C(n>KK}(zdLS&;>;jId{Y!VmB;a=X z5bR-)(w^Hq@mL9B$u5wP@IH`k8(>L21e@@&X=$uu>s|eB>NIzp+|q8Pxtg0xKjLJx zs9mMYZVa~7OvLO!)}o2xS}xv7{e5S+Xb?cEUxGT5iS;t-TpOgXhE&)9#O&wvKalke zz@G1(c;Sd4ki>!cJc-qh!B+GM8aR7ZK#pg1$7r!%uucX!!q+m5S7wxSslu!0+d3x1 zp*wapGh(i&GuK+BW6xAu+)`GqWKm$YN^xct|CYaCifJ7WOJr!h)xl|1CIg{wY6Ym2 z4rB}&$fCJ*AKG6lO6;=*#GP4+1~wGk&NYVO{^r1g&fur|b(c7#sRdrW5HA!BEig_a z?Qk>rni>NV-;M6lb|-6#{}V9BGK$JE*5^z!-+e!Wrf$;4ldP**qgXE=@-^_^!9rQ^ z`>z!q8`P5~4-Sgtj*^00Zm5J3V_JKPF>jEZ<`Bm14jLnqqA*`)xNhQM$ z0}qzoqgk-l;?r5V9+`ws$KN<~bVVLGky9l#oq1kBz>UD~Z;1QbNcOOQyw_H&7un)q zdjr4l;(@}35Gev~fDierus?Blm&99AbGfm|{&jfhWej9+@-d=tib?+vh`>`m^P9}Ux z0?n#UpP0ni@?bVLH0QyB=$RDq5LMO^eOcD%l+@Gw(%Rl;40FQr_Pa?ON&-lbM1Ffl z|1lpH52W`Q6a>V=Kga0*H;-y5Q2s?pfXR3@B%oLg12v!(MxY`3T0Inp3Py7ZjsyvD z@%M$Xa4Z@u$}e`+9J0b`M+(|&7p0x}l4WXTiy)Q1-&=XaM6ztoHJJH6AiFPSPbIQ) zy^@U=%r}lrcYj*Vj=JsKXD1tdzJ5wUXsH-`|9Lp;eopUar2IMgXzxswF%C`MAEQE3 znF%tj0uwRf=qUOo+vzv(1Z-(mTU%yXdDf`*Bg`COOdli~vl27X442cHIt%$Y$VMjD z;MTpJ$Yx3+*y%+o!T|;AerIP@=2Bl0aWhUxygolKc?)Fz^6Re?_;*2_p!tCtD7VZb z*2i++&{bj1Ni=C~dr@nuE6{0WN|x!WYp@ zG+^Zw+b5>(s}Ha;tXE>`sZ?JUt7coA(r0cRbaWeXI&sRm=wqQInD!7T%mn$jDQkZ1Nl&B2-qn`};drPil@fE{L8@HFenV=F*7e;uE zyiP#GvD+PkB0?|Lni~6u^K3V_twazw&eUkoEEa6Q( z0?!%WPXIsjm8EK1zkHtV>bb_8k`j$)j8cVF9T;cW`Jw!ccUi*1R*A*g08={f-tuDf zM>2wq#aheneI%-O2k#C6bs)6NR}N(bOdQ-6$*&zIu#Eyz5RHdKM^NpX`CeGlEr5TV z;S%Y|Ddsd$+6$@6{shguSL7)D0NSUDTtSi%YEaHz)Z@1?;K6FLa!JbVeE1XG#dr43 zM<83q9q(Kj^XYy7XEm^Ek{@#~+VkzsI7C2wM1mAnrpG^GUi=wz1cci&EC8PjsB>wK zIdi{*yCyPC1FRHkgiJUUSWlY-5)50*1Zt!_tpG05t~GV_)ZBB z=Q+{FrtCWAm-FUvH<&}pw#lX{>9g-n#Ew9rIeBp+Pr({{xYSNx&uE6BJ^CKG|D&wh zAEu+h|0qip?tjL>5I;XiL2mFHYJlDHlCJRY(Pc5@!V*?%%-|@JU~EK8=z>uPHig!0 z3JY%9h&AGa-W!tOVBtPuN=3w-E`ZaH-@T<*4@js7g1}5}&w{NTF?XvL5S}7=Re}F! z3yg0$E^YIpis3Pdf$SK`CMiw(Lhd{)03p0Zy4r6ec|&!OaM%z;CY76MiAtEmVbNy@ ze4llIo8c zIk`e$c`ArLw&avf4*iED)tnO*x1@z*>ziGa7cN%8>L#?M3+pgk~jbuMK8} za`T*?ABG>q0Koqnv}KW*GsrBobDbF+OQVWqa}Eq&Vg@OZxfheNoiUo&-Hnb91uR^v zQuug%bxw0Z!6l)Y;|2sX078D=Y%}8%Tu~-w1bDU~dJJnlj<+G^6PYwv-#kn~=zoqV z94igjuS@lj3is>$&OIr^;2lZF9AR)&95RDQMj>*!_Hh31mR~M|uDDzbfJ`PgYU9^kWUD$ml z3{{Fux=n`d(f)@cJU^l>TE&Yl`bG2_se>0=^}{3QEQ^{HLAa77Qu;(&7U_F+QE>Oe zSkev1oOIE1`tF^~T=aDGQ}JRDLd=h2k;087LXbyXf~7p&90qIdcF@A|m-q=~7sGb^ zlth4R9f?9kVLuMKRyS&#nGbc`K2%tvbYDH)zine$l443LG10RQ4RY48)TZImKkX+@ z%5C^5Z=sgNEpsglZxwsEOqMzuDB5*BhR}j-M+T7E0Qg46$6h zW{{Z(f)Ogcu-?tG{kXn`jC^+gW;R1{8Q+v&tQbR-XZSwgJ+w0QD!56#zIk(L$KBr` z$5nvVPkW`qOaix9e&2N*Y&=~4Y$UT~Gzsf~56__#FB?Tte3+o9&=Lcbz-fcScMYg7DtEp>LrSShgnn$+4t>F`F3 zz+!CS5fjX>Oaa2}sv|#^^i(-_p zI&%Fvx~aD2Uw3PFagM7$F>A~L+I3^q&j6PXmLJ}6j70cR?tTiU_;aC7hF$i+I+yJW z-X-5b=a8Rj-=mn)6;_MzqR^ZcI`IX;aJ_m#k78tAz3^K)U0U1O2KCmrimW4z6(?H~ zX2gGIK5I?9uz9s{YMn<0>~Zi0N>ILrP26O-)7j!UrNQ8>qkh#4s}t&@czk=VkJHWikr&{zwE76<#MUpjFo6#zu3IW<(&Ia9=w$6l@&9GmWu5ri(Gk zPyXv}ANI_Tm-9_8i1^!Ydy9{cn-5|fiMAr1c!UzRSeFu&V{#7WC5ZSZ!znmk=F+~V zu1o>d$HiDZGXd@(j^vR=Lv>3Rrb%sXBJucKg0YllrVl;gs#uf0S&R4j#5H+6vNDH} z)1>SZ!G(!(02&P zAQh%MDtA)^B_~^j)OPf>9iQdQQ!*QPURL)mznO!-dk|hwzLhfJYvLe6d>nZD5B%WK zlE!t{?~FlL@O82z0#(o4iWV=mto?9;xuv}HsMF2_*KS+~dN3-W z67CUU)VN;8gW5hT_uXBVH4BvpzxNGGk%-h?0thsg5#ut4<(L0ulf%~;jk5o#9o7FG z9OzI`lIbKcL1L~J<`$0bHYWCNOlI~bZf+Xt&=CKAgMf(D*meVIVEo;tGD+r`^H-)b z(lv8fR9F~GUsA1XYQah7lGbIBV9c6U=%`;u%0gN**<0=v@%QxJFW^fEjzL!P7y*q^ z6OQ^`QGFmIzjQrqxy@W>@BWLF694_Y!~g!X9*0N}@X{&E6K8*(6Ir1i(hi8mM9a-jc<)NZ#*jv$XyLHK=Ug`x-cY!wI8h z|EvqK&2t(aD)z;D|Gq!O7~*q>Mi6=&hioe()e|Z(A8+0^zh@P8`6~ayIZ~I(j0!b0P=%>Z?kozh34@p>uh0_hAmyzmGNl|2p}a}?Sq1Ng zZ|wP!^SkUds-X3z*X}mOlT4L^-Qx);EIGtHXa)F1D;<1D}Ku`zo!Y$S|Q7;aPG}9Yh z(5b^(q9{R=lojr57ZMK@Zmtd_(|PDTkAIqo7{>W9lt-H44IWcMWhO>0YOS$ODp1Z& zU1iNp2qEt;p^Ez($?L#Zj1r`SqLrG=w0LvtRCq{dw*oFml2|D3Yh6*w6|G|~XbZx@qXkHzgo@#(koL-5j_|oFxfxi66#D4T zEwaw(Uw~x+S#P}+=~oGVS$LxsbmDHJik;?jc`xUoS3&=28iJtbNB-Ksb?f*4i5k9y zJSa)dY4ICI*z8;rQ-vOa!^E2f7wr(IazZssLp~gQ1!j3cJ_GekEc@ki!7T;8I0&w{ zuu8oUU5_FV!#PL!8#KIJ3+L!b=Tq*j|Hq#*_U}?RP(nlm7opePaWQ{rFMaV1m+tWl zQz+XP7AhGYldI*b@fRo%58?xKo>lS+KR~7l7(0?mzk~4%iQXco0yI`ge4o7yz!#kR z@Vofd)1vd~pCJoLBXpE(bg?>wNwjU)=ldJ4x~EYL;{sY?oR#b}u)CbT>~igFdIaiFSWidFFuJ8KHh#4ICD{L9t0@xoVo@)I(0@%WHV1=EAo91O!u>KKZmutMyV@F)Riw*`wcfFlxfIap4+lXC z_Q?Rl?$=iDM*yb$?I!<-erI>UHQb4$_G@s7+0up=KDj>Mz%rU65f}34g+n0IH-D=P z)^N8JTb+GCY2ZH-5Ejn)&LUvrpTv#+pAy$b!K9Y?yYhE#?zM1FAmj}c3Wkt@ ze%Fl9kX7;Qdfeflw$gz}byXu5G_=}!arFp8*J1GZPmHo7prA#-)k#S_3bnd7(U3=O ziaLn8blf=b{oy;?e8)vAh>aP6^gSi%L(_<*Rdp)A3p)Y(M5(-#{?O5Wy0lH+4 zNW-n{C5%?Pz^GkdnlKhoahJc+&ht!01Dg2gE-8i(+BImq=mV|_0iRu0SvO&NQOk;b zg>;}}U?z!EW5ZmRF3bK_+?uvpn0+PGEDV%t_*VheVat|WR0^S(b5&&DD*8jy1dtuHT30BtABd-{$SP@U+rDh-KC9bK^65|KCyc;r+-Cm zE-t(5w?s3gZ*T@8_*&G7km#8x)n^*Oo{#64WgmU2BN(epHMi z5;b;3Gso$HRbL6ORd5^iKcmxAy=YwW7PLd`-!%*emRe?^q$xF_qH3d=hey11Qs zeq47yO?P>}OtM2*)sNkLguv1-*Tr%=I>ODeVF7+ROyQL7Uh*==GVo2dkYdBQyu?_|9xhzdpC;l2#3B~0PP|j=MIJ9dJuf;i;P|`zWkm%x zZ$se-W=pM&ph#U*y7>6H^%(UEo&4G1M)Em7cvyxtMlk`L!u9l?eT-V_T#!5Gk@>Fc zyAS$#dQ!~MT=Cndpv!m5z0DxFK`>Bq02ma-A?BI$!R!uCvC5q*63E6HoP=GE0YUvacyt1!xwRg@Y`Y^$Odj|A;=2vb!Zc4Gz}f;H zO}Q~U9*4Cbry}GEHGw7^lmMs0`dxj|F7#uhL#cKl0utIk_#%uL*ST=J1mca5Nfc*X zLle@H$q}PI0O4UC#cKM?LhIOYH7~zs?2D;DmJ!?aU**vp~7b2pBRy{N=m>4vU@7 zNlxqIxP}Cl)&va%lfBb(CQHwSlK@ikj_Ut{vm()8mdwn#?_A(R-u+pZ*-dAQmO_r^ z@i{y3vcEU4+!1tAG=p8yu;QOW1V~1A*C5es2C=PY{^i~Er^5$%VryPceRxdJ@&J8H>x!hXV38zf(4(kXbv1wIoq9%~#&$q5*sg6y z{^=HGx;ia2I15nY$AO%J4pR|Q>=|8fBFv`h98PuKc_xrdtBzI%E!Y0b-@ zi}{{|3ZM9VD;uV`bl-%@?vVTI1joAKeL{RgPif68+`C6BTD4;>CV2Fy1OvYvA;!r6 zO?D8UjPRncp*@_SF8+OkB=+OSbsKIKbnMdi(!l(N!#_*dF_z^+LlFB{4#O?C#&+p1 z7&X+&ts&HKv>cgx@q|s^X_pMX!(INtd__{01Hi%&Z!iW!|9j9S@_(_(RAm+rqQBaS zhw$iFPa{KL%lDxm)P2z#Ij()Q7!sL=!NCR=sC86myc6Ay7U-l}*K5qZrUIpn((zY> zVkCuyF0PGQJyDp($ju~A+OrPJ>*mc3hwZ~v!A?hm&Jx^;C*j>x`HWby$_gVy0g6#?yt|F+wRNjYT~)W@L2gmA$?-vYNv|$tTTJI5`GzWpllXA zr1zvWZij=hi*~EntqFPH+Dysi>rH-cV{F>%g)&Wzm6*)F3633i_2Op3sx9*Z%CRaf z$%Toad$RpFfRY_-Ldh=HN5sm2Z}nw&r=zx6Foh*7-LKpxH`1sT`WP~tZezqx zYh-U5-2|B(GwO(c&gAQ2!FL_4_mM^$uovX}^iL?-DOv|q( zj_YMReYAtR{N$r5IknqQ3uvLtb}=o3#}6ila+U$^$40j1oMCueGOn_apLUCjmeU@% zfvpc3eO6MPsBVb>YU|tERn%7zWb&878uc<&!ctLWuQW`xPwdx6`+va_*qx^B_$lV% z?sjo|Ow08)$b69AAuIP3R&;0BPxrdJb=L##%o!G3DDEN?OjST`xAdVjF5;&_7Y~2R zHq3UXw}R>V<;Yy!C*|-%NP?w0iH>9({n)l+aU&~g)+ohv-4uhpIanZVl&ohEMB8;_ z<3!LggIV3OjUf1VDSykQSd6J8)g{Pg_35QQdC^PiypHrfW;(oWA-I$+9!AFIs!pM-S1jFx5@1mQogWeauG> z(#NL0?(s4n0cFy zTr!oAG(5_*c#iA4PI19UWAqY&Kr(X%;kFDnoVB^Y3&#HveOV~J0-FQ}O$%`zkw|!% zDKys^SLO6I;q==xDCa11vnjtWl$YdZgOBnee_)QBqR}^zJ|?XYHPO!&O5W%u? zS;t8D>2D;5eUJXOoaA3M5sY8VrBO$Ba(3r1SbrHxraSHsC-?#VgOuQZEH-*GvWG_h zjJ-!Kv}-7HxJQ=?fq$hR`siQi-;i~R9YFA?ZU>W7(zJT%-c5 z<9_-tamSz1f8)G(%Cr#?Ka&c7j^2=?-Vl4E9jz&z2d4-QT4oyl_jAO3a8T8taL{p0 z9Di)^qHm^oX}i(OW#T6&EDMGai>+DdCM2hLxqMo4D!njkAR3aM_Qqe}n8p5!E7@1Y zUamq=3xB)xfcZ?VS8JnYb~b2ic_FS-+R{s>rs9=rd|b`7r5SJr=^{iXa#Eo=LuoI` z$J4e7Ltety_;@j2JMB^6Udz__I_S$nDt}E{Mvs~4!E4RW%h>1RrF?xg`xaKRe}su7Lfh9)UJg<$$t=?MioPz;-ioq7g3 zwO2+=^KdSE^~Pr!Ved%R_~jPeBd<=|ID55IPo<&=Avnt_zR|}kdG*2y#xtcH?thTN zC0l3Ny96H0WmMg0+g_M}O%pfQBE0c}S(re}Z6ybCveIXzyxjT=UlVf}YSNpR@ftDl zP44qoRZuwTkz_*Lc^w*vf)DrNVi_;vtCl zk+s7pDbRiYhxYdhDw*p&#+x|o<9~MEEVb@AncY(CcIW1z@ojLw!Uf#`-U7c! z@Sv_4#k-h=?)LL;-s7Xqd?$+E{;hj^x_Wj5`)tXHs#*1NRQ04V5t7MVs(AWA+yD&g1JelqpedRg~FflBf?l%(VY)+km~ zWmaH~o7ZcMca;yC-j^a<-B)e4qOu>=<$6i_PRSbqGBevOON!M8(EN23Qbo`Z zTsYX5F^*-y53jEHRMrUEXkHAs#|N(v5bE#``}hPui13p2)+1gX%=iR9DUN|xkVjq(h!(hJ{4fmI zD^`=QiOG!7lS>aEL%W#j4%2kR&RMre*;Ipfm4*h9fl#s|%@?SV=`q@bNr>rXYKz5oU7)p$#_Q&u z3$%&pRYGPvL-Sh{1oW<^P)nX}+ka-_m8KWKmiZa{wvuOpYN<@4fJUo`-lQgt+BDic z0a-jQ77+f3UVjG)jVryqAmAFRPy()OiXA*SN?V)HQ)kP0+BQx*V%^Q7bVt*9id=u5 zdh&GVS=A#~${W5weF~7M<+gF^iwTE3-PO&JJRR7Tr~X^>G!XXW$q1L{X*gWb)ZB7? zou{t6u40r9ztBBSW~}zUrcrV(DkfF5j?&O#jT&odv40wuP@Ni=(sDHh>1}FUMQhdQ zs=!Y?0T3F|fUBV#9dSjR_chl}{6I4__pUs>dw=bFdpPXjaQPU$KTjWug)7GC!B|)u zr-x!Kqx8{H`b3^S1!FX|;D1c$K9i>>YoF@R)32QqO?*N9{>E47`NwES%ggk9o?eV? zsiAK?MSm4%Xu~+=W8*XyTiPEQrSUvnto>@9Ua70d)2n&<#wh*H#YmkN_MD;D3gfAk zSf2hcTwc>aU-CkGe{xG@N99IuU3qh!{vvj>uk5oF8>8>%>F-X{_9fmGi+v{!cIX?u zEA)dMi|Fsul_#H|swLiKCr+NGMNKP!GCIytWPjO-CEh&!Q=Qg4Z?P{=KLX`OZ^xO5 zFNlD({~?0ZX?5jI=cu#xKlAi@p8h9Km(NDd(E3R64x{vD?L<-f05hgd>h>1{JP!aa z)I7?bizRF>5hMq%I*-g?|I5u6X@wY&L-d*&8)2yx)S_S+1#Y1>Itf_DhXJppJ_XAt z@PA#@uV5JkK1BB^SVn;@{0c0iz>m|@3YJmeXX$eamQmo((-##iqrflXwIr~N0$-%B zD_BN>zeC?uu#5u#h<>bK83q0cmnm3Azk7)ED(FAlN3#8J?IT9rN`gbQVD}TWkwqxbB$rTN+>FKN%s|Ag|&7Mg-0{${> z;OYsY*90~w$S7YSI&VLs5 z4whxh-=O)5y^qT1Mlfr{SR)_T+#||1L6{2IDBCO?Vq?5~|4VRHiuE)HxNVHr?ho*K z8Ib1!d~;}wx5UC8b!dC6r_RHpeCruHir_r}e1JRL9p!bH-!Ai>OSC0)iP|N=>dN~O zV~C{caGrOB+>q)KPGL_dz+E`!Wq*{fe(rA zGEm%(vezO7?xz}!VOgzS7Q|-pD35rPi=05w@VHS{M69NHZcS7n^Exe4E^#Yrcr9FF z4P4?jc-p<-azEVRQ8>htpno1i_5U_}@`rGqH>rxzDRCFvsh1Y80ooe*2wU*fr^%=4 z+9@fF$~zxc-idp6EAXR5FrvVZ7r|W${A3aAQQ*lU81^Xm(Mh3PraaOc^R&#ejNEZw}>J`&Ep$5 z$o2mVP)i30-M3~u@DBh0;U1HrBpi}~7n9vuD1Si|Jwt)rexO)UP*ikPC<)t*qDh0q z1f{@34W_jwJ~hMc?RM#YWp=lQ82KUo3uA&t6Muj|%6PYEjN*eYGjq?JbMLu#=G*tr zUjaP8vcS9J<96eXaUks>g^sad*nMNou%jUMe3^PtXa|v4x ziGQ)tmwrNPM(mn_j7=}kL3ID&x@<64HGb*)neQ`@45WE4r-ZH-5-Bfq86A;IxEAA$ z`g*-#Iy5rg>JS2@PLwH|c08X1RwCtEu9A*V)@vo>n3T0U4!a4dy(pko6b-Xj!=%9M zp&Uuem!WIz9~_dMYM2&S*lzA@bz3ibyMOJi?N+nb?KIoHz5QoRfokiwqLb#%9tr51 zw(o^r`dFY)TYV`o|2OGL=J^gO4Hbdu%`vxvb10WEgYyE#jIGrN>`ljoKU{T=l9U1s z7X`{LrO#Ew{iH_%%eAvkR?k8eT*BoN<}lBN^I?RJfcanApPo6z6ZaM!v`X57gxG`dC>(eI9tz=t@WHY_|G(|8?~hLaxPYmE_wDvR zf0ZlL8}fx*N?ppC)J@%5hn;P_s+)qC2XcgwcvxXnx*~tQiG3aAvP2hYCR?LwY?U2% z5S?ExFlTMZ|NUj}9D`V)IvXY4SWgtJH%tc#k#8~2=Zkr+3L50w1cZR;L(>OM*Vd7M z(q`MUM1*G&sy6<>l za(wd0U=JKp7(=jS0taIS3FjS1egIHQ2M83stMO_F46{wl&uJ zEVYeQx@ci0m-Viv#Z@Vt(ElqyLTp;NhSf`Uyn~n?*0AFIlr?nzx&*Y zCyo%&1*X%O?%TI-)AH+oD!P>5ZZ#IFXs8HwSJYMnwP;^Bq9nsw%p280D%Rs_L{$CDg++ZhWlKomL9#q$Vgd-|br55k0?};m+ zh+4lVuJrY(@%pv;YlrdHri5b>S(s*Ct@JDP5hd1BzoF}DHJFsh#$<_NpJ}#dyKj8o zpA<|qR&8aPF}}Jwq9hU$$xLNEYI0*-OM(bkY}O1K6`m@CMnVmy;^E{#{Y02X2RZ08 znM&z&rZcC9m1rh^(`h(pHI!vY%(P(A5#zfc?xZrA&Y)RLbEkrmXf{(R$ojOPZcHd9 zM>M7;>$hz3fzVuX$ux)NF*)*gBwD~^O=?>!urF6bb=g|dB&dK`{EdxtQ&G5)E zy#Pe40DC!ITuK*F1Gp*TW)fYJ^9FsnUDG|SS?ykiOIItgn3i;h)TA1ZBCEKALZy9BmAhMuyR*lCyDwMb?(Vo2bq5h3UC3qbC1)p= z)Y)kZ^a#MH0vEZsh#t2Wal2wJ-9c9hKMcsUStxvdzOVTQVo7Ch9^*R@xA|vn?u~1E zlrEuk-E6xAl};m+Ho|PNq=OV;_a^Exe4$;5styVnYtWl*N8Qy*ywXlR2>QCdxCWt< zVKrfYr!d?J#*Zi>k;W4cb9oUli#Sj*DR)yuNEu~Xa%x0$aWuhXpONGYafE|8C{7oP z9YnV~&trm-Fw$5ws>DJ*7!(Kz6=9JQls3xLPkRtuN+hD~*%I3w)AqzR=voC8Mm`vz zYfAug9o~BEbOWN)AnQ$minmvbBHO$N`qKJ;jGTB;(R$#Unjhmd=;9{2S#a~-X}RB! zwfL>Df)ejZMIrp=fj(I5jJ#v@GyszCqxYB4ZFD=Bzs64gg%o^EDy$~$^g*mN+vzSC zH!+Y%s!^{nv7P=Kp{r;1uP@YyL`Xm%MPGOyr=!M7+XI z4r4^X7i4;fz9_m6-z2WHAdkzmpT5Mj>|~)(xk`lzjbQety0ZHc9b#JRnZ|Jq?8b=@ zla!m~CnHmuhI3_5w_Pi8tjJOlJ;7uTi?^f}7gFUbs5QF|^?aG0ETs`T!c=>IQmKqT z{-lxw{iky07EqMvE69FmLEF{6NxfDe;J->=E2XFDIC_bgzFgRIWc|%S&(O01?m75t zR2k?}aZ)_FA?x8qD=3IRPcO)HjK0Za@_Oy`Z6@zY1!?LAyV;y1(TgGgPF3gMmFXq= z9%S@-x9?i9v&K$8zzb><+Np$pgI*Tg)XQ=zh-F)e-f_!9jB87<4MuyRuz5}xZh1zrld_$B>Hrq}7$ zpypYbsLJYdMP0R>ehZa`VaOJ2i(BBK|@Sddnzt|3a$HVt987 zgn#EI0-c|x9A>t)JR#GlD4(T44IN21mRPS2I523Tg?@xhOmilRvMLphgiw7MV-8c zR)CiB<$}=q!ckY3LE<*i+39x;dY9(l4d}GFoi`$T7qBVuCS#mSAU?)A--#`bXe%7N znYWa{6SpGRaslt)D@C+F!~u~76D`p`aoBc58CNsL5=$a~d@bT@7s3b&os+6do-~Sp zz&NrfuR%cD)1yT6v^GBOF!IEFgH<<*w>z4OB*O?~x6xqL*|}S0Riu?gS*VbvCfs7I z>s9(yw-OsLKmmzqX33P(x@;h;#`+!HZvY~-*y3tb z>xY5|3}?7DI~3*laACJOzJmj==Nkl_eduwDK}dX~%r^;7brn&OPwVLs!Sh~G^tKt! zeyhy4@NG<2bTn;hZ*5=eZtaPowG6p~sYDXPvY}Rgw{Up3aCmnldzXYUI@TTTNeS3+ zY!Y09+s^MtD-O|`x)NFhqrHB4!5`2ER>ovwj%djIAEY&cg*(MX&tBv+_~+ds<2NxT zn~EY*WG@g}^!oyoH2yF|7D;xx& zl>i-o6VCi1NX?i>BbpMD_!GrFwHQ^2G4z}sQM?U)!zL z`*ca#)TGj_1i{;Y#E&B}M8_AHp3hGVSv+9$Y9XUCB`S@?Q>4^Qg($89{%@Pck<;T= zP2OFtL?ZsMXgc{IACmb?oQ6s=Oi%p3ve>)4dfdQ=okWbOv^Kl%9`8on;`&yZiC7NCRg~gp{T}Ax=`38BnO_viyCeb*#ZgFSRfU?2DN*qO zC@EyyK9Q~O^7q84-_K1h*{>J+b(#+f6UO)Yct^jE{B1M zdDd8anYSY@dGbRlZwtKqgnugYYy2|@DaO+;ge=<&Ke$YRZCLG>GQZ5fDrgUXH}}GT zC?>x_pAbyN#nq{?H1V3lSOpuu<2PjfE&m?kCB!GCSQ1lofe`aNQ**(86Da&fHk@$dpY3f=a^s)tfK6m#nMX|+ zo2|i!mQWog3+70E*<@vES*@iaAwAXTEtBd__NuuyDW^^Mjb~S8jz^g;X@bBRNhJP%nW=>A_|K*i zyuE;RGyVph)-=sXQ+b-^r|GPKFHK9FRcWdpr0SYsy6`YHGWmwc*)c**fwr17HD_pD ztxs(F4ig5E$3|##!15$Xf%WDZzjJH#Fm21w_M_{?dUb}bI!Y!SbUFoSC(Wly^3X~$ znPl+=nk=JuHA%EWqQ%6260IBspz+>BG)gjX#TFiC0|5{_O{F?D!90wI{Z)9D#iu7j zG|2@aLEUnox+ceS5dXWKz0RxC6wA;xX-XPDz7gsV?AXzsp}m$vbiMUSstE+l&V7E1 z^G1J~ZgJKeq7UR&@4)JvVznc;ayM2!Bvt~>djRPC=pnjqm>wK|q5Xjd%LqLb@E)Xx z)AacaJ(i(^Ba{v_SiLSwh7KR5qf8Apm+dfpooSGtby>ypH<+FR=>{oH-x}nHU6S)V zx+%^Wp_hOwP`^Jk`aITun5I_-$pthC27JvWb*Aa(Y5Glrb!hYe_J61E*NOd^E7J7G zWdg7qpnowy%dM7wtMsSW()163vPT*ZWElr_Nw#sYjgQmY_t9JczoP@&hNyIe zMgwRcj(ULx$Ob#4cG=Tx9;8`<7M{m=o9WHcZYU8@B|6ltF6#(e1Fn+JGL|w7R7aX; zV3U3hsnhHnq_Ui(1|KJ$abdl@!D?M*FSom-G`senIOwu}mfI~?2~o@Kx~vU$ovyu* zuFejS0pqeafWpw|5m@T_0(J%Qp%co~oMjYIq>ST4f7QpE=$0<4{PA7 z;~;mq@UU%={4RKFQ-jU959{zgo#maDn}q`zFIQPUMRQy>{mq=_ASfdZ43Rp*YM_jJ zGTeLAc)VIXKF(SP&K%~1etx;&wgJKb$0aquXS`*9oEql6Q|!*rS8SkyrQEI|tS)B* zEDot5sxIes$4Rmbk;N=F8%kVuS4mC}`U+ys>MAi7hWS0hL^qG{ErE8SjXMykIc?x! zTZZ2^NDIBX)g@T{cHQcC7=};tUA1Zc&>%IA@I64RMl=U%NBAcA|3@->??JwQ{Rlr0 zX!BNoALNH{)-XTZnc+ukUACGhc!cPSdC9WYU&c@7vL&*ao)h^lS};ocNiuSv{?jkf zeu<7r^fb}GX_-Vdi!L~4l$;`~k0L$Vi^2j-fLG%0D6K65^m-0x6bZ9rDjF>In@OH( z-}n(gbEW`7N;Uw_nvT;^Dka<4HW`~@d4Ar1vP6&Q8=(0P)eG+4q=iBy>>s6#LLaiI z8Ius$PjnUlOR@A0RT&$X@hAoJ70tH@R`t4bsi-gdvtDkF(|IT~X#VhfF}CW+LQ7FW zSCNg@0d5;A>uzYV4~NGgNQxY^mrkR5QK&vnGw3CnNw3furU7!AZlW^NZ8XbtJC&P% zUZvTlH)xLOZJKMIO)m3%nrB`_^Ubxiz~?+yp|iN&T=EwTkfQDE%!hMSq#BO znPfZowh7rr_-LTI6JC5QuwEpv41d*sTb<#r!bL{Oe)x&GLyY# zLIBZRGLO=gqKSY}SBMZm*Ua_TQ9^uh;QMA2wwOAK9o3H6%iT8%>4Q0Pe|TBUf%$0VOHR=*E~+%SzZrDd+t#Ea7=v2I9{w8WcjX}z#b;jQh&*4=4IZK>gAkr&I%Q-uf7#`b@v z445^+&wQ(+H4C;az4Zb~B9#ysl|-y|$yh#%^l+I5GKSgjYy2pU*>B>c zTd{C8PsNu@i6PRUvsF;PGHb-8HBi`z0ayr&YC?+eT?{WbUxFJB6jmX3I0_AI-2=7(f^3?W&}|!N zOYhPXc4q+M`adSf=X)-NHXLhyh%EbDTX3O48 zY-q^Lv~;AhxmYr3kdvwU>e!xGOEQ+))v~$wYBQcQ$j#(Vrg!Z!GfXFUR+!(Z2UjzB z`qFz-$#krbskRd1I(rzbGlpWhfwkGJIoO*N!HX*KUtG?ENej$<@nk-m*rPXpvo;<# zv)Qg#DyCICuUtYRl`}J`ShA%bj4jD@d^fDrvVPj>5bi!VkxJy&FkMl1f=!-qTW`FF z`b(J{b@i9}shZ~a$e*4GQ>Z9@Y41Ce8Aai{|^uLtgo|z)wD^l5eN@$xk!n z+o??R;3$dy;dO~@E|ciZi+^r^NvCs6o9a6C*(cI1vdrqv2~X(BiIc6aue3kgd6w9; zUA!9B^q0#rXc6pd?!%f{z5mPnw1k%WXfd5W$>pqt460)a=w9fTY-vv?lkh}nnl-3_ z$!iV{<%T;UjcHC@edh$H^sV+&n3{alNX=kPqDNG~y0h!*FQ2?cKb=W`%S4OiOtYqp z8FV&N&4lQ+nM_QtX;7<=R?5LuC9>-h8EBTy4EyOEYeNxiFxH0~5UA^%dY4wq#?Phm zWIh~i=48bUx`4?@WY^2?{M1HEt7t8?GhKC|HhHM8?94)EEX|$~>Pws1P%51Z#nY)= zERhPuQo~@gbV``n=Fs|oeM4xNeW6@B)SpQ8h0J}icrG~{T2|s4ZuZc6oKJr`GZ=$O zɵ=r6CZm*ctobRli@Q9X4qo$){P6@xZ0Eq-I)(^sa;N1fEoU_u76H~NCh{(N>++7UG&DjBFo1z zvelB;geuI!e&ZA2!VYomcG6;6QNc^z_z>aXJsa0HEnm^V#aHj=1(5qJY=Re4~bO_$`->yX;jA-gYvl1DRXZ}YABzBa%K!`Zm6rY(&e4g zi7##kBV}@++Fsh{qdhcSTzoQvLBJvE@-~CsjLU%@#2;6G-Q{g^J>Eh$_~<%%D-4hy z>Wk%IM*~A09df1KMmLIeZYqk^mfbp#N$-vIO5A=s>izT);r*!Oy=(HocYYd?z+X=v7Xtzb=3vuLS~=rWNI!7&wY}MN zGM_WWNBs1lNLWn&#>#!E+`&X#gUL|3ztU|D^~d0UNqwg+O)X7Df%hu%4912-1F=13 zsMj=8pbVm8)o`D!{ZBKsijL=XfjfuJ8 z5JJbWtYt;ECOfh<+vA9=A#v|eB8y0qkuZw<)F)Fyu?$qRV+stWm$Rpb`ZMW4grr<1 zpOuh*oYm;HSvFP;%UQ#rtZC{)2_91!t;_#hzggs*MMr*erw6X4LaL({`kP{*X) zdB{hP(4#=!Kqo!g!3PH0Gn5=`r9a%VPm|1V>Gd^Yxb@5+pSm z3zQ(%=3 z$U>V>R!~yg;LARGioSvXXr^+K`I&-~@Zys8LV=?HPxVWh0 zy3!eQebO9+RNV7#3vl}ueFsr3W$w$_15+bK2{SxH-xK!lBQG7do%K+2*q|RmW5kDU zKmb4eSmMHu=vl|Q zB}tF}B?nrW$8vz*`shXa9TK(16=kZl)OA+2{hSX{u12!t*-W7~Dyj_zuJC5_y;(io&jEo6^*j$t zHhXx!0KSfjfPw?OKsZkZ5UeHF1@y= zy`!VY)@-q5j3uZKy4J1mFsfhIwyhhQR(ZJ2vUuBYPQuc>N@fAp;s$Pi6ph0+z7q(? z%|Kt=QuIUAa04xEiCsl_#mjJC>pCpvYCg-y%lT{pDDRhVt*F1tU7`(n4pns}W3A$I z#5HjJt1sNLc3tQCo!ffWZ`rwVbJuzgpDTAtn{Qjz%xp|cbeTD&OyM>Ek!m$3~s7u?B|QDzD-u2#n)x^byw5( z;KRw-U~gY+$;7Q&awb#!ggIvN!TzH+)X$gj7UVYWndM@Xkkxfl7^)e$Y|(_p6RADv z-DXRtR=CT|#rk8~EC!>ntQwr?V0yaTPwaV^F_7-t2&jd!WJza#I=wqTRG}D~ZsOMA zA@d&_w3a;a-1_53+hfUO55go2bs1mo<0$W#<>o5@D&iPny1im-wBHaap4k7-`RP=E z5*dYM1_@m2siBddck)$ph#2+u3?1lXTvqgRoG(Q}Bk!Ff}tTjZQ_A{A=IDFgyhN3Ld_mdNCg4JR(nEq3{FmdLmLKc9yA!y-II!?(pwXQ z)>Fwvejeg$e4OTti{!sqZ5KF*zxzb7+=bb;;0V)$))S+~QoOggzU1ThKrEFqlUZ%v zcB^6Va1oXs#{xvY+hD0pGkZP!W*_g9*ASm%7K@GPwDMwqypnvF`v!h1rt&}Iaw8*) zP>I6R&69CVx{+`4@wNOfz=EiIdd+qzV=u`k%v^GKBEVv@9w=g7zM0?Qqj`MGB%1;j zo013KiLjeZn&yzyz84Amzw*0$d>h{mp8$^IL4FUEwCe>w-+`K$ujBXO+R8Dc^EoLH zJp2KvQY)l?q_SF*_v7>#b!|%sYoowGofb>vq*xL^DZPY;V*0SGm#d^1f%Ll(@FgnB zca*tRQh?=CyHiMK9=>l7haX{FAkP*Yht!209<|)hekJnrV}hn{=FgxTW{sO0%v^jxyz)emMBYwtX*91K zNO_7{nuVnvXCeDho7GE z1TyWzZn;~2UEJ~;6V+KMx*k_<`S@D`gT4*>XY}*s*0i6$D`nndeg?R1Z7wGd`Ovim z>RRs?&7tB^EzNrP`&OJH0vvTTrx8eh4A)M7WUWy9oUT3iKl~J;)5N2mm$TJQA^5}3 zKLv=OPW~Atn;8_Yfs&3FV^<|4&p+p1co7wU3B)2=*v3J zT0?*H^Jn>Uvdh22p2(KSRq0IGTc%DA9dpEuRP$Bltf(#N!J`^~Vc~SP zS?--jHCZp|7uyeae$|3{p3~~gVwSUhgp&Ad8frQ6^|qc;6;L*YZJ(`Hc-2{|RlnJG zruPCo>5}2}y5qSk)m&@46>ZABD+qi12Kk`;^3&uX2#V-F0b`#fp`!okWFD?AGIL$x3g zV5C$6`s$)VU8J8~)h4-G72c|>qv`Ug^{QLIfc$Qw-@Q7ITO516SY0BVTPD4G+rx(1 zDkeZq-;mDu)uja1ZE8EyNp;gcIjE@cTsG;4$qo8vyPWKDhfiH0kL*r=dH?jNolNKc zuYSv$EKh#UQ!$8Cy?|SjGgKy%AIh11W!Jk;*8V5}v5ikH$TaoU%j$(?cBuj2CWUg^ zn<&cjtKEW^Zc~7T4HK@78w0pw#`8Hr79n`>U?MC3)*&mdj-;+qvaANx-R54M9Mq6b z4(b}9*J9EGf|~qdu2Hssl4@HJQYsxnPEPcN1aHV#vq$A&%l331+G)e}GH>2fDav&lsUvX>LzJmkf<+47UTrhb~C=}ejh>Ltuai`8DV z!sNyrqEJILx?_~)9;SKGO`~*D!=n^ze3VWOKT5StkJ7@2bZ+#2O8T>A@`o_bjlRD( z6zGgQ$u~wVn?~q-w9blddXn5D<1aTHrj^mIQCju*8b_-$;H*7BwG9F1@@T|Wpw;`y z7Y^df`P*-F^2qql!kZc%BV3;SRO|d48PQFS#-2GF8pi0NO^2y7$_=Bm`5;&jEu8n3 z^K6^S<9Ljsik_f<#pqldjdnH6xqOs%K+XMB7uGAE7CuZ@ifTL2?u~XGrCH&}o%fM9 z>{vcRPJXgne%}=N@~wg8o4^IN51%pekHh{7f9r|HVHjo5V!Kf#jTO3ajAj_Lk~uhz z^Ku9`n!>}vV`!d5i^pm0#QY2Jx zqpj`_QB70O=B9vu`>feCe*GAIFd8umbQdgJ6?9ggS)hBjV-0j2*nXoMhyJaw$og0m%6wwK zs1_~I1KSJq=}tq;AKejgIvRSMjXkb#kGrX7&Oa_*L4&R~=sJV0AICh60?{Nk=;m=b zB7H`S^{34T!2LJ!j8kyZ;PnQ;Du!Ou?Qz^WS7{Uy-z}#+lbmHUv~#ow+s*c(X#4fb z`opQud?u7|lUxf$-^X{a{Cr{G-W}MhXnbyi_Uf}ho``lHrH01G&vUG)J>>v}8f%wF zoN^6+8iF{d9b@#xJIUpE;6?|m{}b>(@Brqswg*-^MgfEVo%!UyLatZJC)~}@AcjC(r7+3B`;uDME6OBy;dTxwj*@<@S;BZ@`y& z!%c_j#b~$m*-rSIQF^&RufP?ZQ(W;bnpJdv#lMY=|GFt^yWgw$Gcta|rY51K)5m@O z`$O_k<`C7m4l}4tZ*i`sCn1mtT|`SYt)o^=&!IJ%Zom~2+65E0X+!Un6U065*K~l= zn&#mo)c|#-Hk9oGlR~6%Xw9S zPl`B$7z-B1d_iZ#H9|9jPDj91;8P-huEr>2jParZFO9fs_zXlR#El@n))%;`z-J!j z<MV&qL_y35y2Fj1;a;LmVppBJIuR_{)EhPQM!8?l zA1F=5aI_0o>rPr0)+ug=mEv#&A&HZg7BzhJDDOsKEzT<(;V$kTk%4@n$-7eIMBYYnP#u2g*5)doK4fYy57wLp0 zAoyORxjc@WI(1a%o7ZW7$U`5~`Kg*b$8+dG9dRxo@A1PJ^U&Yy%r&cAKry9R95Q^9 zMnhWGDd6Nm-O!0ncg{uj)SU+JGx%Dk!Pk|RmP~^_`PgU2H1`Dibr$0mM#H-URhxcP8t=m_?OoIq}V&;}34BO45~X3N`= zrGZ+5-T7gW_S(B79Jw580#5zSGn-#&b=Edug@~($k3`&pwj+k4)pHM3)$r#d-Vs8j zP&>v?M!fRjb7?#nsd5CpJ z1dQ7I>50aMs1B$=CU!t=ERUyOortFZp!Uvn^!b_?M<=Im7R^#CsFlB?qiuDgOu&{R z&Jh8*kp8{x4`EH&T+mq?FhqTi-Uuuh@wsIqJ7gmsY{c8+(wq5#-VCH4pjq==I}l6f z@(&X$T{jwkz-bo*okw8cx6wQ31(^6YxjMq^3$Q|*P4H*20+-m-UMz*Kx$gxmxZ;=CM?$iSN%X{UY_sfu= zjdEsMY%v=ZMEspLN>yYbaHx-xResI1e904mFQJTob=(-%_|jGJ6rU|SMZv>Jw)~&_ zsWFVQ;?raNlc+#~7XS&45*+4W(Dg9?Du}L^3jDGhW6*hs{}^#QS`Bxrr%})K1dRQ( z0N@!IZi+c|^Y zoi)l=p48zzfcJpdPc<~kP5{f60@#cxf4HD#VpAjR-5&6`KTLm;H2<<}N{|<a&5Ib?;@(OYFR}@Qfq8sl9@&$B5%2}7V4%ZlK78FctQJ7uiGuTC6&h8G zN7d;CRgVHu0s8u#-^o=Yp-iRJIJe!OTe0Ttwa!uvE~^am z)uHw?zDV^tbfq>Q^NUMCa`hI_K&}G-=E^EYOxO!`RYlY{K13fD5R7JN`MNysy`>tMdRP} zf{b_pkFUc*Ljt-Q(YFQABBi$LSljgrE>$|{4HVJHzVeol5l(ofo2WU@o;!N96dxB| z+4~W%K==ChBvrAeXjF4@+3ju!0=1_rr@7O`)Y@mxW&QN0#itIWJOyy~H{yzweUgfo zu2oqgScc|p)3-%I=}*qE(%X`br_L$c)TR*v)TgCyc~#r{*1qOY%LiuUOdjT(D&OKQ zvY#?f>F}2>QAEh43ni8wsZ+tUWTsXtk0xP* zD$Ijs81t&!6^WFwnG&;*yt4ki>?jH$1au|vSFN;8^|LR1?^dIha7cS=zVJSI!~cOo zAQ1#v^n%we;eUQGX~mb2Qh;asy8C5qqU2=xx24)yLM|`AF9bDmxusl78>p3eH@dnJ zp2Iy%)8A-)KQWQ7qdY~<1QV3zkf5Rod?I3g%|GntyjzzeUVenfBu4e?Na~o##W8f5 zd4ok)dVpgP`VNJoA0uuH0k2|H=!ZMq==!K85BSq0%N@1)si*{UPNCpy{8_;7F>PH< ziNieKm={8W)k)ukS7jvo3F|ss3A4WMcKa#S#j7z~ud0pcCWNxfeP6hH@D}TzyJ4-(@1iM*hV26gnJWkk4M?P}JSUqh?3)~So76fyj{l1!a2Fz8_yLk9qx1Q)!D!9kCmbF!6 z2;YP_-8ijySz7)wS-pVv_(?n&jPt2x>~7Vkb7zlUQ8xvx#lKL%@LL&bsmcD7gfcm_ zqOHHakn1vZ+!NC+r3e0LMYyToAWyK6-MbHmM6+Z5xvH^QZ$NiX0yK|76Zh2q8coimdoOXEheDKHl=Nw9HRvNi^%4W8@lnUMP*;XRu-xEmfc5z8WUs7>xXj}Et zV10&P`Bkk7ihr{}wAs5oV(SQ%ZB@B>Nu3p*6v1F&Ag8yKU- zr1W6Q;ivZTvgv0#$eZm2u#)qVCfbQJju)CY%)CC61;K4`ea)e@$%D4?Bk3&GWMnwv zvzb1rR}d`GT;1ri;ae0^yEV3d755VPYu?3|df!34eWnBZS-u|GK9)Ad z#I9s(7zVD94*;8CPR2+<(sTBp(nK;a5EKBv&==A%e0FAay~}ImA#XRlbdlendqoSj zR2t6aD$PkHs&-NYd-UW0_iiE5lUWB($CezG4t%wUcXURaz1plc*Mt;ch)ed46E4ydGrz;jOW^c@Gh}v+;|d*fvTGv$pNusr z2iI{kSjO7uLk^Z*sw${2mqd!Kp^hw%*sw4JOC62qCA$xopdvCO_m)vEOFdNVnr;y# z@VkAEl>J-{cH7S*=M(;G^JSYxdLyIsdPZ&=)3!jtwbl0f-@}yvHjB`W!R~P7FU}US z73CPU1R2qG+j?BZ`n-nxjU|TGW!6cEgTPm)N9dY5O&L>VQidS!-|6HTEbiTegQ>=f zvyE9(4DWDKDpXEbz6gC0y{~a5p?86bcxt4l60Q(*O^%`~^1uC~UvD#wzvoa!&u6|C z-a#_cx-FdESWX^7<0P1*(!0SRZOI38TIw2H_GIz%ZFVUdW#L!cd$w!7YrI7+V&PJo zpwCi)Hu`d6)CE*b+j^UP5NR+B-jEU@);rLV>r(k}ND-*U&vmw(Z5~l~KnTHHX>I}Q z*aUnJLc~3Xpl;E3OALE2a$!cP)Hk8~kxJ!T`y0L;a1ja;P(Tb6DA?q=A-#bmrDda! zX)ZvUOa13VtFCAT!f6OY1;#lRvNtmAVC$YcV&!umRgj#pmf8AEbJQy%vt2G06LW!i zuGeSS4r>xB??_(>lx7?y&!*xBLU5bqKaY*G%?sl10^Ca+|j$x(jUmL_3Zi$&G#dBCSX@N!uKUk-4mM0 zFMqW6nVWSPvU_69l^9q01?znyR%DI8E-EasLbbo4|wp%PU+ zBlO-gis$Db6E`@j2I@(fm<)3X;-Qh$^b6dnfgt{R@iN!Z8;Q}0egZ)|UI z?qkQg0|VH0HZaJR0?paRL?+&{$}4s1`bSakyUkYfF|>wMl8${MP;T4Xf~*Z)BfT)G$pHQm1oXwZf0@Z6>_T!BEB`y z5D0#Ixs7ICbBlY3lONt$Bu%zb2p9BX#&sVpafifbuEQ)ZZmAE7g-QIa9~{=hm+#rC z-@k+vO?c!G8a>VKlJ-jMC;TzDNFRNm5y;{h%ZzKSb8}2n|ET!O^A++6i#Cog+Wk+( zdG8f4JwJfYUuw>1==m<*vYt|yiVcg(K2zLfC!avaijXp|udMk{FEk?b@zha({rO-J z?V-0`FHU}^a1^dc{){{aStiv+|N07CY$5+7&}j;NUyGyIOg%5H-?VX3hB#H~eJ1;z zPR4HH4Tq<-9(v=9SKJ#9#Eoh91eJkQDUWrOo8mkgI~1Y&2NTJooJ)QV@LHx3NbB$g zxjca=K84Eiwgnc?b5=)vB}arlthX}^&lRr~q!99IFtl+rc^0-V-oYf?jq&TX&!_|6 z-PslyB;6EXPr!r@Al|LQW+R0Sbys6eJIhV(J4bhCmzC{s%bk?n?9Qu+QR4bfTiuvi z%j&JQU&Gv8?Dz~~hNVmPw#i4!K-9~`73;ydW?3jdm5jAsgnH3c&And6>dBw2Im22V z66OlW8HO^qDj2mx&g&Zv@Ni~)?-~ky8n)0jgtJw5(@qc;-=Azw4QX;&1L}mSYA%TT zGBCZu3&oV1MUz?+v{R<+9&k$8j;wM~Uu=>uTfIgGrqX=&k1wSdiu&cd_M>Wy;|oU8 zL4fatQ`3r>!rg9NzRJ}5M!LGKgJRH4)-=wj*Fc9CiBq=geCZE$hYNb46XPh#_yuCb zs5d=Rzg~q_IJE05(V3mJZGi+ggt{g8ylvM5msMyY4YjtxQw8NKhbbuAhf~8Pzx#pIl1P!^4%@GR)@GQ+=VJVEeU0Ze$c(fOs~whK zS-GN-X_uR4?701#W@{#Bmg8>ON%{_lZy~1mUotDMwt{0s(moH30zoFKKw}9|45})w zfu`dNOYcH4t1Gh^v*u^q#TTo=cBZ{f7mk5q1jz3SlEtVsPo8MjUBr`7>M!-uMj2@Z zw#9jh9Fw!@JB#zlwsw1uk^{kvPE6NSO0@p;E#QU1d2&V|gJMo1L29ekkJQYX3SM(z zilz94n7(AWGJCt+W{?-HiJI3TqA$<*`Et>$(6+T@%8qHPfSA}FK2@RkcQc{iiYVMu z8A+>|X`~0#;9Y9|iO!J0yF==G;jiO8c<8PbJQb5vB$=kW>kU!t77Q^NmfI%tJNF&u z&M^H`9nT+j4DHaQ@n=6%{C-9!5TDK_2>|USd*@x$z(E`H0!9I*?Be3L^9H^qgY)&h z;#$4pQ^fb`R%;VOHc0_5*>kjiu$BkB82ohcLy!UVQPfZ_>oBs7my`h%1^ggV@^x)J z?M3$cujgG8XJp8C51Hhgxo{vTGt*1)Rql)i{N{z9}8ARxCU4bR#(~LDVI4R6VqSr~{ z4DC3p-xZQAhXbyyY}Q78wQc>fULD~V5Ab=?;TO>Fa=TF7c_b{=ZQz!;qnW3gXDLL0 z#xUvtGU4Zu=Xam{n6}B|>>6s%SJI0+8p9~><2J))c{ovAXT2bTH)NBq&q_5LhBY?t zq*vkzu9!9ME5UdtiGLYEWK5^!Mk?ChRJ6mzBizTD5il9xJ>Oh$WE&M5c61)hdA()b zsq}-~Bb58C3N!w&p25(1wX5>*P7~o0dp}SftrmMQl~r^YgsenyvI_t@w_xsP_XGuHM-dYg9srF%Q-lSnS`yr zF?sO?$MCW}DQ5X0Fp%(OD+Y36O{lxc1gEF^2GiTio@iV!VNKRbA`O=ih>Fplg}I_F z*g~-<7;Y#y`po9YZ!R2z*7b*)%!COoh!9DG$xSn=Hj$*F!tm{Wgfi!LBmR=`f-+~X zOFfmbUU${RH(nxAgGKv#*_F9hpCMhyN*vlntslnXu;)2g#%2s~F_As23^G^pq1$c?spr3O5&}0P)cdRDyxQc1g8=%G5O1I_OK8mY(q^)0Nz}Fk3 zt(h+rTWuxls{2&!Jz}%BtvgSH(?Mz&`XrDvuUN-QbYM7=Q{p8E808l>L}V#@XMV8g zKI*gN--|r3b=4KqTa_7bIE^VMp~N+HC$_!tbgs)mTRJL%{Vd8kzKYp^Rc0hHUBZbyi% zEDcKZ9XAP-S@ci5bP8(#$|s1hFYRw7YFNFhigS;sF1vV2N-JvJset5Oj8DMIt+zkj zIaGwFVrb3Rc%$U+nS!l0zpPy&g?=ZMCE#eFKU&&8jD0@Zwzi*hYjdhAp55t=xsfBr z>@UaSZbV)z_sltSD@Y`a7(|k+#Xq=e)V7Y3Y_E^RuAOeu6t1*89F*C??144YGDpxV z=Skc%(FyHOyUAZ@VOi&`ja&NgHWQN?&Q_vB*)y$1Yu`R#CgnTHXwr`hJ0t)e~aQYmX>GoL- zBdP)2>wVptv3<)_KGM~kr&t)a44gQ94Kwt!2ZD7E(iLtfd!;^~c3)b_hiMJ*a656a zzV^~|i;LKN>>PBT-!BBi#${1WXWmwg^6YUc2;V91J365jrTKQ{7N798oo+D)C|?}s zq0opTY(B|q4PtGV*8)Wi&Bz~j21|LR8XjR9K*FD$t6WS_iJIjZ=`#I$OdKYqb1=_v=f-q?Ew# zMR35(>8t6G!Mzv4=A}qAGcmW3`YM6J?8O%)gBO_HA+t;#gEHo!$p=o&WV8%D=tG!$ zcRwAQ!#Gf)@J`OJK9K@RIsO;KsKSw7D%dt(;|RNXTnV(ek>KUt=)O%bhTcISCMXz+ zYtqwpn$jAb;$r+3e-E*X89wJQv+L&xP2_JiRxh~2A?qJ3Ri6^8d=tp+T3@J7Dyq=) z`HmOZrFql3QGSSz)b5`guzoqE*6T?cIbvOim7V zg;7c{E2PKqGQprSeTtT8Km0t{GkGA45qK13`ziQM*>f-u%0%(6gF9^4j|X(|`~ixF zG5{Y;!eNodV3D{UMS8>XPtQ-FOh^yz&S0vKgb0aj|CH)~F7q5*es zVn2-Mui@bTo`EhfYPl5BgH0Y-t(*`(PZ*3=PWx~|{(3?EZ~t{g0pI}9hZ6$)>p28d zT7EQu4XHmA8O%IN68P7G0|4NBL|w=Lz?8By82`_t2pkNd0{(Sy006`u)!|(Wx)1=s`UpC+f~O4V9|D9-^Wdc2R!tPIGFBXq@H6rTTGUa$awXOE&;Kpr6GI>slo09rse45+UB Hv&Q@%MAWx6 delta 37584 zcmYg$Q+OTR_jDTL#I|iaX>8lJokpk8iEZ1qZ98e46WeLhG-L zS~D~M4!M60*%*k5(LSs$l~`PnuYXUHVn>i;nQ@(xfJy{}_r~vaYmkA%UqRV(UJ}L8bcw2kwKAgjB&!iYBWEAWae@Gq$s0onN(#>$4!u*hdM== zy#Ghajv4)zx?~0PlEV>t=tK4oZcwf_dI10wN~PX;y5M9A5O`_@V7SCd!S->T>%tW= zjW1{WCJQ*x_GT}aUKJ`t^ml$s&D8SgC>%Pt7ps+W4BvRDeGYefQ*q(2H70P0W`u>4 zSrNVJt(@=X>%S5wY!_S%K?xlX`}1A+2Zb(7300bX#-hk7-Ir|IKHeYSKHXNU)(ih2 zt17_3W1f&zQhb4ca7|GQB2Ed)M@>PYLrr;V#0FYvY^$%RVi`rWhqZ&3#nF4sdl%C| zh%j}j58)5Pis%y@Y<&Gh$r1#zDay$l0`VUaf4(lTk{5(71oyOVl4zFWGif*sN!kV+=Qi}OqZc&3QgPZCTPTfg+ zZUM~muhz!hs^75pogU`t5K>dk25lWEtpV6P1M9g2O^Wq9c5e5b^>CEKRJ~O?N!-->g^aRUYPx@D?EMU8r?OX`SsSHX!2n>!J76JaT&2_5r|TKI6CgWZ zX^HDQ!H&pBasY1bg^gP~ov?H|yu(fv&Vg2mxsAgXc=aF{=Ka=al}?=ogn?l)j}2Sy zu$zWHXAG_CEit|3&NDSRb=>^ZY;qKd?waCLINYM-POw1TDd=JY-w#)5`$BnUNnw{;~Emgwy7B38?4h8I?~V0i3JY=pW8;2!@wU62bUHQG1lNdDJB{ zwY7RqQG($}zA2g|1DzWd+T!*_CI$+n?FW2|1m8_Ml9)e3SQNOOKy3V(*hpZTQq2+R$um|q3?Ro>Yjg7wDyM{Mb`wlno3MT--EWCFs+OiXA;&eI!mQD!R>MYH; z89M1P<;?oy6YOlTeHdJ6)cIZcrfg6rSVUt^Dp*Vl%#P6g3uQ*-vaFqm;n^k)GU86$ zTj3D|ApA!tdLy+cUn;Ix4k}=+27IWR2yP)%$3hrAd#s3e8KJP5?j!(Y(}54-Txi*r zJD0s&WXm7LJ9LXR4I#gI3e7Hb*IX5b8}TgfoiOMun+Hp8!d(pkaAYZiEbxNAYi3-xU| zr{dG^4G6|Rg~hG~!%E2aCSaN9D6imhAYT0GuF6Te!d_21gtOv}m6zKYzTtB=k2kAE z{Te!icGMo|4AE}yKOAifk(@aZ65rD)1Jx$h5NlR!G-|!lfbbH%Arve}z!0}5KpAHp z+iJG#MP)m;=#0Y-NU~Hsu5Pj@P46fF#J+J!{-YqQ8f{6)h4p*qNeS$}&>@RpPDLAJ zUY;!|?swsIi>EW->27UDOr3RpJOH{9R;g#SDUP z8u$-qU+zTc3{t-0I079swzbiOaSfrP;TsZVa%iMs0PW$JijhNh1Y`{;&;oA5u@{P* z8;@h!izAd%i^>(hNaxNzzFX2TXDya~u4nzJEN7fj^o4mS`zhN#FWlp^aJ#oA`nNw2 z)f91`LkRfu+6-*dHvEEYrn9D}WuntkeXEN+a@-I8k$s{G0|wT!!Ms8yx79q;U1ysifeF0h7L~w$ zt+?Rus1Hf8nrNk$3}rUhu467EqaAL=A-0>&Hp96SEsbN(l}Tp4^s$>ujBoGpJ^8K? zXJg$*7~3x&>cEy|{ftD@P7;TnW%%cLC%2C9)PP$g1Y!Vj(C$5`fvr-(%{h9s-|Pnn zm;&C@75XHj46E_?9edD%$veLswo%2JYdw;4{M zsv8K!#!i4%g-tpCGV{Et=J*CGXfUx+?scr}o z6XWFPYXeu(Nui zSbK~BP}TxXMvHD;A^_^fDX+4hAKz~A*Hplk_k0~Uv)ON-pj9cx@DxBF+zgpnv{_|Z zilsuIb#kcXD)!WBWJdP+=(EVtZa>rFLn*qMTlMc*^v40wer$avm=?O}%pqjZ5M{4q zvCH)2QBF#1{+J4uZ#-D)1F-4y9M7mS`ny0L*h^+X(t(eG#C2~cu$0{|26uzr0Nv6< z%VzAXj|~RFzuV@^JrkJs1rGU^0G&+#-M@|e1QNX8A?3Sse#h6;eJ`W z9}?H6;cmC7|9yET4Csq90N$F4STfsf0v>LA0VO>$uT)zirUEFeTXMz9E0+Xrx|NN{H-EqUS7jy3+p3yS5D+PFDZ!XT zDKrG?KolkbQ;Osya+ zViYwuJ|5-l5n6*%F+#rz zO3oecNt~sgErG4>VuAvMK2@l3G@_|yDWXQDjJT9k*DE1gC+#oyuqX&>f(coW!OH$Ub% zfeq;EuIi!1tLJf9zKJv1{n0YlwZbtDM6(rHv}N^I;gHD!Xmw1&bEXM7)PUA zkm@#IYCpja@?RIvSQP8xt(4iNXVt8*6#5Pq%Edua+*fU<$x%jvs$zH`*HLkj8ym62 zEWULF6Dc%_XSjO$IhO;7h*dd|Ocei=1FZ`x;Apr$swd-`ulnT3h;Si50r~>Vhga}@ zl<7gLSz5%@76zQ%y0^F*BH?QyrX?0odE`GD}Ribmb=u^#XI)YlaU|iR1JS#h6;#aZd^? zW07LZc`3s_tOcnRD&W}375I@*!c!|*AEMz?Tyi@`z(fmI(w!g6&R#Wec;bO<{N64k z`|uXCx@AkTsq+PBDVw#nOD}b#yu2=K-yu^!qygyJ0CkDh5E67y2hc=TG)0U%N0CWL zboB}&X?dn9$VUuRyay4^FhSkWjPx`v6eWX8DV=d#c`QG*2u4t6( zDJOdhLy>)D5&G(u>{k(v!=ET~?Nav&>VGsJ+HMu@K1VAqJn!sRD zTT@HNk5A1ZxRT?@A9)g+1-DQ&qt72Y_6FoQnWRvHJv7aD1~S*2NIGWuge5Ek#BBcx z^~=iO=Ll-r^kdlc`BNGW{^IDT*!j)yqDD@}(a&Pb?3-jZQwoKN+JH_XF0-Vw*uxe$t|rp2U6wo0sGz2d(sy(@eD`z?jdiTj0XQqLZV3Gx;D}`ejmAm$S5Bzq^`D`^q6bTowH!jr_qta~ zLS2!-BGEK{LYDlbpNKofF5C=%;uej2Wv*bM;lGSU%~NS6Cwv+9BA`X=9FH772XfHQ^!&d$H?x$BiS<2$jUxE-%$*N!9=07V|*jMLGe`+iQt4G?DM2?bYyKK zhp8u5{T3)yLiKe+bXcfPi~^@^J?1s6p{h6zNVf)|kZMn0B=*}f^AOX4PgIk-7!x4H0QDRoXS73=)ca)Q#3UgNrC~c%sSjCXA>gzy(p>%DBc$`E+FUgTx7)BJEp1}fV(%5mh*-Yh$&%K9LStKqR?@lhZyUR*T0c7@_Nznx;d!Tiv5-6<6cP< zXfpDLqbrB?blwL{+q7=*1~Vd*P0{L?0uJ;Xm$TAb9dA1Uz7gzCAH5^mFc}^@l9$3A zp&#~%*&0)n7ey|#er(v5R@MuCZ4B=iC@}dWIJ6M+LP7tRkY2Pm8*H}9Vu7Yr3mb<-3OwT?#l2TFXf`5Jv`bc4{q5D zNl$mv*Cb$C#rkl5xiHq9);74 zAT{R|k)~X;!W5Kc4Q>KGeonmhrh1(6)~A{Z$Ii_$$tGe?M)!l0u}LvIYFu2QK+lv~_hcmXGsjYt4TuHij+ufG+w_m1qUuC~@Y`Sv>SHG!;{ zxp7^15eQphKl1Xgk}0oUk8p^?TZ!o<4`g$C{VCw-aef)RSoc}!nydI1z*tPWy!Q=a zsSxR~?L0vBn8EG1OO1HujaT1&Gt_q|ea?j|f#~+hG3zasCfB46H7XJqLyrjTuw&O{^RHQLuf2;gPM^`;bkuict zgGVF$r=1y|K$6fd-zxA1dH)DGL!qY$f2_@@%8`@qJ+#q$wMH+OW^Vuu#wx^Ds5l?Q zP_8z8#5B*275FRT<0slL@-HgdwPQ!X7A(WkU-#5vJ@t{cBF>k8(LY@cu`}3nCa4Y7 z+(>W_DI5SWCiTDF@3#{`S}(q4$y{~>{`rYX(N~!X7JG%(RGX-o31wr6ODW?G%XMa% zk-JyI4a^}Ky*G%8YERhRJ+aWfTb=85Xec^4L^7R5RxUb##PtyOsRz91}4%NQgRw#|t(`?>^&0`)om*@{N@>Z};E zHIe5pr6J*>iMoQ}iOV&iv$_{t;J0wN>DET1@~oyrC1ql@F+Vd))% zMu~dJ`6hv!A&E&k7{QV6B-TZ}t7Prd|CD!UcshG0DjM_!Z$fC~?C5B1R;F$6MHozQ z*;?&VL$Adu@H>4ju;$!ec?m5{!3^mZf#cRyWyL3~|16D2C2#MvomTy_zluM=qy-Xr z1do(350A2b*6`gW!!ZX4;S%9M*@|6n*Cj4H!;K(}wp^kcW&;`ras1PBR#lKq0ZDD< za+il~R!E?!Vy>0)V-WLlw^JEzbo_{sMONygp`ZBAhHE%}8&TJPYx1uhTts_(b*;RH zZ>yYKmw)L2mygK79J`$qoFl4tce=)Z?}@Jsz>q&{PxSu~jpP7*z5HJ8qkPmP7xAQt zZ`oJJGa$*L)8Vm3i*3L1v9+YAn6H82q|^e?PR3FZwO-r=EG3c=;GeZY1vp zf5FBDFmVW=hJq;pAeZ0cI^L?KIX#S~G0l)6#9B~` zl42&eB-z_7I~s8ctE@y}>Tp#Cb_8@26E&F>v{r~Lb{a(` z{Ndo-W}YL!_-^{AbXxVJ#2apIBHumKdkMq1ooXj}!2MG%?~@QG@UO7QmqC(R&d#1b zVVA!@VTF3du)o0>^F6osvMF(pcVSmOrf`WLa?2mX$`QF8MNk4<6!Y=!Oo5YSL(Hr( zpJ6urt|V%$8(X_BYW2fpZh26zt4Kz%101 z7Evy8J$oxQ9VZ$v2G{!g=vfOX@F z?aw{OBP}T6Y;rBlY}!hu&?9M=b*24o7|*>M-GrrlS5A*I^m-anH7lB><>qK3eW6fl z8~1Els8!qmvZQsjV)k8nC=ZR5&#dBvu-L}dUl63XdHvVNTbh5w`RIAmaPwwOoi4>( z-0Ma#6w{TIQFIPgpmm5<^kBNr3hx2`eOE!6%g>Y>dMls`rWls6ghR(_T^X}347QQ# z)^gdB`SSM%F^mGVSZ=%k_LbcWZ?gf8o|Cc3zl)*=H8iRiN*`bT(7oK^9LhM*WaaXE z+;#cP@7#&@2S7E(bAwPPCRn#z+E{o|!foscvzJx~vcWyUH}{i2g?C?+#Coyf4~hzB zL{Pm-SYv@Bt_Pqk=>)+dTif8W9-+k>-4U)015}cBI_-AWM}MdZa*At@PZ8p9o6UT* z<)2LE31NULoQIpXb$tWgv810YNaKlDZ%}rT744LGo+kQA3hpcDN+V4<2K`s=3p+Gr zXNDkgmOEItg*>`-twifg{sWob3)cnvTW{1bbb8<(*(!*vhW-3_ojL zV&IG@C59ts=mM-{0zq8}b!)~onG@nD8*ZURk9VIb!8e)W44p3p&&Mzw9=fB%9Kmp3 z=72DIqV%4z0=WB{O<^axhxO5Vvtzd5!Am{%fD7hqcu)XsagqOcXhts~(3$+tcwX=} zHiwxi)d*Jh3cdI-Rgw9%#W35YT3KM4GLq~PB;w2GCnuJ+ikf3?@dv)FdgY&Qg~43p zg+`)cO`7^xU2oT~Tfa-m7?WT$!mSfm zdnlxXml}(PbJ^Uz;K^2!_clOVf_q>VLLdo%AeGNueTRX;<#~E2_@K$^?HlNY9He1l z_YLsnYuM)(L3LIQpKr%(&8@~f@1&$s3D2MixLvU*cNgN<$>ju<5kYR!O1|- z2IeUrkM|xS&cKh%ZH;Tk*(-fI0BabjsgrqpHs~d>5yEZ5qUp9JQdC)|H#Y1Yym&|R zJw#z+#fqwWXa*_Clf<-gCSw4o)PBKOd%^J*^~119^PO^wwE@}I(;BlQbfL@KcWx@~ z*xxGtaKqY>xC7jK#G^bD#L5l3a>Lm1fUI9h5CPIN6KOM$mUSl4zv>dgI4g77Fqy19AdjLY zo5ELUW5MQxNxS<)#$zZjiffrEZaRqH)Z4w4MU_h;J!!69WMnjDO+h=KXmZ9B6)mP|GGmN3sM9YC_97J(I*4`4YF|X<~+LAM(ChBSNZsDfciT^nQndxWQjKOyvb~=$4{5nOd zD-Fl_fW4_UeWp*oc9I9#(j?2wD|k_;jk!cbi;N=83)w|jBXe2T6E=W0(EFDNuP_U- zhj6rDxn{u&>P%sQwe#Z-rw{0hpaXeczezIpzntDQd&yNfP$thY^94`aFi8AVC>TOsU$3!)E z*z}j#;&S>rgAD)@Hioj4xPK|zm7s49H>!JvqthP^2oN);$Py@+EyDNEN4_$dx83T5 z`%Ts4e@&N8D&NQ@OYjym=GoI&Sx%oU{~FEybsr7st+Vrt;rzm!ip0h@=H z5HE0@ObU4?$RGO13+jmd`;eo&tg7HDe-kpdSd=ar2JnAy`;4de^8D8;CjO1JO#kdt z?38YHVqhT`j#Z95LU1C3F8W6_IwK4QRb`y*MWY}UW6o}854c2|)z5F&qc?SC&v#oJ zsXc$o__bWLc%Y>0?)Fg&KL0fLdcOB*mh(>NZsO0w0;>zevsseauc?%%KQa&a^|J^P zaj2tdo4!7V?2KAUXYtkqRnb+5%?9GQJ2` zFa>}^^jfgoj8+oKoJ zrY0+nA|*&^!Mj#`mfFHsYh@uvd*2(keVtu~IdI;>GlIlio zg~}}CGb9ur`*xq5UHCl-1H1`Wp%6Bd&eR)#QQbEk$;0X?9e1GUCjRhm zK%M_26&MP3N(C2Dm4UtcB)MVE^ei7k#ubqiinil3t>t1Sye&Y;lK!#yg5DqptiW1B)qM1$zx|lT7vNCb(I!fIo_b@me z2T8d_fcmK#9Oymz^iNZg)mp1)PU1BqUbAn{5x@lDuIsInqM#?QRWAk3uX(TM=4HtLc*dpNprxa;mj;DgFmz?$( z(@C0qp^%nGo@c7-Q=Jq2K)s(CWlyiGHB$_$TH78)Ri|+ECe>Qi=-#kzjv?NZJ6u7y z8==%AZIj0ut`$S9+)fD=JFmd}{H-P$%gR}%Gu1I}4*@E(LS~V2iQ4xr3w0J!B}X4C z-(6)Y21z_bYy9G#4Qf^3lj+)=~i7$j48OvI2uI3JT z*`Pn@pk1O_lhAdJOMx9?3XH%*QRme>t!z{7{>;^{BrG$m-6ls5e&$>76`H?d&8(} zIzSZBAD`1@^RtHeoRR$-S?bW+7&6Pr6@+QJu<<7#&XN6%vGh=u42MZFBDsOBH+pH` z`-g}BkBN@!l(9pg?grzI(b#9k0V7?U_a`6^j2};Jr)l*@9LVp^wAKfCHviN%&^D5R~yCv+1Js zSML)IR#!y==}Xk z`kV88vHbUOh+N7V530w{>&*<8g3p^glRxi&WFRyqIfeY+pN&6e4$_l1Pe25@2-eL* zvTPQoNZIv#*+4tVr}Akz7q>h{o{EI+XyQ4?r`dX=+3lgM+Tv{?45s7aZ)Ip}k^rr| z?A%TsxpwW|+XCiG0s3nvY60bjok=^`vvliY*`5jJ9QPy<5gvY=gz5m+w=}p|G36{N z#t|1g0UP*CZI<*FEUmMq*!r30Jqo!6|fUu`G(G4UQs93&@s>0gDmAbxo(iC&GN)kiCi0RF7sVMyasna>dzsg-p{7>A)>NW-hacBrWpR82VB z5=q5_iOqQTwmv}ZIyq!!$>2+%TB)MxxKc9(F{MQVyrx@lbbMkHahP1KvZU zm4U4IM;GuCCnmez{c`j-N4nJ7A6}d^9;XW~K~hf(spm#YjQax=b}f1=TY5H08U2=4 zAWc1Wkv)cNw2%Y9@keOSDEUOKijhZw!%%N$M5=4o-55o>r8&vmkfoEQ4WxuO)uNDz zmeCU$VjdhR=6$W*3HIgW3(p|wr@ulxy6`9^{?m_AS1lrdhtnPSFMIsfAw@O1#CBsT zGp$Gj1z*z`n&UZ+mq^9=i@$DAE|^;!s8R4kmO%n=VaU6#A8gPGIu`*+Pau%m>a#^;xm@M zKC%X7fdQ0=<%>DWT$Uo%Jig)0d!KVwa7ZF+vd|(KYPzf3q*!tTkvSE5P&hjX=)$ft z3_aqYn8uc;Oak7Om`xtiZ?#wb!;Dp@H@nb@x(M7O<{up%e|o%Qg@+1NUJ&b?&Xj-y zC)-vXs6bOGrs$TJ(FPfX1aiOatMao5q!eMKuhhtNp5*(7Zv&=ekyqZvWQDB`@sAUM zFKAbUnzer=$iv1;7`jjMGl0lI;=__p3#JSh98yD!bUheFe5f>Dgr~Gu(M6SgI~IFi z>kE!u&vCk;FR;eu7B3Jw=dwhmiSfr#q-15h8-_)xg1MKmr5_jP3IWX~^s^Bv4|>dt zh%lFh9$b7t%UFX&c)C=zQ-Owwij^=>nvrzv$jU0^;yfxV8v4ldh&No8(!v9{H?>2jp}d@#Z*yIoPoGZ@Fb8;qkPWP?ymhobWT9~K z;vF}z55_u=PePS77Cg4PVwpSR~ z?diO9N^j*|P;|DwKtLG)&pO>&@bndrcj|w z&Qy>)i4-5-{t>F~!@-UzJdZ2h3d6grfj8f1Q%ueD##p(u!3yJ7-;gj&R%r59I|?sl zZPOOP*C$20zr%RHerWLso)`>f$!mJEsQ%dOt0{^uV<1|ECir_yT&vj>t&eP_$)GD~ zRQLn@T0B1r7R8DEkweMuaI|UK9u7%q8rUE@_DHM!TSuezrqALNIkN&u2v_wD=09q< z$?dgKPf->20+P>3&?TsoAb#P>#-aL(tO@pZPXXl3hGoeqNDcD#yQ=71|6s^Z2@#G~ zNa%JuQ(pi#ES5a;9{6nR;b0%peI% z;m3}VaPD1ZpSi>7$f(wY6mlHT2IB)mKeMBBZdH`f1#F8Z#HVv#!G4f!ORc=OA5O#z zAHMB3@_(OPzbJTOT~|zjcFv;pUe?m39>Ex9uf>p?2tQJ1N`9sNo%|UUf|p>ZGlUny z-*b9?7-ohD3cE>Fr;fl?OyXct;ltt8kWw#Gc54V22V+F!*vTpLA#UM!vp%`yb98CR z=MnWW0XY$ zfD1=8PEebMcQwgbcF6A+dgV6Z5rNz=+t`f_G<&=pdRlg%{1#WacwW?>WmaJ+jV+1S zZK!sF^6DrvPBr2Q&uZ!b*KSHEJch27a+R9Gz2w;~g(4nl9ubRfq3gHU2)MidyU33# zP83B3rkPr8vFfJ2W~!7bJ#~<4WHqm7-5qOO-q;WtQ6zRF63OB=WH@pL-M7Re{#>R6 zDh#KDD{gboJjEm;6p{WGY(j+s+$<@k%np(LJV3)9Dl|^U*Zn$ynvs=;nU`_j>?z8D z`$FFr!c`UxYawg+BF-0olE(+a#G0n~GE#j$Jj+d(#AYHTz11fT5bDV)A8UWon>SY- zCoMj^7dKOjwn4WVQvoCYs$O{{Yj&CfmPWUvx?EBdtfGO+`jK4Ji{vEg8kTo{8(|I0 zwixW0|9FNLw8$zr)#W}hqJ9$}gsIs#nH>szD?o7pvUZ3QGC z+cG?pNq>?YtTDjYoJX~v*XptP`Jq!^sHIP+qGgo29OH+`V=Z2Q(sNk_+=&n8R`_G{EK)9Q}@f8JRcT{u4~| zf6+l0|6#2MdTyU=Z9!%@Eh*cxv~BHDXmbU4OF6YumNI7lv)7Asgm(c!$n-=qoFjnw|6 z+fNbQGPmY>wSsFJGIs~UwdWVgyJK~_uaT_ha}yOw)g`P2c|-XhrgsvH)A{4z2)^mW zvMWY_Pos#kNdxCcWFV?ra#8%wec$+zFR{(3llOd<=Ly`%+2y2)*+A*$8z)IWSwr0Z zXF^9s<1gc*jUOAFov8)DA=~~l^UiLNiXs@zs7!`{rzsEER8}W{8qA>jW8Y>Sb6Jrw^k$nvS8x# z3W0L3c`!3K_xqv3lwvKnnU4=~mFowxWYVJHQCjzb zEdwyFWVcXuSQDqHUik3M^!fT%WSjR#N02`L$oHHn*8+`cj68I`JnC4MNrBt3H(!@l zUK9&`=mH%wXuq>>R@i;(An16H9LcD(rXpDz>P^LL+i6WpcW#@S^R+aNw3V3hgEIBw zovc|)@pTCU(@%94OG_%oePtH8G?H|fbQ9pYVg@Z_-A!JMi1y;mkc5h9;`9|lUiQvX zkGzImJxqK1J{OHZ0)e%B>`Mii*4X*nQewvjNCts##~X641*zCMA^rs18QY=?z)v#Iw*1=q#{}NuqH}WzHd94 zfXgjqb4u7_zVCG>t6^Ux5VjFT<=_Ymc0TIcNCJPMPU--M8#SDU+lgxE>!;BKiN-~` zNn~3p2mDCsBK=7xGzot&(oNjF&|*%G{NRCw(a}#CYRS$?pA$=(rQh1C-)aU zB6XC3oP!|>pE!A{3+E`V?OlH)!S*~bGaQYsV>uY%qHLLJQC5j)R9ZSaBv?y8HHtb# zmbjObV`j2fwTru&la64Y(~nb$k5hvv6&mODL={$_#_hhlMFm*o#YWkPp)6}t3W-`{ zU=b`ITI}a>)zNDe)1Om=Nk>k2ebaA`*a;j*nTF(4(JH>?43>W(eeYl~oXud5fC+wL z-^5vHTaeDEsR6DSF&&zV^?T}H*f^l1cMYeJPR zxP$F-nvwJW`TenKxV)|{WV;x2PLD5$vmHzWg-%(0NyJJ**LHk#B0t0Rj3Isa{Ngdn zeP5N?Hk@5V`NqT1)B8;?pwoVSZo%usy9I`A%e0j={bc!zOV;0#X@&BeZjoYyU-9#Q zBA?_#1>1H?prRcxk&hg~5EsS!_=SN_Ry)KU9;1SciplM(p+L*c3tvx5O;!^>*&}&? z1WVWV(O}er5;P|`Xj#MZwKc6ZZq9vRz$feh8Y;Gkk#RpsP~?J~N#opMiEhG?acxaA z4-AaPW@#-4&W_vAu^tHXF)F{Y|Gs5;LdJqY==D%QMZOw{*>XSGJTjD00R`>`yL|d; zV?n+lP{S=Z&&64JkDrFjZ+_dPerpsxM@@-6dzgSt75C7b%RR*{Hw||_dF1j*#m?>b z(cHLRUa3YDk$p;zC5CYi-aQJ1uR+Yw$kxzLoLkX3(^w}T?jF9y;MVHCZ`EY!mBK74 zYWy>+i>VC6(iYg|W#)3Lh=OOvPh2;I3zx}j8F-nn0eZ&{AM#A>b|CumlBa}NYv)f> ze}4LW(s#k~{EhOWjA|@HOT!Ag#P$~W%jpCb@y`A+UO#;4@lB((i3W`2JY%w#%wTsC zKxSl6o!s627sjU{nA#JSaA15}+$4$MrG2ZQ$)^pKs*;*2wBWz-vW&YfA|b_1*$t@V zf+>R+1nb}O&@4xUAwdSoYas4~Iq_B8)xx%@NEW5M${fqG3M212ej}&WXD*0O7M`Wg z?K}!exOE~wDI2X#eOn{xjrIddx%G}obr}(@XSw%I=xMf>bYXS{ci<0-DTx9=bf>37 zzt5u9!$ZS2y~#Gy$zq)C(|N(|+cEIXxa-Ow;QOp5*j`m)jCgwCeOvxiZb#I%kF%WNM!M=5_i zyd6oJjX>;Gi5uB}GyxtU5|i>nhpN#KIU`<(60zXZ_Eixd;|6IKb(UM;=^-;ndjTj? zfM0WvxQIqlM~PMb*`{X`e^(BzsZO-qLd0%7cySn=N;$cFS3t;V=m`m#Ed~}B#cE)cHa?TA z<4jHA@)W>>_rD3F-^(>`v@UG`o5HXM$$|XS2M&kIpJs zAy_Pu!6&Duj;CGyvvah=ZO>-AhD&gsD~#!m5peBiG%@+qlPuwsovf332SLkB@J~@D zEbs64Kt!Ja_QH(EDGFBV8@325Ba&WEtHef*7Tf`KZz7I2nEYN@1MsPn4!m8@x8{0; z3k~LG8}-mC#bpeK_ZT|7P=T|wGWu~R8MacPER{3r4x%LEj9yI)j=%{6AL0aqK+a|V zc6NOf#9?H|6u5lN#mU9C=?&j4Y_ab7jajrOAn(UlEc#>)nD%>o0h*47lR@ugjb6{Z zqHm+#HwQEl6>4WOqUMo!4>AOrwhUOUc9F$pFiPj9eA&1|fY(ni6@9I;DkYFHrO2;{ zjeRjqerbH`v6bfgsQVA;C>m2uxOJ{oozUKTFd0gCE(+)Kr%G6eGpIak^J0P@&FtgepYN11oGxbQ!SE~x(pFH&m;AVOzAepGYat2=|8Y zypG1*!1nI%_a6pf15jqCMzf4u6yh#fm4#Qt@dM-X6goo}h!+pS<^^WQ?-}iA4P={H zp2Ug|4%o4;i;Wv_S?~ z(Dv)~=CZrj=XYTK*4&(DphKX2V}F;3)ybo@wh!`5>}f3*ZU0=0p%0%D%7ro)_ozls zp7?x~3-M|Tic9^1O)(nJ%Mbwxy_1?(K(rAg;h=BBTG^3C)n3>-JHkt4LM_)XcQT_Hkly*FA_>ek9A_X zVNze1M$JJf)fd{Xh@sO;8zc&@9F6r&?wsarFm4R#&}id!09wTybytBY0+tT14T=nw ze41^w!xTtl)`EzPqI_~Lf8!wz*zm-S5g8-97vPClZdA)@(U&-Yh(@yt!&UuP2)p<~ zxmpKnUB0>38JH_p&1-!Godb_@;{*ji9dj)RMC}!QjQwgG zB%w$hUqt=#;3Z78MfvhGsYn9?8$y8`jTf#nZ~!`E^ltRH#X%P$fk3(o_D>cR@v)t* zd!U68npiGb|2k*uC#kAVV-on;BI~Hg(E}o95nU4EX|z61Y<42*uqFr0CH_&EME@hV zH6gx^xlnts=^1lOq5uaW zv0Hyh)aN9eNG<**cCMjQtRZiqjsw zEOJi2}(R8d&cqaFrT1F6+*VJq|1l9jOIXgqPWn6 z`w8?Z`^2t38=C5hK)t4E>hxG;9|IxvWiKaf?-HAq$%Wx|zD`#>`Fl+iDbUp&-gy3+ z1srvUBq_yk0c{|7qaBL1;j^G0Y|}CqSkkG#Ap7>k*Zo=)CVd~ZTsQsxf z_hZitMPICUL!s=I{msf%Ye$Udfe~pnhK;Ejgx<|65-A8}I}(9czuoSwpaPUxpsCw0 zQfiwE4D8E(Zspls%a-zKEYHa{6A+RrlT%RorgI=_Bpxd*zD0AP%B;k_!~=_HuB3RC zW|V^F0T9U4&fH={*LXk&-2-d05JjXbEB36$qZpdsk2)E@_q|C{zmL%c0}rdm*_jzM9_F1~NwZZwZB)*khR zfO9pu_!$$W8MS2mv7^OsTM?>>t$EL1Jv*F~JhgalqDq~yF&r$vE%s)YEbJTuQ6esi3S*eP9l*<#@2OBACYyIw9Iac-(b*)&t0#v-MNqn29B- zU;V1^&<(`Dy+QwGFV~zM1Y=SWiFexAmXp21t+m+m$rrQ7dp`$}KiEOX`u>|o+CWq2 z#7OCC+;B;drT%o|W)(I7ZXdhq!Lv&$8Hr)~&nrF``@i(ioRtL>C@a2h!)TXy=E=K3 z4IAa{OB?8$`lVmKo((XwTe$pCMl-zfk5kddalC;&;{@KkK)r+N!NV?F3#b7zvl&gLK37iR)UtS?I0SQ^*Z)TXIlGotQ#TNFRMs zFG*i@qNkH1b(C_X&W^@ff0|uD6vMxWx(PKT10*67SeWb_$H_%3J%}?Hx|$ARIm2yO zLmyFwhY?REyANUoqndJV&q1tVI0Th-@5Kqtk|K6@B-&iWh1>Q{J`&kSY8hUl-xz$8 z2w{$bg$lL(v~fg1TtV9;+2ZrKMA08`m{`=`ttO;Z0{~&=LJO! zwEBwRt^Oj0T5BUs%}c|+us>Woj@|n@CtxK*S4PI+J|vaQqxVIQyjUm45EjXCF}<Y`_XRe|jzmf=v=h9#M!_Cz|Jyi3y4Tqp>M+FE)gR58~Bx$gg#h+9RpQ zP&a{VlY%pj*WZWh#X09lwY8XY+7SxxBz*^nw~SPsMPnV_g134bu%~HNEsgV~%C||C z52G#FBk6aP=~mxkXb97fHh~+H(VgRXR}r@?Xf5KlF!|_~eLw^h4zo*vmx^9!DO=47n&&I^Pw-+Jb(j59BTE4 zzAWgk_=rx{gua#_X4ubYS}Ed5;ws5#&AI;2w~P4RBL7aBev&Mt?N@FK`$9hyvd>n^ zvXaOJQetUYe_-$A6U~vPsAqf;&+Yd@`g1R&b8$7Ur+efX^3*MIycKuI@lM<=$Nl6N zF+NK5dk&3HQPmaWGk8{x&*6DFda>w(`T{n*C;;6?cwZ!7tKc4q>PcLV8VT_mi6uZl z*sp{Ty+NQ{ z1ol_uz;+7iH)X0zP`@iv-Gcfp#Wm3PRwYDboe8Ly{d%_=0 z)P{WtCG1bAk;H=9ro;lJIT1P>uDuU0?vwdQEtAA+&A$OqO9u!PF%D7L2><}*5&!^D zO9KQHllWy+e^C%Umjc~>pjc5r{9F}E!giy@q(NeWQsAKm(^?asn#=BVyL7*DcejQZ z`62!bV}e8ze}F&AI9oJE@xhmSXU@!-IWzZu`~LYWfORYjygxo}H{R+8(i&1=>l?b& z*Vl9_^dr}ki5munAKJvYB9CND9305lum)rea~Vp(@1}(K?oE(VX7?JaXk`P z36*0yO4=ToZaYB9`mjy}=B`;LS^CU+C%hmHrR?kCa zT*1{M<}lBVvt#P@ynRxrU9u=E8puRme7QaQ!K39eUe@^J$F zBkp|w#7v6erO?tuHnpFRb<<6| z*1e{(BYzw@Y9ynTfyzi{Wld$oO!UO!;Y`d-`V(f9%APKNBHZJT2^!Jp>QyVRS_RnDx&nS@HXg@9x;yM&flnjZ6-ydMDwgcR z>Ms9E}@w$5Y{+9wSw^ zMSkwHzFNbvq)K+CsW*g=h3n$sWLMpejvI_fMkObcJ%N3u8C3^@Bm39k5Zlc&qb>`a*%5CMx#rbVN&YN)AeCe3DYjowjdE|Vi;?%CBc4y^@f^J#%j^T=0>)}m4+QyI=|hmRy6#`FT}Xl=V_ z5iQnfAzcZpbi%kARTWvyf>UW3lhe2{3x6MDs;CN%HS30@`(0E+ex0hR7PhiDiJ5hR zX5G$krW;0F&SV2a@Smz;Aqp~$h6igaX_ZbZXf>02{Ju(Sz*5GvJaSks01+#|UPtT8 zX)Oi7O$j$s>FR+bp7O;e_F$ptaTtq6cel2&Wcl zv;*E#+mkX8S(%uT*63B>D`oV=!y+P6X{dBviE~SEQpy9`X}2)j9;PLiM?{LVPcV6% z6)l!HLP0LtPwU0b0Vdz5ED?#v5PuJeL^v4@BHsWZZ9u<=;1N|8y~8?PPe)*^a6E1v z-;+F=G><2D^oVGI%Q4)mgCb>siQ=nEqfQvzBJR(EmcQFfzq|V`;5MH{pb+k&dKddHuLcIm69#i{SItLK2Xt z*QZk9UIg$Pq1|v=@WQmXNPoM9ED$Va83f-%Z`SD~-8NpA(g~uYG^)~Dp}Y|aTf^yY zh^x}uP!cSwrW<-KR^ceYV#wBT4~}~~y+b(3JI4{iwo3m60i;6UQnRW?bK7Xf<5ndA zkvr+#I-R2TFnOy=!&pB1KArBM)1r_C$8ntpdB0A#)7?yKUMUzBHGdeLX37fZ_H0Lf zU!@N+ZK=A1(^}XY#zKr!Zl0eH>+~V|NFk$2+qGnjRJcPVw~sPuG4Yi#Q$niI3Tnx( zLp>j-Pn6TgsE?`U6{WHs?U`@}^gmTNw}_%jpGN*eH`8XE$jF3%VE+u=UrzVY11L*L zxm;Yn^8V(c&(VVd?tk;}*F?Ct!@x|Es9K}P@R0~-P?^&%`jX(Ln!b$Ekj{3b^X^?y z)lxEBf0fP)=*N+H&18|Z`!BNuyrQTU!BLjOv0tOF3zhvh(|^kU9ABkxAe-gc6;`fK zLBi!#m%&Rh7f;bQb$XJ%1!`5-q?hLPxv_ScM&E`?W67v-Vh1XN9m;EQ(Rb;4LRa4x zzT7gAI)5lYeuNI!OxEYqI8#F@&-qWe{V_c&xcwg#2+6HrR`U8&WUoc23!Xzkfig&SUrw34~u2noG$~eE~DyrTj*x--^;%9x;;{bg}8}Mz4#0C%Umy z^nXk<$BNRBjm4v){{9}t2LbR0ot_u1iBmN1NfcOrN%1Ej14;ixe-ojP>2EL=dIY4!f_h!_54vAy=ATmQP-9Qr$e?$4$$v8M%ituA!6efyvjGe_1VE~0 z%pv7wvdzr*1unJ;4d2UR(2#Tr=4ehvUF;M+#l5T+_p`Ees$7=uT!x#fu?1mdXM>B& z*`>42lY~N{=&LWsJH};$k@kY8qAKt-rYkQGM`aHZLU2q$&KKA_xuT4x^Nd2*T@0Y| zESOrB?$H%gRB~iauHvOS&t;4rlY3G|8lE%U4~{MVqTsr?hW%wwECvv*5DG3{ zF5=)0ULo>Bx;fF4>2>ic_#b;2lZ8DUd$r+W%zqMMVePoQJ6vd1@_GS*abm%!(uszk zD;$>r-+Ursv1e-B1{;H{kv!(& zofaTwmudO)M~yVx&a|+qc!rx`^x!=hFnBLhRSCt6xV9j%6=4)dqT}nV`vWWbM+g0a zF=s9vwiVj*>CZ8MCZdC76bDML?B!+BGO$wBe7PN zAd$Z_X+B{@vZ5X0PI$dYGfPV9V{CS^&W!2Y#W&zgIDTgg)wL)ejXA1O!emonD6|%QWFNTxEYSB+*8^aOHoxB9pq#T_{YuE(cQ6xVTz=|EiTS*wv5w^xqoLS zcs&Lw##^PjY64kH_56H-dv(5%F)^*IDkZgLqYWi+TP)?hR-nI*X?6+ZmSj4EkyPc^ z7f&$54j0aJi-Mf!kdAiCc$XUEVDiK_=zJ?jujI4w?N==75jXkLt z)BFi;bB0OZ$?p~l#yB-8W7fAfwzTA11b&~qKw*qfw$`SrG=4uku=oNqVgir#CsWaOXMa~C>ssjz8R(*=^6*NCxsI%zqyXzWaT`kFsArr)BfE1M+h)f~L zJ;0w8IG@8#Rf{A8dwpK#`}vIMp3aN6oM@qt3#N`XUqd*Jn)Q&#=V^Wzw%ECA$F}Ci z-5P&k45YlL;zupWbAWtxtbfPC{-U+^C2P%s`--*pRYZbuA`;K0W5?u;Z+#>J6}E`aWslC z-o@Xu@;>H|@))}O6gmkrh4$lz);flc*&`HpWs@1?$x&^@k1-=Pn%Q_%wg!=u0gv=+Kb4n?{4<@O6@7=63@1&Im1Tpy z&BeduUy0iMYX^ycQ-2z+wGn^kvBJ~=b?-tYH4~O4df?!zXKVSe)9oP7eIzJ~0x-PVBfiYcCHR@Wp6n$v_FZ@@5`XZb-lj;>j zMLL=YPwWHf@B9y)pJxmo8~z`Dtny1}WaOPgW86#|uM*dJ@qgZt?19teh8XQ+JA09b zbbeW(qIqO@H_RGU6$Pmz9XE^~ksY=HT(K(-U9l<7LSJ71H;>E98bt$S1g`B;bb1i( zs+2ng1E%0)MQmHFGWuc2&thdENmIK8je4bLP)Cu(E zaAjDmHs349!`Wn{8~wV~`U`t$%1U7&VCGZQ;#cU|^GQottz0Gautvi`Cx4Gnu6okan(*DC>?%9Ra8Hx|WEsD4DClE&Euo(hycXspWvkMH=0VwpVvz5L#l5|z1jR3mB`&8%-L5EY z=mL}-Om#lE82FC*j)!9z0Lkn>T&sOynW20cQ-2nN0H|Zya*Bd4-Z5g8`(kNd*7|Wp zQ}z_)mXXS%>;q3D>cb4%4JBb#_gS}-&`OAD*`@Crhf`HPh%iMxt6++%$(LQ<$n_KId^5>J8Z(BI!>r9ymU&M?W9T2); z!ha)$wld!-wD%@6;S;0e?GU#=m*71rc!#gr#c#UE1IUz-qZlA|3mDW}aaGfnO>`J3 zxq=k$AXS!9#20D!kCiT>Nk{NjPNY@19XXnkqlz5O$caPS{D0Tx-s#?zqrLqU%F#jVFE~iohYlWW>!+~& zEE$eRs5%s~xx3o!?pS+{67K4=lrF4hv3gvr?klYHV&yerCFFh`0Nt-YOK%vUw+zzl zp@4mm?g;tM(7ST<-hR5PpFS{19|{E=ey_cs?s22S(Gy{h|RAtp^5q%Qzhpq}d+x`6dB=IAS@$qO_U%6Y=89?sE)96cRy^bOsI z{qM;ATCqQMV~&2XMgUd-^cf4Z!eKum-=4_PPXy9&ApJ}t`2>=E1k|fKN5FPINWZ*` zW&!xu64=>C<%9IwP(S_eIX}<<8Gq0qwO7m0bEj##pe5c5yiN7zX$Q&#RGEZ&gV!-g z&xgEahutsq(;sv6*Bt#_>|KD+Ir`UW@)QKM*tqyLFFq~?9F8?wh2~XrtlV?)tk+SY z*^dZGD>Nx;K$B#(BC-}U7XtwCY5@@F8#)I&8O6+A6sJTcCaU+@WLD~+1EGpv{#Da zRc#fTkVds1$(vekf8J{k`Nfgd?k=GxcJDjGbz))VX=?Yv0qX+}cNf+}0jK2QD*LU% zC#;Wk_K(s`;dc14<#+>_L4VZrkuk^{Lms}SpRYYVNk?@*pY-?hZGaE8o#D3$`qTu5J^c0@zbmvxy<0f;WUsTr(z&pmhffvubjYOk z(Il_aR-sDE_(LEw!0*lRT>;I*cMtGAp+K1zuOG|tCv$w?Am0x^vaiu{{9uI!p3Y8P zl;eKsUMfBZ;9TN#`hV+T%gq9+u%C8@2SEs`m3ct-Is#>Va1*RNB36_;s{>_zujVZi zl>CCw8GdY-7MxQOgH8ptvNQbUP(UwGEAu*nLQ1_r?8+K%S@kGF=ZgvDU!B7=&+yj= z`9dh@g`{444OIG6j=wFlaHv(p$-#X1Ncq|%iSG_$V>{HA<9{FAMJxQmo-_%MXJkt8 z4f3-gfm?If!#@$B$3HLN{o)+Aalk&nznRXzO?dcsC&OzU98kULT}2-L!R( zp9{(O`cn-!_;Zf`CLQTtp|;0qJ|f*dpfLWX(Gw>J6xdVW?p53RxB@Av4fY-S?DjrJ z^qr^gSLYNL+gg`=wr8QEB%9=sN6Kd^Orq|?@S)tbR zG_~eY`-e%dv8`S*fxV!4}m>JrHv{rBv$E~A)1{3 z2H7F{2&vYG{JUPI+f}+(rTd6pqBSa2FIau$5P!KvgEWLjNh=8pFaf>@&mr1e0_e#C z&=A_HvWaN0*l#3#qJ8U60L`2L2=ZG1zDsdBgwD=6yiL}og*8eSJXda?dit{bRJk-bX9#56~+6k7%|1MY_uVFIwYZTI*Ou>l}Vs?^sR&M+*#RX9jk@%lGGtDGT zBKf|_dFS49&whW;IrpKL?>PkEG}W$f%Qe?*S@-(-omT8hI~A{w)W>@3o9bh3a==Mg zp5vy%NjGkDJ#8m!D`RuB-^zqz{dVliOg5RRkMvrJjNMc}&=*cx17Sya#N(%}S-o}* zY18Y9=X1Q#;>R(KUrJJsi;Y&-3w`nbB=PG=~K>+64-*EFvS$L-zqZ#1D40$px4 z9kVw(30q;Io9=7rOIz`T-LfZb4Gh@nmiAP}vl5A=s|=JW%-&_~wptQas;}juoxALq zXP`piB)yvToJ32^O~tb5w4L%=+IY;`nXnC*JhILmzY87QxR{ zs1lmElktBxI%$QPB9?Y`X2nz6(ure-QnuH!ZA&{3%@Hz6?REOHY3)&kze;d!hz; zaxx2}S(vrZ)8d0vTp`?WJmK+Y3!=zk6;_M1H8j52z0$;51=Dl$R6(3B0#;z1!jefN zI8J|xc3ngilDu>>%t$)QO<%1Ydsz@?W4-L2Lv@{ua0y~Ve(5}gSu}RT&WxMLdiKSZ z*B`{jymgxt7EGNI2F~Y&v|=$k!;DDgM9q+ZAL^f?-NIzJ8OquG*66R7wMcQSo6q7JCu!BiAAPWgrgxbkci9x;sJpo*f z*D{Q87GRH7?97KT#^hlb+Y(kLLlNVWRxeTo8@+P7`X+bUWS7~1LuE>%NStFSK7$|@9GYoU@VHB(3G-9N4y?y2;g;iBS{ln5%F}| zoQCDwC)SKN;msoNExaTX_6)qW7)pQ5dP6#GX_*Gz9>6{+B7Q3#pAgGJ1(PfJ4!l$7 z-o*qOub_eVFqn>KGX^d*aPBx0+6(Jc?!998;|{8H4zOw31!8 zgAKrQH*~eNw-@W@m!yQb_%i*+al+}ndZW81m2j} zO})+;=#V*Ks)Rmf1`i%YP7Z$#v8;{-j0{>hWNg|Svj_5b?yLF!lP|?1c{{$wwdRbz zd?pSNN!u*gyIF1Or*1pN%M`@daldf+2E9?#>bz`kubsBzTWm|WzHc&W#l7~_K(pM7E|K!pN-qt+Mjm! z?Y*GnD*yJRe{m{713o=gXMf2)gfI3chV!$2wxk z9#8%oFIM6O{D-1Fx5M4T-oqEgnCMdKNk#t`F9&cHMrp_%Cl!Bp_hd}PH-gFW+OwP# zOZthWR`HC@B z6${zvYuB1;291~IYo*+jLw)tlRkQRErDjV7-#$fptLlIXs2cL*q>}ceTa=nw5PoJ* z)vCEdIgc0ZxNUz!g~SDx<879H!HKUus7_Q118RZdXg!mvmE1Jmq)Vw#OS}H%j36KDW-vP@g)!ES-2A z+lk(5Hr0Pd2C9wEZ7R{_@kM{3HLz7Q02!d1fwu3!*t}9!5v>!a=+y+Ia*O2mG^E+>LHB*`9-yL%h2&8r?x^ zQq1oh#KK4!k44G{u_zj;Xv(3#dl1Qp;cqo7S}VhvyIE`QN1!PjD$5}oD$il>EvOpC zH4%UF0NMq=HX1RHQr76RA#()#qLIK5t~=CP~?uXsIDH6bKhW5zbStETLo^=#UW{j_!~XN24QnkQxr*JJk;l;n5-dFo&N+ z%p4vMnGxdvI>lj?Az8SuDO$A1=&62^77gQfIXqMS$75y{_syQ_XSKzDJ+`GHMp=KW zSzGCQZM3!WW9rOW^Ol#piz&e0Le1>Xl0;BdvK@_-Nr0=L8^%BH#!ERSukz(o#eT*P zKhidrhijBc!&K*p3PdaJ#Z}R0sJtiYuTjCSvKlqBtGu-$r{>gF^mGlW6LM-k(I4G*iNhL7OnP+8GUsmpmZ96_38`_&sJMB zOsWC(B%V-Lsds4jE_Ji(jc&i%L@N4Q(4IfoMR8Ilw$LcYSKc)UC(09G>1OAz+ zMZ7pLgNAjzs>gPGN|Od&uulVHIvORLe{7lS-U9 zM#HTF6(q2w8!clSWu<=`;`02)3pja{9lDHtxNvuyD%A)q#(N^L|?^aw(oMx@x@T>>qCw2 z8l2$oLaqM_%=O1H&+lNqKY@^cK+Ey#vBUpAP)i30lY;XF#0&%g0J0d9@ntiUxO^{v z*F)>!#=BMU)OFETC@S6vqM!&0f|qf3x{YQJB-?r+`XIiA7b1A!1NczlY*j>LAT#sl zn?E6W|9E`^(8Qd;(0HB!3`y$yX^*Tx9$dMoGC4Hl_p-ChQzudP0|u?cBJ)! z4h1*18(Vj~Ew!b(n?+tMGfx#BVc2YcY;HA}HLaidc2{c_Y)5(<+)@&$gvh8QVzo!c z@>#66)*I_BFQlG(KLR08IZwMLpaZ2zU@0|`9~l{H@^6jIGBW;AVsokW;&^~% zz|^(uNngt(@=vd>DagwhX1}lT!!%~UiQ_(_Qor!uVWBOR?ixBFYh}bl?fBPesilu(15s;6J=_Ay8Ugxp3fMqJlCe9gJXf6ho*ws9>z9rUeG~`IS)Rrp!Mx zz!g(mRSSl*;BYX`>nwNkC~*LjtCyEAm|A;At^SOeC!mj(`WB^6P)i30YP#z4YLiWV zPJg9X3wRvWbw1bonAK|ikYw3jZ17mJu(Yd{{J@rxc}cPXS?dRqAFSH7#uab7xlC zl_f}9fByE)x%b?2&pqcqkE_?-|KbZobbpn&N6_i}?i<{Cchj(zJf>$;P2Ek&k*4;h zq?ySXY0WmwY%F7@bj;`Vw60k?7RNLzmK@WQ$E-reYU&=*(w5%dlpBp@v|P+!8L8A& zn>KFV1m67C^8S%RI*kcyOp9#*sb@!xtgh#c>?mfB>v;=jVSa1JrjD(#lzzPF-hTiI zLBS!jkWcD28fjh7WoCY~b2P7|(t783Ud!e5d}n{wvbA(tA+Mk%cWB48&a{>t?c6hb zhn}<*@(c2(&CyXkFKA_aj{R}DxJ^(XWsYalrj`eZ7> z>Xx-j%WCqJYb!S!SzFI%wRGnQ7=Js{X7U&=+__`k?GWz2#>g7>b%H+9`T_cWpoViT z?$zwE9?Q}*!)a`9J0Qr@+IApBi)cxZ6si-n?f;>-LJdJ$N_8O$(ZU+?(XtQ)sD{5* zgeXY0{B;@JsmWby*RNkMXmrjCx(?kIm(DcIPCm?~q-%$4M$NXi57@lc9e?{6rtI5M z-R?_kmL;g6wXH&yoZJ?oD`+)aK@}9LJXWD5I7B~TShgh%b|^$^sU=9wbY&IX9Gw(u z71Sta3$~H&>@(A8pb*Hm6p9F{(K9)FA`WSS>dSgaPM(7r?Gy`Alsdqg#tf@~bL(2$ z4p&Yo^O`(Up)En`Vo%o^)^;Ng&CL8nh^}@n)Qt;j zDWJcxH9k9zw(-TUp=)_Rkh!Q@afNOWq!`u?zFmlVsil^Bs87)CH%afPDKO=Y;R0Ji zUDsl*Q&XmHsaexjlV;Y|jI6303BpiZUtZ3 z7!J@OMg;V2o5L8rrhjQeO)a+ziVfLX9;ssO28BKnq}v!>ZPhl(Y8lQKHfNnVV0=5D zqzT&j;aK70wLD*S8a3)1yKvv6pk=5j#>hlDC-%7oOVH*yQ1anU1i*)G?ul*Oyd^-R zC?%4`(vyX}VNZ1KLQX>(+-{8O91aFT4Ca<-$tL0N4Rf67`hQ_=88FQ;N(boF33N}ROT1Fw0lS8%g4&LqzQjSoJ798$X$S&st@KkL-4nX1yG4E?V+{=(WK@&k5 zr@IhUgVwGSZ|0Pq<^1aAwOBZR)tA=3r0G{wdALR^bjMdZib^D1xePKpMh;{^Je{ov*!{> zPe=66(Z_=Hv-I=a0HE8j$3paRx`l)M6PRKwWpVLUt$mm7b`^n;U!Y%PT|Ox&Hopt! z*?Ee0o<{Mp&9bgbTjx~um*_Lh`xw`nI}7NiLi7YD+kZCtWi}u>FB>-ftdpmI1t}lk z>KV4obivlSu7~JXSwb^SiUs}yjC&&~n>W=QnJYrn5e-mDt!c@&WE1GG=H$s}6Y7|D zTvvy6J*(PU2Cja=L;66 zK}&Xv9elCvm6zF{Pj{;=7G_;JYTR^888jI&X#VYJkug~a>jD9kyL$pfxTmnz<*Z;PN*~=5_|uMW36EZlv=Q09!*W+ zlDKXqYrAUcx^#+a*cMy+xB&nn2mTuR)ETS|7P7XH(b2)_Io_wx=Vn#EhW#j~{ zo`18Z&g8eM77IH%4;eY9S^H9up69Hm=vkZVqo8nAm$f5X$mn_Lb|`m&US$54s^nF$ zDD=AsHN19qnR$IjTF*c#BJ=mSz4zH!iiu{!LFzzekXG50q?dV~HJ-K8v@)2o6yTjO(^u6&v5x`z9_Mc-oAej8qy>p+G60e^5C zN7;qJ|B0*GKhk&j=cBv}MJp(w$SEQnqA${UM(Fn|tLUDJK>8QF1p3SZ!jzj7xl;|$ zzj8)L1bI371N85L1cLHEVT5@fbqc-9{g*i!qW|Uy{4aVB)ngFZgws@jN>B{8aT|pY zUdMpS17ZQD(E{UuKZJX7Y3BOR_c@bdu z1Bu8CRaxrfv{YyZp|BsGcVpjac;A}8R* z)vH-XvZsL3fE4W%rI{wWY?=9lA#}u*VjbHIZ_j!FHd#ocZ`*I_`JPco42cL}g5@Y+ z!m}|s9T2f{M!H0(B03?;(tqtibR+29_PQk;Z=-p8=UF90Y!DlRV!hY|(?I^XnLoA< z<;N@_QHuVM*etfxK&LKL6`bQ9Jl{%-h+sS# zIDVa}*~Q111<>}313|G*9K;60;uboeFXYhXghT?F9V>@?#Q&BM;UqKBqftiCZ^RF^N8 zojVyUDWL~NQj8$MPWO1@nxz^ux9$jtF{ncbd2gcOf&Z=j9C5p#&*#l?Pt|s=-$s|6NUvAzFx0fe#naViIBk)H?8cF|Ldx zj!aSgd0Ltnn4-qWv$Q<=EQQ;jrIlx-?`vokUG8iWuVRZIV{J52q%{YNwC*$o&r#>V zBwZgZ(x$|~D}UslEd3yIp1Kn8DcbtNb)GHWM(^cM(&dpx@5V&8uSnZYQ7{_D$MpwK zdc|bvt>{4HIodAh6sg|lNl6TN+K1|IjGUvL1LrB8h>OS+?U|%cf(y|0K3>VT{}Q%b z#Pb{_7SM~-jQQq7A|9zfJVi&K>?vxE%JbJm&(m$J;D1rj!-@FIv^e^L_X(Z9}D|Djs7D2*d*LdpJ?WDS^Hq}w-zH{_Qq8pnZg~4mX-X-gc^na;?5Ra)(A3W&;BEH_vavo3YF4B{y zpi(qZq^E$kr{fBHC2^$N>xm3`qeH&-A%ASB{@24^$3@R1;Go~UAhoyv3pCPYFgXFi z&2ntR@8)TTeVl^6_i33zcPNxos8FI6B=a3e5(+&~V)Me{juWT(;I4}lC_%cvVzHp0 z7Jm>rGbUXJyNeL`5c_lyc`G(ZH+NQ_DE+tyn)~3#M{xXW_^#nckQ=u9B}|C6L?n=7 z7@lSPuJv5IDheyFV#r6Lt2P4h=jgf9G?!r7cBZhk$#6`^nVqO(UbW2eSz?LJ+Ye)14?2=`onYdXEMnC z{1h!_`~T&^$2Q1OJiWo3ZzdQ-Q}oTSZ;Jk|NPpk$t@F-;)~9K48Cu_+EPW@I zaPjmu{!f3e7R=K``>5LfAyMq4V!<)q57iCW~?N?YW3HC-pi9e=b_ zj&a%}$3Z$G$0KwU1}D-G7CerTDaQgmEJyzBm7w{Q932Ry83&6vG`}p}`aJt|lam9U zpT>}HdRd{@If}v5#Ne5peM6yfK#1sFT2aESyix$>rHpsUzr75OAmpV0j)yVU(La~H zMt5QZ=kr^l?dRwRXA-+3iL(^uFn^35t^c74{?wdyFN6{fhULG(lIu;M5;C3apI2m`j0^nG_MhJA^m*wgK=YXzWp z6~*8dZ%tQCO;>H$-!75uLw|xyofEef#o^PmcUkSSnnvG)N4jdXE_`bESSpTWY99Rz zg_hMedLMlBG%b%U<4L`%=B&^#wXC)%M#F)2Pa|UGyDXurwyS2c^aShMAPiP38V-d0 zv9sci29bsh%b|n17l^XGBk+lN@C>T;=7I7x;hY9>XZd~&!op`vnturQE;#OrOoBR8DJDf+j-Lfk@^r7Hd1U%tx}UxWn#XU0K1rXGG>=Sw zo{Ey@k?EJ{RY~*6^jGl9G>=UG5KmyHd1U%Mu|U#1f)*a(XIhR-FA_^7%_Gw*#TrTT z$aI(3CTSj-9u)f}&3_})w~7%-^T_m_;vPx!$n?|V8}gnqHwc54l%P6VF`>340(V9BJBqvANoekUJZL*Ar$Qmuy$;%JjI-AuX+4+S z2dZQdtLK-qR6e~%p5S&r^+#c>}K|z^StLw&dm4UU%vrZ!xF>M;oi+^x@zpG z3##F}f$i|v_C3w@O+k7n9Kj<&iwz!WMnf2TQQ}7GfBFu0BC((bmge$6v!#b=uC1=z zU8UHte9G@6jzdD!;My|%3eU1VAwt`;NIei?M7c;WFRm_@HB%g@@A|+P(ltK`4e`i! z1jD2sTDlc-(-HdXkOzSX^{Q`KB2>`LFucnTxbASz(x29Mg%K<0Wf(nE9}?l2yzU4E zeGEPOe~B$(2DZ)6d*Al#_yI$AVY|4+kSY|nGRR;k4F%Z@(irGR4|25P_!h%hp?c<9 zi{(Blk~>#J?M)O5SHT!DenNT1nuzV|&nP}7N^rN5!4*vOV;qwV`8ELxrWlk!3XYe- z3`WzK#x*LLpKOO=>3l644Ib9Sej+?WREpJhf19r`=$9e?6gdl3=Do?V(vjWV?3i%* za;QzpIhpbfHNLRX(Rt$US{s9sG?=HZZqO-Y7_7x~&>!>Qg@hThRXT)E61OhG69qZy zu>yvEdULYrbWeI{p1~k}HToMz7Y!g?di4dvQ=c*N0rJTqkI`1lTq`D9`h<}qq(9>7 zU;Hty%Rq+3rsYoz5i^S$EoQC7^q$17Q|cG8&}rIBl$52z?UutmbkhLx zO@~40Fgx_xe2m7M&cGV3Ws!= z3Kz%}<;txy$EORS9S(Vs1equTe^u{@I1Ft`rb)f^kG7oLoVbHju zFF+5PWb0ydI`;gxEqgLNB&R1sk9eET&#?GC4^GCNtyA87NEbst^8%_CX)}+NY!~YuN|ieD^o_ z8+dMNV>;n_TlaDJz|;rpJ>pr<|&4PRfuN#p1;Ht^=+OTKB6z^iDfOLXK`*|0cw4XaGj4eojri{zQH@v%&*$Twm?guocoob9_hzipVD zA#S_nblF{+`pq-*x_`{f`+m;%oVoYh?VRstBuUitW<%DjpF%jkW?6)J z!!Y|wFRb`wUQGU7lktI}5_cfQW1L($6N>gJvqz8pT&-&BOA}Kx6Y++V&lfL-^Kw+=Cfd#{lQUp4KFiT0d5p~^vm(2`&)YH1$c)`u z28LO&U$j$_V$CpyNd$2kGGw_dDd(9#EU`Kj-I!J3fUZ6swiq~1toSzg^rCgutnuiEm@ddUFyGZp!G zQ$GV+j~94RlQbGp_fL8ik$Nw1#*0-=Q3TSUf6Dqhu>W`4^zPIP?;a|3qKGK%$@V1S zwngUBuw?ltGXyreJBBKulZ|+|q&m^X?a%+VsB%(lVdm4Zrz-wMoMFwS^aWDZ_IHtO za1xpjhOC^kYkU5ktE+7ahu!*~elt_AUd0oPcDKg|7G^_y_2zFpR9;!@cgE@p1xUsY zwM;lm+d&{uy2+#oB$qR)2IcvapE-q|RjY+nd1@*wfCS_x@#^8q8@Gu@M? zp5}G%%1RYBfAz!AuEXX_+6_AJ*9@_Q?(YUzodkZm6js+IVU|tf0yNSzPt{<$+GlI= z$C$F?bf;59gzOX3&m6A_uX(1%Ixiet;&W5op+3R_X8gF-}OWTmps?UMbA2d!S-%CM(UyVreuT*yyN-4~y%3 z*vf-?Cu@XxehEa-UG;Qvong|5Jl&%>-Z*T|IzHzfxOkX7`E=~}_Fk7M=tCP_lqom& zuZiQ!v0VL`qQ=JNmBPIj^qOsv7T)3w>18X3_K=tt_p+E{ASmyWB#4#j`Bh7#t%TW# z+j;ZXIb}n(Mg%1{rR*nHKje*ms1JKlUZ&`5<>}2De-RGnaYYxT-KuS6K7nuhHF3jT zKI739o!yflZ2_BsRsB>oYYTmW5?-L^$gAoZTBLhDl9?LeG0x%u7oTq!{91iFjHay= zt2Hb!(z85?L87d%`vbj}1t}{wozLN|Z6O|syD}y1EeQHI% zp0~Ki4_TC+(vMB4QPJHn1q(34er_-S2}nC3uKzG!271@8L=)P) zlvNB3-N%gWKq~YM!y6aYEXNrF$c_;zqzdMl zwuD=>wvtce#$mbn?-1j2Nx02wD4q>gl{SBl7F?GUBN)wTRyFX+GBX#hF z_gMf@#AfGRsk#aQ66{Z#;u2&Z2FVTmM}`|kcij;;Y}1rMT94i!KbNge8|L2tY?Llj z(P5mQBT;)nC-gWEN(>tXbp`U%>N?L1l^Dh}y;8NX)r9+q(+qGz>biv;8piH7W~awT zCb3-()6nXuBWcp6`9L83L}RFpYM>c&k8Xo=hM`ay~(a1kBv`P5BI;TM9Pt3 z2y2zDjmjyy=(#O=JR)^FH9#JmT(ljgWp>SY5LFZG*zcF6fa|%28J?-Q(K+0%s^-G= z!`&_1%F2X4nbV)xWS;iW8SHi+)U>V;DGOz#^(-t9ADv`|+g@KENh$O>7gJi}a}#u1x}S|f zOZ&j|CU{|Q@SYQhYC@XnK28R7+CA}29Eyr0V;3grPH)jA=qyg#%_dQDO}YH|F&u-! zUL~{hjONJvMUf^DEOS*1UWb@)@>8mgb3(uEx_m0jZafseB_?S`V4*tOwN70T4N~%D z`9Oz1n=u`7P4h`A=qo$q!T2fVm;Ql@=CaAWS+CO12dTn!^imaniNQS2r6$EHLQqQU zNyx`1twtra@4PS0l=T(aSzF1^1lued9N%!ty#AdhnYne;*2k=F#73yBA|3q6LOf{j z6!1U_{j1&RKUpt?!y=ba=mZqZDBFb6j$`t&ik$x@dF%ldp*oQiQF^ZRy#aSq+ zjdX_a>C~-q`4FW99qNe8TJ2&QJGPRL)^&5!hfjLi$_w1hGA&oTPP$Bnn)SxYO)@64 za!S=S`xP6+SEF;;-q`q-FKrS~-C3jGtnAu`KYyueNX>Y?o9%w}+vnAS1FcZH{@q*D z{W7|TcURZ><+o%)5_Xfu-%=f}^M ztCL``qevC43^oP6De>_^8lH$g{f5x%&*yC^+|)aeX?3Ua+B77iS49ztL{)VM2sar_ zoq6lH9NAsKy9jXR))Q=sK3gV(&L>P-^F=dQMHXt$&xvnHrJ|(u|F2_+P66| z$G=&FgVTp=EkZx&u~qe0I4N4oUv=$6k`x}Pkav!lc4h@{5!vI-=73PT6>smf32|#L z^1gCDz)1P_G~uqs+YY_5O_b;F^MrObYR8sS;fc?5=`*ftFAd!Zy*Vg;vUG#c zysAZ1_tOtm88{P_&|$xO$l}Ct7M;|9)p2*QFoi2{-(iQM8_~{)oNu(MSp(dz4Cv8d-iyXELuv{PK8RSM=b)A zXb3AJMv~D|VR3~^ova>E)H|U*(i#06vkqqu)o4s#aMD4?2Z7vvNl)A*mzY@nM1J_i zw!xOlhc@>f|AMtU&T!cT)0QH`*DIG49TUfbKX#58%jPy4g;pEhRbR&G$2j2)x9As4 znXm6aAdE9XlxLDp$J)fOF$Sw= zlfU$6;Me*Il4!%#NKwD#HsMRbS?g<}cw{B(jzQbkYinrjCCa(S_mW&u>f+7VgQqNRSL+EiwvQ;gfW`c z?7aVWa#y1O*)i-@SD;76+dyfQLUV#-AwC#ci1xp(#)K*eb)hi%hm>kMj9~RS=pX;w zeBjbH9Ee$wqJ(v^|AErbBhyqMX39$a7C%x`mVo?;8A>+k1Qh!KMFfRn;#o4>a+Ze- z9@#4b!D~=}nNnnMSW1ix{@aL5lmd*F0YDgF%g9DDU@sv0IV+xR8NaSV^tfYRm+PxsUt&fj}?{xcl~>A{maRC}Cu(PeaM$$AETN1QyD|7b3|K z;=+W;E&BI1DF`G$p^J?sg9eSFQ1b09pc=NoR&|;J;(JVnavMdUM>lkUA}KeNzH~B_ zmJ1~pNxpUil-z+mRf&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,29 +65,18 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% From 4a9fd056eb51a76d18f39471cb1885ad8e30b7f3 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 17 Jul 2026 16:29:43 +0200 Subject: [PATCH 151/383] CI: fix 'Update Gradle Wrapper' (#7238) The action needs a JDK 21, but the step to install it wasn't running for us because an incorrect check was added. --- .github/workflows/gradle-wrapper-update.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/gradle-wrapper-update.yml b/.github/workflows/gradle-wrapper-update.yml index e98c7ca9eb..f1681c5a76 100644 --- a/.github/workflows/gradle-wrapper-update.yml +++ b/.github/workflows/gradle-wrapper-update.yml @@ -18,7 +18,6 @@ jobs: persist-credentials: false - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 name: Use JDK 21 - if: (github.event_name == 'pull_request' && github.event.pull_request.fork == null) || github.event_name == 'workflow_dispatch' with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' From 968d271f2ce9ac174ba2ebd6bd0060cb8b4a2d7e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 17 Jul 2026 16:38:41 +0200 Subject: [PATCH 152/383] Fix checkDependencies.py, looks like gradle 9.6.1 surrounds the dependencies with `'` --- tools/dependencies/checkDependencies.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/dependencies/checkDependencies.py b/tools/dependencies/checkDependencies.py index 64ae6341e6..5cb1a4f70a 100755 --- a/tools/dependencies/checkDependencies.py +++ b/tools/dependencies/checkDependencies.py @@ -35,7 +35,7 @@ def checkThatModulesExist(dependencies): line = line.split(" ") for elem in line: if ":" in elem: - modules.add(elem) + modules.add(elem.replace("'", "")) for module in modules: path = "." + module.replace(":", "/") + "/build.gradle.kts" if not os.path.exists(path): @@ -51,12 +51,12 @@ def checkThatThereIsNoTestDependency(dependencies): currentProject = "" for line in dependencies: if line.startswith("+--- project "): - currentProject = line.split(" ")[2] + currentProject = line.split(" ")[2].replace("'", "") else: if ":test" in currentProject: continue else: - subProject = line.split(" ")[-1] + subProject = line.split(" ")[-1].replace("'", "") if subProject.endswith(":test") or ":tests:" in subProject and "detekt-rules" not in subProject: error = "Error: '" + currentProject + "' depends on the test project '" + subProject + "'\n" error += " Please replace occurrence(s) of 'implementation(projects" + subProject.replace(":", ".") + ")'" From 3cef8c2796cf1d9be2427f6d6683fc6e33a00dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Wischer?= <33184634+unclejay80@users.noreply.github.com> Date: Mon, 20 Jul 2026 08:50:51 +0200 Subject: [PATCH 153/383] Announce expanded/collapsed state on the timeline group header (#7226) * Announce expanded/collapsed state on the timeline group header GroupHeaderView (the accordion-style header used for grouped state events in the timeline) uses toggleable() combined with clearAndSetSemantics { contentDescription = text }. The clearAndSetSemantics block discards the state information that toggleable() would otherwise expose, so TalkBack never announces whether the group is currently expanded or collapsed. Add an explicit stateDescription (two new a11y_state_expanded / a11y_state_collapsed strings in temporary.xml) alongside the existing contentDescription so the expanded/collapsed state is communicated to assistive technology. Internal note: this single-file/single-root-cause fix addresses three separate BITV findings raised in the same accessibility audit against this component's toggle semantics. * Update screenshots --------- Co-authored-by: ElementBot --- .../impl/timeline/components/group/GroupHeaderView.kt | 6 ++++++ libraries/ui-strings/src/main/res/values/temporary.xml | 2 ++ .../images/features.messages.impl_MessagesViewA11y_en.png | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/group/GroupHeaderView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/group/GroupHeaderView.kt index 883c591fd2..9dbeb83a3c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/group/GroupHeaderView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/group/GroupHeaderView.kt @@ -26,9 +26,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.rotate import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.stateDescription import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons @@ -37,6 +39,7 @@ 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.Surface import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.ui.strings.CommonStrings private val CORNER_RADIUS = 8.dp @@ -52,6 +55,8 @@ fun GroupHeaderView( val backgroundColor = Color.Transparent val shape = RoundedCornerShape(CORNER_RADIUS) + val expandedStateDescription = stringResource(CommonStrings.a11y_state_expanded) + val collapsedStateDescription = stringResource(CommonStrings.a11y_state_collapsed) Box( modifier = modifier .fillMaxWidth() @@ -62,6 +67,7 @@ fun GroupHeaderView( ) .clearAndSetSemantics { contentDescription = text + stateDescription = if (isExpanded) expandedStateDescription else collapsedStateDescription }, contentAlignment = Alignment.Center ) { diff --git a/libraries/ui-strings/src/main/res/values/temporary.xml b/libraries/ui-strings/src/main/res/values/temporary.xml index c0573cc6c2..2526f254d3 100644 --- a/libraries/ui-strings/src/main/res/values/temporary.xml +++ b/libraries/ui-strings/src/main/res/values/temporary.xml @@ -8,6 +8,8 @@ "Mark as read" "Jump to first unread message" + "Expanded" + "Collapsed" Allow access to local network Your homeserver is on your local network. To connect, Element needs permission to reach other devices on this network. Active 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 b2b3f0b813..f47e74ab7b 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:02c4892eaa7d27c867266c428374b64e5915ec50ddcdf8b1d532e1cbc6f56462 -size 130436 +oid sha256:5823ae9a382421609200d569799505706180b94c6923f315caa81f8767ac58f8 +size 131340 From 925376b6afbdf906c77dbcb4a3341184a21bf828 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 21 Jul 2026 10:18:56 +0200 Subject: [PATCH 154/383] Allow adding extra elements to the developer settings from external modules (#7230) * Add `ExtraDeveloperOptionsRenderer` to display extra UI components in the developer settings screen. It defaults to not displaying anything, using `NoopExtraDeveloperOptionsRenderer` * Add `EnterpriseService.overriddenElementWellKnown` method to fetch the current overridden element well known value, if any * Modify the well known retrievers to use the overridden value if it's there. Also extract the JSON parsing to its own `ElementWellKnownParser` component. * Bump enterprise repo reference. --- enterprise | 2 +- features/enterprise/api/build.gradle.kts | 1 + .../enterprise/api/EnterpriseService.kt | 6 ++++ .../enterprise/impl-foss/build.gradle.kts | 1 + .../impl/DefaultEnterpriseService.kt | 3 ++ features/enterprise/test/build.gradle.kts | 1 + .../enterprise/test/FakeEnterpriseService.kt | 6 ++++ features/preferences/api/build.gradle.kts | 2 +- .../api/ExtraDeveloperOptionsRenderer.kt | 19 +++++++++++ .../impl/developer/DeveloperSettingsNode.kt | 3 ++ .../impl/developer/DeveloperSettingsView.kt | 4 +++ .../NoopExtraDeveloperOptionsRenderer.kt | 22 +++++++++++++ .../appsettings/AppDeveloperSettingsNode.kt | 3 ++ .../appsettings/AppDeveloperSettingsPage.kt | 2 ++ .../wellknown/api/ElementWellKnownParser.kt | 12 +++++++ libraries/wellknown/impl/build.gradle.kts | 2 ++ .../impl/DefaultElementWellKnownParser.kt | 27 ++++++++++++++++ .../impl/DefaultSessionWellknownRetriever.kt | 13 ++++++-- .../wellknown/impl/DefaultWellKnownStore.kt | 6 ++-- .../impl/DefaultWellknownRetriever.kt | 7 ++++ .../DefaultSessionWellknownRetrieverTest.kt | 32 ++++++++++++++++--- .../impl/DefaultWellKnownStoreTest.kt | 4 ++- .../impl/DefaultWellknownRetrieverTest.kt | 25 +++++++++++++++ .../tests/konsist/KonsistPreviewTest.kt | 2 ++ 24 files changed, 192 insertions(+), 13 deletions(-) create mode 100644 features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/ExtraDeveloperOptionsRenderer.kt create mode 100644 features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/NoopExtraDeveloperOptionsRenderer.kt create mode 100644 libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnownParser.kt create mode 100644 libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultElementWellKnownParser.kt diff --git a/enterprise b/enterprise index cca96c4fc2..60de13ffd7 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit cca96c4fc24b6e2fd1ccf9265c8283ac9bf63dc0 +Subproject commit 60de13ffd7dea97fd4fec6fb6af49b5288e67ff2 diff --git a/features/enterprise/api/build.gradle.kts b/features/enterprise/api/build.gradle.kts index 1c541c5080..5e7f81e4b4 100644 --- a/features/enterprise/api/build.gradle.kts +++ b/features/enterprise/api/build.gradle.kts @@ -17,4 +17,5 @@ dependencies { implementation(projects.libraries.compound) implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) + implementation(projects.libraries.wellknown.api) } 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..7b595966d4 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 @@ -11,6 +11,7 @@ package io.element.android.features.enterprise.api import androidx.compose.ui.graphics.Color import io.element.android.compound.colors.SemanticColorsLightDark import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.wellknown.api.ElementWellKnown import kotlinx.coroutines.flow.Flow interface EnterpriseService { @@ -41,6 +42,11 @@ interface EnterpriseService { */ fun getNoisyNotificationChannelId(sessionId: SessionId): String? + /** + * Gets the overridden Element Well-Known data if it has been set, or null if not set. + */ + fun overriddenElementWellKnown(): ElementWellKnown? + companion object { const val ANY_ACCOUNT_PROVIDER = "*" } diff --git a/features/enterprise/impl-foss/build.gradle.kts b/features/enterprise/impl-foss/build.gradle.kts index f0c63f5655..a45c8ae167 100644 --- a/features/enterprise/impl-foss/build.gradle.kts +++ b/features/enterprise/impl-foss/build.gradle.kts @@ -23,6 +23,7 @@ dependencies { api(projects.features.enterprise.api) implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) + implementation(projects.libraries.wellknown.api) testCommonDependencies(libs) testImplementation(projects.libraries.matrix.test) 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..bc2a3f1bf1 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 @@ -15,6 +15,7 @@ import io.element.android.compound.colors.SemanticColorsLightDark import io.element.android.features.enterprise.api.BugReportUrl import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.wellknown.api.ElementWellKnown import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf @@ -45,4 +46,6 @@ class DefaultEnterpriseService : EnterpriseService { } override fun getNoisyNotificationChannelId(sessionId: SessionId): String? = null + + override fun overriddenElementWellKnown(): ElementWellKnown? = null } diff --git a/features/enterprise/test/build.gradle.kts b/features/enterprise/test/build.gradle.kts index c37fc53de3..99dbe733dd 100644 --- a/features/enterprise/test/build.gradle.kts +++ b/features/enterprise/test/build.gradle.kts @@ -18,5 +18,6 @@ dependencies { implementation(projects.libraries.architecture) implementation(projects.libraries.compound) implementation(projects.libraries.matrix.api) + implementation(projects.libraries.wellknown.api) implementation(projects.tests.testutils) } 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..f6379bef30 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 @@ -13,6 +13,7 @@ import io.element.android.compound.colors.SemanticColorsLightDark import io.element.android.features.enterprise.api.BugReportUrl import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.wellknown.api.ElementWellKnown import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.simulateLongTask import kotlinx.coroutines.flow.Flow @@ -31,6 +32,7 @@ class FakeEnterpriseService( private val unifiedPushDefaultPushGatewayResult: () -> String? = { lambdaError() }, private val getNoisyNotificationChannelIdResult: (SessionId?) -> String? = { lambdaError() }, private val tweakMasUrlResult: (String, String) -> String = { _, _ -> lambdaError() }, + private val overrideWellKnownResult: () -> ElementWellKnown? = { lambdaError() }, ) : EnterpriseService { private val brandColorState = MutableStateFlow(initialBrandColor) private val semanticColorsState = MutableStateFlow(initialSemanticColors) @@ -79,4 +81,8 @@ class FakeEnterpriseService( override fun getNoisyNotificationChannelId(sessionId: SessionId): String? { return getNoisyNotificationChannelIdResult(sessionId) } + + override fun overriddenElementWellKnown(): ElementWellKnown? { + return overrideWellKnownResult() + } } diff --git a/features/preferences/api/build.gradle.kts b/features/preferences/api/build.gradle.kts index b5a08b9435..c43259918d 100644 --- a/features/preferences/api/build.gradle.kts +++ b/features/preferences/api/build.gradle.kts @@ -6,7 +6,7 @@ * Please see LICENSE files in the repository root for full details. */ plugins { - id("io.element.android-library") + id("io.element.android-compose-library") id("kotlin-parcelize") } diff --git a/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/ExtraDeveloperOptionsRenderer.kt b/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/ExtraDeveloperOptionsRenderer.kt new file mode 100644 index 0000000000..7d7eec9d8b --- /dev/null +++ b/features/preferences/api/src/main/kotlin/io/element/android/features/preferences/api/ExtraDeveloperOptionsRenderer.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.api + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +/** + * Component for rendering extra developer options in the preferences screen. + */ +interface ExtraDeveloperOptionsRenderer { + @Composable + fun Render(modifier: Modifier) +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsNode.kt index 98c7d89633..a8a8c63eed 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsNode.kt @@ -18,6 +18,7 @@ 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.features.preferences.api.ExtraDeveloperOptionsRenderer import io.element.android.libraries.architecture.callback import io.element.android.libraries.designsystem.showkase.getBrowserIntent import io.element.android.libraries.di.SessionScope @@ -28,6 +29,7 @@ class DeveloperSettingsNode( @Assisted buildContext: BuildContext, @Assisted plugins: List, private val presenter: DeveloperSettingsPresenter, + private val extraDeveloperOptionsRenderer: ExtraDeveloperOptionsRenderer, ) : Node(buildContext, plugins = plugins) { interface Callback : Plugin { fun navigateToPushHistory() @@ -51,6 +53,7 @@ class DeveloperSettingsNode( onOpenShowkase = ::openShowkase, onPushHistoryClick = callback::navigateToPushHistory, onBackClick = callback::onDone, + extraOptions = { extraDeveloperOptionsRenderer.Render(Modifier) }, ) } } 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 45009d1f71..0e5f4026ef 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 @@ -43,6 +43,7 @@ fun DeveloperSettingsView( onPushHistoryClick: () -> Unit, onBackClick: () -> Unit, modifier: Modifier = Modifier, + extraOptions: @Composable () -> Unit = {}, ) { if (state.showLoader) { ProgressDialog() @@ -97,6 +98,9 @@ fun DeveloperSettingsView( ) } } + + extraOptions() + val cache = state.cacheSize PreferenceCategory(title = "Cache") { ListItem( diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/NoopExtraDeveloperOptionsRenderer.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/NoopExtraDeveloperOptionsRenderer.kt new file mode 100644 index 0000000000..da0540a93f --- /dev/null +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/NoopExtraDeveloperOptionsRenderer.kt @@ -0,0 +1,22 @@ +/* + * 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 + +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.preferences.api.ExtraDeveloperOptionsRenderer + +@ContributesBinding(AppScope::class) +class NoopExtraDeveloperOptionsRenderer : ExtraDeveloperOptionsRenderer { + @Composable + override fun Render(modifier: Modifier) { + // No-op + } +} 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 index ae5e710d4b..89ef240a95 100644 --- 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 @@ -18,6 +18,7 @@ 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.ExtraDeveloperOptionsRenderer import io.element.android.features.preferences.api.PreferencesEntryPoint import io.element.android.libraries.architecture.callback import io.element.android.libraries.designsystem.showkase.getBrowserIntent @@ -28,6 +29,7 @@ class AppDeveloperSettingsNode( @Assisted buildContext: BuildContext, @Assisted plugins: List, private val presenter: AppDeveloperSettingsPresenter, + private val extraDeveloperOptionsRenderer: ExtraDeveloperOptionsRenderer, ) : Node(buildContext, plugins = plugins) { private val callback: PreferencesEntryPoint.DeveloperSettingsCallback = callback() @@ -45,6 +47,7 @@ class AppDeveloperSettingsNode( modifier = modifier, onOpenShowkase = ::openShowkase, onBackClick = callback::onDone, + extraOptions = { extraDeveloperOptionsRenderer.Render(Modifier) }, ) } } 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 index 81e1304e7b..d7d62aa325 100644 --- 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 @@ -24,6 +24,7 @@ fun AppDeveloperSettingsPage( onOpenShowkase: () -> Unit, onBackClick: () -> Unit, modifier: Modifier = Modifier, + extraOptions: @Composable () -> Unit = {}, ) { BackHandler( onBack = onBackClick, @@ -40,6 +41,7 @@ fun AppDeveloperSettingsPage( onOpenShowkase = onOpenShowkase, modifier = Modifier.padding(top = 8.dp) ) + extraOptions() } } diff --git a/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnownParser.kt b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnownParser.kt new file mode 100644 index 0000000000..db0a323a5f --- /dev/null +++ b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnownParser.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.wellknown.api + +fun interface ElementWellKnownParser { + fun parse(json: String): Result +} diff --git a/libraries/wellknown/impl/build.gradle.kts b/libraries/wellknown/impl/build.gradle.kts index 1e2c4d7d61..6e7cc5ef1c 100644 --- a/libraries/wellknown/impl/build.gradle.kts +++ b/libraries/wellknown/impl/build.gradle.kts @@ -34,6 +34,7 @@ dependencies { implementation(projects.libraries.matrix.api) implementation(projects.libraries.network) implementation(projects.libraries.cachestore.api) + implementation(projects.features.enterprise.api) implementation(projects.services.toolbox.api) testCommonDependencies(libs) @@ -41,5 +42,6 @@ dependencies { testImplementation(projects.libraries.cachestore.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.wellknown.test) + testImplementation(projects.features.enterprise.test) testImplementation(projects.services.toolbox.test) } diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultElementWellKnownParser.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultElementWellKnownParser.kt new file mode 100644 index 0000000000..4cf72366e0 --- /dev/null +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultElementWellKnownParser.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.wellknown.impl + +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.androidutils.json.JsonProvider +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.wellknown.api.ElementWellKnown +import io.element.android.libraries.wellknown.api.ElementWellKnownParser + +@ContributesBinding(AppScope::class) +class DefaultElementWellKnownParser( + private val jsonProvider: JsonProvider, +) : ElementWellKnownParser { + override fun parse(json: String): Result { + return runCatchingExceptions { + val decoder = jsonProvider() + decoder.decodeFromString(json).map() + } + } +} 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 3446cdcb65..66654dd228 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 @@ -9,13 +9,14 @@ package io.element.android.libraries.wellknown.impl import dev.zacsweers.metro.ContributesBinding -import io.element.android.libraries.androidutils.json.JsonProvider +import io.element.android.features.enterprise.api.EnterpriseService 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.ElementWellKnownParser import io.element.android.libraries.wellknown.api.ElementWellknownStore import io.element.android.libraries.wellknown.api.SessionWellknownRetriever import io.element.android.libraries.wellknown.api.WellknownRetrieverResult @@ -26,14 +27,20 @@ import timber.log.Timber @ContributesBinding(SessionScope::class) class DefaultSessionWellknownRetriever( private val matrixClient: MatrixClient, - private val json: JsonProvider, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, private val elementWellknownStore: ElementWellknownStore, + private val elementWellKnownParser: ElementWellKnownParser, + private val enterpriseService: EnterpriseService, ) : SessionWellknownRetriever { private val domain by lazy { matrixClient.userIdServerName() } override suspend fun getElementWellKnown(): WellknownRetrieverResult { + val overriddenElementWellKnown = enterpriseService.overriddenElementWellKnown() + if (overriddenElementWellKnown != null) { + return WellknownRetrieverResult.Success(overriddenElementWellKnown) + } + val cacheData = elementWellknownStore.get(domain) return when (cacheData) { is WellknownRetrieverResult.Success -> { @@ -69,7 +76,7 @@ class DefaultSessionWellknownRetriever( .getUrl(url) .mapCatchingExceptions { val data = String(it) - val parsed = json().decodeFromString(data).map() + val parsed = elementWellKnownParser.parse(data).getOrThrow() // Also store in cache, if valid elementWellknownStore.update(domain, data) .onFailure { exception -> diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStore.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStore.kt index c3cfcc5019..50c8caeafc 100644 --- a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStore.kt +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStore.kt @@ -9,11 +9,11 @@ package io.element.android.libraries.wellknown.impl import dev.zacsweers.metro.AppScope 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.runCatchingExceptions import io.element.android.libraries.wellknown.api.ElementWellKnown +import io.element.android.libraries.wellknown.api.ElementWellKnownParser import io.element.android.libraries.wellknown.api.ElementWellknownStore import io.element.android.libraries.wellknown.api.WellknownRetrieverResult import io.element.android.services.toolbox.api.systemclock.SystemClock @@ -21,14 +21,14 @@ import io.element.android.services.toolbox.api.systemclock.SystemClock @ContributesBinding(AppScope::class) class DefaultWellKnownStore( private val cacheStore: CacheStore, - private val json: JsonProvider, + private val elementWellKnownParser: ElementWellKnownParser, private val systemClock: SystemClock, ) : ElementWellknownStore { override suspend fun get(domain: String): WellknownRetrieverResult { return runCatchingExceptions { val cachedData = cacheStore.getData(key(domain)) if (cachedData != null) { - val data = json().decodeFromString(cachedData.value).map() + val data = elementWellKnownParser.parse(cachedData.value).getOrThrow() if (systemClock.epochMillis() > cachedData.updatedAt + CACHE_VALIDITY_MILLIS) { WellknownRetrieverResult.Outdated(data) } else { diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt index a43584d542..10f668cfb0 100644 --- a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetriever.kt @@ -10,6 +10,7 @@ package io.element.android.libraries.wellknown.impl import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding +import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.libraries.androidutils.json.JsonProvider import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.core.uri.ensureProtocol @@ -28,8 +29,14 @@ class DefaultWellknownRetriever( private val retrofitFactory: RetrofitFactory, private val elementWellknownStore: ElementWellknownStore, private val jsonProvider: JsonProvider, + private val enterpriseService: EnterpriseService, ) : WellknownRetriever { override suspend fun getElementWellKnown(baseUrl: String): WellknownRetrieverResult { + val overriddenElementWellKnown = enterpriseService.overriddenElementWellKnown() + if (overriddenElementWellKnown != null) { + return WellknownRetrieverResult.Success(overriddenElementWellKnown) + } + val domain = URL(baseUrl).host return buildWellknownApi(baseUrl) .map { wellknownApi -> 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 6a2a12774b..f54cf919d9 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 @@ -11,15 +11,16 @@ package io.element.android.libraries.wellknown.impl import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.wellknown.test.FakeElementWellknownStore 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.matrix.api.exception.ClientException import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.wellknown.api.CustomRecoveryPassphrase import io.element.android.libraries.wellknown.api.ElementWellKnown +import io.element.android.libraries.wellknown.api.ElementWellKnownParser import io.element.android.libraries.wellknown.api.WellknownRetrieverResult import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder @@ -276,7 +277,7 @@ class DefaultSessionWellknownRetrieverTest { Result.success("{}".toByteArray()) }, cacheStore = cacheStore, - jsonProvider = JsonProvider { error("Failed to parse JSON") } + elementWellKnownParser = { Result.failure(IllegalStateException("Failed to parse JSON")) } ) assertThat(sut.getElementWellKnown()).isInstanceOf(WellknownRetrieverResult.Error::class.java) // Ensure that the cache is deleted after the failure to parse it @@ -320,20 +321,43 @@ class DefaultSessionWellknownRetrieverTest { ) } + @Test + fun `get element wellknown was overridden`() = runTest { + val getLambda = lambdaRecorder> { Result.failure(IllegalStateException("BOOM")) } + val wellKnown = anElementWellKnown() + + val sut = createDefaultSessionWellknownRetriever( + getUrlLambda = getLambda, + enterpriseService = FakeEnterpriseService( + overrideWellKnownResult = { wellKnown } + ) + ) + + // The overridden value is returned + assertThat(sut.getElementWellKnown()).isEqualTo( + WellknownRetrieverResult.Success(wellKnown) + ) + + // And the endpoint is never hit + getLambda.assertions().isNeverCalled() + } + private fun parsedWellKnownContent() = DefaultJsonProvider().invoke().decodeFromString(WELLKNOWN_CONTENT).map() private fun TestScope.createDefaultSessionWellknownRetriever( cacheStore: FakeElementWellknownStore = FakeElementWellknownStore(), getUrlLambda: (String) -> Result, - jsonProvider: JsonProvider = DefaultJsonProvider(), + elementWellKnownParser: ElementWellKnownParser = DefaultElementWellKnownParser(DefaultJsonProvider()), + enterpriseService: FakeEnterpriseService = FakeEnterpriseService(overrideWellKnownResult = { null }), ) = DefaultSessionWellknownRetriever( matrixClient = FakeMatrixClient( userIdServerNameLambda = { "user.domain.org" }, getUrlLambda = getUrlLambda, ), - json = jsonProvider, sessionCoroutineScope = backgroundScope, elementWellknownStore = cacheStore, + elementWellKnownParser = elementWellKnownParser, + enterpriseService = enterpriseService, ) companion object { diff --git a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStoreTest.kt b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStoreTest.kt index 11ec521fed..b53041faf8 100644 --- a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStoreTest.kt +++ b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellKnownStoreTest.kt @@ -13,6 +13,7 @@ import io.element.android.libraries.androidutils.json.DefaultJsonProvider import io.element.android.libraries.cachestore.api.CacheData import io.element.android.libraries.sessionstorage.test.InMemoryCacheStore import io.element.android.libraries.wellknown.api.CustomRecoveryPassphrase +import io.element.android.libraries.wellknown.api.ElementWellKnownParser import io.element.android.libraries.wellknown.api.WellknownRetrieverResult import io.element.android.services.toolbox.test.systemclock.A_FAKE_TIMESTAMP import io.element.android.services.toolbox.test.systemclock.FakeSystemClock @@ -150,9 +151,10 @@ class DefaultWellKnownStoreTest { private fun createDefaultWellKnownStore( cacheStore: InMemoryCacheStore = InMemoryCacheStore(), systemClock: FakeSystemClock = FakeSystemClock(), + elementWellKnownParser: ElementWellKnownParser = DefaultElementWellKnownParser(jsonProvider), ) = DefaultWellKnownStore( cacheStore = cacheStore, - json = jsonProvider, systemClock = systemClock, + elementWellKnownParser = elementWellKnownParser, ) } diff --git a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt index 3ee5b2b91f..96ae4c2b17 100644 --- a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt +++ b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultWellknownRetrieverTest.kt @@ -11,6 +11,7 @@ package io.element.android.libraries.wellknown.impl import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.wellknown.test.FakeElementWellknownStore import io.element.android.features.wellknown.test.anElementWellKnown import io.element.android.libraries.androidutils.json.DefaultJsonProvider @@ -19,6 +20,7 @@ import io.element.android.libraries.network.RetrofitFactory import io.element.android.libraries.wellknown.api.CustomRecoveryPassphrase import io.element.android.libraries.wellknown.api.ElementWellKnown import io.element.android.libraries.wellknown.api.WellknownRetrieverResult +import io.element.android.tests.testutils.lambda.lambdaRecorder import io.mockk.every import io.mockk.mockk import io.mockk.verify @@ -236,6 +238,27 @@ class DefaultWellknownRetrieverTest { assertThat(cacheStore.get(WELLKNOWN_URL)).isEqualTo(WellknownRetrieverResult.NotFound) } + @Test + fun `get element wellknown was overridden`() = runTest { + val getLambda = lambdaRecorder { mockCall() } + val wellKnown = anElementWellKnown() + + val sut = createDefaultWellknownRetriever( + callFactory = getLambda, + enterpriseService = FakeEnterpriseService( + overrideWellKnownResult = { wellKnown } + ) + ) + + // The overridden value is returned + assertThat(sut.getElementWellKnown(WELLKNOWN_URL)).isEqualTo( + WellknownRetrieverResult.Success(wellKnown) + ) + + // And the endpoint is never hit + getLambda.assertions().isNeverCalled() + } + private fun defaultResponse( body: String = WELLKNOWN_CONTENT, status: Int = 200, @@ -251,6 +274,7 @@ class DefaultWellknownRetrieverTest { callFactory: Call.Factory = Call.Factory { _: Request -> mockCall(defaultResponse()) }, cacheStore: FakeElementWellknownStore = FakeElementWellknownStore(), jsonProvider: JsonProvider = DefaultJsonProvider(), + enterpriseService: FakeEnterpriseService = FakeEnterpriseService(overrideWellKnownResult = { null }), ) = DefaultWellknownRetriever( retrofitFactory = RetrofitFactory( callFactory = { callFactory }, @@ -258,6 +282,7 @@ class DefaultWellknownRetrieverTest { ), jsonProvider = jsonProvider, elementWellknownStore = cacheStore, + enterpriseService = enterpriseService, ) companion object { 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 97def07130..914941d766 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 @@ -88,6 +88,8 @@ class KonsistPreviewTest { "BackgroundVerticalGradientPreview", "ColorAliasesPreview", "EmojiItemWithPopupPreview", + "EnterpriseExtraDeveloperOptionsRendererBottomSheetPreview", + "EnterpriseExtraDeveloperOptionsRendererListItemPreview", "FocusedEventPreview", "GradientFloatingActionButtonCircleShapePreview", "HeaderFooterPageScrollablePreview", From 5ddb56572ad570db6c7a24ac6f23961c6b2722b6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 08:20:43 +0000 Subject: [PATCH 155/383] Update dependencyAnalysis to v3.16.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 cdc77980a6..82579cff58 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.16.0" +dependencyAnalysis = "3.16.1" # DI metro = "1.3.0" From 5fc212fa26eb830fcaecff2ee793610b639304e3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 08:20:52 +0000 Subject: [PATCH 156/383] Update metro to v1.3.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 cdc77980a6..757d015b98 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -54,7 +54,7 @@ haze = "1.7.2" dependencyAnalysis = "3.16.0" # DI -metro = "1.3.0" +metro = "1.3.2" # Auto service autoservice = "1.1.1" From eddac3eaaa5dcf2ef0016a5aac0203ad3b9c7d3e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 08:21:05 +0000 Subject: [PATCH 157/383] Update actions/setup-java action to v5.5.0 --- .github/workflows/build.yml | 2 +- .github/workflows/build_enterprise.yml | 2 +- .github/workflows/generate_github_pages.yml | 2 +- .github/workflows/gradle-wrapper-update.yml | 2 +- .github/workflows/maestro-local.yml | 2 +- .github/workflows/nightly.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 +- 13 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 521eafb3d3..d2f3ca18d1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,7 +51,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/build_enterprise.yml b/.github/workflows/build_enterprise.yml index 861efd7665..3ff2803bf8 100644 --- a/.github/workflows/build_enterprise.yml +++ b/.github/workflows/build_enterprise.yml @@ -56,7 +56,7 @@ jobs: - name: Clone submodules run: git submodule update --init --recursive - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/generate_github_pages.yml b/.github/workflows/generate_github_pages.yml index a9bee5c09d..33fdec38a4 100644 --- a/.github/workflows/generate_github_pages.yml +++ b/.github/workflows/generate_github_pages.yml @@ -19,7 +19,7 @@ jobs: - name: ⏬ Checkout with LFS uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5 - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/gradle-wrapper-update.yml b/.github/workflows/gradle-wrapper-update.yml index f1681c5a76..8db2b5fb6b 100644 --- a/.github/workflows/gradle-wrapper-update.yml +++ b/.github/workflows/gradle-wrapper-update.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 name: Use JDK 21 with: distribution: 'temurin' # See 'Supported distributions' for available options diff --git a/.github/workflows/maestro-local.yml b/.github/workflows/maestro-local.yml index a3f08728e5..99a64da5f2 100644 --- a/.github/workflows/maestro-local.yml +++ b/.github/workflows/maestro-local.yml @@ -44,7 +44,7 @@ jobs: # https://github.com/actions/checkout/issues/881 ref: ${{ github.ref }} persist-credentials: false - - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 name: Use JDK 21 with: distribution: 'temurin' # See 'Supported distributions' for available options diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index f9c960fa8d..c32b277f5c 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -36,7 +36,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml index e3e1ad6d72..ff2b74a753 100644 --- a/.github/workflows/nightlyReports.yml +++ b/.github/workflows/nightlyReports.yml @@ -37,7 +37,7 @@ jobs: uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5 - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -80,7 +80,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 8aac9e5794..14dc493029 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -69,7 +69,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -108,7 +108,7 @@ jobs: 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@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -149,7 +149,7 @@ jobs: 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@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -183,7 +183,7 @@ jobs: 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@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -228,7 +228,7 @@ jobs: 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@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -269,7 +269,7 @@ jobs: 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@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/recordScreenshots.yml b/.github/workflows/recordScreenshots.yml index 6edb0492e4..273eac3c34 100644 --- a/.github/workflows/recordScreenshots.yml +++ b/.github/workflows/recordScreenshots.yml @@ -54,7 +54,7 @@ jobs: with: persist-credentials: false - name: ☕️ Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5d59c9530b..e6b83a1fc3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,7 +38,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -82,7 +82,7 @@ jobs: - name: Clone submodules run: git submodule update --init --recursive - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -126,7 +126,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index ac9a69c0e8..db1cf2ecfb 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -45,7 +45,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml index 6bd5c84283..bb8ead3aa3 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -17,7 +17,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5f646cacf7..6edb31ce4f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -63,7 +63,7 @@ jobs: 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@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 + uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' From fbffcb5c68a8722926ca2dc84c243c9fda34284f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:04:41 +0000 Subject: [PATCH 158/383] Update roborazzi to v1.68.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 82579cff58..7a3c284fa6 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.67.0" +roborazzi = "1.68.0" # Jetbrain datetime = "0.8.0" From 5a7c5e6fe78326b3ec487cc7bdd2176b53da0676 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 11:20:35 +0200 Subject: [PATCH 159/383] Update dependency io.element.android:element-call-embedded to v0.22.0 (#7161) 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 82579cff58..73dbcf496a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -242,7 +242,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.3" +element_call_embedded = "io.element.android:element-call-embedded:0.22.0" # Auto services google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" } From 82679012609a6337861820d81ced33688ce29e0c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:42:51 +0000 Subject: [PATCH 160/383] Update kotlin to v2.4.10 (#7244) 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 73dbcf496a..049fb9e0a5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,7 @@ # Project android_gradle_plugin = "9.2.1" # When updating this, please also update the version in the file ./idea/kotlinc.xml -kotlin = "2.4.0" +kotlin = "2.4.10" kotlinpoet = "2.3.0" ksp = "2.3.10" firebaseAppDistribution = "5.3.0" From 05917bd65fae39958486186e32c113f5e3534693 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 22 Jul 2026 13:36:21 +0200 Subject: [PATCH 161/383] Fix padding for captions of media in 'not found' state (#7247) * Fix padding for captions of media in 'not found' state * Update screenshots --------- Co-authored-by: ElementBot --- .../TimelineItemContentScannerPreviews.kt | 16 ++++++++++++++++ .../event/TimelineItemEventContentView.kt | 2 +- .../android/tests/konsist/KonsistPreviewTest.kt | 1 + ...ustomreaction_EmojiItemWithPopup_Day_0_en.png | 4 ++-- ...tomreaction_EmojiItemWithPopup_Night_0_en.png | 4 ++-- ...ents.event_ATimelineItemEventRow_Day_0_en.png | 4 ++-- ...ts.event_ATimelineItemEventRow_Night_0_en.png | 4 ++-- ...imelineItemEventRowDisambiguated_Day_0_en.png | 4 ++-- ...elineItemEventRowDisambiguated_Night_0_en.png | 4 ++-- ...ItemEventRowWithReplyInformative_Day_0_en.png | 4 ++-- ...ItemEventRowWithReplyInformative_Day_1_en.png | 4 ++-- ...emEventRowWithReplyInformative_Night_0_en.png | 4 ++-- ...emEventRowWithReplyInformative_Night_1_en.png | 4 ++-- ...melineItemEventRowWithReplyOther_Day_0_en.png | 4 ++-- ...melineItemEventRowWithReplyOther_Day_1_en.png | 4 ++-- ...lineItemEventRowWithReplyOther_Night_0_en.png | 4 ++-- ...lineItemEventRowWithReplyOther_Night_1_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReply_Day_0_en.png | 4 ++-- ...s_TimelineItemEventRowWithReply_Day_10_en.png | 4 ++-- ...s_TimelineItemEventRowWithReply_Day_11_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReply_Day_1_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReply_Day_2_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReply_Day_3_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReply_Day_4_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReply_Day_5_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReply_Day_6_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReply_Day_7_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReply_Day_8_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReply_Day_9_en.png | 4 ++-- ..._TimelineItemEventRowWithReply_Night_0_en.png | 4 ++-- ...TimelineItemEventRowWithReply_Night_10_en.png | 4 ++-- ...TimelineItemEventRowWithReply_Night_11_en.png | 4 ++-- ..._TimelineItemEventRowWithReply_Night_1_en.png | 4 ++-- ..._TimelineItemEventRowWithReply_Night_2_en.png | 4 ++-- ..._TimelineItemEventRowWithReply_Night_3_en.png | 4 ++-- ..._TimelineItemEventRowWithReply_Night_4_en.png | 4 ++-- ..._TimelineItemEventRowWithReply_Night_5_en.png | 4 ++-- ..._TimelineItemEventRowWithReply_Night_6_en.png | 4 ++-- ..._TimelineItemEventRowWithReply_Night_7_en.png | 4 ++-- ..._TimelineItemEventRowWithReply_Night_8_en.png | 4 ++-- ..._TimelineItemEventRowWithReply_Night_9_en.png | 4 ++-- ...elineItemScanningContentNotFound_Day_0_en.png | 3 +++ ...ineItemScanningContentNotFound_Night_0_en.png | 3 +++ ...pl.blockedusers_BlockedUsersView_Day_4_en.png | 4 ++-- ...pl.blockedusers_BlockedUsersView_Day_5_en.png | 4 ++-- ....blockedusers_BlockedUsersView_Night_4_en.png | 4 ++-- ....blockedusers_BlockedUsersView_Night_5_en.png | 4 ++-- ...s.impl.userstatus_UserStatusView_Day_5_en.png | 4 ++-- ...s.impl.userstatus_UserStatusView_Day_6_en.png | 4 ++-- ...impl.userstatus_UserStatusView_Night_5_en.png | 4 ++-- ...impl.userstatus_UserStatusView_Night_6_en.png | 4 ++-- ...on.impl_RoomMemberModerationView_Day_5_en.png | 4 ++-- ...on.impl_RoomMemberModerationView_Day_7_en.png | 4 ++-- ....impl_RoomMemberModerationView_Night_5_en.png | 4 ++-- ....impl_RoomMemberModerationView_Night_7_en.png | 4 ++-- ...s_HorizontalFloatingToolbarNoFab_Day_0_en.png | 4 ++-- ...HorizontalFloatingToolbarNoFab_Night_0_en.png | 4 ++-- ...onents_HorizontalFloatingToolbar_Day_0_en.png | 4 ++-- ...ents_HorizontalFloatingToolbar_Night_0_en.png | 4 ++-- 59 files changed, 132 insertions(+), 109 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Night_0_en.png diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemContentScannerPreviews.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemContentScannerPreviews.kt index 5c5414646d..a59a1c0ae0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemContentScannerPreviews.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemContentScannerPreviews.kt @@ -147,6 +147,22 @@ internal fun TimelineItemScanningContentFailedPreview() = ElementPreview { } } +@PreviewsDayNight +@Composable +internal fun TimelineItemScanningContentNotFoundPreview() = ElementPreview { + val cache = remember { + InMemoryEventContentValidationCache(initial = mapOf( + AN_EVENT_ID to NoopContentValidationState(ContentValidationValue.UnrecoverableError(IllegalStateException("Not found"))) + )) + } + CompositionLocalProvider(LocalEventContentValidationState provides cache) { + Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { + ATimelineItemEventRow(event = aTimelineItemEvent(eventId = AN_EVENT_ID, content = aTimelineItemImageContent())) + ATimelineItemEventRow(event = aTimelineItemEvent(eventId = AN_EVENT_ID, content = aTimelineItemImageContent(caption = "A caption"))) + } + } +} + @PreviewsDayNight @Composable internal fun TimelineItemScanningContentWithInvalidRepliesPreview() = ElementPreview { 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 c622a3044a..4b7ab9372d 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 @@ -232,7 +232,7 @@ fun TimelineItemEventContentView( } if (showCaption) { - val padding = if (displayInvalidContent) { + val padding = if (displayInvalidContent || displayContentNotFound) { PaddingValues(start = 12.dp, end = 12.dp, top = 4.dp, bottom = 0.dp) } else { when (content) { 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 914941d766..deaa903e25 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 @@ -166,6 +166,7 @@ class KonsistPreviewTest { "TimelineItemImageViewScanningContentPreview", "TimelineItemRedactedMessagesGroupPreview", "TimelineItemScanningContentFailedPreview", + "TimelineItemScanningContentNotFoundPreview", "TimelineItemScanningContentWithInvalidRepliesPreview", "TimelineItemScanningContentWithRepliesFailedPreview", "TimelineItemStickerViewScanningContentPreview", diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png index a2b35f18ca..912b90b537 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c5572491b675a16724cd9e33ebb477c82edf285fa07d57ebef09c670fcaaddf1 -size 21285 +oid sha256:4746d11c30648f7c517b0880021e5a1dc6ed2819af6c800b081b0d842ac2c384 +size 5325 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png index 9c425cec6e..45011fea4d 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:290a2be6838445739b0181006f9fea87337a85cfed3573c153e9f503c66624a6 -size 4994 +oid sha256:eede6f990a7a1dbddee1cd9e722b30600160d475ad2ae72faebcb773f52aaa7b +size 20793 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 index 12bd190dd1..0ab00359b7 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce15ca9f89274620728715e3448ce671e2253f4fed22a44035460e9a3709ca0b -size 647404 +oid sha256:7b5e6f4c5ec97e67bb20f03f25f18d9f32d5d1aed5ff30d161b331894ad03443 +size 647384 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 index 0ccdcbb603..160d58f9ec 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0424685437a433b35b589668b409d55f26ab41bcae01af0121a54033c56a8c2 -size 646194 +oid sha256:c4e7b28b78cfbcbb6abf00317eea945859ac6465cecf81a3ad15801b0de721e4 +size 646216 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 0435f55de6..ab6392a424 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:ff839731834d7d0c94fa9a2c412014ddbaeaa053c5af1c8cbd00a3f3a583f364 -size 379511 +oid sha256:94f89a37549a3f198442db467bc7d8539f0b5649d97927bfe731f090d6dfb03d +size 379505 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 f0b5506b89..9cbd5c1d95 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:04ea6c2947a21d3d4a3d43e9c4750c4f2a49056536a4da3f34c95df8353e9de3 -size 377990 +oid sha256:d0e170b4bea262de612bf3374d475fcd25470ff91b7554d20809c51857a78cec +size 377963 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 1f0fdabe6d..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:b8bb5a6de6601da8d7fe59f110a054577e2e25dae4bb449f60c04e7d7a1b9551 -size 365073 +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 195aa04fe2..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:76e5ae44362792d570cd82f3910c8bd0acde509b8418c5892e0385e7d636f042 -size 370223 +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 058a3992c3..29771235f0 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:00fe1e676086766a3eac3e4457eff52c989789fc5d8d0df2624c019ed25ce9af -size 363322 +oid sha256:60b9f2b920cd2a2a414805d1f0f77925232d9ae60bd607fa18d4395cda2dd73d +size 363291 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 db4ea8296a..c6d4541184 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:2f0d24b8011564ee7a8b2f8c2e6a24eda668ee42d451d862f884acb7926aa06c -size 368529 +oid sha256:c00e504593d8eb61b598f05f46ee4d591757975a80c0b4227b240847d2cd4868 +size 368510 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 84d9d4e5c3..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:7c609a633ab23eae5729ecb57a17a385bac65e81cbf0180c01e0847f1028039e -size 347890 +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 73b7e674e2..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:991deacdfb7bc371a2df960a2364ae3b2187e588aa5afe7f39409e367040dd9c -size 363893 +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 bac23aab98..22ff4965d1 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:e30686c7c037ef102717e0316543faf4d3ed2671c21eca96a667150daab380d6 -size 346614 +oid sha256:787151f8f242a8794a804bf14831f6ca680814d617e85feb3652103e8a0f20cd +size 346565 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 b6e4650d9d..4e17de6908 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:2cd357a1fbaa425eca95587bff2f768a45e773f983f75664875653ba1900e534 -size 361625 +oid sha256:c1e15400fa2c5ee6087316501445c551a3932b65e16de31e68acc5efbd16a559 +size 361603 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 01d4dca84b..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:ef2bf449671b652cb152b3baab92ab100eab77a54229ab49daeab156f2f484d0 -size 369724 +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 f0dfbc3321..1600afff71 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:f7a6302320bd1e4258e03487539bf46b0b12781dfc8a22b3f9f267017a6146fa -size 354751 +oid sha256:273351cc9c533b2424859a0de00a8a3786628abc3a88175705c4205dedf7e9aa +size 354737 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 c4943b892c..e38cf03ad6 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:4c410e853089cc2c4a2c48a00dd9a8babc8095aed72bb4625057444710559c6c -size 368129 +oid sha256:41a0e404dea7f52359b24b3ec3926b1405429b165cfed44c63b3922ea6d3cb46 +size 368114 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 b5dac8434c..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:1a92f8af94682facac66d4aacb6e49f345561c15be2f8b689041b78aeaaae831 -size 345062 +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 8aa2cca147..1b99468924 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:02ecb903124273e24151ea2088f6b99144f7dcadba00a582b6210dd23835b5c9 -size 357743 +oid sha256:3a9509411777f342261cab58b92a022b3c9f8f0f7a9e4d0527120a91976575f0 +size 357733 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 cececc229a..b5032c29b3 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:f0c6dafaa41849af00d5097a85bd88e3a054a0a9e41c0466a08e6ff8dd6102b2 -size 356857 +oid sha256:dce23463c335d01eb67293cfcede5d85e96ab2ba035cc9a188d42e8e6866bc63 +size 356831 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 a332744358..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:588967869cbd25ed8b82aff5618175660a8a9e45a5a861b1c7867cf1913f575b -size 364646 +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 d7b969fd5b..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:2528df873713755f542f61cd794080929586c1bd5f316c0378ce9e837c21d50b -size 397145 +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 0041a870b9..63bd9c3f6d 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:a2bd77c08be705c66225f16c29fd6826decd92b41922d0f8ffc0d1a63d8c59d2 -size 356193 +oid sha256:a6cd94664f89bdad2a9761ea8b20acb83fed3ed7cb5be41af8fe4852643c0bfc +size 356175 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 9fcf389708..f67906a37c 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:9daeee1aaa04247da3c8bb5aaae9947aab1ed2d2057995e53d6ebdb63e5cd356 -size 355848 +oid sha256:ffa68c8398d789444151855496e5df4ffa03218a383db6ea46fd4f979829b823 +size 355831 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 6e83d6491d..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:34152c742abc486a48234e22101833bc163cf11979890d06aac41e68e3c404d0 -size 364846 +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 0021619c44..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:7b23d3a37774283067a8919b8c332b1bb5a79e90dceb7216b484b985491282e5 -size 355389 +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 77abe20982..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:5c3d87862c6d7fc88d0f23cd54c5b9f77028992fdd7c282a195b964dd17e85ac -size 367855 +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 1d34761a9b..448bcec677 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:f7d9b5fc0ff5d7828ad6f4dc0c9bd9520b4920553da97ed7b4e030ee844c0208 -size 353054 +oid sha256:fe0daf9161bc2da194992a2fc9505bf2009c5dbed78cdb35d2eb7ed1380a7df5 +size 353037 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 c081fa16a5..5243218ae3 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:6a92bcf5885322e11a706071969fb674b1f6e60e021af153aaa125baa4a602ae -size 366285 +oid sha256:9a85db2f5958db867578663533f204b2e803372d470da890fd8056ffed0cf46c +size 366254 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 47a9a6b630..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:54372845e922d047408dd960d048b9b5eae2263d589117d8e7d197741aa34f32 -size 342827 +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 ceca184bd7..5560c21967 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:8e82011a72f36889c53ab61ed2b9947c7fb5f868c9b7010904fc10f4ca587082 -size 356082 +oid sha256:af4a48ee80535f2c0a226c4ffa4344054fb63b7b0a88ea2c030a4eb8dd5e9644 +size 356078 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 5cc5cfe4fc..5cdad1df92 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:6524cc87257cc9d3f135904f4e14594b56df695e71fe576418d2319c472d710b -size 355285 +oid sha256:9e2d8caf5aaae7d3406c703288e491f328552f0acd18e56afd5265b4ceaf1cd1 +size 355272 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 a431a9429a..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:93c2df04d65f6078ce3f7067fbae8a7317ec42ed0fc013dee962a3953269f3b7 -size 362813 +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 b51a89586b..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:e642229c58169775fe702769a306bbef22698516ae6f7ac75a761213c3f195fa -size 395446 +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 ae8495618a..aa322fc2e4 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:08057fdc1e1184720b438ddd2a8753f00791baf2456cc30b45de8e6bdeb57e8e -size 354404 +oid sha256:5fae87094ea13b14e2dc7c16ca96e4f8096ff39e962799468fb4ead4c666620f +size 354381 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 40105c1498..9d617f6688 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:5ed24d190f10c079f8cf176404372d40eb25cc78ce595a22febc540315057b86 -size 354075 +oid sha256:dabad9dcd5b8f0d4bb964a0187ad7c94b023b04552dacd29a077daddfd48d550 +size 354052 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 1a8ea3e4e9..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:66aba7b4271a990fac85b0bbc7cbdc371fa1e38a4da5bb4e2f62a80b21cb3a8f -size 363012 +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 c9227ebf94..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:e614f4a8657637c584a283d69124236d00fe1251c2b8d739c5688a57a6fd152e -size 353693 +oid sha256:756f0cff90ddd61adce2f467c0384d74d430f6d51c091e4980e45bcc9ee6f0fd +size 353705 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Day_0_en.png new file mode 100644 index 0000000000..3c30442331 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d082ac0333068f5da70cf40d310d321e6304999ddb6288b680350cfc3a7f40c0 +size 31006 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Night_0_en.png new file mode 100644 index 0000000000..688fa2736b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f275ffe26e055fd8f912b7234eae39dfb9f597e23c408dcb58e46d164ce391e9 +size 31959 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png index 7cca911c45..074820e157 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26e14b77fa3c3aeaea58782309e6de8b9047e07945009322990ebf5f4c283309 -size 52770 +oid sha256:7caacb336793b8ae4b83e9a10a82325e25e8b3c036f881898ed28688250eb6e0 +size 55744 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png index 7cca911c45..2af459c158 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26e14b77fa3c3aeaea58782309e6de8b9047e07945009322990ebf5f4c283309 -size 52770 +oid sha256:28a95d4b7ebca92c4e0467f3ecd9acdaf7f6257604d190f5d088a9a25e87d637 +size 55305 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png index a68f886f73..616c06bf46 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5a2e306087a967849f61872b56a83f194d1a76df5723f0bbae6e6e2f4a98c63 -size 55725 +oid sha256:0ce2519906f1aaf34700ca9ba4bdeaa72030f1f5aff3f7e24352a1435ac67d98 +size 53966 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png index 616c06bf46..36d19c6b72 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ce2519906f1aaf34700ca9ba4bdeaa72030f1f5aff3f7e24352a1435ac67d98 -size 53966 +oid sha256:7dfa2767c55a81d3f121b8fa55443b7b05f9369e91639b80e0be349863799ad7 +size 55438 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png index 270dbe6d1e..7ef9b7ae0a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:195338046951366fd2345fdc8471e3e2b2786723c8bfffa9fa9057929c608afb -size 12113 +oid sha256:d19e7a09114e76294a0626e5d617cf55fe7c13a0188a7d5b364f57c0d9daedc1 +size 12123 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png index 0ca6f66438..f831ed92a2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5896eb5df6f5398bdb94e74280d0d5c04b6a5a53c2378b7377c60fa58eef544b -size 12013 +oid sha256:7fe1f51d385bba8821dfc0f0da84990cf0d148e991d765484b343d8764abd47d +size 11724 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index fb72cafe03..1e04c3e7d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ef1b643a16b5a94c75f8bb845c36d3cbc7f7ed96a0cac32fdb9f0b09d26b4d1 -size 11747 +oid sha256:6bbc8c05e6f6818d00282228f52424ebe93e6e3dca3431d742e8c652d56460d6 +size 11712 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png index ce1258d2ac..8e1b9c99d2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce754ce205fd864e01828659aff42ab19dccf7c921c1c733ed1757f1b2122309 -size 11403 +oid sha256:66f6d0d6b03ee4c999cd4edc9c6ae567d31b8b537ca6f9cc8fbe436d06ce80ab +size 11643 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png index 5c597300e4..73b8b8e50c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 -size 3853 +oid sha256:e8a3ad99763929d2783147814e44fa9ec7e7efb7b99949e3580f23c38fb5d971 +size 9398 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png index f8a1f24b34..5c597300e4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1342b6427f5b2e3075ae3ccee60bf1d3b11afaccf3e152643d6ef2d65c21b54e -size 9108 +oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 +size 3853 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png index 4ae7279fe7..d47bf90664 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:410a8596d4c70b9a3856d959d6d71ade8e831e8581ff410c9900957a93b3eb50 -size 8114 +oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c +size 3664 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png index d47bf90664..a87d89c701 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c -size 3664 +oid sha256:0f3a0cb5d9bae6725a1c527f3d9575aabf85d3edf63a28d9faa23f4f0b65e2d0 +size 7624 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png index 58546b8522..ee5c582240 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30357bf18792db5ab20085010251170a724ffe8c00313facd04ee704e806af64 -size 10982 +oid sha256:75de341f705bb22955f9399180519b65ad59c2e1917317d56e50ea4db78f35bc +size 12102 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png index 52fd9b9693..fedead0fa8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58b9491aaa5554b89d86c62a5c9c44975367538c6baa5562f8dc5768f76d8264 -size 8705 +oid sha256:4811667dec0f32accc5e2c8a5dd5c0b34017fcff8d1e0376ee7a4708426bca0f +size 9838 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png index 83302d6ba4..38ad0e4b56 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:16dee1dfe746cd40dac9fe8f0af3ecb42cd14bab5cc490917b589beed065ed1b -size 14686 +oid sha256:326d59cf768b2dbd96eb7964d54c8eda509a5cd57c6e62087625e3314da0bb4d +size 13658 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png index 687e0d436a..4da2a98aca 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d57df7110371c9224e232b707d6a1b10ce14afcb56c803a78220792f2a0d4cf2 -size 11354 +oid sha256:ef0dc4d53daeb986f378b6e4d85928b4b6729336c89cf21e642c88c53688a3ab +size 10292 From e492f0638667f1f1a4af573fef442e161dbbc77a Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 17 Jul 2026 22:09:01 +0200 Subject: [PATCH 162/383] Migrate libraries/recentemojis into libraries/emoji --- .../io/element/android/x/di/AppModule.kt | 10 ++----- features/messages/impl/build.gradle.kts | 5 ++-- .../messages/impl/MessagesPresenter.kt | 2 +- .../impl/actionlist/ActionListPresenter.kt | 2 +- .../customreaction/CustomReactionPresenter.kt | 4 +-- .../messages/impl/MessagesPresenterTest.kt | 2 +- .../actionlist/ActionListPresenterTest.kt | 2 +- .../CustomReactionPresenterTest.kt | 2 +- .../api/build.gradle.kts | 7 ++--- .../libraries/emoji}/api/EmojibaseProvider.kt | 2 +- .../emoji/api/recentemojis}/AddRecentEmoji.kt | 2 +- .../api/recentemojis}/GetRecentEmojis.kt | 2 +- .../impl/build.gradle.kts | 28 +++++++++++-------- .../emoji}/impl/DefaultEmojibaseProvider.kt | 12 ++++++-- .../recentemojis}/DefaultAddRecentEmoji.kt | 4 +-- .../recentemojis}/DefaultGetRecentEmojis.kt | 6 ++-- .../DefaultGetRecentEmojisTest.kt | 4 +-- .../test/build.gradle.kts | 9 +++--- .../emoji}/test/FakeEmojibaseProvider.kt | 4 +-- .../kotlin/extension/DependencyHandleScope.kt | 2 +- 20 files changed, 57 insertions(+), 54 deletions(-) rename libraries/{recentemojis => emoji}/api/build.gradle.kts (69%) rename libraries/{recentemojis/api/src/main/kotlin/io/element/android/libraries/recentemojis => emoji/api/src/main/kotlin/io/element/android/libraries/emoji}/api/EmojibaseProvider.kt (87%) rename libraries/{recentemojis/api/src/main/kotlin/io/element/android/libraries/recentemojis/api => emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/recentemojis}/AddRecentEmoji.kt (84%) rename libraries/{recentemojis/api/src/main/kotlin/io/element/android/libraries/recentemojis/api => emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/recentemojis}/GetRecentEmojis.kt (88%) rename libraries/{recentemojis => emoji}/impl/build.gradle.kts (51%) rename libraries/{recentemojis/impl/src/main/kotlin/io/element/android/libraries/recentemojis => emoji/impl/src/main/kotlin/io/element/android/libraries/emoji}/impl/DefaultEmojibaseProvider.kt (52%) rename libraries/{recentemojis/impl/src/main/kotlin/io/element/android/libraries/recentemojis/impl => emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/recentemojis}/DefaultAddRecentEmoji.kt (86%) rename libraries/{recentemojis/impl/src/main/kotlin/io/element/android/libraries/recentemojis/impl => emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/recentemojis}/DefaultGetRecentEmojis.kt (87%) rename libraries/{recentemojis/impl/src/test/kotlin/io/element/android/libraries/recentemojis/impl => emoji/impl/src/test/kotlin/io/element/android/libraries/emoji/impl/recentemojis}/DefaultGetRecentEmojisTest.kt (95%) rename libraries/{recentemojis => emoji}/test/build.gradle.kts (70%) rename libraries/{recentemojis/test/src/main/kotlin/io/element/android/libraries/recentemojis => emoji/test/src/main/kotlin/io/element/android/libraries/emoji}/test/FakeEmojibaseProvider.kt (85%) diff --git a/app/src/main/kotlin/io/element/android/x/di/AppModule.kt b/app/src/main/kotlin/io/element/android/x/di/AppModule.kt index 87d0ece7a1..80d68bd17d 100644 --- a/app/src/main/kotlin/io/element/android/x/di/AppModule.kt +++ b/app/src/main/kotlin/io/element/android/x/di/AppModule.kt @@ -28,8 +28,8 @@ import io.element.android.libraries.di.BaseDirectory import io.element.android.libraries.di.CacheDirectory import io.element.android.libraries.di.annotations.AppCoroutineScope import io.element.android.libraries.di.annotations.ApplicationContext -import io.element.android.libraries.recentemojis.api.EmojibaseProvider -import io.element.android.libraries.recentemojis.impl.DefaultEmojibaseProvider +import io.element.android.libraries.emoji.api.EmojibaseProvider +import io.element.android.libraries.emoji.impl.DefaultEmojibaseProvider import io.element.android.x.BuildConfig import io.element.android.x.R import kotlinx.coroutines.CoroutineName @@ -115,10 +115,4 @@ object AppModule { fun provideSnackbarDispatcher(): SnackbarDispatcher { return SnackbarDispatcher() } - - @Provides - @SingleIn(AppScope::class) - fun providesEmojibaseProvider(@ApplicationContext context: Context): EmojibaseProvider { - return DefaultEmojibaseProvider(context) - } } diff --git a/features/messages/impl/build.gradle.kts b/features/messages/impl/build.gradle.kts index 116a3a7c41..b40aebab39 100644 --- a/features/messages/impl/build.gradle.kts +++ b/features/messages/impl/build.gradle.kts @@ -51,7 +51,7 @@ dependencies { implementation(projects.libraries.mediaupload.api) implementation(projects.libraries.permissions.api) implementation(projects.libraries.preferences.api) - implementation(projects.libraries.recentemojis.api) + implementation(projects.libraries.emoji.api) implementation(projects.libraries.roomselect.api) implementation(projects.libraries.slashcommands.api) implementation(projects.libraries.audio.api) @@ -106,6 +106,7 @@ dependencies { testImplementation(projects.libraries.testtags) testImplementation(projects.features.poll.test) testImplementation(projects.libraries.eventformatter.test) - testImplementation(projects.libraries.recentemojis.test) + testImplementation(projects.libraries.emoji.impl) + testImplementation(projects.libraries.emoji.test) testImplementation(projects.libraries.slashcommands.test) } 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 1109b2c70d..17127ff6ec 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 @@ -69,6 +69,7 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatch import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState import io.element.android.libraries.di.annotations.SessionCoroutineScope +import io.element.android.libraries.emoji.api.recentemojis.AddRecentEmoji import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.core.toThreadId @@ -85,7 +86,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransa import io.element.android.libraries.matrix.ui.messages.reply.map import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.room.getDirectRoomMember -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 diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt index f17a841c52..8caa95f31d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenter.kt @@ -44,13 +44,13 @@ 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.di.RoomScope +import io.element.android.libraries.emoji.api.recentemojis.GetRecentEmojis 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.room.BaseRoom import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.preferences.api.store.AppPreferencesStore -import io.element.android.libraries.recentemojis.api.GetRecentEmojis import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt index a1ebb66ea7..1fddf4e3bb 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt @@ -18,8 +18,8 @@ import androidx.compose.runtime.setValue import dev.zacsweers.metro.Inject import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.recentemojis.api.EmojibaseProvider -import io.element.android.libraries.recentemojis.api.GetRecentEmojis +import io.element.android.libraries.emoji.api.EmojibaseProvider +import io.element.android.libraries.emoji.api.recentemojis.GetRecentEmojis import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableSet 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 65aa1d857e..0a0d310b16 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 @@ -52,6 +52,7 @@ import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher +import io.element.android.libraries.emoji.api.recentemojis.AddRecentEmoji 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 @@ -94,7 +95,6 @@ import io.element.android.libraries.matrix.test.room.threads.FakeThreadsListServ 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 -import io.element.android.libraries.recentemojis.api.AddRecentEmoji import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.libraries.textcomposer.model.TextEditorState import io.element.android.libraries.textcomposer.model.aTextEditorStateMarkdown 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 20b636081a..fb597df290 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 @@ -27,6 +27,7 @@ import io.element.android.features.messages.impl.timeline.model.event.aTimelineI import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVoiceContent import io.element.android.features.poll.api.pollcontent.aPollAnswerItemList import io.element.android.libraries.dateformatter.test.FakeDateFormatter +import io.element.android.libraries.emoji.api.recentemojis.GetRecentEmojis 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 @@ -42,7 +43,6 @@ 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.aRoomInfo import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore -import io.element.android.libraries.recentemojis.api.GetRecentEmojis import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.test import kotlinx.collections.immutable.persistentListOf diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt index e3317b3d42..d0765bd5e7 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt @@ -11,8 +11,8 @@ package io.element.android.features.messages.impl.timeline.components.customreac import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineItemReactions +import io.element.android.libraries.emoji.test.FakeEmojibaseProvider import io.element.android.libraries.matrix.test.AN_EVENT_ID -import io.element.android.libraries.recentemojis.test.FakeEmojibaseProvider import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.test import kotlinx.collections.immutable.persistentListOf diff --git a/libraries/recentemojis/api/build.gradle.kts b/libraries/emoji/api/build.gradle.kts similarity index 69% rename from libraries/recentemojis/api/build.gradle.kts rename to libraries/emoji/api/build.gradle.kts index 2fc74c03c7..749e13a4c7 100644 --- a/libraries/recentemojis/api/build.gradle.kts +++ b/libraries/emoji/api/build.gradle.kts @@ -1,17 +1,16 @@ /* - * 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. */ plugins { - id("io.element.android-library") + id("io.element.android-compose-library") } android { - namespace = "io.element.android.libraries.recentemojis.api" + namespace = "io.element.android.libraries.emoji.api" } dependencies { diff --git a/libraries/recentemojis/api/src/main/kotlin/io/element/android/libraries/recentemojis/api/EmojibaseProvider.kt b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/EmojibaseProvider.kt similarity index 87% rename from libraries/recentemojis/api/src/main/kotlin/io/element/android/libraries/recentemojis/api/EmojibaseProvider.kt rename to libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/EmojibaseProvider.kt index 9d6e41eb55..d8f9c92777 100644 --- a/libraries/recentemojis/api/src/main/kotlin/io/element/android/libraries/recentemojis/api/EmojibaseProvider.kt +++ b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/EmojibaseProvider.kt @@ -6,7 +6,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.recentemojis.api +package io.element.android.libraries.emoji.api import io.element.android.emojibasebindings.EmojibaseStore diff --git a/libraries/recentemojis/api/src/main/kotlin/io/element/android/libraries/recentemojis/api/AddRecentEmoji.kt b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/recentemojis/AddRecentEmoji.kt similarity index 84% rename from libraries/recentemojis/api/src/main/kotlin/io/element/android/libraries/recentemojis/api/AddRecentEmoji.kt rename to libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/recentemojis/AddRecentEmoji.kt index 5b50823f77..5865568511 100644 --- a/libraries/recentemojis/api/src/main/kotlin/io/element/android/libraries/recentemojis/api/AddRecentEmoji.kt +++ b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/recentemojis/AddRecentEmoji.kt @@ -6,7 +6,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.recentemojis.api +package io.element.android.libraries.emoji.api.recentemojis fun interface AddRecentEmoji { suspend operator fun invoke(emoji: String): Result diff --git a/libraries/recentemojis/api/src/main/kotlin/io/element/android/libraries/recentemojis/api/GetRecentEmojis.kt b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/recentemojis/GetRecentEmojis.kt similarity index 88% rename from libraries/recentemojis/api/src/main/kotlin/io/element/android/libraries/recentemojis/api/GetRecentEmojis.kt rename to libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/recentemojis/GetRecentEmojis.kt index 6517512f44..9a9983805e 100644 --- a/libraries/recentemojis/api/src/main/kotlin/io/element/android/libraries/recentemojis/api/GetRecentEmojis.kt +++ b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/recentemojis/GetRecentEmojis.kt @@ -6,7 +6,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.recentemojis.api +package io.element.android.libraries.emoji.api.recentemojis import kotlinx.collections.immutable.ImmutableList diff --git a/libraries/recentemojis/impl/build.gradle.kts b/libraries/emoji/impl/build.gradle.kts similarity index 51% rename from libraries/recentemojis/impl/build.gradle.kts rename to libraries/emoji/impl/build.gradle.kts index 061a7ecd89..871c19a41a 100644 --- a/libraries/recentemojis/impl/build.gradle.kts +++ b/libraries/emoji/impl/build.gradle.kts @@ -1,37 +1,41 @@ /* - * 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. */ import extension.setupDependencyInjection +import extension.testCommonDependencies plugins { id("io.element.android-compose-library") - id("kotlin-parcelize") } android { - namespace = "io.element.android.libraries.recentemojis.impl" + namespace = "io.element.android.libraries.emoji.impl" + testOptions { + unitTests { + isIncludeAndroidResources = true + } + } } setupDependencyInjection() dependencies { - api(projects.libraries.recentemojis.api) + api(projects.libraries.emoji.api) implementation(projects.libraries.architecture) + implementation(projects.libraries.core) + implementation(projects.libraries.designsystem) + implementation(projects.libraries.di) implementation(projects.libraries.matrix.api) + implementation(projects.libraries.uiStrings) + implementation(libs.kotlinx.collections.immutable) implementation(libs.matrix.emojibase.bindings) - testImplementation(projects.libraries.recentemojis.test) - testImplementation(libs.test.junit) - testImplementation(libs.coroutines.test) - testImplementation(libs.molecule.runtime) - testImplementation(libs.test.truth) - testImplementation(libs.test.turbine) + testImplementation(projects.libraries.emoji.test) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.tests.testutils) + testCommonDependencies(libs) } diff --git a/libraries/recentemojis/impl/src/main/kotlin/io/element/android/libraries/recentemojis/impl/DefaultEmojibaseProvider.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/DefaultEmojibaseProvider.kt similarity index 52% rename from libraries/recentemojis/impl/src/main/kotlin/io/element/android/libraries/recentemojis/impl/DefaultEmojibaseProvider.kt rename to libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/DefaultEmojibaseProvider.kt index 161dd0cc56..f0ad797648 100644 --- a/libraries/recentemojis/impl/src/main/kotlin/io/element/android/libraries/recentemojis/impl/DefaultEmojibaseProvider.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/DefaultEmojibaseProvider.kt @@ -6,14 +6,20 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.recentemojis.impl +package io.element.android.libraries.emoji.impl import android.content.Context +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.SingleIn import io.element.android.emojibasebindings.EmojibaseDatasource import io.element.android.emojibasebindings.EmojibaseStore -import io.element.android.libraries.recentemojis.api.EmojibaseProvider +import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.android.libraries.emoji.api.EmojibaseProvider -class DefaultEmojibaseProvider(val context: Context) : EmojibaseProvider { +@SingleIn(AppScope::class) +@ContributesBinding(AppScope::class) +class DefaultEmojibaseProvider(@ApplicationContext val context: Context) : EmojibaseProvider { override val emojibaseStore: EmojibaseStore by lazy { EmojibaseDatasource().load(context) } diff --git a/libraries/recentemojis/impl/src/main/kotlin/io/element/android/libraries/recentemojis/impl/DefaultAddRecentEmoji.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultAddRecentEmoji.kt similarity index 86% rename from libraries/recentemojis/impl/src/main/kotlin/io/element/android/libraries/recentemojis/impl/DefaultAddRecentEmoji.kt rename to libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultAddRecentEmoji.kt index 4444d7e01a..cc9da75fd8 100644 --- a/libraries/recentemojis/impl/src/main/kotlin/io/element/android/libraries/recentemojis/impl/DefaultAddRecentEmoji.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultAddRecentEmoji.kt @@ -6,13 +6,13 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.recentemojis.impl +package io.element.android.libraries.emoji.impl.recentemojis import dev.zacsweers.metro.ContributesBinding import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.emoji.api.recentemojis.AddRecentEmoji import io.element.android.libraries.matrix.api.MatrixClient -import io.element.android.libraries.recentemojis.api.AddRecentEmoji import kotlinx.coroutines.withContext @ContributesBinding(SessionScope::class) diff --git a/libraries/recentemojis/impl/src/main/kotlin/io/element/android/libraries/recentemojis/impl/DefaultGetRecentEmojis.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultGetRecentEmojis.kt similarity index 87% rename from libraries/recentemojis/impl/src/main/kotlin/io/element/android/libraries/recentemojis/impl/DefaultGetRecentEmojis.kt rename to libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultGetRecentEmojis.kt index 9c5ed178dd..acd5e012ce 100644 --- a/libraries/recentemojis/impl/src/main/kotlin/io/element/android/libraries/recentemojis/impl/DefaultGetRecentEmojis.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultGetRecentEmojis.kt @@ -6,14 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.recentemojis.impl +package io.element.android.libraries.emoji.impl.recentemojis import dev.zacsweers.metro.ContributesBinding import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.emoji.api.EmojibaseProvider +import io.element.android.libraries.emoji.api.recentemojis.GetRecentEmojis import io.element.android.libraries.matrix.api.MatrixClient -import io.element.android.libraries.recentemojis.api.EmojibaseProvider -import io.element.android.libraries.recentemojis.api.GetRecentEmojis import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.withContext diff --git a/libraries/recentemojis/impl/src/test/kotlin/io/element/android/libraries/recentemojis/impl/DefaultGetRecentEmojisTest.kt b/libraries/emoji/impl/src/test/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultGetRecentEmojisTest.kt similarity index 95% rename from libraries/recentemojis/impl/src/test/kotlin/io/element/android/libraries/recentemojis/impl/DefaultGetRecentEmojisTest.kt rename to libraries/emoji/impl/src/test/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultGetRecentEmojisTest.kt index 722aaee234..2ae8a86c25 100644 --- a/libraries/recentemojis/impl/src/test/kotlin/io/element/android/libraries/recentemojis/impl/DefaultGetRecentEmojisTest.kt +++ b/libraries/emoji/impl/src/test/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultGetRecentEmojisTest.kt @@ -6,14 +6,14 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.recentemojis.impl +package io.element.android.libraries.emoji.impl.recentemojis import com.google.common.truth.Truth.assertThat import io.element.android.emojibasebindings.Emoji import io.element.android.emojibasebindings.EmojibaseCategory import io.element.android.emojibasebindings.EmojibaseCategory.People +import io.element.android.libraries.emoji.test.FakeEmojibaseProvider import io.element.android.libraries.matrix.test.FakeMatrixClient -import io.element.android.libraries.recentemojis.test.FakeEmojibaseProvider import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableMap diff --git a/libraries/recentemojis/test/build.gradle.kts b/libraries/emoji/test/build.gradle.kts similarity index 70% rename from libraries/recentemojis/test/build.gradle.kts rename to libraries/emoji/test/build.gradle.kts index 7c32d162ee..42192c8061 100644 --- a/libraries/recentemojis/test/build.gradle.kts +++ b/libraries/emoji/test/build.gradle.kts @@ -1,6 +1,5 @@ /* - * 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. @@ -11,16 +10,16 @@ plugins { } android { - namespace = "io.element.android.libraries.recentemojis.test" + namespace = "io.element.android.libraries.emoji.test" } dependencies { + api(projects.libraries.emoji.api) api(projects.libraries.matrix.api) api(libs.coroutines.core) implementation(libs.kotlinx.collections.immutable) implementation(libs.coroutines.test) - implementation(projects.tests.testutils) - implementation(projects.libraries.recentemojis.api) implementation(libs.matrix.emojibase.bindings) + implementation(projects.tests.testutils) } diff --git a/libraries/recentemojis/test/src/main/kotlin/io/element/android/libraries/recentemojis/test/FakeEmojibaseProvider.kt b/libraries/emoji/test/src/main/kotlin/io/element/android/libraries/emoji/test/FakeEmojibaseProvider.kt similarity index 85% rename from libraries/recentemojis/test/src/main/kotlin/io/element/android/libraries/recentemojis/test/FakeEmojibaseProvider.kt rename to libraries/emoji/test/src/main/kotlin/io/element/android/libraries/emoji/test/FakeEmojibaseProvider.kt index 4774144707..0e7c42e538 100644 --- a/libraries/recentemojis/test/src/main/kotlin/io/element/android/libraries/recentemojis/test/FakeEmojibaseProvider.kt +++ b/libraries/emoji/test/src/main/kotlin/io/element/android/libraries/emoji/test/FakeEmojibaseProvider.kt @@ -6,12 +6,12 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.recentemojis.test +package io.element.android.libraries.emoji.test import io.element.android.emojibasebindings.Emoji import io.element.android.emojibasebindings.EmojibaseCategory import io.element.android.emojibasebindings.EmojibaseStore -import io.element.android.libraries.recentemojis.api.EmojibaseProvider +import io.element.android.libraries.emoji.api.EmojibaseProvider import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toPersistentMap diff --git a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt index 3e01ffc25f..babd9f27ff 100644 --- a/plugins/src/main/kotlin/extension/DependencyHandleScope.kt +++ b/plugins/src/main/kotlin/extension/DependencyHandleScope.kt @@ -123,7 +123,7 @@ fun DependencyHandlerScope.allLibrariesImpl() { implementation(project(":libraries:wellknown:impl")) implementation(project(":libraries:oauth:impl")) implementation(project(":libraries:workmanager:impl")) - implementation(project(":libraries:recentemojis:impl")) + implementation(project(":libraries:emoji:impl")) } fun DependencyHandlerScope.allServicesImpl() { From 5d8290b24001cbd83e4e17b8b295ba3cca51003d Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 17 Jul 2026 22:11:23 +0200 Subject: [PATCH 163/383] Extract EmojiPicker into libraries/emoji with Renderer/Presenter pattern --- .../io/element/android/x/di/AppModule.kt | 2 - features/messages/impl/build.gradle.kts | 1 - .../features/messages/impl/MessagesNode.kt | 12 ++ .../messages/impl/MessagesStateProvider.kt | 3 - .../features/messages/impl/MessagesView.kt | 11 +- .../MessagesViewWithIdentityChangePreview.kt | 1 + .../impl/threads/ThreadedMessagesNode.kt | 1 + .../CustomReactionBottomSheet.kt | 69 +++++---- .../customreaction/CustomReactionPresenter.kt | 67 ++++----- .../customreaction/CustomReactionState.kt | 6 +- .../picker/EmojiPickerPresenter.kt | 114 --------------- .../src/main/res/values-be/translations.xml | 8 -- .../src/main/res/values-bg/translations.xml | 8 -- .../src/main/res/values-ca/translations.xml | 9 -- .../src/main/res/values-cs/translations.xml | 9 -- .../src/main/res/values-cy/translations.xml | 9 -- .../src/main/res/values-da/translations.xml | 9 -- .../src/main/res/values-de/translations.xml | 9 -- .../src/main/res/values-el/translations.xml | 9 -- .../src/main/res/values-es/translations.xml | 8 -- .../src/main/res/values-et/translations.xml | 9 -- .../src/main/res/values-eu/translations.xml | 8 -- .../src/main/res/values-fa/translations.xml | 9 -- .../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-in/translations.xml | 9 -- .../src/main/res/values-it/translations.xml | 9 -- .../src/main/res/values-ja/translations.xml | 9 -- .../src/main/res/values-ka/translations.xml | 8 -- .../src/main/res/values-ko/translations.xml | 9 -- .../src/main/res/values-lt/translations.xml | 8 -- .../src/main/res/values-nb/translations.xml | 9 -- .../src/main/res/values-nl/translations.xml | 8 -- .../src/main/res/values-pl/translations.xml | 9 -- .../main/res/values-pt-rBR/translations.xml | 9 -- .../src/main/res/values-pt/translations.xml | 9 -- .../src/main/res/values-ro/translations.xml | 9 -- .../src/main/res/values-ru/translations.xml | 9 -- .../src/main/res/values-sk/translations.xml | 9 -- .../src/main/res/values-sv/translations.xml | 8 -- .../src/main/res/values-tr/translations.xml | 8 -- .../src/main/res/values-uk/translations.xml | 9 -- .../src/main/res/values-ur/translations.xml | 8 -- .../src/main/res/values-uz/translations.xml | 9 -- .../src/main/res/values-vi/translations.xml | 9 -- .../main/res/values-zh-rTW/translations.xml | 9 -- .../src/main/res/values-zh/translations.xml | 9 -- .../impl/src/main/res/values/localazy.xml | 9 -- .../messages/impl/MessagesViewTest.kt | 41 ++++-- .../CustomReactionPresenterTest.kt | 6 +- .../picker/EmojiPickerPresenterTest.kt | 125 ---------------- .../emoji/api/picker/EmojiPickerPresenter.kt | 12 ++ .../emoji/api/picker/EmojiPickerRenderer.kt | 33 +++++ .../emoji/api/picker/EmojiPickerState.kt | 20 +++ libraries/emoji/impl/build.gradle.kts | 1 - .../emoji/impl/DefaultEmojibaseProvider.kt | 18 ++- .../emoji/impl}/EmojibaseProvider.kt | 7 +- .../picker/DefaultEmojiPickerPresenter.kt | 133 ++++++++++++++++++ .../impl/picker/DefaultEmojiPickerRenderer.kt | 43 ++++++ .../impl/picker/DefaultEmojiPickerState.kt | 16 +-- .../picker/DefaultEmojiPickerStateProvider.kt | 56 ++++---- .../libraries/emoji/impl/picker}/EmojiItem.kt | 28 +--- .../emoji/impl}/picker/EmojiPickerEvent.kt | 4 +- .../emoji/impl/picker/EmojiPickerView.kt | 18 ++- .../emoji/impl/picker}/EmojibaseExtensions.kt | 8 +- .../emoji/impl}/picker/SkinTonePicker.kt | 10 +- .../recentemojis/DefaultGetRecentEmojis.kt | 4 +- .../impl/src/main/res/values/temporary.xml | 13 ++ .../impl/fixtures}/FakeEmojibaseProvider.kt | 12 +- .../impl/picker/EmojiPickerPresenterTest.kt | 112 +++++++++++++++ .../DefaultGetRecentEmojisTest.kt | 2 +- libraries/emoji/test/build.gradle.kts | 25 ---- 74 files changed, 571 insertions(+), 804 deletions(-) delete mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenter.kt delete mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenterTest.kt create mode 100644 libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerPresenter.kt create mode 100644 libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerRenderer.kt create mode 100644 libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerState.kt rename libraries/emoji/{api/src/main/kotlin/io/element/android/libraries/emoji/api => impl/src/main/kotlin/io/element/android/libraries/emoji/impl}/EmojibaseProvider.kt (60%) create mode 100644 libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt create mode 100644 libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerRenderer.kt rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerState.kt => libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerState.kt (72%) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerStateProvider.kt => libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerStateProvider.kt (58%) rename {features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction => libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker}/EmojiItem.kt (86%) rename {features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction => libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl}/picker/EmojiPickerEvent.kt (71%) rename features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt => libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiPickerView.kt (91%) rename {features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction => libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker}/EmojibaseExtensions.kt (91%) rename {features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction => libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl}/picker/SkinTonePicker.kt (95%) create mode 100644 libraries/emoji/impl/src/main/res/values/temporary.xml rename libraries/emoji/{test/src/main/kotlin/io/element/android/libraries/emoji/test => impl/src/test/kotlin/io/element/android/libraries/emoji/impl/fixtures}/FakeEmojibaseProvider.kt (60%) create mode 100644 libraries/emoji/impl/src/test/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiPickerPresenterTest.kt delete mode 100644 libraries/emoji/test/build.gradle.kts diff --git a/app/src/main/kotlin/io/element/android/x/di/AppModule.kt b/app/src/main/kotlin/io/element/android/x/di/AppModule.kt index 80d68bd17d..7564db5d95 100644 --- a/app/src/main/kotlin/io/element/android/x/di/AppModule.kt +++ b/app/src/main/kotlin/io/element/android/x/di/AppModule.kt @@ -28,8 +28,6 @@ import io.element.android.libraries.di.BaseDirectory import io.element.android.libraries.di.CacheDirectory import io.element.android.libraries.di.annotations.AppCoroutineScope import io.element.android.libraries.di.annotations.ApplicationContext -import io.element.android.libraries.emoji.api.EmojibaseProvider -import io.element.android.libraries.emoji.impl.DefaultEmojibaseProvider import io.element.android.x.BuildConfig import io.element.android.x.R import kotlinx.coroutines.CoroutineName diff --git a/features/messages/impl/build.gradle.kts b/features/messages/impl/build.gradle.kts index b40aebab39..d442e1bb95 100644 --- a/features/messages/impl/build.gradle.kts +++ b/features/messages/impl/build.gradle.kts @@ -107,6 +107,5 @@ dependencies { testImplementation(projects.features.poll.test) testImplementation(projects.libraries.eventformatter.test) testImplementation(projects.libraries.emoji.impl) - testImplementation(projects.libraries.emoji.test) testImplementation(projects.libraries.slashcommands.test) } 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 18c02d8f40..d4fce982e8 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 @@ -38,6 +38,7 @@ import io.element.android.features.messages.impl.messagecomposer.MessageComposer import io.element.android.features.messages.impl.timeline.TimelineController import io.element.android.features.messages.impl.timeline.TimelineEvent import io.element.android.features.messages.impl.timeline.TimelinePresenter +import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionBottomSheet import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.model.TimelineItem @@ -54,6 +55,7 @@ import io.element.android.libraries.designsystem.utils.OnLifecycleEvent import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.annotations.ApplicationContext import io.element.android.libraries.di.annotations.SessionCoroutineScope +import io.element.android.libraries.emoji.api.picker.EmojiPickerRenderer import io.element.android.libraries.matrix.api.analytics.toAnalyticsViewRoom import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId @@ -100,6 +102,7 @@ class MessagesNode( private val knockRequestsBannerRenderer: KnockRequestsBannerRenderer, private val roomMemberModerationRenderer: RoomMemberModerationRenderer, private val eventContentValidationCache: EventContentValidationCache, + private val emojiPickerRenderer: EmojiPickerRenderer, ) : Node(buildContext, plugins = plugins), MessagesNavigator { data class Inputs( val focusedEventId: EventId?, @@ -329,6 +332,15 @@ class MessagesNode( onViewRequestsClick = callback::navigateToKnockRequestsList, ) }, + customReactionBottomSheet = { + CustomReactionBottomSheet( + state = state.customReactionState, + onSelectEmoji = { uniqueId, emoji -> + state.eventSink(MessagesEvent.ToggleReaction(emoji.unicode, uniqueId)) + }, + emojiPickerRenderer = emojiPickerRenderer, + ) + }, onThreadsListClick = callback::navigateToThreadsList, ) roomMemberModerationRenderer.Render( 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 6389089e07..f47e76fbef 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 @@ -53,7 +53,6 @@ import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.libraries.textcomposer.model.aTextEditorStateMarkdown import io.element.android.libraries.textcomposer.model.aTextEditorStateRich -import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentSetOf @@ -193,11 +192,9 @@ fun aReactionSummaryState( fun aCustomReactionState( target: CustomReactionState.Target = CustomReactionState.Target.None, - recentEmojis: ImmutableList = persistentListOf(), eventSink: (CustomReactionEvent) -> Unit = {}, ) = CustomReactionState( target = target, - recentEmojis = recentEmojis, selectedEmoji = persistentSetOf(), 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 ec014a4ff6..74d6c71aab 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 @@ -81,7 +81,6 @@ import io.element.android.features.messages.impl.timeline.aTimelineItemDaySepara 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 import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryView @@ -149,6 +148,7 @@ fun MessagesView( modifier: Modifier = Modifier, forceJumpToBottomVisibility: Boolean = false, knockRequestsBannerView: @Composable () -> Unit, + customReactionBottomSheet: @Composable () -> Unit, ) { val eventContentValidationState = LocalEventContentValidationState.current @@ -409,12 +409,7 @@ fun MessagesView( }, ) - CustomReactionBottomSheet( - state = state.customReactionState, - onSelectEmoji = { uniqueId, emoji -> - state.eventSink(MessagesEvent.ToggleReaction(emoji.unicode, uniqueId)) - } - ) + customReactionBottomSheet() ReactionSummaryView(state = state.reactionSummaryState) ReadReceiptBottomSheet( @@ -669,6 +664,7 @@ internal fun MessagesViewPreview(@PreviewParameter(MessagesStateProvider::class) onViewAllPinnedMessagesClick = { }, forceJumpToBottomVisibility = true, knockRequestsBannerView = {}, + customReactionBottomSheet = {}, onThreadsListClick = {}, ) } @@ -726,5 +722,6 @@ internal fun MessagesViewA11yPreview() = ElementPreview { onThreadsListClick = {}, forceJumpToBottomVisibility = true, knockRequestsBannerView = {}, + customReactionBottomSheet = {}, ) } 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 d7dd95eb95..4e9bf9249a 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 @@ -43,6 +43,7 @@ internal fun MessagesViewWithIdentityChangePreview( onJoinCallClick = {}, onViewAllPinnedMessagesClick = {}, knockRequestsBannerView = {}, + customReactionBottomSheet = {}, 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 c3e06b880b..b56268eb02 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 @@ -322,6 +322,7 @@ class ThreadedMessagesNode( onViewAllPinnedMessagesClick = {}, modifier = modifier, knockRequestsBannerView = {}, + customReactionBottomSheet = {}, onThreadsListClick = {}, ) 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 5b66a7a9ba..cc971e16ba 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 @@ -13,15 +13,13 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.SheetValue import androidx.compose.material3.rememberBottomSheetState import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import io.element.android.emojibasebindings.Emoji -import io.element.android.features.messages.impl.timeline.components.customreaction.picker.EmojiPicker -import io.element.android.features.messages.impl.timeline.components.customreaction.picker.EmojiPickerPresenter -import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.features.messages.impl.timeline.a11y.a11yReactionAction import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet import io.element.android.libraries.designsystem.theme.components.hide +import io.element.android.libraries.emoji.api.picker.EmojiPickerRenderer import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId @OptIn(ExperimentalMaterial3Api::class) @@ -29,46 +27,45 @@ import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransa fun CustomReactionBottomSheet( state: CustomReactionState, onSelectEmoji: (EventOrTransactionId, Emoji) -> Unit, + emojiPickerRenderer: EmojiPickerRenderer, modifier: Modifier = Modifier, ) { - val sheetState = rememberBottomSheetState( - initialValue = SheetValue.Hidden, - ) + val sheetState = rememberBottomSheetState(initialValue = SheetValue.Hidden) val coroutineScope = rememberCoroutineScope() - val target = state.target as? CustomReactionState.Target.Success - fun onDismiss() { - state.eventSink(CustomReactionEvent.DismissCustomReactionSheet) - } + when (state.target) { + CustomReactionState.Target.None, + is CustomReactionState.Target.Loading -> Unit + is CustomReactionState.Target.Success -> { - fun onEmojiSelectedDismiss(emoji: Emoji) { - if (target?.event == null) return - sheetState.hide(coroutineScope) { - state.eventSink(CustomReactionEvent.DismissCustomReactionSheet) - onSelectEmoji(target.event.eventOrTransactionId, emoji) - } - } + fun onEmojiSelectedDismiss(emoji: Emoji) { + sheetState.hide(coroutineScope) { + state.eventSink(CustomReactionEvent.DismissCustomReactionSheet) + onSelectEmoji(state.target.event.eventOrTransactionId, emoji) + } + } - if (target?.emojibaseStore != null && target.event.eventId != null) { - ModalBottomSheet( - onDismissRequest = ::onDismiss, - sheetState = sheetState, - modifier = modifier, - scrollable = false, - ) { - val presenter = remember { - EmojiPickerPresenter( - emojibaseStore = target.emojibaseStore, - recentEmojis = state.recentEmojis, - coroutineDispatchers = CoroutineDispatchers.Default, + fun onDismiss() { + state.eventSink(CustomReactionEvent.DismissCustomReactionSheet) + } + + + ModalBottomSheet( + onDismissRequest = ::onDismiss, + sheetState = sheetState, + modifier = modifier, + scrollable = false, + ) { + emojiPickerRenderer.Render( + state = state.target.emojiPickerState, + onSelectEmoji = ::onEmojiSelectedDismiss, + selectedEmojis = state.selectedEmoji, + modifier = Modifier.fillMaxSize(), + contentDescription = { emoji, isSelected -> + a11yReactionAction(emoji = emoji.unicode, userAlreadyReacted = isSelected) + }, ) } - EmojiPicker( - onSelectEmoji = ::onEmojiSelectedDismiss, - state = presenter.present(), - selectedEmojis = state.selectedEmoji, - modifier = Modifier.fillMaxSize(), - ) } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt index 1fddf4e3bb..7a9f5fe4ff 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt @@ -9,59 +9,50 @@ package io.element.android.features.messages.impl.timeline.components.customreaction import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState 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.Inject import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.emoji.api.EmojibaseProvider -import io.element.android.libraries.emoji.api.recentemojis.GetRecentEmojis -import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.persistentListOf +import io.element.android.libraries.emoji.api.picker.EmojiPickerPresenter import kotlinx.collections.immutable.toImmutableSet -import kotlinx.coroutines.launch @Inject class CustomReactionPresenter( - private val emojibaseProvider: EmojibaseProvider, - private val getRecentEmojis: GetRecentEmojis, + private val emojiPickerPresenter: EmojiPickerPresenter, ) : Presenter { @Composable override fun present(): CustomReactionState { - val localCoroutineScope = rememberCoroutineScope() - var recentEmojis by remember { mutableStateOf>(persistentListOf()) } - - val target: MutableState = remember { - mutableStateOf(CustomReactionState.Target.None) - } - - fun handleShowCustomReactionSheet(event: TimelineItem.Event) { - target.value = CustomReactionState.Target.Loading(event) - localCoroutineScope.launch { - recentEmojis = getRecentEmojis().getOrNull() ?: persistentListOf() - target.value = CustomReactionState.Target.Success( - event = event, - emojibaseStore = emojibaseProvider.emojibaseStore - ) - } - } - - fun handleDismissCustomReactionSheet() { - target.value = CustomReactionState.Target.None - } + var internalTarget by remember { mutableStateOf(InternalTarget.None) } + val emojiPickerState = emojiPickerPresenter.present() fun handleEvent(event: CustomReactionEvent) { when (event) { - is CustomReactionEvent.ShowCustomReactionSheet -> handleShowCustomReactionSheet(event.event) - is CustomReactionEvent.DismissCustomReactionSheet -> handleDismissCustomReactionSheet() + is CustomReactionEvent.ShowCustomReactionSheet -> { + internalTarget = InternalTarget.Showing(event.event) + } + is CustomReactionEvent.DismissCustomReactionSheet -> { + internalTarget = InternalTarget.None + } } } - val event = (target.value as? CustomReactionState.Target.Success)?.event - val selectedEmoji = event + + val computedTarget = when (val target = internalTarget) { + InternalTarget.None -> CustomReactionState.Target.None + is InternalTarget.Showing -> if (emojiPickerState.isReady) { + CustomReactionState.Target.Success( + event = target.event, + emojiPickerState = emojiPickerState, + ) + } else { + CustomReactionState.Target.Loading(target.event) + } + } + + val eventForSelection = (computedTarget as? CustomReactionState.Target.Success)?.event + val selectedEmoji = eventForSelection ?.reactionsState ?.reactions ?.mapNotNull { if (it.isHighlighted) it.key else null } @@ -69,10 +60,14 @@ class CustomReactionPresenter( .toImmutableSet() return CustomReactionState( - target = target.value, + target = computedTarget, selectedEmoji = selectedEmoji, - recentEmojis = recentEmojis, eventSink = ::handleEvent, ) } } + +private sealed interface InternalTarget { + data object None : InternalTarget + data class Showing(val event: TimelineItem.Event) : InternalTarget +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionState.kt index 1897d4e5a7..566453b32b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionState.kt @@ -8,15 +8,13 @@ package io.element.android.features.messages.impl.timeline.components.customreaction -import io.element.android.emojibasebindings.EmojibaseStore import io.element.android.features.messages.impl.timeline.model.TimelineItem -import kotlinx.collections.immutable.ImmutableList +import io.element.android.libraries.emoji.api.picker.EmojiPickerState import kotlinx.collections.immutable.ImmutableSet data class CustomReactionState( val target: Target, val selectedEmoji: ImmutableSet, - val recentEmojis: ImmutableList, val eventSink: (CustomReactionEvent) -> Unit, ) { sealed interface Target { @@ -24,7 +22,7 @@ data class CustomReactionState( data class Loading(val event: TimelineItem.Event) : Target data class Success( val event: TimelineItem.Event, - val emojibaseStore: EmojibaseStore, + val emojiPickerState: EmojiPickerState, ) : Target } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenter.kt deleted file mode 100644 index 3a4cf6c9ce..0000000000 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenter.kt +++ /dev/null @@ -1,114 +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.messages.impl.timeline.components.customreaction.picker - -import androidx.compose.foundation.text.input.rememberTextFieldState -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.setValue -import androidx.compose.ui.platform.LocalInspectionMode -import io.element.android.compound.tokens.generated.CompoundIcons -import io.element.android.emojibasebindings.Emoji -import io.element.android.emojibasebindings.EmojibaseStore -import io.element.android.features.messages.impl.R -import io.element.android.features.messages.impl.timeline.components.customreaction.icon -import io.element.android.features.messages.impl.timeline.components.customreaction.title -import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.core.coroutine.CoroutineDispatchers -import io.element.android.libraries.designsystem.theme.components.IconSource -import io.element.android.libraries.designsystem.theme.components.SearchBarResultState -import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.toImmutableList -import kotlinx.coroutines.delay -import kotlinx.coroutines.withContext -import kotlin.time.Duration.Companion.milliseconds - -class EmojiPickerPresenter( - private val emojibaseStore: EmojibaseStore, - private val recentEmojis: ImmutableList, - private val coroutineDispatchers: CoroutineDispatchers, -) : Presenter { - @Composable - override fun present(): EmojiPickerState { - val queryState = rememberTextFieldState() - var isSearchActive by remember { mutableStateOf(false) } - var emojiResults by remember { mutableStateOf>>(SearchBarResultState.Initial()) } - - val recentEmojiIcon = CompoundIcons.History() - val categories = remember { - val providedCategories = emojibaseStore.categories.map { (category, emojis) -> - EmojiCategory( - titleId = category.title, - icon = IconSource.Vector(category.icon), - emojis = emojis - ) - } - if (recentEmojis.isNotEmpty()) { - val recentEmojis = recentEmojis.mapNotNull { recentEmoji -> - emojibaseStore.allEmojis.find { it.unicode == recentEmoji } - }.toImmutableList() - val recentCategory = - EmojiCategory( - titleId = R.string.emoji_picker_category_recent, - icon = IconSource.Vector(recentEmojiIcon), - emojis = recentEmojis - ) - (listOf(recentCategory) + providedCategories).toImmutableList() - } else { - providedCategories.toImmutableList() - } - } - - val searchQuery = queryState.text.toString() - LaunchedEffect(searchQuery) { - emojiResults = if (searchQuery.isEmpty()) { - SearchBarResultState.Initial() - } else { - // Add a small delay to avoid doing too many computations when the user is typing quickly - delay(100.milliseconds) - - val lowercaseQuery = searchQuery.lowercase() - val results = withContext(coroutineDispatchers.computation) { - emojibaseStore.allEmojis - .asSequence() - .filter { emoji -> - emoji.tags.orEmpty().any { it.contains(lowercaseQuery) } || - emoji.shortcodes.any { it.contains(lowercaseQuery) } - } - .take(60) - .toImmutableList() - } - - SearchBarResultState.Results(results) - } - } - - val isInPreview = LocalInspectionMode.current - fun handleEvent(event: EmojiPickerEvent) { - when (event) { - // For some reason, in preview mode the SearchBar emits this event with an `isActive = true` value automatically - is EmojiPickerEvent.ToggleSearchActive -> if (!isInPreview) { - isSearchActive = event.isActive - } - } - } - - return EmojiPickerState( - categories = categories, - allEmojis = emojibaseStore.allEmojis, - searchQuery = queryState, - isSearchActive = isSearchActive, - searchResults = emojiResults, - eventSink = ::handleEvent, - ) - } -} diff --git a/features/messages/impl/src/main/res/values-be/translations.xml b/features/messages/impl/src/main/res/values-be/translations.xml index 8b40c72040..b6cac43616 100644 --- a/features/messages/impl/src/main/res/values-be/translations.xml +++ b/features/messages/impl/src/main/res/values-be/translations.xml @@ -6,14 +6,6 @@ "Зашыфравана невядомай ці выдаленай прыладай." "Зашыфравана прыладай, не пацверджанай яе ўладальнікам." "Зашыфравана неправераным карыстальнікам." - "Актыўнасці" - "Сцягі" - "Ежа & Напоі" - "Жывёлы & Прырода" - "Аб\'екты" - "Усмешкі & Удзельнікі" - "Падарожжы & Месцы" - "Сімвалы" "Не атрымалася апрацаваць медыяфайл для загрузкі, паспрабуйце яшчэ раз." "Не атрымалася загрузіць медыяфайлы, паспрабуйце яшчэ раз." "Апрацоўка…" diff --git a/features/messages/impl/src/main/res/values-bg/translations.xml b/features/messages/impl/src/main/res/values-bg/translations.xml index 1e675f52ae..2db2e6930f 100644 --- a/features/messages/impl/src/main/res/values-bg/translations.xml +++ b/features/messages/impl/src/main/res/values-bg/translations.xml @@ -1,14 +1,6 @@ "Без шифроване" - "Дейности" - "Знамена" - "Храна & Напитки" - "Животни & Природа" - "Обекти" - "Усмивки & Хора" - "Пътуване & Места" - "Символи" "Докоснете, за да промените качеството на качване на видео" "Файлът не можа да бъде качен." "Неуспешна обработка на мултимедия за качване, моля, опитайте отново." diff --git a/features/messages/impl/src/main/res/values-ca/translations.xml b/features/messages/impl/src/main/res/values-ca/translations.xml index f9b2685c7d..44fe948683 100644 --- a/features/messages/impl/src/main/res/values-ca/translations.xml +++ b/features/messages/impl/src/main/res/values-ca/translations.xml @@ -7,15 +7,6 @@ "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." 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 9bf1c5c079..6c39d67583 100644 --- a/features/messages/impl/src/main/res/values-cs/translations.xml +++ b/features/messages/impl/src/main/res/values-cs/translations.xml @@ -7,15 +7,6 @@ "Šifrováno neznámým nebo smazaným zařízením." "Šifrováno zařízením, které nebylo ověřeno jeho vlastníkem." "Šifrováno neověřeným uživatelem." - "Aktivity" - "Vlajky" - "Jídlo a nápoje" - "Zvířata a příroda" - "Předměty" - "Smajlíci a lidé" - "Cestování a místa" - "Nedávné emotikony" - "Symboly" "Titulky nemusí být viditelné pro lidi, kteří používají starší aplikace." "Klepnutím změníte kvalitu nahrávání videa" "Soubor nelze nahrát." diff --git a/features/messages/impl/src/main/res/values-cy/translations.xml b/features/messages/impl/src/main/res/values-cy/translations.xml index 736a9a34f9..f0db099f8e 100644 --- a/features/messages/impl/src/main/res/values-cy/translations.xml +++ b/features/messages/impl/src/main/res/values-cy/translations.xml @@ -7,15 +7,6 @@ "Wedi\'i amgryptio gan ddyfais anhysbys neu wedi\'i dileu." "Wedi\'i amgryptio gan ddyfais nad yw wedi\'i wirio gan ei pherchennog." "Wedi\'i amgryptio gan ddefnyddiwr heb ei wirio." - "Gweithgareddau" - "Baneri" - "Bwyd a Diod" - "Anifeiliaid a Natur" - "Gwrthrychau" - "Wynebau Hapus a Phobl" - "Teithio a Llefydd" - "Emojis diweddar" - "Symbolau" "Efallai na fydd capsiynau yn weladwy i bobl sy\'n defnyddio apiau hŷn." "Tapiwch i newid ansawdd llwytho\'r fideo" "Nid oedd modd llwytho\'r ffeil." 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 e068df293a..f168dd7896 100644 --- a/features/messages/impl/src/main/res/values-da/translations.xml +++ b/features/messages/impl/src/main/res/values-da/translations.xml @@ -7,15 +7,6 @@ "Krypteret af en ukendt eller slettet enhed." "Krypteret af en enhed, der ikke er verificeret af sin ejer." "Krypteret af en ikke-verificeret bruger." - "Aktiviteter" - "Flag" - "Mad og drikke" - "Dyr og natur" - "Objekter" - "Smileys og personer" - "Rejser og steder" - "Seneste emojis" - "Symboler" "Billedtekster er muligvis ikke synlige for personer, der bruger ældre apps." "Tryk for at ændre videokvaliteten i uploadet" "Filen kunne ikke uploades." 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 4848f1f282..1bdb3e0b16 100644 --- a/features/messages/impl/src/main/res/values-de/translations.xml +++ b/features/messages/impl/src/main/res/values-de/translations.xml @@ -7,15 +7,6 @@ "Verschlüsselt von einem unbekannten oder gelöschten Gerät." "Verschlüsselt durch ein Gerät, das nicht von seinem Besitzer verifiziert wurde." "Verschlüsselt durch einen nicht verifizierten Nutzer." - "Aktivitäten" - "Flaggen" - "Essen & Trinken" - "Tiere & Natur" - "Objekte" - "Smileys & Menschen" - "Reisen & Orte" - "Zuletzt verwendete Emojis" - "Symbole" "Bildunterschriften sind für Nutzer älterer Apps möglicherweise nicht sichtbar." "Tippe, um die Qualität des Video-Uploads zu ändern" "Die Datei konnte nicht hochgeladen werden." diff --git a/features/messages/impl/src/main/res/values-el/translations.xml b/features/messages/impl/src/main/res/values-el/translations.xml index bfecdbb944..4a944d5250 100644 --- a/features/messages/impl/src/main/res/values-el/translations.xml +++ b/features/messages/impl/src/main/res/values-el/translations.xml @@ -7,15 +7,6 @@ "Κρυπτογραφημένο από άγνωστη ή διαγεγραμμένη συσκευή." "Κρυπτογραφημένο από μια συσκευή που δεν έχει επαληθευτεί από τον ιδιοκτήτη της." "Κρυπτογραφημένο από μη επαληθευμένο χρήστη." - "Δραστηριότητες" - "Σημαίες" - "Φαγητό & Ποτό" - "Ζώα & Φύση" - "Αντικείμενα" - "Φατσούλες & Άνθρωποι" - "Ταξίδια & Μέρη" - "Πρόσφατα emoji" - "Σύμβολα" "Οι λεζάντες ενδέχεται να μην είναι ορατές σε άτομα που χρησιμοποιούν παλαιότερες εφαρμογές." "Πατήστε για να αλλάξετε την ποιότητα μεταφόρτωσης βίντεο" "Δεν ήταν δυνατή η μεταφόρτωση του αρχείου." diff --git a/features/messages/impl/src/main/res/values-es/translations.xml b/features/messages/impl/src/main/res/values-es/translations.xml index 81ca655676..0a0b57cc5e 100644 --- a/features/messages/impl/src/main/res/values-es/translations.xml +++ b/features/messages/impl/src/main/res/values-es/translations.xml @@ -7,14 +7,6 @@ "Cifrado por un dispositivo desconocido o eliminado." "Cifrado por un dispositivo no verificado por su propietario." "Cifrado por un usuario no verificado." - "Actividades" - "Banderas" - "Comida y bebida" - "Animales y naturaleza" - "Objetos" - "Emojis y personas" - "Viajes y lugares" - "Símbolos" "Es posible que las leyendas no sean visibles para las personas que usan aplicaciones más antiguas." "Error al procesar el contenido multimedia, por favor inténtalo de nuevo." "Error al subir el contenido multimedia, por favor inténtalo de nuevo." 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 86b1995f32..aa6576fc17 100644 --- a/features/messages/impl/src/main/res/values-et/translations.xml +++ b/features/messages/impl/src/main/res/values-et/translations.xml @@ -7,15 +7,6 @@ "Krüptitud tundmatu või kustutatud seadme poolt." "Krüptitud seadme poolt, mida tema omanik pole verifitseerinud." "Krüptitud verifitseerimata kasutaja poolt." - "Tegevused" - "Lipud" - "Toit ja jook" - "Loomad ja loodus" - "Esemed" - "Emotikonid ja inimesed" - "Reisimine ja kohad" - "Hiljutised emojid" - "Sümbolid" "Pööra pilti ümber rõhttelje" "Pilt on pööratud ümber rõhttelje" "Pildi algne variant" diff --git a/features/messages/impl/src/main/res/values-eu/translations.xml b/features/messages/impl/src/main/res/values-eu/translations.xml index 6c76b4dfd9..8c158d688a 100644 --- a/features/messages/impl/src/main/res/values-eu/translations.xml +++ b/features/messages/impl/src/main/res/values-eu/translations.xml @@ -1,14 +1,6 @@ "Ez dago zifratuta." - "Jarduerak" - "Banderak" - "Jana eta edana" - "Animaliak eta natura" - "Objektuak" - "Irribartxoak eta jendea" - "Bidaiak eta tokiak" - "Ikurrak" "Huts egin du multimedia igotzeak, saiatu berriro." "Blokeatu erabiltzailea" "Mezua zure zerbitzariko administratzaileari jakinaraziko zaio. Ezingo dute zifratutako mezurik irakurri." 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 19f55a5559..4f8f737f9c 100644 --- a/features/messages/impl/src/main/res/values-fa/translations.xml +++ b/features/messages/impl/src/main/res/values-fa/translations.xml @@ -6,15 +6,6 @@ "رمز شده به دست افزاره‌ای ناشناخته یا حذف شده." "رمز شده به دست افزاره‌ای که از سوی مالکش تأیید نشده." "رمز شده به دست کاربری تأیید نشده." - "فعّالیت‌ها" - "پرچم‌ها" - "غذا و نوشیدنی" - "حیوانات و طبعیت" - "اشیا" - "شکلک‌ها و افراد" - "سفر و مکان‌ها" - "شکلک‌های اخیر" - "نمادها" "پردازش رسانه برای بارگذاری شکست خورد. لطفاً دوباره تلاش کنید." "بارگذاری رسانه شکست خورد. لطفاً دوباره تلاش کنید." "پردازش کردن…" 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 881a5386e7..3705047087 100644 --- a/features/messages/impl/src/main/res/values-fi/translations.xml +++ b/features/messages/impl/src/main/res/values-fi/translations.xml @@ -7,15 +7,6 @@ "Tuntemattoman tai poistetun laitteen salaama." "Salattu laitteella, jota sen omistaja ei ole vahvistanut." "Vahvistamattoman käyttäjän salaama." - "Aktiviteetit" - "Liput" - "Ruoka ja juoma" - "Eläimet ja luonto" - "Esineet" - "Hymiöt ja ihmiset" - "Matkustaminen ja paikat" - "Viimeaikaiset emojit" - "Symbolit" "Käännä kuva vaakasuunnassa" "Käännetty vaakasuunnassa" "Alkuperäinen" 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 3505fd520d..0062421326 100644 --- a/features/messages/impl/src/main/res/values-fr/translations.xml +++ b/features/messages/impl/src/main/res/values-fr/translations.xml @@ -7,15 +7,6 @@ "Chiffré par un appareil inconnu ou supprimé." "Chiffré par un appareil non vérifié par son propriétaire." "Chiffré par un utilisateur non vérifié." - "Activités" - "Drapeaux" - "Nourriture et boissons" - "Animaux et nature" - "Objets" - "Émoticônes et personnes" - "Voyages & lieux" - "Emojis récents" - "Symboles" "Retourner l’image horizontalement" "Retournée horizontalement" "Originale" 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 0f04f2179a..23912aaf78 100644 --- a/features/messages/impl/src/main/res/values-hr/translations.xml +++ b/features/messages/impl/src/main/res/values-hr/translations.xml @@ -7,15 +7,6 @@ "Šifrirano nepoznatim ili izbrisanim uređajem." "Šifrirano uređajem koji vlasnik nije potvrdio." "Šifrirao neprovjereni korisnik." - "Aktivnosti" - "Zastave" - "Hrana i piće" - "Životinje i priroda" - "Objekti" - "Emotikoni i osobe" - "Putovanja i mjesta" - "Nedavni emotikoni" - "Simboli" "Okreni sliku vodoravno" "Okrenuto vodoravno" "Izvornik" 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 bb33520cb6..2b428f92b2 100644 --- a/features/messages/impl/src/main/res/values-hu/translations.xml +++ b/features/messages/impl/src/main/res/values-hu/translations.xml @@ -7,15 +7,6 @@ "Ismeretlen vagy törölt eszköz által titkosítva." "A tulajdonos által nem ellenőrzött eszköz által titkosítva." "Nem ellenőrzött felhasználó által titkosítva." - "Tevékenységek" - "Zászlók" - "Étel és ital" - "Állatok és természet" - "Tárgyak" - "Mosolyok és emberek" - "Utazás és helyek" - "Legutóbbi emodzsik" - "Szimbólumok" "Kép vízszintes tükrözése" "Vízszintesen tükrözve" "Eredeti" 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 d052efb769..00233facfd 100644 --- a/features/messages/impl/src/main/res/values-in/translations.xml +++ b/features/messages/impl/src/main/res/values-in/translations.xml @@ -7,15 +7,6 @@ "Dienkripsi oleh perangkat yang tidak dikenal atau dihapus." "Dienkripsi oleh perangkat yang tidak diverifikasi oleh pemiliknya." "Dienkripsi oleh pengguna yang tidak terverifikasi." - "Aktivitas" - "Bendera" - "Makanan & Minuman" - "Hewan & Alam" - "Objek" - "Senyuman & Orang" - "Wisata & Tempat" - "Emojis Sebelumnya" - "Simbol" "Putar gambar ke kiri" "%1$d derajat" 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 0f2e0d37be..53812093ee 100644 --- a/features/messages/impl/src/main/res/values-it/translations.xml +++ b/features/messages/impl/src/main/res/values-it/translations.xml @@ -7,15 +7,6 @@ "Cifrato da un dispositivo sconosciuto o eliminato." "Cifrato da un dispositivo non verificato dal proprietario." "Cifrato da un utente non verificato." - "Attività" - "Bandiere" - "Cibi & Bevande" - "Animali & Natura" - "Oggetti" - "Faccine & Persone" - "Viaggi & Luoghi" - "Emoji recenti" - "Simboli" "Capovolgi l\'immagine orizzontalmente" "Capovolto orizzontalmente" "Originale" 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 26d33c4aa1..15851b893e 100644 --- a/features/messages/impl/src/main/res/values-ja/translations.xml +++ b/features/messages/impl/src/main/res/values-ja/translations.xml @@ -7,15 +7,6 @@ "削除されたまたは不明な端末により暗号化されています。" "所有者に検証されていない端末により暗号化されています。" "未検証のユーザーにより暗号化されています。" - "アクティビティ" - "旗" - "食べ物" - "動物・自然" - "物" - "顔・人" - "旅・場所" - "最近使用" - "記号" "水平に反転" "垂直に反転" "元画像" diff --git a/features/messages/impl/src/main/res/values-ka/translations.xml b/features/messages/impl/src/main/res/values-ka/translations.xml index 842fa4bf5b..54002be4b2 100644 --- a/features/messages/impl/src/main/res/values-ka/translations.xml +++ b/features/messages/impl/src/main/res/values-ka/translations.xml @@ -1,13 +1,5 @@ - "აქტივობები" - "დროშები" - "Საჭმელ-სასმელი" - "ცხოველები & ბუნება" - "ობიექტები" - "ღიმილები & ხალხი" - "მოგზაურობა და ადგილები" - "სიმბოლოები" "მედიის ატვირთვა ვერ მოხერხდა. გთხოვთ, სცადოთ ხელახლა." "მედიის ატვირთვა ვერ მოხერხდა, გთხოვთ, სცადოთ ხელახლა." "მომხმარებლის დაბლოკვა" 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 fbcb0cab52..82d81f42cd 100644 --- a/features/messages/impl/src/main/res/values-ko/translations.xml +++ b/features/messages/impl/src/main/res/values-ko/translations.xml @@ -7,15 +7,6 @@ "알 수 없거나 삭제된 장치에 의해 암호화됩니다." "소유자가 확인하지 않은 장치에 의해 암호화되었습니다." "검증되지 않은 사용자에 의해 암호화되었습니다." - "활동" - "깃발" - "음식 & 음료" - "동물 & 자연" - "사물" - "표정 & 사람" - "여행 & 장소" - "최근 이모지" - "상징" "이미지를 왼쪽으로 회전" "%1$d도" diff --git a/features/messages/impl/src/main/res/values-lt/translations.xml b/features/messages/impl/src/main/res/values-lt/translations.xml index 379f9ae853..39f1b43627 100644 --- a/features/messages/impl/src/main/res/values-lt/translations.xml +++ b/features/messages/impl/src/main/res/values-lt/translations.xml @@ -1,13 +1,5 @@ - "Veikla" - "Vėliavos" - "Maistas ir Gėrimai" - "Gyvūnai ir Gamta" - "Objektai" - "Šypsenėlės ir Žmonės" - "Kelionės ir Vietovės" - "Simboliai" "Nepavyko apdoroti įkeliamos laikmenos, bandykite dar kartą." "Nepavyko įkelti laikmenos, pabandykite dar kartą." "Blokuoti vartotoją" diff --git a/features/messages/impl/src/main/res/values-nb/translations.xml b/features/messages/impl/src/main/res/values-nb/translations.xml index a0dafdd136..a68aeabcdf 100644 --- a/features/messages/impl/src/main/res/values-nb/translations.xml +++ b/features/messages/impl/src/main/res/values-nb/translations.xml @@ -7,15 +7,6 @@ "Kryptert av en ukjent eller slettet enhet." "Kryptert med en enhet som ikke er verifisert av eieren." "Kryptert av en ubekreftet bruker." - "Aktiviteter" - "Flagg" - "Mat og drikke" - "Dyr og natur" - "Gjenstander" - "Smilefjes og mennesker" - "Reising og steder" - "Nylige emojier" - "Symboler" "Teksting er kanskje ikke synlig for personer som bruker eldre apper." "Trykk for å endre kvaliteten på videoopplastingen" "Filen kunne ikke lastes opp." diff --git a/features/messages/impl/src/main/res/values-nl/translations.xml b/features/messages/impl/src/main/res/values-nl/translations.xml index d2305229a7..dbce48fc97 100644 --- a/features/messages/impl/src/main/res/values-nl/translations.xml +++ b/features/messages/impl/src/main/res/values-nl/translations.xml @@ -6,14 +6,6 @@ "Versleuteld door een onbekend of verwijderd apparaat." "Versleuteld door een apparaat dat niet is geverifieerd door de eigenaar." "Versleuteld door een niet-geverifieerde gebruiker." - "Activiteiten" - "Vlaggen" - "Eten & Drinken" - "Dieren & Natuur" - "Voorwerpen" - "Smileys & Mensen" - "Reizen & Locaties" - "Symbolen" "Het verwerken van media voor uploaden is mislukt. Probeer het opnieuw." "Het uploaden van media is mislukt. Probeer het opnieuw." "Gebruiker blokkeren" 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 d8ffaac54c..651a8e460e 100644 --- a/features/messages/impl/src/main/res/values-pl/translations.xml +++ b/features/messages/impl/src/main/res/values-pl/translations.xml @@ -7,15 +7,6 @@ "Zaszyfrowana przez nieznane lub usunięte urządzenie." "Zaszyfrowana przez urządzenie niezweryfikowane przez jego właściciela." "Zaszyfrowana przez niezweryfikowanego użytkownika." - "Aktywności" - "Flagi" - "Jedzenie i napoje" - "Zwierzęta i natura" - "Obiekty" - "Buźki i osoby" - "Podróż i miejsca" - "Ostatnie emoji" - "Symbole" "Odwróć obraz w poziomie" "Odwrócono w poziomie" "Oryginalny" diff --git a/features/messages/impl/src/main/res/values-pt-rBR/translations.xml b/features/messages/impl/src/main/res/values-pt-rBR/translations.xml index f93f0d71ca..5c8b62e5dd 100644 --- a/features/messages/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/messages/impl/src/main/res/values-pt-rBR/translations.xml @@ -7,15 +7,6 @@ "Criptografado por um dispositivo desconhecido ou apagado." "Criptografado por um dispositivo que não foi verificado pelo seu dono." "Criptografado por um usuário não verificado." - "Atividades" - "Bandeiras" - "Comida & Bebida" - "Animais & Natureza" - "Objetos" - "Sorrisos & Pessoas" - "Viagens & Lugares" - "Emojis recentes" - "Símbolos" "As legendas podem não ser visíveis para pessoas que usam apps mais antigos." "Toque para alterar a qualidade do envio do vídeo" "O arquivo não pôde ser enviado." 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 2fb5173169..6329956b05 100644 --- a/features/messages/impl/src/main/res/values-pt/translations.xml +++ b/features/messages/impl/src/main/res/values-pt/translations.xml @@ -7,15 +7,6 @@ "Cifragem com origem num dispositivo eliminado ou desconhecido." "Cifragem com origem num dispositivo não verificado pelo seu dono." "Cifragem com origem num utilizador não verificado." - "Atividades" - "Bandeiras" - "Comidas e Bebidas" - "Animais e Natureza" - "Objetos" - "Caras e Pessoas" - "Viagens e Lugares" - "Emojis recentes" - "Símbolos" "As legendas poderão não ser visíveis em versões mais antigas da aplicação." "Toca para alterar a qualidade de carregamento do vídeo" "Não foi possível enviar o ficheiro" 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 67b72dc2a8..e9e4da87c3 100644 --- a/features/messages/impl/src/main/res/values-ro/translations.xml +++ b/features/messages/impl/src/main/res/values-ro/translations.xml @@ -7,15 +7,6 @@ "Criptat de un dispozitiv necunoscut sau șters." "Criptat de un dispozitiv care nu este verificat de proprietarul său." "Criptat de un utilizator neverificat." - "Activități" - "Steaguri" - "Mâncare & Băutură" - "Animale și Natură" - "Obiecte" - "Fețe zâmbitoare & Oameni" - "Călătorii & Locuri" - "Emoticoane recente" - "Simboluri" "Este posibil ca descrierile să nu fie vizibile pentru persoanele care folosesc aplicații mai vechi." "Atingeți pentru a modifica calitatea încărcării videoclipului" "Fișierul nu a putut fi încărcat." 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 3744beff8f..32e6e16980 100644 --- a/features/messages/impl/src/main/res/values-ru/translations.xml +++ b/features/messages/impl/src/main/res/values-ru/translations.xml @@ -7,15 +7,6 @@ "Зашифровано неизвестным или удаленным устройством." "Зашифровано устройством, не проверенным его владельцем." "Зашифровано непроверенным пользователем." - "Активности" - "Флаги" - "Еда и напитки" - "Животные и природа" - "Объекты" - "Эмодзи и люди" - "Путешествия и места" - "Недавние эмодзи" - "Символы" "Перевернуть изображение по горизонтали" "Перевернуто по горизонтали" "Оригинал" 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 d2022c4882..c64e5ba62e 100644 --- a/features/messages/impl/src/main/res/values-sk/translations.xml +++ b/features/messages/impl/src/main/res/values-sk/translations.xml @@ -7,15 +7,6 @@ "Zašifrované neznámym alebo odstráneným zariadením." "Šifrované zariadením, ktoré nie je overené jeho majiteľom." "Šifrované neovereným používateľom." - "Aktivity" - "Vlajky" - "Jedlo a nápoje" - "Zvieratá a príroda" - "Predmety" - "Smajlíky a ľudia" - "Cestovanie a miesta" - "Nedávne emotikony" - "Symboly" "Titulky nemusia byť viditeľné pre ľudí používajúcich staršie aplikácie." "Ťuknutím zmeníte kvalitu nahratého videa" "Súbor sa nepodarilo nahrať." 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 2e10fd3166..6de0b1ebcc 100644 --- a/features/messages/impl/src/main/res/values-sv/translations.xml +++ b/features/messages/impl/src/main/res/values-sv/translations.xml @@ -7,14 +7,6 @@ "Krypterad av en okänd eller raderad enhet." "Krypterad av en enhet som inte verifierats av ägaren." "Krypterad av en overifierad användare." - "Aktiviteter" - "Flaggor" - "Mat & dryck" - "Djur & natur" - "Föremål" - "Smileys & personer" - "Resor & platser" - "Symboler" "Bildtexter kanske inte är synliga för personer som använder äldre appar." "Tryck för att ändra videouppladdningskvaliteten" "Filen kunde inte laddas upp." diff --git a/features/messages/impl/src/main/res/values-tr/translations.xml b/features/messages/impl/src/main/res/values-tr/translations.xml index a40687444b..a987f63ce3 100644 --- a/features/messages/impl/src/main/res/values-tr/translations.xml +++ b/features/messages/impl/src/main/res/values-tr/translations.xml @@ -7,14 +7,6 @@ "Bilinmeyen veya silinmiş bir cihaz tarafından şifrelenmiştir." "Sahibi tarafından doğrulanmamış bir cihaz tarafından şifrelenmiştir." "Doğrulanmamış bir kullanıcı tarafından şifrelenmiştir." - "Aktiviteler" - "Bayraklar" - "Yiyecek ve İçecek" - "Hayvanlar ve Doğa" - "Nesneler" - "İfadeler ve İnsanlar" - "Seyahat ve Yerler" - "Simgeler" "Açıklamalar, eski uygulamaları kullanan kişiler tarafından görülemeyebilir." "Medya yüklenemedi, lütfen tekrar deneyin." "Medya yüklenemedi, lütfen tekrar deneyin." 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 cae9560768..c5f5ddde91 100644 --- a/features/messages/impl/src/main/res/values-uk/translations.xml +++ b/features/messages/impl/src/main/res/values-uk/translations.xml @@ -7,15 +7,6 @@ "Зашифровано невідомим або видаленим пристроєм." "Зашифровано пристроєм, який не звірено його власником." "Зашифровано не звіреним користувачем." - "Дії" - "Прапори" - "Їжа та напої" - "Тварини та природа" - "Об\'єкти" - "Смайлики та люди" - "Подорожі та місця" - "Нещодавні емодзі" - "Символи" "Повернути зображення по горизонталі" "Перевернуто по горизонталі" "Оригінал" diff --git a/features/messages/impl/src/main/res/values-ur/translations.xml b/features/messages/impl/src/main/res/values-ur/translations.xml index cb110ef5c6..6f549a5ba3 100644 --- a/features/messages/impl/src/main/res/values-ur/translations.xml +++ b/features/messages/impl/src/main/res/values-ur/translations.xml @@ -6,14 +6,6 @@ "کسی نامعلوم یا حذف شدہ آلے کے ذریعے مرموز کردہ۔" "کسی ایسے آلے کے ذریعے مرموز کردہ جس کی توثیق اسکے مالک سے نہیں ہوئی۔" "ایک غیر توثیق شدہ صارف کے ذریعے مرموز کردہ۔" - "سرگرمیاں" - "جھنڈے" - "طعم و مشروب" - "حیوانات و فطرت" - "اشیاء" - "مسکراہٹیں و لوگ" - "سفر و مقامات" - "علامتیں" "وسائط کا معالجہ برائے ترفیع ناکام، برائے مہربانی دوبارہ کوشش کریں۔" "وسائط رفع کرنے میں ناکام، برائے مہربانی دوبارہ کوشش کریں۔" "صارف کو مسدود کریں" diff --git a/features/messages/impl/src/main/res/values-uz/translations.xml b/features/messages/impl/src/main/res/values-uz/translations.xml index 03a1f6ef7e..8941917f5f 100644 --- a/features/messages/impl/src/main/res/values-uz/translations.xml +++ b/features/messages/impl/src/main/res/values-uz/translations.xml @@ -7,15 +7,6 @@ "Nomaʼlum yoki oʻchirib tashlangan qurilma tomonidan shifrlangan." "Egasi tasdiqlamagan qurilma tomonidan shifrlangan." "Tasdiqlanmagan foydalanuvchi tomonidan shifrlangan." - "Faoliyatlar" - "Bayroqlar" - "Oziq-ovqat va ichimliklar" - "Hayvonlar va tabiat" - "Ob\'ektlar" - "Smayllar va odamlar" - "Sayohat va Joylar" - "Oxirgi kulgichlar" - "Belgilar" "Rasmni gorizontal ravishda aylantiring" "Gorizontal ravishda aylantirildi" "Asl nusxasi" 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 5104cd5a5b..a16d7378b3 100644 --- a/features/messages/impl/src/main/res/values-vi/translations.xml +++ b/features/messages/impl/src/main/res/values-vi/translations.xml @@ -7,15 +7,6 @@ "Đượ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 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." "Chặn người dùng" 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 0eea6e808e..e8cd285b5e 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 @@ -7,15 +7,6 @@ "由未知或已刪除的裝置加密。" "由未經其擁有者驗證的裝置加密。" "由未經驗證的使用者加密。" - "活動" - "旗幟" - "食物與飲料" - "動物與大自然" - "物品" - "表情與人物" - "旅行與景點" - "最近使用的表情符號" - "標誌" "使用舊應用程式的使用者可能看不到標題。" "輕點即可變更影片上傳品質" "無法上傳檔案。" 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 e2300912ae..41e55e1cce 100644 --- a/features/messages/impl/src/main/res/values-zh/translations.xml +++ b/features/messages/impl/src/main/res/values-zh/translations.xml @@ -7,15 +7,6 @@ "由未知或已删除的设备加密。" "由未经其所有者验证的设备加密。" "由未经验证的用户加密。" - "节假日" - "旗帜" - "饮食" - "动物和自然" - "日常物品" - "表情和人物" - "文旅景点" - "最近的 Emoji" - "符号" "水平翻转图像" "水平翻转" "原始" diff --git a/features/messages/impl/src/main/res/values/localazy.xml b/features/messages/impl/src/main/res/values/localazy.xml index e4790feba0..556ab00ee0 100644 --- a/features/messages/impl/src/main/res/values/localazy.xml +++ b/features/messages/impl/src/main/res/values/localazy.xml @@ -7,15 +7,6 @@ "Encrypted by an unknown or deleted device." "Encrypted by a device not verified by its owner." "Encrypted by an unverified user." - "Activities" - "Flags" - "Food & Drink" - "Animals & Nature" - "Objects" - "Smileys & People" - "Travel & Places" - "Recent emojis" - "Symbols" "Flip image horizontally" "Flipped horizontally" "Original" 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 5d2dceaf31..2800c737ad 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 @@ -31,7 +31,6 @@ import androidx.compose.ui.test.v2.runAndroidComposeUiTest import androidx.compose.ui.text.AnnotatedString import io.element.android.emojibasebindings.Emoji import io.element.android.emojibasebindings.EmojibaseCategory -import io.element.android.emojibasebindings.EmojibaseStore 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 @@ -48,6 +47,7 @@ import io.element.android.features.messages.impl.timeline.aTimelineItemList 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.aTimelineState +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.customreaction.CustomReactionState import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvent @@ -56,6 +56,8 @@ import io.element.android.features.messages.impl.timeline.components.receipt.bot import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent import io.element.android.features.roomcall.api.aStandByCallState +import io.element.android.libraries.emoji.impl.picker.DefaultEmojiPickerRenderer +import io.element.android.libraries.emoji.impl.picker.anEmojiPickerState 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.tombstone.SuccessorRoom @@ -538,24 +540,23 @@ class MessagesViewTest : RobolectricTest() { eventSink = eventsRecorder, ) val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event + val emojisByCategory = persistentMapOf( + EmojibaseCategory.People to persistentListOf( + Emoji( + hexcode = "", + label = "", + tags = persistentListOf(), + shortcodes = persistentListOf(), + unicode = aUnicode, + skins = null, + ) + ) + ) val stateWithCustomReactionState = state.copy( customReactionState = aCustomReactionState( target = CustomReactionState.Target.Success( event = timelineItem, - emojibaseStore = EmojibaseStore( - categories = persistentMapOf( - EmojibaseCategory.People to persistentListOf( - Emoji( - hexcode = "", - label = "", - tags = persistentListOf(), - shortcodes = persistentListOf(), - unicode = aUnicode, - skins = null, - ) - ) - ) - ), + emojiPickerState = anEmojiPickerState(emojis = emojisByCategory), ), eventSink = customReactionStateEventsRecorder ), @@ -695,6 +696,7 @@ private fun AndroidComposeUiTest.setMessagesView( onViewAllPinnedMessagesClick: () -> Unit = EnsureNeverCalled(), onThreadsListClicked: () -> Unit = EnsureNeverCalled(), ) { + val emojiPickerRenderer = DefaultEmojiPickerRenderer() setSafeContent { // Cannot use the RichTextEditor, so simulate a LocalInspectionMode CompositionLocalProvider(LocalInspectionMode provides true) { @@ -711,6 +713,15 @@ private fun AndroidComposeUiTest.setMessagesView( onJoinCallClick = onJoinCallClick, onViewAllPinnedMessagesClick = onViewAllPinnedMessagesClick, knockRequestsBannerView = {}, + customReactionBottomSheet = { + CustomReactionBottomSheet( + state = state.customReactionState, + onSelectEmoji = { uniqueId, emoji -> + state.eventSink(MessagesEvent.ToggleReaction(emoji.unicode, uniqueId)) + }, + emojiPickerRenderer = emojiPickerRenderer, + ) + }, onThreadsListClick = onThreadsListClicked, ) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt index d0765bd5e7..be765554de 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt @@ -11,11 +11,10 @@ package io.element.android.features.messages.impl.timeline.components.customreac import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineItemReactions -import io.element.android.libraries.emoji.test.FakeEmojibaseProvider +import io.element.android.libraries.emoji.impl.picker.anEmojiPickerState import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.test -import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -25,8 +24,7 @@ class CustomReactionPresenterTest { val warmUpRule = WarmUpRule() private val presenter = CustomReactionPresenter( - emojibaseProvider = FakeEmojibaseProvider(), - getRecentEmojis = { Result.success(persistentListOf()) }, + emojiPickerPresenter = { anEmojiPickerState() }, ) @Test diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenterTest.kt deleted file mode 100644 index 9ebbfd5a3a..0000000000 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerPresenterTest.kt +++ /dev/null @@ -1,125 +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.messages.impl.timeline.components.customreaction.picker - -import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd -import androidx.compose.runtime.InternalComposeApi -import androidx.compose.runtime.currentComposer -import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.platform.LocalContext -import androidx.test.platform.app.InstrumentationRegistry -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.TurbineTestContext -import app.cash.turbine.test -import com.google.common.truth.Truth.assertThat -import io.element.android.emojibasebindings.Emoji -import io.element.android.emojibasebindings.EmojibaseCategory -import io.element.android.emojibasebindings.EmojibaseStore -import io.element.android.libraries.designsystem.theme.components.SearchBarResultState -import io.element.android.tests.testutils.WarmUpRule -import io.element.android.tests.testutils.robolectric.RobolectricTest -import io.element.android.tests.testutils.testCoroutineDispatchers -import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.toImmutableMap -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runTest -import org.junit.Rule -import org.junit.Test - -class EmojiPickerPresenterTest : RobolectricTest() { - @get:Rule - val warmUpRule = WarmUpRule() - - @Test - fun `updating search query loads new results`() = runTest { - testPresenter { - skipItems(1) - - val initialState = awaitItem() - assertThat(initialState.searchQuery.text.toString()).isEmpty() - assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java) - - initialState.searchQuery.setTextAndPlaceCursorAtEnd("smile") - assertThat(awaitItem().searchQuery.text.toString()).isEqualTo("smile") - - val stateWithResults = awaitItem() - assertThat(stateWithResults.searchQuery.text.toString()).isEqualTo("smile") - assertThat(stateWithResults.searchResults).isInstanceOf(SearchBarResultState.Results::class.java) - } - } - - @Test - fun `ToggleSearchActive toggles the search state`() = runTest { - testPresenter { - skipItems(1) - - val initialState = awaitItem() - assertThat(initialState.isSearchActive).isFalse() - - initialState.eventSink(EmojiPickerEvent.ToggleSearchActive(true)) - assertThat(awaitItem().isSearchActive).isTrue() - - initialState.eventSink(EmojiPickerEvent.ToggleSearchActive(false)) - assertThat(awaitItem().isSearchActive).isFalse() - } - } - - @Test - fun `recent emojis are automatically added to the categories if present`() = runTest { - val providedCategories = persistentListOf(emojiCategory(EmojibaseCategory.Activity)) - val presenter = createPresenter( - categories = providedCategories, - recentEmojis = persistentListOf("😊"), - ) - testPresenter(presenter) { - skipItems(1) - - val initialState = awaitItem() - assertThat(providedCategories.size).isNotEqualTo(initialState.categories.size) - assertThat(initialState.categories.size).isEqualTo(2) - } - } - - private fun TestScope.createPresenter( - categories: ImmutableList>> = persistentListOf(emojiCategory()), - recentEmojis: ImmutableList = persistentListOf(), - ) = EmojiPickerPresenter( - emojibaseStore = EmojibaseStore(categories.toMap().toImmutableMap()), - recentEmojis = recentEmojis, - coroutineDispatchers = testCoroutineDispatchers(), - ) - - private fun emojiCategory( - category: EmojibaseCategory = EmojibaseCategory.Activity, - emojis: ImmutableList = persistentListOf( - Emoji("1F3C3", "Smile", persistentListOf("smile"), persistentListOf("smile"), "😊", skins = null) - ) - ) = category to emojis - - @OptIn(InternalComposeApi::class) - private suspend fun TestScope.testPresenter( - presenter: EmojiPickerPresenter = createPresenter(), - testBlock: suspend TurbineTestContext.() -> Unit, - ) { - moleculeFlow(RecompositionMode.Immediate) { - // These are needed to load the history icon in the presenter - currentComposer.startProviders(arrayOf( - LocalContext provides InstrumentationRegistry.getInstrumentation().context, - LocalConfiguration provides InstrumentationRegistry.getInstrumentation().context.resources.configuration, - )) - val state = presenter.present() - currentComposer.endProviders() - state - }.test { - testBlock() - } - } -} diff --git a/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerPresenter.kt b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerPresenter.kt new file mode 100644 index 0000000000..5e29ee01ab --- /dev/null +++ b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerPresenter.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.emoji.api.picker + +import io.element.android.libraries.architecture.Presenter + +fun interface EmojiPickerPresenter : Presenter diff --git a/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerRenderer.kt b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerRenderer.kt new file mode 100644 index 0000000000..6d2f67a5a6 --- /dev/null +++ b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerRenderer.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.emoji.api.picker + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.ui.Modifier +import io.element.android.emojibasebindings.Emoji +import kotlinx.collections.immutable.ImmutableSet + +@Immutable +interface EmojiPickerRenderer { + /** + * @param state opaque state produced by [EmojiPickerPresenter.present]. + * @param onSelectEmoji invoked when the user taps an emoji (including a skin-tone variant). + * @param selectedEmojis emojis to visually mark as already selected. + * @param modifier layout modifier for the picker container. + * @param contentDescription accessibility label for each emoji cell. + */ + @Composable + fun Render( + state: EmojiPickerState, + onSelectEmoji: (Emoji) -> Unit, + selectedEmojis: ImmutableSet, + modifier: Modifier = Modifier, + contentDescription: @Composable (Emoji, Boolean) -> String = { emoji, _ -> emoji.unicode }, + ) +} diff --git a/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerState.kt b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerState.kt new file mode 100644 index 0000000000..a5c820e648 --- /dev/null +++ b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerState.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.emoji.api.picker + +/** + * Opaque state produced by an [EmojiPickerPresenter] and consumed by an [EmojiPickerRenderer]. + */ +interface EmojiPickerState { + /** + * `true` once the picker has finished loading its data and is safe to display. + * Callers should typically defer showing the picker (or its container, e.g. a bottom sheet) + * until this flips to `true` to avoid flashing an empty picker. + */ + val isReady: Boolean +} diff --git a/libraries/emoji/impl/build.gradle.kts b/libraries/emoji/impl/build.gradle.kts index 871c19a41a..1cb274e6c0 100644 --- a/libraries/emoji/impl/build.gradle.kts +++ b/libraries/emoji/impl/build.gradle.kts @@ -35,7 +35,6 @@ dependencies { implementation(libs.kotlinx.collections.immutable) implementation(libs.matrix.emojibase.bindings) - testImplementation(projects.libraries.emoji.test) testImplementation(projects.libraries.matrix.test) testCommonDependencies(libs) } diff --git a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/DefaultEmojibaseProvider.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/DefaultEmojibaseProvider.kt index f0ad797648..9f64879a80 100644 --- a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/DefaultEmojibaseProvider.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/DefaultEmojibaseProvider.kt @@ -11,16 +11,28 @@ package io.element.android.libraries.emoji.impl import android.content.Context import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.Inject import dev.zacsweers.metro.SingleIn import io.element.android.emojibasebindings.EmojibaseDatasource import io.element.android.emojibasebindings.EmojibaseStore +import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.di.annotations.AppCoroutineScope import io.element.android.libraries.di.annotations.ApplicationContext -import io.element.android.libraries.emoji.api.EmojibaseProvider +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.async +@Inject @SingleIn(AppScope::class) @ContributesBinding(AppScope::class) -class DefaultEmojibaseProvider(@ApplicationContext val context: Context) : EmojibaseProvider { - override val emojibaseStore: EmojibaseStore by lazy { +class DefaultEmojibaseProvider( + @ApplicationContext private val context: Context, + dispatchers: CoroutineDispatchers, + @AppCoroutineScope appScope: CoroutineScope, +) : EmojibaseProvider { + private val deferred = appScope.async(dispatchers.io, start = CoroutineStart.LAZY) { EmojibaseDatasource().load(context) } + + override suspend fun getStore(): EmojibaseStore = deferred.await() } diff --git a/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/EmojibaseProvider.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/EmojibaseProvider.kt similarity index 60% rename from libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/EmojibaseProvider.kt rename to libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/EmojibaseProvider.kt index d8f9c92777..ddd18f8861 100644 --- a/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/EmojibaseProvider.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/EmojibaseProvider.kt @@ -1,15 +1,14 @@ /* - * 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.emoji.api +package io.element.android.libraries.emoji.impl import io.element.android.emojibasebindings.EmojibaseStore interface EmojibaseProvider { - val emojibaseStore: EmojibaseStore + suspend fun getStore(): EmojibaseStore } diff --git a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt new file mode 100644 index 0000000000..e7afe50c0f --- /dev/null +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt @@ -0,0 +1,133 @@ +/* + * 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.emoji.impl.picker + +import androidx.compose.foundation.text.input.rememberTextFieldState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +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 androidx.compose.ui.platform.LocalInspectionMode +import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.Inject +import io.element.android.emojibasebindings.Emoji +import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.designsystem.theme.components.IconSource +import io.element.android.libraries.designsystem.theme.components.SearchBarResultState +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.emoji.api.picker.EmojiPickerPresenter +import io.element.android.libraries.emoji.api.picker.EmojiPickerState +import io.element.android.libraries.emoji.api.recentemojis.GetRecentEmojis +import io.element.android.libraries.emoji.impl.EmojibaseProvider +import io.element.android.libraries.emoji.impl.R +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.async +import kotlinx.coroutines.delay +import kotlinx.coroutines.withContext +import kotlin.time.Duration.Companion.milliseconds + +@Inject +@ContributesBinding(SessionScope::class) +class DefaultEmojiPickerPresenter( + private val emojibaseProvider: EmojibaseProvider, + private val getRecentEmojis: GetRecentEmojis, + private val coroutineDispatchers: CoroutineDispatchers, +) : EmojiPickerPresenter { + @Composable + override fun present(): EmojiPickerState { + val queryState = rememberTextFieldState() + var isSearchActive by remember { mutableStateOf(false) } + var emojiResults by remember { mutableStateOf>>(SearchBarResultState.Initial()) } + + val data by produceState(EmojiPickerData.Empty) { + val storeDeferred = async { emojibaseProvider.getStore() } + val recentsDeferred = async { getRecentEmojis().getOrNull() ?: persistentListOf() } + val store = storeDeferred.await() + val recentEmojiUnicodes = recentsDeferred.await() + value = withContext(coroutineDispatchers.computation) { + val baseCategories = store.categories.map { (category, emojis) -> + EmojiCategory( + titleId = category.title, + icon = IconSource.Vector(category.icon), + emojis = emojis, + ) + } + val recentEmojis = recentEmojiUnicodes + .mapNotNull { unicode -> store.allEmojis.find { it.unicode == unicode } } + .toImmutableList() + val categories = if (recentEmojis.isEmpty()) { + baseCategories.toImmutableList() + } else { + val recentCategory = EmojiCategory( + titleId = R.string.emoji_picker_category_recent, + icon = IconSource.Resource(io.element.android.compound.R.drawable.ic_compound_history), + emojis = recentEmojis, + ) + (listOf(recentCategory) + baseCategories).toImmutableList() + } + EmojiPickerData( + categories = categories, + allEmojis = store.allEmojis, + ) + } + } + + val searchQuery = queryState.text.toString() + LaunchedEffect(searchQuery, data) { + if (searchQuery.isEmpty() || data.allEmojis.isEmpty()) { + emojiResults = SearchBarResultState.Initial() + return@LaunchedEffect + } + delay(100.milliseconds) + val lowercaseQuery = searchQuery.lowercase() + val results = withContext(coroutineDispatchers.computation) { + data.allEmojis + .asSequence() + .filter { emoji -> + emoji.tags.orEmpty().any { it.contains(lowercaseQuery) } || + emoji.shortcodes.any { it.contains(lowercaseQuery) } + } + .take(60) + .toImmutableList() + } + emojiResults = SearchBarResultState.Results(results) + } + + val isInPreview = LocalInspectionMode.current + fun handleEvent(event: EmojiPickerEvent) { + when (event) { + is EmojiPickerEvent.ToggleSearchActive -> if (!isInPreview) { + isSearchActive = event.isActive + } + } + } + + return DefaultEmojiPickerState( + categories = data.categories, + searchQuery = queryState, + isSearchActive = isSearchActive, + searchResults = emojiResults, + eventSink = ::handleEvent, + ) + } +} + +private data class EmojiPickerData( + val categories: ImmutableList, + val allEmojis: ImmutableList, +) { + companion object { + val Empty = EmojiPickerData(persistentListOf(), persistentListOf()) + } +} diff --git a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerRenderer.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerRenderer.kt new file mode 100644 index 0000000000..4b6fcd8554 --- /dev/null +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerRenderer.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.emoji.impl.picker + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.Inject +import io.element.android.emojibasebindings.Emoji +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.emoji.api.picker.EmojiPickerRenderer +import io.element.android.libraries.emoji.api.picker.EmojiPickerState +import kotlinx.collections.immutable.ImmutableSet + +@Inject +@ContributesBinding(SessionScope::class) +class DefaultEmojiPickerRenderer : EmojiPickerRenderer { + @Composable + override fun Render( + state: EmojiPickerState, + onSelectEmoji: (Emoji) -> Unit, + selectedEmojis: ImmutableSet, + modifier: Modifier, + contentDescription: @Composable (Emoji, Boolean) -> String, + ) { + if (state is DefaultEmojiPickerState) { + EmojiPickerView( + state = state, + onSelectEmoji = onSelectEmoji, + selectedEmojis = selectedEmojis, + contentDescription = contentDescription, + modifier = modifier, + ) + } else { + error("Unsupported state type: ${state::class.java}") + } + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerState.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerState.kt similarity index 72% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerState.kt rename to libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerState.kt index c1d306dece..8b3835724b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerState.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerState.kt @@ -6,7 +6,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.messages.impl.timeline.components.customreaction.picker +package io.element.android.libraries.emoji.impl.picker import androidx.annotation.StringRes import androidx.compose.foundation.text.input.TextFieldState @@ -14,23 +14,21 @@ import androidx.compose.runtime.Immutable import io.element.android.emojibasebindings.Emoji import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.SearchBarResultState +import io.element.android.libraries.emoji.api.picker.EmojiPickerState import kotlinx.collections.immutable.ImmutableList -// Emoji is unstable (because from an external library?), so we annotate with @Immutable @Immutable -data class EmojiPickerState( +internal data class DefaultEmojiPickerState( val categories: ImmutableList, - val allEmojis: ImmutableList, val searchQuery: TextFieldState, val isSearchActive: Boolean, val searchResults: SearchBarResultState>, val eventSink: (EmojiPickerEvent) -> Unit, -) +) : EmojiPickerState { + override val isReady = categories.isNotEmpty() +} -/** - * Represents a category of emojis with a title id, icon, and the list of associated emojis. - */ -data class EmojiCategory( +internal data class EmojiCategory( @StringRes val titleId: Int, val icon: IconSource, val emojis: ImmutableList, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerStateProvider.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerStateProvider.kt similarity index 58% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerStateProvider.kt rename to libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerStateProvider.kt index 958b3849f5..0a091a2b66 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerStateProvider.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerStateProvider.kt @@ -6,29 +6,26 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.messages.impl.timeline.components.customreaction.picker +package io.element.android.libraries.emoji.impl.picker import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.emojibasebindings.Emoji import io.element.android.emojibasebindings.EmojibaseCategory -import io.element.android.features.messages.impl.R -import io.element.android.features.messages.impl.timeline.components.customreaction.icon -import io.element.android.features.messages.impl.timeline.components.customreaction.title -import io.element.android.libraries.designsystem.icons.CompoundDrawables import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.SearchBarResultState +import io.element.android.libraries.emoji.api.picker.EmojiPickerState import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList -class EmojiPickerStateProvider : PreviewParameterProvider { - override val values: Sequence +internal class DefaultEmojiPickerStateProvider : PreviewParameterProvider { + override val values: Sequence get() = sequenceOf( - anEmojiPickerState(), - anEmojiPickerState(isSearchActive = true), - anEmojiPickerState(isSearchActive = true, searchQuery = "smile"), - anEmojiPickerState( + aDefaultEmojiPickerState(), + aDefaultEmojiPickerState(isSearchActive = true), + aDefaultEmojiPickerState(isSearchActive = true, searchQuery = "smile"), + aDefaultEmojiPickerState( isSearchActive = true, searchQuery = "smile", searchResults = SearchBarResultState.Results(emojiList()) @@ -36,12 +33,6 @@ class EmojiPickerStateProvider : PreviewParameterProvider { ) } -private fun recentEmojisCategory() = EmojiCategory( - titleId = R.string.emoji_picker_category_recent, - icon = IconSource.Resource(CompoundDrawables.ic_compound_history), - emojis = emojiList(), -) - private fun emojiList(): ImmutableList = persistentListOf( Emoji( "0x00", @@ -56,29 +47,46 @@ private fun emojiList(): ImmutableList = persistentListOf( "crying face", persistentListOf("crying"), persistentListOf("smile, crying"), - "\uD83E\uDD72", + "🥲", null ) ) -internal fun anEmojiPickerState( - categories: ImmutableList = (listOf(recentEmojisCategory()) + EmojibaseCategory.entries.map { +internal fun aDefaultEmojiPickerState( + categories: ImmutableList = EmojibaseCategory.entries.map { EmojiCategory( titleId = it.title, icon = IconSource.Vector(it.icon), emojis = emojiList(), ) - }).toImmutableList(), - allEmojis: ImmutableList = categories.flatMap { it.emojis }.toImmutableList(), + }.toImmutableList(), searchQuery: String = "", isSearchActive: Boolean = false, searchResults: SearchBarResultState> = SearchBarResultState.Initial(), eventSink: (EmojiPickerEvent) -> Unit = {}, -) = EmojiPickerState( +) = DefaultEmojiPickerState( categories = categories, - allEmojis = allEmojis, searchQuery = TextFieldState(initialText = searchQuery), isSearchActive = isSearchActive, searchResults = searchResults, eventSink = eventSink, ) + +/** + * Public helper for external tests that need an [EmojiPickerState] instance the impl's + * [DefaultEmojiPickerRenderer] will accept. The no-arg overload returns a ready state + * (see [EmojiPickerState.isReady]); use the [emojis] overload to inject specific categories. + */ +fun anEmojiPickerState(): EmojiPickerState = aDefaultEmojiPickerState() + +fun anEmojiPickerState( + emojis: Map>, +): EmojiPickerState = aDefaultEmojiPickerState( + categories = emojis.map { (category, list) -> + EmojiCategory( + titleId = category.title, + icon = IconSource.Vector(category.icon), + emojis = list, + ) + }.toImmutableList(), +) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojiItem.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiItem.kt similarity index 86% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojiItem.kt rename to libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiItem.kt index db3a70715d..27c80af961 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojiItem.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiItem.kt @@ -6,7 +6,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.messages.impl.timeline.components.customreaction +package io.element.android.libraries.emoji.impl.picker import androidx.compose.foundation.Canvas import androidx.compose.foundation.background @@ -52,12 +52,6 @@ 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.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.features.messages.impl.timeline.components.customreaction.picker.aSkinList 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 @@ -66,7 +60,7 @@ import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentSetOf @Composable -fun EmojiItem( +internal fun EmojiItem( item: Emoji, isSelected: Boolean, onSelectEmoji: (Emoji) -> Unit, @@ -75,6 +69,7 @@ fun EmojiItem( skinPickerEmoji: Emoji?, selectedSkinUnicodes: ImmutableSet, hasSelectedSkin: Boolean, + contentDescription: @Composable (emoji: Emoji, isSelected: Boolean) -> String = { emoji, _ -> emoji.unicode }, modifier: Modifier = Modifier, emojiSize: TextUnit = 20.sp, ) { @@ -89,18 +84,13 @@ fun EmojiItem( var hoveredIndex by remember { mutableIntStateOf(-1) } var dismissed by remember { mutableStateOf(false) } val interactionSource = remember { MutableInteractionSource() } - val description = a11yReactionAction( - emoji = item.unicode, - userAlreadyReacted = isSelected, - ) + val description = contentDescription(item, isSelected) 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 { @@ -112,7 +102,6 @@ fun EmojiItem( .background(backgroundColor, CircleShape) .indication(interactionSource, ripple()) .pointerInput(item) { - // Always detect long press and tap gestures detectTapGestures( onPress = { pressOffset -> val press = PressInteraction.Press(pressOffset) @@ -130,7 +119,6 @@ fun EmojiItem( ) } .then( - // Only detect drag after long press for those items which have a skin tone picker if (hasSkinTones) { Modifier.pointerInput(item) { val slotWidthPx = with(density) { SkinToneSlotSize.toPx() } @@ -147,8 +135,6 @@ fun EmojiItem( 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 { @@ -160,15 +146,11 @@ fun EmojiItem( onDismissSkinPicker() } else { 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 - // 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 { @@ -210,7 +192,7 @@ fun EmojiItem( } ) .clearAndSetSemantics { - contentDescription = description + this.contentDescription = description }, contentAlignment = Alignment.Center ) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerEvent.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiPickerEvent.kt similarity index 71% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerEvent.kt rename to libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiPickerEvent.kt index 6ea5eea0f6..57cbf8e08b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPickerEvent.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiPickerEvent.kt @@ -6,8 +6,8 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.messages.impl.timeline.components.customreaction.picker +package io.element.android.libraries.emoji.impl.picker -sealed interface EmojiPickerEvent { +internal sealed interface EmojiPickerEvent { data class ToggleSearchActive(val isActive: Boolean) : EmojiPickerEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiPickerView.kt similarity index 91% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt rename to libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiPickerView.kt index ce65a435f4..325f1d792b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/EmojiPicker.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiPickerView.kt @@ -6,7 +6,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.messages.impl.timeline.components.customreaction.picker +package io.element.android.libraries.emoji.impl.picker import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -35,7 +35,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.emojibasebindings.Emoji -import io.element.android.features.messages.impl.timeline.components.customreaction.EmojiItem import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.text.toSp @@ -50,11 +49,12 @@ import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @Composable -fun EmojiPicker( +internal fun EmojiPickerView( + state: DefaultEmojiPickerState, onSelectEmoji: (Emoji) -> Unit, - state: EmojiPickerState, selectedEmojis: ImmutableSet, modifier: Modifier = Modifier, + contentDescription: @Composable (emoji: Emoji, isSelected: Boolean) -> String = { emoji, _ -> emoji.unicode }, ) { val coroutineScope = rememberCoroutineScope() val pagerState = rememberPagerState(pageCount = { state.categories.size }) @@ -78,6 +78,7 @@ fun EmojiPicker( skinPickerEmoji = skinPickerEmoji, onDismissSkinPicker = { skinPickerEmoji = null }, selectedEmojis = selectedEmojis, + contentDescription = contentDescription, ) } @@ -120,6 +121,7 @@ fun EmojiPicker( skinPickerEmoji = skinPickerEmoji, onDismissSkinPicker = { skinPickerEmoji = null }, selectedEmojis = selectedEmojis, + contentDescription = contentDescription, ) } } @@ -135,6 +137,7 @@ private fun EmojiResults( skinPickerEmoji: Emoji?, onDismissSkinPicker: () -> Unit, selectedEmojis: ImmutableSet, + contentDescription: @Composable (emoji: Emoji, isSelected: Boolean) -> String, ) { LazyVerticalGrid( modifier = Modifier.fillMaxSize(), @@ -155,6 +158,7 @@ private fun EmojiResults( emojiSize = 32.dp.toSp(), selectedSkinUnicodes = selectedEmojis, hasSelectedSkin = item.skins?.any { skin -> skin.unicode in selectedEmojis } == true, + contentDescription = contentDescription, ) } } @@ -162,10 +166,10 @@ private fun EmojiResults( @PreviewsDayNight @Composable -internal fun EmojiPickerPreview(@PreviewParameter(EmojiPickerStateProvider::class) state: EmojiPickerState) = ElementPreview { - EmojiPicker( - onSelectEmoji = {}, +internal fun EmojiPickerViewPreview(@PreviewParameter(DefaultEmojiPickerStateProvider::class) state: DefaultEmojiPickerState) = ElementPreview { + EmojiPickerView( state = state, + onSelectEmoji = {}, selectedEmojis = persistentSetOf("😀", "😄", "😃"), modifier = Modifier.fillMaxWidth(), ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojibaseExtensions.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojibaseExtensions.kt similarity index 91% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojibaseExtensions.kt rename to libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojibaseExtensions.kt index 0f967cc41d..c6b428a13d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/EmojibaseExtensions.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojibaseExtensions.kt @@ -6,7 +6,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.messages.impl.timeline.components.customreaction +package io.element.android.libraries.emoji.impl.picker import androidx.annotation.StringRes import androidx.compose.material.icons.Icons @@ -20,10 +20,10 @@ import androidx.compose.material.icons.outlined.EmojiSymbols import androidx.compose.material.icons.outlined.EmojiTransportation import androidx.compose.ui.graphics.vector.ImageVector import io.element.android.emojibasebindings.EmojibaseCategory -import io.element.android.features.messages.impl.R +import io.element.android.libraries.emoji.impl.R @get:StringRes -val EmojibaseCategory.title: Int +internal val EmojibaseCategory.title: Int get() = when (this) { EmojibaseCategory.People -> R.string.emoji_picker_category_people EmojibaseCategory.Nature -> R.string.emoji_picker_category_nature @@ -35,7 +35,7 @@ val EmojibaseCategory.title: Int EmojibaseCategory.Flags -> R.string.emoji_picker_category_flags } -val EmojibaseCategory.icon: ImageVector +internal val EmojibaseCategory.icon: ImageVector get() = when (this) { EmojibaseCategory.People -> Icons.Outlined.EmojiPeople EmojibaseCategory.Nature -> Icons.Outlined.EmojiNature diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/SkinTonePicker.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/SkinTonePicker.kt similarity index 95% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/SkinTonePicker.kt rename to libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/SkinTonePicker.kt index 1ac66b5378..6d2618873a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/picker/SkinTonePicker.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/SkinTonePicker.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.messages.impl.timeline.components.customreaction.picker +package io.element.android.libraries.emoji.impl.picker import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -36,12 +36,12 @@ import kotlinx.collections.immutable.ImmutableSet import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentSetOf -val SkinToneSlotSize = 48.dp -val SkinToneSlotSpacing = 2.dp -val SkinTonePadding = 4.dp +internal val SkinToneSlotSize = 48.dp +internal val SkinToneSlotSpacing = 2.dp +internal val SkinTonePadding = 4.dp @Composable -fun SkinTonePicker( +internal fun SkinTonePicker( emoji: Emoji, hoveredIndex: Int, selectedUnicodes: ImmutableSet, diff --git a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultGetRecentEmojis.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultGetRecentEmojis.kt index acd5e012ce..412332e984 100644 --- a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultGetRecentEmojis.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultGetRecentEmojis.kt @@ -11,8 +11,8 @@ package io.element.android.libraries.emoji.impl.recentemojis import dev.zacsweers.metro.ContributesBinding import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.di.SessionScope -import io.element.android.libraries.emoji.api.EmojibaseProvider import io.element.android.libraries.emoji.api.recentemojis.GetRecentEmojis +import io.element.android.libraries.emoji.impl.EmojibaseProvider import io.element.android.libraries.matrix.api.MatrixClient import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList @@ -25,7 +25,7 @@ class DefaultGetRecentEmojis( private val emojibaseProvider: EmojibaseProvider, ) : GetRecentEmojis { override suspend operator fun invoke(): Result> = withContext(dispatchers.io) { - val allEmojis = emojibaseProvider.emojibaseStore.allEmojis + val allEmojis = emojibaseProvider.getStore().allEmojis client.getRecentEmojis() .map { emojis -> // Remove any possible duplicates diff --git a/libraries/emoji/impl/src/main/res/values/temporary.xml b/libraries/emoji/impl/src/main/res/values/temporary.xml new file mode 100644 index 0000000000..34467795b9 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values/temporary.xml @@ -0,0 +1,13 @@ + + + + "Activities" + "Flags" + "Food & Drink" + "Animals & Nature" + "Objects" + "Smileys & People" + "Travel & Places" + "Recent emojis" + "Symbols" + diff --git a/libraries/emoji/test/src/main/kotlin/io/element/android/libraries/emoji/test/FakeEmojibaseProvider.kt b/libraries/emoji/impl/src/test/kotlin/io/element/android/libraries/emoji/impl/fixtures/FakeEmojibaseProvider.kt similarity index 60% rename from libraries/emoji/test/src/main/kotlin/io/element/android/libraries/emoji/test/FakeEmojibaseProvider.kt rename to libraries/emoji/impl/src/test/kotlin/io/element/android/libraries/emoji/impl/fixtures/FakeEmojibaseProvider.kt index 0e7c42e538..f01b6a1268 100644 --- a/libraries/emoji/test/src/main/kotlin/io/element/android/libraries/emoji/test/FakeEmojibaseProvider.kt +++ b/libraries/emoji/impl/src/test/kotlin/io/element/android/libraries/emoji/impl/fixtures/FakeEmojibaseProvider.kt @@ -6,18 +6,18 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.emoji.test +package io.element.android.libraries.emoji.impl.fixtures import io.element.android.emojibasebindings.Emoji import io.element.android.emojibasebindings.EmojibaseCategory import io.element.android.emojibasebindings.EmojibaseStore -import io.element.android.libraries.emoji.api.EmojibaseProvider +import io.element.android.libraries.emoji.impl.EmojibaseProvider import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toPersistentMap -class FakeEmojibaseProvider( - val emojis: Map> = mapOf(), +internal class FakeEmojibaseProvider( + emojis: Map> = mapOf(), ) : EmojibaseProvider { - override val emojibaseStore: EmojibaseStore - get() = EmojibaseStore(emojis.toPersistentMap()) + private val store = EmojibaseStore(emojis.toPersistentMap()) + override suspend fun getStore(): EmojibaseStore = store } diff --git a/libraries/emoji/impl/src/test/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiPickerPresenterTest.kt b/libraries/emoji/impl/src/test/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiPickerPresenterTest.kt new file mode 100644 index 0000000000..cf1a68f9d5 --- /dev/null +++ b/libraries/emoji/impl/src/test/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiPickerPresenterTest.kt @@ -0,0 +1,112 @@ +/* + * 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.emoji.impl.picker + +import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd +import app.cash.turbine.TurbineTestContext +import com.google.common.truth.Truth.assertThat +import io.element.android.emojibasebindings.Emoji +import io.element.android.emojibasebindings.EmojibaseCategory +import io.element.android.libraries.designsystem.theme.components.SearchBarResultState +import io.element.android.libraries.emoji.api.picker.EmojiPickerState +import io.element.android.libraries.emoji.api.recentemojis.GetRecentEmojis +import io.element.android.libraries.emoji.impl.fixtures.FakeEmojibaseProvider +import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.robolectric.RobolectricTest +import io.element.android.tests.testutils.test +import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test + +class EmojiPickerPresenterTest : RobolectricTest() { + @get:Rule + val warmUpRule = WarmUpRule() + + @Test + fun `updating search query loads new results`() = runTest { + createPresenter().test { + val initialState = awaitStoreLoaded() + assertThat(initialState.searchQuery.text.toString()).isEmpty() + assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java) + + initialState.searchQuery.setTextAndPlaceCursorAtEnd("smile") + val stateAfterQuery = awaitItem() as DefaultEmojiPickerState + assertThat(stateAfterQuery.searchQuery.text.toString()).isEqualTo("smile") + + val stateWithResults = awaitItem() as DefaultEmojiPickerState + assertThat(stateWithResults.searchQuery.text.toString()).isEqualTo("smile") + assertThat(stateWithResults.searchResults).isInstanceOf(SearchBarResultState.Results::class.java) + } + } + + @Test + fun `recent emojis are prepended as a category when the source returns any`() = runTest { + createPresenter( + categories = persistentListOf(emojiCategory(EmojibaseCategory.Activity)), + getRecentEmojis = GetRecentEmojis { Result.success(persistentListOf("😊")) }, + ).test { + val state = awaitStoreLoaded() + assertThat(state.categories.size).isEqualTo(2) + } + } + + @Test + fun `ToggleSearchActive toggles the search state`() = runTest { + createPresenter().test { + val initialState = awaitStoreLoaded() + assertThat(initialState.isSearchActive).isFalse() + + initialState.eventSink(EmojiPickerEvent.ToggleSearchActive(true)) + assertThat((awaitItem() as DefaultEmojiPickerState).isSearchActive).isTrue() + + initialState.eventSink(EmojiPickerEvent.ToggleSearchActive(false)) + assertThat((awaitItem() as DefaultEmojiPickerState).isSearchActive).isFalse() + } + } + + @Test + fun `presenter exposes categories from the emoji store when the recent source is empty`() = runTest { + val providedCategories = persistentListOf( + emojiCategory(EmojibaseCategory.Activity), + emojiCategory(EmojibaseCategory.People), + ) + createPresenter(categories = providedCategories).test { + val state = awaitStoreLoaded() + assertThat(state.categories.size).isEqualTo(providedCategories.size) + } + } + + private suspend fun TurbineTestContext.awaitStoreLoaded(): DefaultEmojiPickerState { + var state = awaitItem() as DefaultEmojiPickerState + while (state.categories.isEmpty()) { + state = awaitItem() as DefaultEmojiPickerState + } + return state + } + + private fun TestScope.createPresenter( + categories: ImmutableList>> = persistentListOf(emojiCategory()), + getRecentEmojis: GetRecentEmojis = GetRecentEmojis { Result.success(persistentListOf()) }, + ) = DefaultEmojiPickerPresenter( + emojibaseProvider = FakeEmojibaseProvider(emojis = categories.toMap()), + getRecentEmojis = getRecentEmojis, + coroutineDispatchers = testCoroutineDispatchers(), + ) + + private fun emojiCategory( + category: EmojibaseCategory = EmojibaseCategory.Activity, + emojis: ImmutableList = persistentListOf( + Emoji("1F3C3", "Smile", persistentListOf("smile"), persistentListOf("smile"), "😊", skins = null) + ) + ) = category to emojis +} diff --git a/libraries/emoji/impl/src/test/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultGetRecentEmojisTest.kt b/libraries/emoji/impl/src/test/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultGetRecentEmojisTest.kt index 2ae8a86c25..822e6e652a 100644 --- a/libraries/emoji/impl/src/test/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultGetRecentEmojisTest.kt +++ b/libraries/emoji/impl/src/test/kotlin/io/element/android/libraries/emoji/impl/recentemojis/DefaultGetRecentEmojisTest.kt @@ -12,7 +12,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.emojibasebindings.Emoji import io.element.android.emojibasebindings.EmojibaseCategory import io.element.android.emojibasebindings.EmojibaseCategory.People -import io.element.android.libraries.emoji.test.FakeEmojibaseProvider +import io.element.android.libraries.emoji.impl.fixtures.FakeEmojibaseProvider import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.collections.immutable.ImmutableList diff --git a/libraries/emoji/test/build.gradle.kts b/libraries/emoji/test/build.gradle.kts deleted file mode 100644 index 42192c8061..0000000000 --- a/libraries/emoji/test/build.gradle.kts +++ /dev/null @@ -1,25 +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. - */ - -plugins { - id("io.element.android-library") -} - -android { - namespace = "io.element.android.libraries.emoji.test" -} - -dependencies { - api(projects.libraries.emoji.api) - api(projects.libraries.matrix.api) - api(libs.coroutines.core) - - implementation(libs.kotlinx.collections.immutable) - implementation(libs.coroutines.test) - implementation(libs.matrix.emojibase.bindings) - implementation(projects.tests.testutils) -} From 93d6d5c84c6edbd0eb93bc6dab6d967d0a198050 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 22 Jul 2026 15:31:40 +0200 Subject: [PATCH 164/383] Migrate EmojiPickerPresenter to assisted-factory pattern with EmptyGetRecentEmojis --- .../CustomReactionBottomSheet.kt | 2 -- .../customreaction/CustomReactionPresenter.kt | 5 ++++- .../CustomReactionPresenterTest.kt | 9 ++++----- libraries/emoji/api/build.gradle.kts | 2 +- .../emoji/api/picker/EmojiPickerPresenter.kt | 7 ++++++- .../emoji/api/recentemojis/GetRecentEmojis.kt | 9 +++++++++ .../picker/DefaultEmojiPickerPresenter.kt | 19 ++++++++++++++----- 7 files changed, 38 insertions(+), 15 deletions(-) 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 cc971e16ba..c90a0e5acc 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 @@ -37,7 +37,6 @@ fun CustomReactionBottomSheet( CustomReactionState.Target.None, is CustomReactionState.Target.Loading -> Unit is CustomReactionState.Target.Success -> { - fun onEmojiSelectedDismiss(emoji: Emoji) { sheetState.hide(coroutineScope) { state.eventSink(CustomReactionEvent.DismissCustomReactionSheet) @@ -49,7 +48,6 @@ fun CustomReactionBottomSheet( state.eventSink(CustomReactionEvent.DismissCustomReactionSheet) } - ModalBottomSheet( onDismissRequest = ::onDismiss, sheetState = sheetState, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt index 7a9f5fe4ff..fe68092be0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenter.kt @@ -17,12 +17,15 @@ import dev.zacsweers.metro.Inject import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.emoji.api.picker.EmojiPickerPresenter +import io.element.android.libraries.emoji.api.recentemojis.GetRecentEmojis import kotlinx.collections.immutable.toImmutableSet @Inject class CustomReactionPresenter( - private val emojiPickerPresenter: EmojiPickerPresenter, + emojiPickerPresenterFactory: EmojiPickerPresenter.Factory, + getRecentEmojis: GetRecentEmojis, ) : Presenter { + private val emojiPickerPresenter = emojiPickerPresenterFactory.create(getRecentEmojis) @Composable override fun present(): CustomReactionState { var internalTarget by remember { mutableStateOf(InternalTarget.None) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt index be765554de..8ba316ea4d 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt @@ -11,6 +11,8 @@ package io.element.android.features.messages.impl.timeline.components.customreac import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineItemReactions +import io.element.android.libraries.emoji.api.picker.EmojiPickerPresenter +import io.element.android.libraries.emoji.api.recentemojis.EmptyGetRecentEmojis import io.element.android.libraries.emoji.impl.picker.anEmojiPickerState import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.tests.testutils.WarmUpRule @@ -24,7 +26,8 @@ class CustomReactionPresenterTest { val warmUpRule = WarmUpRule() private val presenter = CustomReactionPresenter( - emojiPickerPresenter = { anEmojiPickerState() }, + emojiPickerPresenterFactory = EmojiPickerPresenter.Factory { EmojiPickerPresenter { anEmojiPickerState() } }, + getRecentEmojis = EmptyGetRecentEmojis, ) @Test @@ -36,8 +39,6 @@ class CustomReactionPresenterTest { initialState.eventSink(CustomReactionEvent.ShowCustomReactionSheet(event)) - assertThat(awaitItem().target).isEqualTo(CustomReactionState.Target.Loading(event)) - val eventId = (awaitItem().target as? CustomReactionState.Target.Success)?.event?.eventId assertThat(eventId).isEqualTo(AN_EVENT_ID) @@ -57,8 +58,6 @@ class CustomReactionPresenterTest { val key = reactions.reactions.first().key initialState.eventSink(CustomReactionEvent.ShowCustomReactionSheet(event)) - assertThat(awaitItem().target).isEqualTo(CustomReactionState.Target.Loading(event)) - val stateWithSelectedEmojis = awaitItem() val eventId = (stateWithSelectedEmojis.target as? CustomReactionState.Target.Success)?.event?.eventId assertThat(eventId).isEqualTo(AN_EVENT_ID) diff --git a/libraries/emoji/api/build.gradle.kts b/libraries/emoji/api/build.gradle.kts index 749e13a4c7..48143d9512 100644 --- a/libraries/emoji/api/build.gradle.kts +++ b/libraries/emoji/api/build.gradle.kts @@ -18,5 +18,5 @@ dependencies { implementation(projects.libraries.matrix.api) implementation(libs.kotlinx.collections.immutable) - implementation(libs.matrix.emojibase.bindings) + api(libs.matrix.emojibase.bindings) } diff --git a/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerPresenter.kt b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerPresenter.kt index 5e29ee01ab..a20b53a480 100644 --- a/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerPresenter.kt +++ b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/picker/EmojiPickerPresenter.kt @@ -8,5 +8,10 @@ package io.element.android.libraries.emoji.api.picker import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.emoji.api.recentemojis.GetRecentEmojis -fun interface EmojiPickerPresenter : Presenter +fun interface EmojiPickerPresenter : Presenter { + fun interface Factory { + fun create(getRecentEmojis: GetRecentEmojis): EmojiPickerPresenter + } +} diff --git a/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/recentemojis/GetRecentEmojis.kt b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/recentemojis/GetRecentEmojis.kt index 9a9983805e..cf6015d799 100644 --- a/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/recentemojis/GetRecentEmojis.kt +++ b/libraries/emoji/api/src/main/kotlin/io/element/android/libraries/emoji/api/recentemojis/GetRecentEmojis.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.emoji.api.recentemojis import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf /** * Returns the list of recently used emojis for reactions. @@ -16,3 +17,11 @@ import kotlinx.collections.immutable.ImmutableList fun interface GetRecentEmojis { suspend operator fun invoke(): Result> } + +/** + * A [GetRecentEmojis] that never returns any recent emojis. Handy for pickers that don't want + * a "Recent" tab (e.g. the user-status picker). + */ +object EmptyGetRecentEmojis : GetRecentEmojis { + override suspend fun invoke(): Result> = Result.success(persistentListOf()) +} diff --git a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt index e7afe50c0f..6a0c4924b3 100644 --- a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt @@ -17,8 +17,10 @@ import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalInspectionMode +import dev.zacsweers.metro.Assisted +import dev.zacsweers.metro.AssistedFactory +import dev.zacsweers.metro.AssistedInject import dev.zacsweers.metro.ContributesBinding -import dev.zacsweers.metro.Inject import io.element.android.emojibasebindings.Emoji import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.designsystem.theme.components.IconSource @@ -37,13 +39,18 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.withContext import kotlin.time.Duration.Companion.milliseconds -@Inject -@ContributesBinding(SessionScope::class) +@AssistedInject class DefaultEmojiPickerPresenter( private val emojibaseProvider: EmojibaseProvider, - private val getRecentEmojis: GetRecentEmojis, + @Assisted private val getRecentEmojis: GetRecentEmojis, private val coroutineDispatchers: CoroutineDispatchers, ) : EmojiPickerPresenter { + @AssistedFactory + @ContributesBinding(SessionScope::class) + interface Factory : EmojiPickerPresenter.Factory { + override fun create(getRecentEmojis: GetRecentEmojis): DefaultEmojiPickerPresenter + } + @Composable override fun present(): EmojiPickerState { val queryState = rememberTextFieldState() @@ -86,7 +93,9 @@ class DefaultEmojiPickerPresenter( val searchQuery = queryState.text.toString() LaunchedEffect(searchQuery, data) { if (searchQuery.isEmpty() || data.allEmojis.isEmpty()) { - emojiResults = SearchBarResultState.Initial() + if (emojiResults !is SearchBarResultState.Initial) { + emojiResults = SearchBarResultState.Initial() + } return@LaunchedEffect } delay(100.milliseconds) From 89deff8a5321f430690ac672544113c07f6f1218 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 22 Jul 2026 15:33:54 +0200 Subject: [PATCH 165/383] Add libraries/emoji/test module with picker fakes --- features/messages/impl/build.gradle.kts | 1 + .../CustomReactionPresenterTest.kt | 5 ++--- libraries/emoji/test/build.gradle.kts | 19 +++++++++++++++++++ .../emoji/test/FakeEmojiPickerPresenter.kt | 19 +++++++++++++++++++ .../emoji/test/FakeEmojiPickerState.kt | 18 ++++++++++++++++++ 5 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 libraries/emoji/test/build.gradle.kts create mode 100644 libraries/emoji/test/src/main/kotlin/io/element/android/libraries/emoji/test/FakeEmojiPickerPresenter.kt create mode 100644 libraries/emoji/test/src/main/kotlin/io/element/android/libraries/emoji/test/FakeEmojiPickerState.kt diff --git a/features/messages/impl/build.gradle.kts b/features/messages/impl/build.gradle.kts index d442e1bb95..b40aebab39 100644 --- a/features/messages/impl/build.gradle.kts +++ b/features/messages/impl/build.gradle.kts @@ -107,5 +107,6 @@ dependencies { testImplementation(projects.features.poll.test) testImplementation(projects.libraries.eventformatter.test) testImplementation(projects.libraries.emoji.impl) + testImplementation(projects.libraries.emoji.test) testImplementation(projects.libraries.slashcommands.test) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt index 8ba316ea4d..4d3c4ab41a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionPresenterTest.kt @@ -11,9 +11,8 @@ package io.element.android.features.messages.impl.timeline.components.customreac import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineItemReactions -import io.element.android.libraries.emoji.api.picker.EmojiPickerPresenter import io.element.android.libraries.emoji.api.recentemojis.EmptyGetRecentEmojis -import io.element.android.libraries.emoji.impl.picker.anEmojiPickerState +import io.element.android.libraries.emoji.test.fakeEmojiPickerPresenterFactory import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.test @@ -26,7 +25,7 @@ class CustomReactionPresenterTest { val warmUpRule = WarmUpRule() private val presenter = CustomReactionPresenter( - emojiPickerPresenterFactory = EmojiPickerPresenter.Factory { EmojiPickerPresenter { anEmojiPickerState() } }, + emojiPickerPresenterFactory = fakeEmojiPickerPresenterFactory(), getRecentEmojis = EmptyGetRecentEmojis, ) diff --git a/libraries/emoji/test/build.gradle.kts b/libraries/emoji/test/build.gradle.kts new file mode 100644 index 0000000000..3a18a239ad --- /dev/null +++ b/libraries/emoji/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-compose-library") +} + +android { + namespace = "io.element.android.libraries.emoji.test" +} + +dependencies { + api(projects.libraries.emoji.api) + implementation(projects.libraries.architecture) +} diff --git a/libraries/emoji/test/src/main/kotlin/io/element/android/libraries/emoji/test/FakeEmojiPickerPresenter.kt b/libraries/emoji/test/src/main/kotlin/io/element/android/libraries/emoji/test/FakeEmojiPickerPresenter.kt new file mode 100644 index 0000000000..76a239ac49 --- /dev/null +++ b/libraries/emoji/test/src/main/kotlin/io/element/android/libraries/emoji/test/FakeEmojiPickerPresenter.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.emoji.test + +import io.element.android.libraries.emoji.api.picker.EmojiPickerPresenter +import io.element.android.libraries.emoji.api.picker.EmojiPickerState + +fun fakeEmojiPickerPresenter( + state: EmojiPickerState = FakeEmojiPickerState(), +): EmojiPickerPresenter = EmojiPickerPresenter { state } + +fun fakeEmojiPickerPresenterFactory( + presenter: EmojiPickerPresenter = fakeEmojiPickerPresenter(), +): EmojiPickerPresenter.Factory = EmojiPickerPresenter.Factory { presenter } diff --git a/libraries/emoji/test/src/main/kotlin/io/element/android/libraries/emoji/test/FakeEmojiPickerState.kt b/libraries/emoji/test/src/main/kotlin/io/element/android/libraries/emoji/test/FakeEmojiPickerState.kt new file mode 100644 index 0000000000..234fe2e9b2 --- /dev/null +++ b/libraries/emoji/test/src/main/kotlin/io/element/android/libraries/emoji/test/FakeEmojiPickerState.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.emoji.test + +import io.element.android.libraries.emoji.api.picker.EmojiPickerState + +/** + * Minimal [EmojiPickerState] for use in tests that don't render the picker (typically presenter + * tests). + */ +data class FakeEmojiPickerState( + override val isReady: Boolean = true, +) : EmojiPickerState From 4dadb3c8c8463756c55b796ae09b28980ddd6dee Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 22 Jul 2026 15:35:21 +0200 Subject: [PATCH 166/383] Wire the emoji picker into the user-status feature --- .idea/codeStyles/Project.xml | 34 +++++++++++ features/preferences/impl/build.gradle.kts | 2 + .../impl/root/PreferencesRootNode.kt | 3 + .../impl/root/PreferencesRootView.kt | 12 +++- .../impl/userstatus/UserStatusEvent.kt | 2 + .../impl/userstatus/UserStatusPresenter.kt | 61 ++++++++++++++----- .../impl/userstatus/UserStatusState.kt | 9 +++ .../userstatus/UserStatusStateProvider.kt | 16 ++++- .../impl/userstatus/UserStatusView.kt | 51 +++++++++++++++- .../impl/root/PreferencesRootViewTest.kt | 2 + .../userstatus/UserStatusPresenterTest.kt | 6 +- .../emoji/api/picker/EmojiPickerRenderer.kt | 11 ++++ 12 files changed, 189 insertions(+), 20 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 @@ + + + "On the map" + "Your homeserver is on your local network. To connect, Element needs permission to reach devices on this network." + "Allow access to local network" "Failed selecting media, please try again." "Press on a message and choose “%1$s” to include here." "Pin important messages so that they can be easily discovered" diff --git a/tools/localazy/config.json b/tools/localazy/config.json index 5753fe5f47..02b9205ef6 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -330,6 +330,7 @@ "includeRegex" : [ "screen_advanced_settings_.*", "screen\\.advanced_settings\\..*", + "screen\\.settings\\..*", "screen_edit_profile_.*", "screen_notification_settings_.*", "screen\\.notification_settings\\..*", From 140074f23c5c024e161f47617627c37e2978c537 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 16 Jul 2026 14:43:40 +0000 Subject: [PATCH 173/383] Update screenshots --- .../images/appnav.loggedin_LoggedInView_Day_4_en.png | 4 ++-- .../images/appnav.loggedin_LoggedInView_Day_5_en.png | 4 ++-- .../images/appnav.loggedin_LoggedInView_Night_4_en.png | 4 ++-- .../images/appnav.loggedin_LoggedInView_Night_5_en.png | 4 ++-- .../features.invitepeople.impl_InvitePeopleView_Day_5_en.png | 4 ++-- ...features.invitepeople.impl_InvitePeopleView_Night_5_en.png | 4 ++-- ...ures.login.impl.changeserver_ChangeServerView_Day_6_en.png | 4 ++-- ...es.login.impl.changeserver_ChangeServerView_Night_6_en.png | 4 ++-- ...essages.impl.actionlist_ActionListViewContent_Day_3_en.png | 4 ++-- ...sages.impl.actionlist_ActionListViewContent_Night_3_en.png | 4 ++-- ...agecomposer.suggestions_SuggestionsPickerView_Day_0_en.png | 4 ++-- ...ecomposer.suggestions_SuggestionsPickerView_Night_0_en.png | 4 ++-- ...ures.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png | 4 ++-- ...es.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png | 4 ++-- ...eatures.preferences.impl.user_UserPreferences_Day_2_en.png | 3 +++ ...tures.preferences.impl.user_UserPreferences_Night_2_en.png | 3 +++ .../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 ++-- ...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 ++-- ...ProfileHeaderSectionWithVerificationViolation_Day_0_en.png | 4 ++-- ...ofileHeaderSectionWithVerificationViolation_Night_0_en.png | 4 ++-- ...s.userprofile.shared_UserProfileHeaderSection_Day_0_en.png | 4 ++-- ...userprofile.shared_UserProfileHeaderSection_Night_0_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_0_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_1_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_2_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_3_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_4_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_5_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_6_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_7_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_8_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_9_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_0_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_1_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_2_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_3_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_4_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_5_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_6_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_7_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_8_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_9_en.png | 4 ++-- ...aries.matrix.ui.components_CheckableResolvedUserRow_en.png | 4 ++-- ...braries.matrix.ui.components_MatrixUserHeader_Day_2_en.png | 3 +++ ...aries.matrix.ui.components_MatrixUserHeader_Night_2_en.png | 3 +++ .../libraries.matrix.ui.components_MatrixUserRow_Day_2_en.png | 3 +++ ...ibraries.matrix.ui.components_MatrixUserRow_Night_2_en.png | 3 +++ 100 files changed, 206 insertions(+), 188 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_2_en.png diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png index 5cfd616c0e..652703aae3 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:924b97967296d3f50e1f911a14bd63b9d5d0d3d5d171053c1a0e6a5048c4d336 -size 34048 +oid sha256:d9eff127b4c393418646e3874a174e807aaaeea37587b07ca2716a551fb10d8e +size 33418 diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png index ea86b6f571..88e414ee25 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f98480a126f3cd955fc10e42404d8aa812e2f7fb59a9655593bbebb1c8fa972 -size 33249 +oid sha256:bb2dc44a39b82a4138b15214cccc945eef34b2f244b4646e925a2a62568dec37 +size 32619 diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png index 348422394b..8dae0180a8 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c89fc51cf4c9a8b623bb7582aa1490109220cec3b0bfc9ce58e150c5a7702029 -size 32158 +oid sha256:94d9e39df7c1aba7a6ca7eb6abf073f0170469ef837c95afcb5f199f8c2bd7ec +size 31504 diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png index d66f1ab4f2..603fbef2f1 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:794613b9e61283cab807a35b23875b4ea9c1198789c844958c755699279fa3b7 -size 31413 +oid sha256:7ba2563c905c2400a50f81c6d029bc9cf4a99d1cb6483ee3ee8cfe373601a0dd +size 30770 diff --git a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_5_en.png index e2c64a6d5b..c67c062ddc 100644 --- a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:686b6dbb0e54dc133a504bb56bf254c8bc6d76faf1c51e696c2b980ad67ffd35 -size 37320 +oid sha256:5a9237dbe1fd700357d7d073408977653a52d9f8c2ca92aad26569c10c0247a1 +size 37488 diff --git a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_5_en.png index 2f41c0ac43..eb0e3331e0 100644 --- a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:33e7d75e2f1ebed36e05491eb27475ce74cce35a4121aaa053aff34ac6f8c0dc -size 38272 +oid sha256:ed1399fb1ec24eddadaf91700ac446a9f76784953b8b84cf1675c979fc9aebb9 +size 38509 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_6_en.png index 7ff27996e2..09b645e184 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee3174b63b166511e6c51725a8b6fe00b31eafff011f9059f2f728b77823b465 -size 33670 +oid sha256:487e0a1f72382c418f95d337edbf8047228e8d3b116d192ce3f8abf3cf97fbd4 +size 33063 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_6_en.png index 2c304a2695..6cbd05d003 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7910112f7ab526dbf0e5326213e03c3f3fe109dc8cc1bd3a8bf5fb05ddb5b0a7 -size 32054 +oid sha256:36300a7d6bd6f2529bcd72ae3f654b6ef40706e0533f54d9473a9dff23df560e +size 31406 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 b6f510f5f1..3756f9ed3e 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:6e42d39ee8965360d92cb66485670b48c265c0728240529c3d35d14a27f325d1 -size 46965 +oid sha256:29b6dc68656a924ba73148f570eaf72b20e9f887b1ae42bfd3c5dc378f2b3791 +size 46613 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 a3529b5d97..948d5d1f87 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:bf69710dd5e9926970b9c13ebbe5dbaa9d2e87773ba7c439fe18f3474459fc40 -size 46325 +oid sha256:a0177ab6b9034de7eb35bc5774bef46f8ecf89b63695aa92e20407e605c1b0f5 +size 45968 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 ed3c8abf17..064bc60974 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:a1a4672f87cf79f8052e29650be198bee1ee6c00a24ded5fb243b6a32b51c372 -size 38017 +oid sha256:8cb541e97832b6dfc8190c017f4bd8fef3f952fadaa13dc0622a52e22ba664cb +size 41970 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 6798590348..bd64300ada 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:f8c69700f738d00379102fac8d2d1f33891983558d4a650edce317282e16b6c7 -size 37737 +oid sha256:955ec27126825710b2829fe2447773ccaabd0f4415c92195853bbafcc8b2c1ea +size 41552 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 3ea918900d..bcbf444dd1 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:e088da462be419f059caa750afe0ce5d806ce25e682cb5aaaf37f88e5c236ee3 -size 55745 +oid sha256:7faf196e521dd713a99a7ea22786a429c937884a25194ce4bbbd55bde12e8bdf +size 62797 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 695f6809c7..abd96c1fb9 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:f5658c53966bfab8a24a1e123d10a1b3c98b7d43361469ba8d6519c2d2f1cc22 -size 55067 +oid sha256:292167265d9c1135e545b911f7268d45a9a0195768fd09fc88c1eaf7a5c57b09 +size 62322 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 new file mode 100644 index 0000000000..0a34d0b390 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3ecf110c258f4ec5fd5d2a4126395e248d73d894afd54a0135dc710f680c0ee +size 12395 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 new file mode 100644 index 0000000000..58a30a7304 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6bc66cd4269ee462103e77bfa24723a740d8a91dc7e06ca808b8109e74d1784f +size 12127 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 232eff8a27..e9863d1b93 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:dd57c6da7471850cbf9d4fd749b249589cd1dd71eebeac50fcef8a1db9efc04e -size 67420 +oid sha256:8a6fbd84c3f2a9e40a2e8e81a00ffb82d48e8714035a2da737953e15bac7ea93 +size 67635 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 77c11f54a2..29980e7099 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:a78e7d4a345b9beca19dedd29282f9a891ceabdc05d203cb4091790924b0bbf3 -size 40335 +oid sha256:fbb8a435e9753f441c832db6622ed94b404dce4237996add3aeb72e518cc14fb +size 40522 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 5764767fef..b45888cc98 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:29304b6e03fae0031e6fb536ffa038c436b224cf6c2fe095af1509d8cf1729ff -size 38520 +oid sha256:c4c5e6f2905960f6042ecb61d57a7a2a2b882c73fb49d043bd2d9d71e075c3e8 +size 38657 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 d242f48a87..18caac8b41 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:966f9a73b258b8b0036255d2519c64a306c07098001f9a140d5a3af9a7ed7734 -size 38088 +oid sha256:f45a01ce91d5e56c19d47a01fd3845a92d32f364925d2490ccaca889e288077e +size 38221 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 d3baeac29c..231dfeaa33 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:44fbeb3efaad275d864b9cf58075fcc1df67c49f5498017e53a6c203ad5d0513 -size 38858 +oid sha256:9d87f7b70a1043231c213cc2e11c8d6aec03b49b24a7fce2261a865d16fd3146 +size 39008 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 a1e27998fa..78ddf668e3 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:82f34129e77fb9e84c513a950b7c3d2e20af376f357135cd7bfec67ec0850b62 -size 38790 +oid sha256:4684ba74e78e6ed36ce3fa168ce50c3bd828d70e9bf54c9c3f8d8ddccf7e5d81 +size 38948 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 fb02b6a6ed..c7db94c48b 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:cfa7cf1c8e98ecf02f00a20096e5edd5a720050dffd8a359335d479493b40f50 -size 40212 +oid sha256:e6a301bdb68740effd68841d5f4afab2ad211ff02fdf99828f9780bb43975709 +size 40361 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 1da1c133bb..8d2ee2032e 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:8f5be262e881a33b9ad1425164ff8424ca72e12a276918f173fd3ff5cffb9ed5 -size 40555 +oid sha256:7cdd7dce0071f305c82c4a084a8d6112fde6ee79c0e347109edba61baddebeb6 +size 40714 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 645a7ac9f4..58f6776089 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:dd555ca1156752b9d07d808702c2e7bb04af00bf8240947e1cb4a7ffdc4814a4 -size 39066 +oid sha256:548a7a2b247dca3a454951d168eb30a8fdce2d1c0c5de77ee7e623e3a2355b3d +size 39235 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 99451027b5..e1dccc7bc3 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:8630ba0169ecb20ed5076623fc9a6bfab6d30c75c8040958fcbe3663661f5cf1 -size 38502 +oid sha256:1131ffbf59970257df26ba42bf2a5612398a7b62393c41753e84af0fe1a61af2 +size 38648 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 9647ec0023..68b81c731a 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:57d4c23cf1f13899370c0bf0c99e23b0113039dd50a8fdbc1706df7691943044 -size 37354 +oid sha256:6922b04770ab6805693ef7fe9f0c5ddd93afdceb2725b3b1b795c6ab8c10d136 +size 37520 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 b786e48fd2..f1f356e0a1 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:9256ef115348a6fbcdc5bd275c7dd97c5018b890104c1074b65d0eef6d2ca319 -size 37334 +oid sha256:ffccceb346d0c768fa98e233701058fa5b73f480f6390b26dbbf2ab7240511ad +size 37525 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 9114e9a598..211d398cdb 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:9c4a343ba9e0a8a6c75eb9cc54c4fbd460606de184c8078242a4e06eef7c3304 -size 34641 +oid sha256:3abf55145dd71a1f511ebb07b7481f4538eeb2730bf3a23d83e4dbd2fbd5100d +size 34829 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 449946c634..bc377f0cf3 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:ef52fdbd2ed8efdf526efe2fab402d7100952522b7e01023ec73e10415e27700 -size 39183 +oid sha256:c5137c3539f68dd9d501d8745645847304ca40a58517baa4d4fc21fc99702520 +size 39382 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 b10f7d38d0..8a5000cdf7 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:0215a5c510ebd2b99176525f7f317654e3c3b2fda4f5599c63b589f5c6286efc -size 38951 +oid sha256:c6a26f7ac512ab192f0b022bf59ade1c0275b34943e4c06016d873ee6dc1b49e +size 39107 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 5fd4e0e5ca..1ef2d75e9f 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:bf37f6deee46b8949ab91e88c49811013876307009b9c84ffaefd8229034a26a -size 38837 +oid sha256:3b8cfb69cf931f52a5110b08b262cfe943e82cc95d10afb5c3126acdd6908055 +size 39002 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 96f469822a..28bf4f49dc 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:569c1c17bae3b57d21f04d9ffec1ee91f7bae1ee773e75e7418850e9f83f3281 -size 32286 +oid sha256:9e086cdd74b0f4620ab8e1fd026792e91365f6d71b246d7f34688f55f29e9d91 +size 32270 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 557f249715..1bcec82516 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:6db7bc187b92d8fda605212e54168649f1385f7fd5d938496510289cbbdcfe63 -size 30729 +oid sha256:af53108a51bba6dd19f89d416a513a014dc93709bb92e84f1a97a3936e9a656b +size 30989 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 240291e5da..c02a47d24c 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:8be6501b50d413f75e860bd04f03803cc13965a991e7d64019e1a7e39a0bbf2b -size 37416 +oid sha256:250ec00454674d1a240eb1189586bb313f61950d8bf736d6812208c0c49c223c +size 37459 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 7ee59b0d02..2dd2e61820 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:c56e98e7ff452bd15b7a635d748815b1c8dd5490b9309e09a93a3cd4832db660 -size 37066 +oid sha256:446b9f6e5b9fd3ead36ef3983eec7445fb647b28719ac37ea42911a34ba639d8 +size 37236 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 f30bbd9f27..f3b24f79b7 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:a10328f429081b196dba40ae60a6100f2489a60a2aab37388deb645549fadfcb -size 31485 +oid sha256:de8a33b55900579b94ba7201a924a35e0d64a7c231591743386f3653f334f3be +size 31516 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 ea46034c38..35b64abb88 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:cb772e96c733fddf80ba6dda94039d971b1541a39ae349b3736e1a272f0857b2 -size 39440 +oid sha256:8c15274bfe393b43066b7885e300b8fbeba83993d4ada34c260cb41fb6425476 +size 39555 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 00e9e79aa4..5af1e44f46 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:cbdce666db6f4fb2a35f854b3e3c652dbbf4c0ba798aff3f5f7bfe0da4510950 -size 38841 +oid sha256:69cb1432c2fdcf5b9f29774baa8cd5d628a76feee10fda86e3aeb284078a108f +size 39005 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 7530f500f9..5d0b8251fa 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:d9fbc551023fce72f97c6f562306e80e4e43bf83ed35ddbfcd86a1a3053c1545 -size 38936 +oid sha256:cf9e568b617a863fc2c4ad221f6453a739a385867e30cb2f813c55964fd27646 +size 39153 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 f63ae1fe95..ffea1c96ec 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:3b7a58ad7ba5f3a81f0b06a9f464f91ec3b4b39fea3e4db6657bb9bd43f80321 -size 41501 +oid sha256:bdc91adbd0eafe0ca75381cf1362e4421c12b9871efc558f8203fba43b119e84 +size 41670 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 d292c67bfc..b17010db4a 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:5f92b85722afbc65a584f6e6f064fe6b3b38a888965d97c569c727253f4cc7d7 -size 39519 +oid sha256:4078a0609c3b9c45307bbe5d2a1dcf8aedbcd58e3fefa24c0d1ae4156702ad49 +size 39733 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 f36d741372..04927b495b 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:77e3e9dd2ec03e1a4a988e25a8a094d96296149ce7b6dc1d319c71b84dabfb2f -size 39357 +oid sha256:7ef80e3950422cb5ea2cbbf4822d3a34229286719cb0d43159f6d252eaed5cf7 +size 39515 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 069df089eb..af9e54e79a 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:8c182019343e29d186a1f2a7551f82573999a26d12c77c10ee2563aee44045d9 -size 39893 +oid sha256:e17a12f4586b3b6f57a99a0dd6a26e5b6029bcac995ee6f70c9047f913708242 +size 40060 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 d8d659411d..048c1037ba 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:85e5490ba14a46176971c2c23eec05d352e871463eed9241862faa9929c11188 -size 39837 +oid sha256:fd6ec055f0139812c8b0ab9017526760706d5ee7ba29aedc9e292e8286994687 +size 40004 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 01041d80be..00c3a5cf5b 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:c07ef87165b3f4e13108882f108cd3f217f3c6f8930c703b8909f431b2a9ed2a -size 41337 +oid sha256:3a443622d261092af01abe5717ba1e52b06ab5e46c5428d21523b57c6dd76738 +size 41511 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 5a90de8c66..964d90da1f 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:19dbd2929dda9108118ede7627241db2249f8ab7a062f17bdc3619ff42253594 -size 41768 +oid sha256:20fd55f968c30945318e80f2c003c67c02d7495b661475087fc0b0e724210f84 +size 41940 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 3d2700e9af..e099e70827 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:c87ff2cbbe4d5912cb17fccfe5fa7614d5260b43ada3b952dedee57a3c004cbb -size 40117 +oid sha256:25ec51f2100062e64501a88595a4f4ca7a8ab2e70aaf18ce65df49fd444b81ad +size 40303 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 10b75e049f..21cfb86dab 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:77359209da8ffbdd933d123a1a6952da961c75b3ca6a70b6d49ee9be188fca7c -size 39670 +oid sha256:27a90a335b3ea802a72e6157493b2aa3f8e131a9de39e88a3cad6843f1f4c038 +size 39833 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 4cbe816fd3..ca593f67c9 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:a7190a790a208709d20691052ea3de64a359e7ca16d8a988d0ef62b33a64da3f -size 38756 +oid sha256:72bbf2ec4beb1b9cb526d47013773b26267ac2e019c218cf81231f86cca6b13b +size 39164 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 8eeffdbcf1..781c3c3aa6 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:15458edded2d32980c16163e6674d714d67442a2421d0af73594590cf6f144d3 -size 38718 +oid sha256:e93f90d704f810f2cd0ddc82170e429c53d09039a39c45d2177e431f1c3e683c +size 39102 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 c4c2f1822d..76bbb7afe4 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:13ac1bdcdacb72bd268cf00e8e754f5746928723891fe1f70277daa46f67ef1f -size 35720 +oid sha256:8ee504b49e9b7595feeff6a2cb7e96a581ae39cf096732fff9b8eedaf2779ccd +size 35959 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 c70dbc195d..bfcb5051ef 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:b4b9ca327302ed396498c60db4341c78e3d48079e04bfdbb4ce8f024e82684f8 -size 40307 +oid sha256:8cfc4b97ed57ae7bf2f54ab574cd82b3190fcc2bc6873447a5d1fbe63e374b73 +size 40418 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 3a06126d05..ffb83196e8 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:f4c7a00882958b916e99ef643cd698229f8659fb8f21e4e2b86db1432362f508 -size 40007 +oid sha256:8a1aa73c2c4316ce86d8d657d563d146080bfb81e120328b512cef714e57d340 +size 40176 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 e6ccda4710..c1d344c706 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:a9bab5037912d2bdeb85ed013e169d98f5f7333c274430d69667e32dfc72c1fa -size 39880 +oid sha256:616d6eeae9be6af14620508ad4ac835e6651537b8656b556624b062c89e84ae8 +size 40064 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 0f9431284b..bfc5a1bdd1 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:c074ba644aa7ab073e2b1893a2f82a8e11eb479e8f50ab9cbd6e991709cc5d5e -size 33376 +oid sha256:1804ad3cea84565e84944959c9d57faa546e8f2ddefe59998c9dae352951d72d +size 33392 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 56cfd78cd6..347ca6f537 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:a07f005c828af6a622527a062e6cd2d8f4120ed4ac4a63daf675cfaf1b36da11 -size 31486 +oid sha256:89a7d8046a9206a5bb0d5969eaf406fc1a4922d47871782b3e153fb7859ec36f +size 31928 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 f82973cda9..97cfa26a7d 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:ee239549a179ce7678494cc20b32db88a211bba1f6368ba17fa1b18ca3400810 -size 38586 +oid sha256:e3b592944d49fa32a35042fada1a6fe7ccc64fac066c14214a351ac922dcb860 +size 38524 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 a37eaa2ae6..0cbdcde004 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:b56916b6d08aa4fcf55ee414ae928946d5a2bc5eeb610f9ec4ac86cf783aa11e -size 38429 +oid sha256:5500501d34b1cf5db3b68b0c620e915fe882536d5cede2bc920de05ca43100b6 +size 38825 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 f305d86263..25545ffdcc 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:b576b33a5c3bedaa8d1e7df6e95541730559c8149f5a0d920c9245449b33c26d -size 32616 +oid sha256:f7f6d55c95501d8c8259a4318f7897f11f5e0effd53f37b441a7adfd409935d3 +size 32822 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 964ccd2680..a32798b98b 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:a7b1c29bca9904fc55d17356c27a8dbe035e1fbbf0ffa27ee2b466cf1558c418 -size 40573 +oid sha256:ff81f7a43722314cedd1d4fc271d994002502141fab672d5d1d142403eaf4732 +size 40714 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 2ced0a9e17..37ec51d503 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:8ad0f0df59f4231bd85a0ae99ad6eccb74b338975353a201f434e5047fd58628 -size 39963 +oid sha256:b8776b535fa481298d2b3e29621174048b42590a9a4f8a2aaf644dc020bd08eb +size 40131 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 9e24db9017..951615ddbd 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:616b6050ca126b0630b5283901afe4096f7d041a40a5d6ae8e64ff808f2d4e7d -size 39971 +oid sha256:f2ce271672bcae59e254facedf7fdfe7f71ae21f9f3a147fe9657d2943281bcb +size 40165 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 202f8a06db..60997dceec 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:75880628a454ca00a186e5d1c5438117e7af4ab9b23eb6fbf9c9696210234169 -size 17246 +oid sha256:bc0c611e5c552906b26adda91bd3601f34fc190860a1b1368b0e1c9b0835c9eb +size 20056 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 9186ac2de4..f646e0ee30 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:1fe61c20e2c6a7bb72e82aefd546469dfc49bf736b6d12f4c1927628df1bdb3e -size 20211 +oid sha256:03e68ff235e90c659a3a15d26f3ede94aa169fd7142eabc19b5511047577df93 +size 22912 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 ca8464fad9..51dd1fea52 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:ca3ee9a09bbbc69f2ba7e8b40cdc5196cc53745fe3222282d98bcf948dc16745 -size 22596 +oid sha256:baa29dce32895f21a4799a47a62e7152c99d56fc22a3882ac7da7f005a3532f2 +size 25259 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 945743ff26..72bc2e1d8b 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:96971a8981aea8918c01827403933c9e75275a2fda92716f803e6f28ad284bae -size 22702 +oid sha256:e02e039a0586a8f36c00d4e237885a55713040036b4481f0626beb2b3b8ea161 +size 25365 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 c1b0c4ff1e..834857696d 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:bc96eec2d61713f01d43c92812bbf27bc44a202ce55f0fa1dc8e8659dabcfcf2 -size 16347 +oid sha256:38d2e1c53d09debe38dbd49a058f3612c4a6cc4d3a604f53f86d0db29f0efecb +size 19047 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 16b567164c..778f0c8209 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:56c4df7da32b71dca109a1db1f4a797a2930e3b42c00eb51d72f0e1f5b99bf48 -size 19200 +oid sha256:4680eb47d53ea43ba48e4164ad819278fd8844e24f77badee742aa4e8ddca452 +size 21859 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 ec10d3fd8a..1bcdbbd146 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:592c6ec197b193803679eee5df7769fa4858fe883a2f3a1294f39ad87f9f4ff1 -size 21610 +oid sha256:d07c9ab2a4bea18c3604675225d23b0d4dfa41d16676eba821adcbcc619bdabf +size 24246 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 5ff44ac3a4..9a97f2911f 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:62e99b8070a394ea5b2d666f3a8abf0fe41ea4a34a382223903f2de4085195dc -size 21710 +oid sha256:e596a8cda9c1054b5f780798fd455a004acb1b848bc21069e415dc700a106b10 +size 24337 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en.png index a141a26bce..2a90fdd71b 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ceaeb4841d4d480fd66d1014dd0f1257fe7c40db3a66cf18f0ff71d7ef79b9d -size 24170 +oid sha256:26a21536fcc98041b4c349498f126da520251e57b601f0f5943225c191d00910 +size 26241 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en.png index ba0aee9b41..649da85f0e 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bcba7790fd7f16a1f0db0dc248a8ce895534c1a5155b96f4877b2137ec5a6412 -size 23456 +oid sha256:84a13525255fc639f817d1ef8dacef0dcfd48c2d72bab309175f99ccd56a34cd +size 25903 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Day_0_en.png index cf5c451505..809e2624f6 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d09796f261ba9552fd94f595467a958ff7cf7113c3ca23117128cdf76f729e43 -size 15808 +oid sha256:326840103b3ad46a5d80c80c5cb58604d0c561dc484cdd505ae837ff4cf71bad +size 18632 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Night_0_en.png index 09475dd0ac..39e2b34bda 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileHeaderSection_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49216216b3078897afd41a04c3eea2d82cc89d13390c2f61ef8045b84ad69e6f -size 15253 +oid sha256:dc027c17c7e4b41774ba20b39b38fd98fc7199b41ea7610ec01b184c4bf9ec99 +size 17925 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_0_en.png index 1e86845bc2..fc6d33f7f0 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d705422db764094ca6e92ace3cb61eb7b855a9bc1fb37e840b8a886b5306e181 -size 23994 +oid sha256:413a3f42ad23bbab9a920128950b40f9eac5ef9248fd5ca164b838b7d10d9cdc +size 24062 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_1_en.png index 6f74640f03..c5b576ef74 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:197ce66690463abeed16142edb0a212d5e49f2ef1df1233a3d6a0fd9d5153f2e -size 21772 +oid sha256:5893b1d1b8851d26d3bdb12f6b68954d03c9234d4ebf0ced6aff13b155595f83 +size 21828 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 3419a50b07..f255914d84 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:9973d9a9fa00d362eae8f50c2936e5ae0adc2653b4671413b856c1e73538eb73 -size 24261 +oid sha256:ba293e027a30171d36aba06bbead8b616c706822fefea912b1f4beb9a3985da0 +size 24290 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_3_en.png index fca3f7ed9b..43b8414534 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f707615c108e66cda3ccac1f70f6b1f6909ac88f4e8c43b86062ac11d7ad3f27 -size 36171 +oid sha256:a233930f23a1ffd82b9c48a3106218de88df49ef785b252ba1844a126c7eddd9 +size 36159 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_4_en.png index 45e42c6ad0..51a45218fc 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c6a2a849c7335452fc79215f4fc1c50ca606d491879cd6ec6b265e4f443f665e -size 27706 +oid sha256:2583c6fca6d7528b7bb8ea2eb3d82e012b970ef7b024c5bbeefc1c4973794e32 +size 28715 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 7e6ca5d507..2d7523e28c 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:4a4154169fd6e74358001ecc151a0cb4635423bf4a0b2d72f1d5bb12dfb0ea95 -size 22446 +oid sha256:94b86f639e03998bd47b423f0c90dbb9767165cd2905a700b5ed29ecfa63d525 +size 22496 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_6_en.png index f7ee67c10a..1b3752626a 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b3e9e3da0ba44d070fbc0e434be2c52dc0391eda581792b227587cb4d16997a2 -size 22945 +oid sha256:9848fa1e1af5dd63be1f6df0375627efab136fbada1c6afb7aa058db697f245b +size 22284 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_7_en.png index 1c84803007..356db152ec 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa809d53b1ad821c047fabc9b655e47150e201941e004d5b8f769a0ebe1a2b74 -size 26629 +oid sha256:db9f567fdf457f2ce5072c0c848ad48942f92f5af96c7d0f144d4e12fd651e6e +size 26688 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 aef669fae0..805f752c50 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:781bf8c86e88c9ee564f45de7446ee2eb554efe68ae9e708aa1b5bde7fce6d6b -size 34137 +oid sha256:5fa1c110fa0804eb0363cf6c9631ed5664a547e2213eb76c211b7d11194c64a0 +size 33532 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_9_en.png index d30cff8678..bd9cb74dc5 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85b62859396f9c34ee7bbb4166d6f030474bd750b043c7bc1f14eb6e75e613d6 -size 32374 +oid sha256:e87058ca16fa51807d79a8112aa3c105957c9785ae057686a92403133a556c2c +size 32353 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_0_en.png index c3e2d149b3..3b4a36e777 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7fb347c3b537220d85af8e6473dac0e7658b2104cc4a1746a8019265f8085947 -size 23379 +oid sha256:33356c2a7ba816a0a6920e50eb8bf20212a062d11d6ba117923c9ea973d171d8 +size 23455 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_1_en.png index 95e144b3f3..ce6861e02c 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7378680765db7cf811b1ba3c7901cb954765794cc741454bf31b4418c5f77da0 -size 21317 +oid sha256:c4d8861aae54ab13cc8fdba1d506b8bb682fc41bf05584db55ca8fce688ef240 +size 21435 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 224210123e..097e96258f 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:e28754f90d584c329a5e3c51eba89c166320c69fda309b6b06b6f5ee9c74c1b2 -size 23549 +oid sha256:e42a2617242df3e2dcad13ca623ef2a2f60fd133a2da287a49255808cf31ff4e +size 23640 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_3_en.png index 0c63f7b2c5..34304b7884 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0d88762c47be041fa9978b987f3a1226c55d711e8eab1a68c7c1fed72bc4a0ac -size 33925 +oid sha256:3acb94720610f1a0ea9a1861a091109b1fb9555b09faf432fb1bd702f5c81320 +size 33946 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_4_en.png index b7c5aa9fa2..cc712188d9 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:24310edc91b912416a1c20240bfce6a5a14165fe9c77f2123a35a9148e2ea50c -size 25833 +oid sha256:490fcf83d06592f39d88906b445aa826f6f4c0d0735e7fd8187b1eada5474d79 +size 26981 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 408be83664..2056976aac 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:3b815d4cf8ed95cb983072d75419637c10bd4808ddfbf14865409d0a4fd64c37 -size 22070 +oid sha256:89b989f3c910c24270a09e2804e9e5bf1901d0247d00f7abc6045f394acb7dfa +size 22030 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_6_en.png index d945d1c6f8..981ac8e6a6 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85a6cf5a532ecbcfc07cc4a6e3bfa2370f7a401c357aa1e251bb15f7cd8611ba -size 21672 +oid sha256:25496e6505e3905108d74bbd0d299576a24d1a40e78107b0780f50a5ed1617ab +size 21065 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_7_en.png index 46417d9248..43a79d0897 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b6f0f76fd0bb0f6f8dc9532c801d86e7574e53a62e828400c2fcfcf5fe9fe29 -size 25880 +oid sha256:e29852c6193c1fdac9b81629844d32399d8e8451e1ec7ff1f5185904a2eb2361 +size 25947 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 3c90a4f7ef..c3527328e3 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:45c706bb63ab7df8e66898ec67fabbf8c227cac421b8c5eda84a2f6532c8f199 -size 32504 +oid sha256:2446d1ac74dceba5fc64507eea199773549dc65769aa8950fb88cdf411046abf +size 31858 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_9_en.png index 2021017f88..3b411f6e37 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c382fc5a53d664ce6fd78e1187be311cd8675a75a217992ad21bbc943139d8a0 -size 31438 +oid sha256:92b56ea3b119795c4d4f9b4a8f430a5ddac400f87651419e35d1668c90833e13 +size 31285 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 32ed8ebc5e..185aeb6a20 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:ef82fb23d7da19f1c3f37c3fbd1472f138a8edb27c307072cebb3b2444c239ae -size 46245 +oid sha256:e7b042410cfc2999e599534c263abd27ef43a64444e90aeed3a45a72ec8f0a15 +size 46735 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_2_en.png new file mode 100644 index 0000000000..0a34d0b390 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3ecf110c258f4ec5fd5d2a4126395e248d73d894afd54a0135dc710f680c0ee +size 12395 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_2_en.png new file mode 100644 index 0000000000..58a30a7304 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6bc66cd4269ee462103e77bfa24723a740d8a91dc7e06ca808b8109e74d1784f +size 12127 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_2_en.png new file mode 100644 index 0000000000..181261b486 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e685aef8bc10159ba5cde38217382b3b33273bb04bf3c7e8dda392a0612d8a20 +size 10460 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_2_en.png new file mode 100644 index 0000000000..a13027690a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserRow_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff742cfbc02f4a728a034e7cb3f161c98d706f5c05d8032cb8e3bb1d9e52a646 +size 10242 From 2152552daad1d0282c988f958c31ae1c435d69a5 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 16 Jul 2026 20:04:53 +0200 Subject: [PATCH 174/383] Add displayedStatus parameter to test fixtures for user status --- .../features/home/impl/model/RoomListBaseRoomSummaryTest.kt | 5 ++++- .../android/libraries/matrix/test/room/RoomMemberFixture.kt | 3 +++ .../android/libraries/previewutils/room/RoomMemberFixture.kt | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) 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 63f1ecebd7..0e00f43712 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 @@ -12,6 +12,7 @@ import com.google.common.truth.Truth.assertThat 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.RoomNotificationMode +import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_NAME import kotlinx.collections.immutable.toImmutableList @@ -87,6 +88,7 @@ internal fun createRoomListRoomSummary( timestamp: String? = null, isTombstoned: Boolean = false, isSpace: Boolean = false, + dmUserStatus: DisplayedStatus? = null, ) = RoomListRoomSummary( id = A_ROOM_ID.value, roomId = A_ROOM_ID, @@ -109,5 +111,6 @@ internal fun createRoomListRoomSummary( isDm = false, heroes = heroes.toImmutableList(), isTombstoned = isTombstoned, - isSpace = isSpace + isSpace = isSpace, + dmUserStatus = dmUserStatus, ) 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 33a1b68ba3..1a19eddba0 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 @@ -11,6 +11,7 @@ package io.element.android.libraries.matrix.test.room 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.api.user.DisplayedStatus import kotlinx.collections.immutable.persistentListOf fun aRoomMember( @@ -24,6 +25,7 @@ fun aRoomMember( role: RoomMember.Role = RoomMember.Role.User, membershipChangeReason: String? = null, isServiceMember: Boolean = false, + displayedStatus: DisplayedStatus? = null, ) = RoomMember( userId = userId, displayName = displayName, @@ -35,6 +37,7 @@ fun aRoomMember( role = role, membershipChangeReason = membershipChangeReason, isServiceMember = isServiceMember, + displayedStatus = displayedStatus, ) fun aRoomMemberList() = persistentListOf( 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 6fe6e82fa7..e835075d81 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 @@ -35,7 +35,7 @@ fun aRoomMember( role: RoomMember.Role = RoomMember.Role.User, membershipChangeReason: String? = null, isServiceMember: Boolean = false, - userStatus: DisplayedStatus? = null, + displayedStatus: DisplayedStatus? = null, ) = RoomMember( userId = userId, displayName = displayName, @@ -47,7 +47,7 @@ fun aRoomMember( role = role, membershipChangeReason = membershipChangeReason, isServiceMember = isServiceMember, - displayedStatus = userStatus, + displayedStatus = displayedStatus, ) fun aRoomMemberList() = persistentListOf( From 3fdd6be832fefd3c88383e02f8f93dc4d23e1b2a Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 16 Jul 2026 21:26:23 +0200 Subject: [PATCH 175/383] Extract dmUserStatus helper for DM user status resolution --- .../impl/datasource/RoomListRoomSummaryFactory.kt | 3 ++- .../features/messages/impl/MessagesPresenter.kt | 3 ++- .../libraries/matrix/ui/model/RoomInfoExtension.kt | 12 ++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) 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 232a21e42e..96e9f9344b 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 @@ -21,6 +21,7 @@ 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.roomlist.LatestEventValue import io.element.android.libraries.matrix.api.roomlist.RoomSummary +import io.element.android.libraries.matrix.ui.model.dmUserStatus import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.model.toInviteSender import kotlinx.collections.immutable.toImmutableList @@ -76,7 +77,7 @@ class RoomListRoomSummaryFactory( }.toImmutableList(), isTombstoned = roomInfo.successorRoom != null, isSpace = roomInfo.isSpace, - dmUserStatus = if (roomInfo.isDm) roomInfo.heroes.firstOrNull()?.displayedStatus else null, + dmUserStatus = roomInfo.dmUserStatus(), ) } 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 85c61f2131..712413c9f4 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 @@ -83,6 +83,7 @@ import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsSta 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.dmUserStatus import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.room.getDirectRoomMember import io.element.android.libraries.recentemojis.api.AddRecentEmoji @@ -319,7 +320,7 @@ class MessagesPresenter( appName = buildMeta.applicationName, pinnedMessagesBannerState = pinnedMessagesBannerState, dmUserVerificationState = dmUserVerificationState, - dmUserStatus = dmRoomMember?.displayedStatus, + dmUserStatus = roomInfo.dmUserStatus(), roomMemberModerationState = roomMemberModerationState, topBarSharedHistoryIcon = topBarSharedHistoryIcon, successorRoom = roomInfo.successorRoom, diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/RoomInfoExtension.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/RoomInfoExtension.kt index 3a03d8329b..cf5ac37d74 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/RoomInfoExtension.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/RoomInfoExtension.kt @@ -13,6 +13,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomMember +import io.element.android.libraries.matrix.api.user.DisplayedStatus fun RoomInfo.getAvatarData(size: AvatarSize) = AvatarData( id = id.value, @@ -45,3 +46,14 @@ fun RoomInfo.roleOf(userId: UserId): RoomMember.Role { val powerLevel = powerLevelOf(userId = userId) return RoomMember.Role.forPowerLevel(powerLevel) } + +/** + * Return the [DisplayedStatus] of the other member in a DM. + */ +fun RoomInfo.dmUserStatus(): DisplayedStatus? { + return if (isDm) { + heroes.firstOrNull()?.displayedStatus + } else { + null + } +} From 7935dc2ac7461d38e1e1ab103123d512d001d1d5 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 17 Jul 2026 10:13:33 +0200 Subject: [PATCH 176/383] Restore disabled-state color on UserRow AnnotatedString overload --- .../io/element/android/libraries/matrix/ui/components/UserRow.kt | 1 + 1 file changed, 1 insertion(+) 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 c0a7e969ff..fba2f606e3 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 @@ -46,6 +46,7 @@ internal fun UserRow( text = name, maxLines = 1, overflow = TextOverflow.Ellipsis, + color = if (enabled) ElementTheme.colors.textPrimary else ElementTheme.colors.textDisabled, style = ElementTheme.typography.fontBodyLgRegular, ) }, From 9c3fe5ad230d913fe642af9510aa5053cb49826d Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 17 Jul 2026 10:13:37 +0200 Subject: [PATCH 177/383] Drop mutating setter for MentionSpan trailingText --- .../libraries/textcomposer/mentions/MentionSpan.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 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 6442b70a42..937561e2a5 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 @@ -46,9 +46,7 @@ class MentionSpan( private set var trailingText: String? = null - set(value) { - field = value?.let { " $it" } - } + private set /** * Updates the visual properties of this span. @@ -101,7 +99,7 @@ class MentionSpan( textPaint.typeface = typeface // Measure the full text width without truncation measuredTextWidth = textPaint.measureText(displayText, 0, displayText.length).roundToInt() - measuredTrailingWidth = trailingText?.let { textPaint.measureText(it).roundToInt() } ?: 0 + measuredTrailingWidth = trailingText?.let { textPaint.measureText(" $it").roundToInt() } ?: 0 return measuredTextWidth + measuredTrailingWidth + startPadding + endPadding } @@ -140,7 +138,7 @@ class MentionSpan( trailingText?.let { val drawnTextWidth = minOf(availableWidthForText, measuredTextWidth.toFloat()) - canvas.drawText(it, x + startPadding + drawnTextWidth, y.toFloat(), textPaint) + canvas.drawText(" $it", x + startPadding + drawnTextWidth, y.toFloat(), textPaint) } } } From b9831734a0af0e8672dfe7b6765a0b24ff64b32a Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 17 Jul 2026 10:13:45 +0200 Subject: [PATCH 178/383] Take DisplayedStatus directly in DisplayNameWithStatus and always show emoji --- .../features/home/impl/components/RoomSummaryRow.kt | 3 +-- .../messagecomposer/suggestions/SuggestionsPickerView.kt | 7 +++---- .../features/messages/impl/topbars/MessagesViewTopBar.kt | 3 +-- .../matrix/ui/components/DisplayNameWithStatus.kt | 6 ++++-- .../libraries/matrix/ui/components/MatrixUserHeader.kt | 5 ++--- .../libraries/matrix/ui/components/MatrixUserRow.kt | 3 +-- 6 files changed, 12 insertions(+), 15 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 286576e344..2a21518e83 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 @@ -67,7 +67,6 @@ import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.ui.components.DisplayNameWithStatus import io.element.android.libraries.matrix.ui.components.InviteSenderView import io.element.android.libraries.matrix.ui.model.InviteSender -import io.element.android.libraries.matrix.ui.model.toEmojiText import io.element.android.libraries.ui.strings.CommonStrings import timber.log.Timber @@ -233,7 +232,7 @@ private fun NameAndTimestampRow( val displayName = name?.toSafeLength(ellipsize = true) ?: stringResource(id = CommonStrings.common_no_room_name) DisplayNameWithStatus( name = displayName, - status = dmUserStatus?.toEmojiText(), + status = dmUserStatus, modifier = Modifier.weight(1f), style = ElementTheme.typography.fontBodyLgMedium, nameColor = ElementTheme.colors.roomListRoomName, 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 9cc76b2458..d19061d8ed 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 @@ -43,7 +43,6 @@ 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.components.DisplayNameWithStatus import io.element.android.libraries.matrix.ui.model.getAvatarData -import io.element.android.libraries.matrix.ui.model.toEmojiText import io.element.android.libraries.slashcommands.api.SlashCommandSuggestion import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion import kotlinx.collections.immutable.ImmutableList @@ -120,8 +119,8 @@ private fun SuggestionItemView( is ResolvedSuggestion.Alias -> suggestion.roomName is ResolvedSuggestion.Command -> suggestion.command.command } - val statusEmoji = when (suggestion) { - is ResolvedSuggestion.Member -> suggestion.roomMember.displayedStatus?.toEmojiText() + val status = when (suggestion) { + is ResolvedSuggestion.Member -> suggestion.roomMember.displayedStatus else -> null } val details = when (suggestion) { @@ -156,7 +155,7 @@ private fun SuggestionItemView( title?.let { DisplayNameWithStatus( name = title, - status = statusEmoji, + status = status, style = ElementTheme.typography.fontBodyLgRegular, nameColor = ElementTheme.colors.textPrimary, ) 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 67fb07e4d2..2daa90af53 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 @@ -51,7 +51,6 @@ import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.ui.components.DisplayNameWithStatus import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.matrix.ui.model.getAvatarData -import io.element.android.libraries.matrix.ui.model.toEmojiText import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -163,7 +162,7 @@ private fun RoomAvatarAndNameRow( ) DisplayNameWithStatus( name = roomName ?: stringResource(CommonStrings.common_no_room_name), - status = dmUserStatus?.toEmojiText(), + status = dmUserStatus, modifier = Modifier.padding(start = 8.dp), style = ElementTheme.typography.fontBodyLgMedium, nameColor = ElementTheme.colors.textPrimary, diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/DisplayNameWithStatus.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/DisplayNameWithStatus.kt index 7c6e5854da..627b892fc5 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/DisplayNameWithStatus.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/DisplayNameWithStatus.kt @@ -21,6 +21,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.libraries.designsystem.theme.components.Text +import io.element.android.libraries.matrix.api.user.DisplayedStatus +import io.element.android.libraries.matrix.ui.model.toEmojiText /** * Component to display side by side a display name and an optional status. @@ -28,7 +30,7 @@ import io.element.android.libraries.designsystem.theme.components.Text @Composable fun DisplayNameWithStatus( name: String, - status: String?, + status: DisplayedStatus?, style: TextStyle, modifier: Modifier = Modifier, nameColor: Color = Color.Unspecified, @@ -52,7 +54,7 @@ fun DisplayNameWithStatus( if (status != null) { Spacer(Modifier.width(4.dp)) Text( - text = status, + text = status.toEmojiText(), style = style, color = ElementTheme.colors.textSecondary, ) 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 3132fe1140..89b0532580 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 @@ -31,7 +31,6 @@ import io.element.android.libraries.designsystem.theme.components.Text 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 -import io.element.android.libraries.matrix.ui.model.toEmojiText @Composable fun MatrixUserHeader( @@ -60,9 +59,9 @@ fun MatrixUserHeader( // Name DisplayNameWithStatus( name = matrixUser.getBestName(), - status = matrixUser.displayedStatus?.toEmojiText(), + status = matrixUser.displayedStatus, nameColor = ElementTheme.colors.textPrimary, - style = ElementTheme.typography.fontHeadingMdRegular + style = ElementTheme.typography.fontHeadingMdRegular, ) // Id if (matrixUser.displayName.isNullOrEmpty().not()) { 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 7fa4fe4557..9fc7ea7b4a 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 @@ -20,7 +20,6 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight 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 -import io.element.android.libraries.matrix.ui.model.toEmojiText @Composable fun MatrixUserRow( @@ -34,7 +33,7 @@ fun MatrixUserRow( nameContent = { DisplayNameWithStatus( name = matrixUser.getBestName(), - status = matrixUser.displayedStatus?.toEmojiText(), + status = matrixUser.displayedStatus, nameColor = ElementTheme.colors.textPrimary, style = ElementTheme.typography.fontBodyLgRegular, ) From 8d9bec57d755a76e63b0261d09abe0857054e15f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Jul 2026 17:58:57 +0200 Subject: [PATCH 179/383] Update zizmorcore/zizmor-action action to v0.6.0 (#7256) 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 14dc493029..4d5f568dac 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -336,7 +336,7 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7 + - uses: zizmorcore/zizmor-action@6599ee8b7a49aef6a770f63d261d214911a7ce02 # v0.6.0 upload_reports: name: Project Check Suite From 471b80af18176b24b6fc3423c13b5fae8c324f86 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 22 Jul 2026 18:32:35 +0200 Subject: [PATCH 180/383] Fix duplicate string resources after rebase --- libraries/ui-strings/src/main/res/values/temporary.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/ui-strings/src/main/res/values/temporary.xml b/libraries/ui-strings/src/main/res/values/temporary.xml index 2526f254d3..c704e811ff 100644 --- a/libraries/ui-strings/src/main/res/values/temporary.xml +++ b/libraries/ui-strings/src/main/res/values/temporary.xml @@ -6,12 +6,8 @@ --> - "Mark as read" - "Jump to first unread message" "Expanded" "Collapsed" - Allow access to local network - Your homeserver is on your local network. To connect, Element needs permission to reach other devices on this network. Active Inactive From e4f8139791a4c45ee90e4746702e07b177d8fe40 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 22 Jul 2026 18:19:12 +0200 Subject: [PATCH 181/383] Sync emoji picker translations from Localazy --- .../libraries/emoji/impl/picker/EmojiPickerView.kt | 4 ++-- .../impl/src/main/res/values-be/translations.xml | 11 +++++++++++ .../impl/src/main/res/values-bg/translations.xml | 11 +++++++++++ .../impl/src/main/res/values-ca/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-cs/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-cy/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-da/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-de/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-el/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-es/translations.xml | 11 +++++++++++ .../impl/src/main/res/values-et/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-eu/translations.xml | 11 +++++++++++ .../impl/src/main/res/values-fa/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-fi/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-fr/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-hr/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-hu/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-in/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-it/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-ja/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-ka/translations.xml | 11 +++++++++++ .../impl/src/main/res/values-ko/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-lt/translations.xml | 11 +++++++++++ .../impl/src/main/res/values-nb/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-nl/translations.xml | 11 +++++++++++ .../impl/src/main/res/values-pl/translations.xml | 13 +++++++++++++ .../src/main/res/values-pt-rBR/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-pt/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-ro/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-ru/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-sk/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-sv/translations.xml | 12 ++++++++++++ .../impl/src/main/res/values-tr/translations.xml | 11 +++++++++++ .../impl/src/main/res/values-uk/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-ur/translations.xml | 11 +++++++++++ .../impl/src/main/res/values-uz/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-vi/translations.xml | 13 +++++++++++++ .../src/main/res/values-zh-rTW/translations.xml | 13 +++++++++++++ .../impl/src/main/res/values-zh/translations.xml | 13 +++++++++++++ .../emoji/impl/src/main/res/values/localazy.xml | 13 +++++++++++++ .../emoji/impl/src/main/res/values/temporary.xml | 13 ------------- .../src/main/res/values-ca/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-et/translations.xml | 1 - .../src/main/res/values-fa/translations.xml | 1 - .../src/main/res/values-hr/translations.xml | 1 - .../src/main/res/values-nb/translations.xml | 1 - .../src/main/res/values-pl/translations.xml | 1 - .../src/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-uk/translations.xml | 1 - .../src/main/res/values-uz/translations.xml | 1 - .../src/main/res/values-vi/translations.xml | 1 - .../src/main/res/values-zh-rTW/translations.xml | 1 - .../src/main/res/values-zh/translations.xml | 1 - .../ui-strings/src/main/res/values/localazy.xml | 1 - tools/localazy/config.json | 7 ++++++- 64 files changed, 496 insertions(+), 38 deletions(-) create mode 100644 libraries/emoji/impl/src/main/res/values-be/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-bg/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-ca/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-cs/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-cy/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-da/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-de/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-el/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-es/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-et/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-eu/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-fa/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-fi/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-fr/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-hr/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-hu/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-in/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-it/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-ja/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-ka/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-ko/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-lt/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-nb/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-nl/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-pl/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-pt/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-ro/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-ru/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-sk/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-sv/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-tr/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-uk/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-ur/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-uz/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-vi/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-zh-rTW/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values-zh/translations.xml create mode 100644 libraries/emoji/impl/src/main/res/values/localazy.xml delete mode 100644 libraries/emoji/impl/src/main/res/values/temporary.xml diff --git a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiPickerView.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiPickerView.kt index 325f1d792b..94eaea1595 100644 --- a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiPickerView.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiPickerView.kt @@ -41,7 +41,7 @@ import io.element.android.libraries.designsystem.text.toSp import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.SearchBar -import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.libraries.emoji.impl.R import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableSet import kotlinx.collections.immutable.persistentSetOf @@ -68,7 +68,7 @@ internal fun EmojiPickerView( active = state.isSearchActive, onActiveChange = { state.eventSink(EmojiPickerEvent.ToggleSearchActive(it)) }, windowInsets = WindowInsets(0, 0, 0, 0), - placeHolderTitle = stringResource(CommonStrings.emoji_picker_search_placeholder), + placeHolderTitle = stringResource(R.string.emoji_picker_search_placeholder), ) { emojis -> EmojiResults( emojis = emojis, diff --git a/libraries/emoji/impl/src/main/res/values-be/translations.xml b/libraries/emoji/impl/src/main/res/values-be/translations.xml new file mode 100644 index 0000000000..6b07d89e30 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-be/translations.xml @@ -0,0 +1,11 @@ + + + "Актыўнасці" + "Сцягі" + "Ежа & Напоі" + "Жывёлы & Прырода" + "Аб\'екты" + "Усмешкі & Удзельнікі" + "Падарожжы & Месцы" + "Сімвалы" + diff --git a/libraries/emoji/impl/src/main/res/values-bg/translations.xml b/libraries/emoji/impl/src/main/res/values-bg/translations.xml new file mode 100644 index 0000000000..465b88d91f --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-bg/translations.xml @@ -0,0 +1,11 @@ + + + "Дейности" + "Знамена" + "Храна & Напитки" + "Животни & Природа" + "Обекти" + "Усмивки & Хора" + "Пътуване & Места" + "Символи" + diff --git a/libraries/emoji/impl/src/main/res/values-ca/translations.xml b/libraries/emoji/impl/src/main/res/values-ca/translations.xml new file mode 100644 index 0000000000..eec4847ec4 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-ca/translations.xml @@ -0,0 +1,13 @@ + + + "Activitats" + "Banderes" + "Menjar & begudes" + "Animals i naturalesa" + "Objectes" + "Cares i persones" + "Viatges i llocs" + "Emoticones recents" + "Símbols" + "Cerca emoticones" + diff --git a/libraries/emoji/impl/src/main/res/values-cs/translations.xml b/libraries/emoji/impl/src/main/res/values-cs/translations.xml new file mode 100644 index 0000000000..899a4ab0da --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-cs/translations.xml @@ -0,0 +1,13 @@ + + + "Aktivity" + "Vlajky" + "Jídlo a nápoje" + "Zvířata a příroda" + "Předměty" + "Smajlíci a lidé" + "Cestování a místa" + "Nedávné emotikony" + "Symboly" + "Hledat emotikony" + diff --git a/libraries/emoji/impl/src/main/res/values-cy/translations.xml b/libraries/emoji/impl/src/main/res/values-cy/translations.xml new file mode 100644 index 0000000000..d2dc0d1f3c --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-cy/translations.xml @@ -0,0 +1,13 @@ + + + "Gweithgareddau" + "Baneri" + "Bwyd a Diod" + "Anifeiliaid a Natur" + "Gwrthrychau" + "Wynebau Hapus a Phobl" + "Teithio a Llefydd" + "Emojis diweddar" + "Symbolau" + "Chwilio emojis" + diff --git a/libraries/emoji/impl/src/main/res/values-da/translations.xml b/libraries/emoji/impl/src/main/res/values-da/translations.xml new file mode 100644 index 0000000000..ae0e860608 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-da/translations.xml @@ -0,0 +1,13 @@ + + + "Aktiviteter" + "Flag" + "Mad og drikke" + "Dyr og natur" + "Objekter" + "Smileys og personer" + "Rejser og steder" + "Seneste emojis" + "Symboler" + "Søg emojis" + diff --git a/libraries/emoji/impl/src/main/res/values-de/translations.xml b/libraries/emoji/impl/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..874769c469 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-de/translations.xml @@ -0,0 +1,13 @@ + + + "Aktivitäten" + "Flaggen" + "Essen & Trinken" + "Tiere & Natur" + "Objekte" + "Smileys & Menschen" + "Reisen & Orte" + "Zuletzt verwendete Emojis" + "Symbole" + "Emojis suchen" + diff --git a/libraries/emoji/impl/src/main/res/values-el/translations.xml b/libraries/emoji/impl/src/main/res/values-el/translations.xml new file mode 100644 index 0000000000..c61f78e1da --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-el/translations.xml @@ -0,0 +1,13 @@ + + + "Δραστηριότητες" + "Σημαίες" + "Φαγητό & Ποτό" + "Ζώα & Φύση" + "Αντικείμενα" + "Φατσούλες & Άνθρωποι" + "Ταξίδια & Μέρη" + "Πρόσφατα emoji" + "Σύμβολα" + "Αναζήτηση emoji" + diff --git a/libraries/emoji/impl/src/main/res/values-es/translations.xml b/libraries/emoji/impl/src/main/res/values-es/translations.xml new file mode 100644 index 0000000000..7a694296b2 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-es/translations.xml @@ -0,0 +1,11 @@ + + + "Actividades" + "Banderas" + "Comida y bebida" + "Animales y naturaleza" + "Objetos" + "Emojis y personas" + "Viajes y lugares" + "Símbolos" + diff --git a/libraries/emoji/impl/src/main/res/values-et/translations.xml b/libraries/emoji/impl/src/main/res/values-et/translations.xml new file mode 100644 index 0000000000..881a342c8d --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-et/translations.xml @@ -0,0 +1,13 @@ + + + "Tegevused" + "Lipud" + "Toit ja jook" + "Loomad ja loodus" + "Esemed" + "Emotikonid ja inimesed" + "Reisimine ja kohad" + "Hiljutised emojid" + "Sümbolid" + "Otsi emojisid" + diff --git a/libraries/emoji/impl/src/main/res/values-eu/translations.xml b/libraries/emoji/impl/src/main/res/values-eu/translations.xml new file mode 100644 index 0000000000..a5cce4e187 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-eu/translations.xml @@ -0,0 +1,11 @@ + + + "Jarduerak" + "Banderak" + "Jana eta edana" + "Animaliak eta natura" + "Objektuak" + "Irribartxoak eta jendea" + "Bidaiak eta tokiak" + "Ikurrak" + diff --git a/libraries/emoji/impl/src/main/res/values-fa/translations.xml b/libraries/emoji/impl/src/main/res/values-fa/translations.xml new file mode 100644 index 0000000000..7c19e79b30 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-fa/translations.xml @@ -0,0 +1,13 @@ + + + "فعّالیت‌ها" + "پرچم‌ها" + "غذا و نوشیدنی" + "حیوانات و طبعیت" + "اشیا" + "شکلک‌ها و افراد" + "سفر و مکان‌ها" + "شکلک‌های اخیر" + "نمادها" + "حست‌وجوی شکلک‌ها" + diff --git a/libraries/emoji/impl/src/main/res/values-fi/translations.xml b/libraries/emoji/impl/src/main/res/values-fi/translations.xml new file mode 100644 index 0000000000..d41d0a8af1 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-fi/translations.xml @@ -0,0 +1,13 @@ + + + "Aktiviteetit" + "Liput" + "Ruoka ja juoma" + "Eläimet ja luonto" + "Esineet" + "Hymiöt ja ihmiset" + "Matkustaminen ja paikat" + "Viimeaikaiset emojit" + "Symbolit" + "Etsi emojeja" + diff --git a/libraries/emoji/impl/src/main/res/values-fr/translations.xml b/libraries/emoji/impl/src/main/res/values-fr/translations.xml new file mode 100644 index 0000000000..856b5a1064 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-fr/translations.xml @@ -0,0 +1,13 @@ + + + "Activités" + "Drapeaux" + "Nourriture et boissons" + "Animaux et nature" + "Objets" + "Émoticônes et personnes" + "Voyages & lieux" + "Emojis récents" + "Symboles" + "Chercher des emojis" + diff --git a/libraries/emoji/impl/src/main/res/values-hr/translations.xml b/libraries/emoji/impl/src/main/res/values-hr/translations.xml new file mode 100644 index 0000000000..db677e5362 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-hr/translations.xml @@ -0,0 +1,13 @@ + + + "Aktivnosti" + "Zastave" + "Hrana i piće" + "Životinje i priroda" + "Objekti" + "Emotikoni i osobe" + "Putovanja i mjesta" + "Nedavni emotikoni" + "Simboli" + "Pretraživanje emotikona" + diff --git a/libraries/emoji/impl/src/main/res/values-hu/translations.xml b/libraries/emoji/impl/src/main/res/values-hu/translations.xml new file mode 100644 index 0000000000..a6542d118a --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-hu/translations.xml @@ -0,0 +1,13 @@ + + + "Tevékenységek" + "Zászlók" + "Étel és ital" + "Állatok és természet" + "Tárgyak" + "Mosolyok és emberek" + "Utazás és helyek" + "Legutóbbi emodzsik" + "Szimbólumok" + "Emodzsik keresése" + diff --git a/libraries/emoji/impl/src/main/res/values-in/translations.xml b/libraries/emoji/impl/src/main/res/values-in/translations.xml new file mode 100644 index 0000000000..20ff1aa10a --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-in/translations.xml @@ -0,0 +1,13 @@ + + + "Aktivitas" + "Bendera" + "Makanan & Minuman" + "Hewan & Alam" + "Objek" + "Senyuman & Orang" + "Wisata & Tempat" + "Emojis Sebelumnya" + "Simbol" + "Cari emoji" + diff --git a/libraries/emoji/impl/src/main/res/values-it/translations.xml b/libraries/emoji/impl/src/main/res/values-it/translations.xml new file mode 100644 index 0000000000..dbfb9ac6f4 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-it/translations.xml @@ -0,0 +1,13 @@ + + + "Attività" + "Bandiere" + "Cibi & Bevande" + "Animali & Natura" + "Oggetti" + "Faccine & Persone" + "Viaggi & Luoghi" + "Emoji recenti" + "Simboli" + "Cerca emoji" + diff --git a/libraries/emoji/impl/src/main/res/values-ja/translations.xml b/libraries/emoji/impl/src/main/res/values-ja/translations.xml new file mode 100644 index 0000000000..273422bd11 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-ja/translations.xml @@ -0,0 +1,13 @@ + + + "アクティビティ" + "旗" + "食べ物" + "動物・自然" + "物" + "顔・人" + "旅・場所" + "最近使用" + "記号" + "絵文字を検索" + diff --git a/libraries/emoji/impl/src/main/res/values-ka/translations.xml b/libraries/emoji/impl/src/main/res/values-ka/translations.xml new file mode 100644 index 0000000000..0cfa48d863 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-ka/translations.xml @@ -0,0 +1,11 @@ + + + "აქტივობები" + "დროშები" + "Საჭმელ-სასმელი" + "ცხოველები & ბუნება" + "ობიექტები" + "ღიმილები & ხალხი" + "მოგზაურობა და ადგილები" + "სიმბოლოები" + diff --git a/libraries/emoji/impl/src/main/res/values-ko/translations.xml b/libraries/emoji/impl/src/main/res/values-ko/translations.xml new file mode 100644 index 0000000000..7ab40e73ed --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-ko/translations.xml @@ -0,0 +1,13 @@ + + + "활동" + "깃발" + "음식 & 음료" + "동물 & 자연" + "사물" + "표정 & 사람" + "여행 & 장소" + "최근 이모지" + "상징" + "이모지 검색" + diff --git a/libraries/emoji/impl/src/main/res/values-lt/translations.xml b/libraries/emoji/impl/src/main/res/values-lt/translations.xml new file mode 100644 index 0000000000..3affbd9124 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-lt/translations.xml @@ -0,0 +1,11 @@ + + + "Veikla" + "Vėliavos" + "Maistas ir Gėrimai" + "Gyvūnai ir Gamta" + "Objektai" + "Šypsenėlės ir Žmonės" + "Kelionės ir Vietovės" + "Simboliai" + diff --git a/libraries/emoji/impl/src/main/res/values-nb/translations.xml b/libraries/emoji/impl/src/main/res/values-nb/translations.xml new file mode 100644 index 0000000000..dd7ddd8cd2 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-nb/translations.xml @@ -0,0 +1,13 @@ + + + "Aktiviteter" + "Flagg" + "Mat og drikke" + "Dyr og natur" + "Gjenstander" + "Smilefjes og mennesker" + "Reising og steder" + "Nylige emojier" + "Symboler" + "Søk etter emojier" + diff --git a/libraries/emoji/impl/src/main/res/values-nl/translations.xml b/libraries/emoji/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..bd4f28f420 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,11 @@ + + + "Activiteiten" + "Vlaggen" + "Eten & Drinken" + "Dieren & Natuur" + "Voorwerpen" + "Smileys & Mensen" + "Reizen & Locaties" + "Symbolen" + diff --git a/libraries/emoji/impl/src/main/res/values-pl/translations.xml b/libraries/emoji/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..c59f2c6b54 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,13 @@ + + + "Aktywności" + "Flagi" + "Jedzenie i napoje" + "Zwierzęta i natura" + "Obiekty" + "Buźki i osoby" + "Podróż i miejsca" + "Ostatnie emoji" + "Symbole" + "Wyszukaj emoji" + diff --git a/libraries/emoji/impl/src/main/res/values-pt-rBR/translations.xml b/libraries/emoji/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..aa0c06f602 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,13 @@ + + + "Atividades" + "Bandeiras" + "Comida & Bebida" + "Animais & Natureza" + "Objetos" + "Sorrisos & Pessoas" + "Viagens & Lugares" + "Emojis recentes" + "Símbolos" + "Pesquisar emojis" + diff --git a/libraries/emoji/impl/src/main/res/values-pt/translations.xml b/libraries/emoji/impl/src/main/res/values-pt/translations.xml new file mode 100644 index 0000000000..02ecf31351 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-pt/translations.xml @@ -0,0 +1,13 @@ + + + "Atividades" + "Bandeiras" + "Comidas e Bebidas" + "Animais e Natureza" + "Objetos" + "Caras e Pessoas" + "Viagens e Lugares" + "Emojis recentes" + "Símbolos" + "Pesquisar emojis" + diff --git a/libraries/emoji/impl/src/main/res/values-ro/translations.xml b/libraries/emoji/impl/src/main/res/values-ro/translations.xml new file mode 100644 index 0000000000..410bcef3bc --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-ro/translations.xml @@ -0,0 +1,13 @@ + + + "Activități" + "Steaguri" + "Mâncare & Băutură" + "Animale și Natură" + "Obiecte" + "Fețe zâmbitoare & Oameni" + "Călătorii & Locuri" + "Emoticoane recente" + "Simboluri" + "Căutați emoticoane" + diff --git a/libraries/emoji/impl/src/main/res/values-ru/translations.xml b/libraries/emoji/impl/src/main/res/values-ru/translations.xml new file mode 100644 index 0000000000..2b975ac252 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-ru/translations.xml @@ -0,0 +1,13 @@ + + + "Активности" + "Флаги" + "Еда и напитки" + "Животные и природа" + "Объекты" + "Эмодзи и люди" + "Путешествия и места" + "Недавние эмодзи" + "Символы" + "Поиск эмодзи" + diff --git a/libraries/emoji/impl/src/main/res/values-sk/translations.xml b/libraries/emoji/impl/src/main/res/values-sk/translations.xml new file mode 100644 index 0000000000..09257c943c --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-sk/translations.xml @@ -0,0 +1,13 @@ + + + "Aktivity" + "Vlajky" + "Jedlo a nápoje" + "Zvieratá a príroda" + "Predmety" + "Smajlíky a ľudia" + "Cestovanie a miesta" + "Nedávne emotikony" + "Symboly" + "Hľadať emotikony" + diff --git a/libraries/emoji/impl/src/main/res/values-sv/translations.xml b/libraries/emoji/impl/src/main/res/values-sv/translations.xml new file mode 100644 index 0000000000..8484eb80bb --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-sv/translations.xml @@ -0,0 +1,12 @@ + + + "Aktiviteter" + "Flaggor" + "Mat & dryck" + "Djur & natur" + "Föremål" + "Smileys & personer" + "Resor & platser" + "Symboler" + "Sök emojier" + diff --git a/libraries/emoji/impl/src/main/res/values-tr/translations.xml b/libraries/emoji/impl/src/main/res/values-tr/translations.xml new file mode 100644 index 0000000000..f27e7d29eb --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-tr/translations.xml @@ -0,0 +1,11 @@ + + + "Aktiviteler" + "Bayraklar" + "Yiyecek ve İçecek" + "Hayvanlar ve Doğa" + "Nesneler" + "İfadeler ve İnsanlar" + "Seyahat ve Yerler" + "Simgeler" + diff --git a/libraries/emoji/impl/src/main/res/values-uk/translations.xml b/libraries/emoji/impl/src/main/res/values-uk/translations.xml new file mode 100644 index 0000000000..c05a4576bf --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-uk/translations.xml @@ -0,0 +1,13 @@ + + + "Дії" + "Прапори" + "Їжа та напої" + "Тварини та природа" + "Об\'єкти" + "Смайлики та люди" + "Подорожі та місця" + "Нещодавні емодзі" + "Символи" + "Пошук емоджі" + diff --git a/libraries/emoji/impl/src/main/res/values-ur/translations.xml b/libraries/emoji/impl/src/main/res/values-ur/translations.xml new file mode 100644 index 0000000000..b1c0848e2b --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-ur/translations.xml @@ -0,0 +1,11 @@ + + + "سرگرمیاں" + "جھنڈے" + "طعم و مشروب" + "حیوانات و فطرت" + "اشیاء" + "مسکراہٹیں و لوگ" + "سفر و مقامات" + "علامتیں" + diff --git a/libraries/emoji/impl/src/main/res/values-uz/translations.xml b/libraries/emoji/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..692c23b0cc --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,13 @@ + + + "Faoliyatlar" + "Bayroqlar" + "Oziq-ovqat va ichimliklar" + "Hayvonlar va tabiat" + "Ob\'ektlar" + "Smayllar va odamlar" + "Sayohat va Joylar" + "Oxirgi kulgichlar" + "Belgilar" + "Emojilarni qidiring" + diff --git a/libraries/emoji/impl/src/main/res/values-vi/translations.xml b/libraries/emoji/impl/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..1b8e165600 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-vi/translations.xml @@ -0,0 +1,13 @@ + + + "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 cảm xúc gần đây" + "Biểu tượng" + "Tìm kiếm biểu tượng cảm xúc" + diff --git a/libraries/emoji/impl/src/main/res/values-zh-rTW/translations.xml b/libraries/emoji/impl/src/main/res/values-zh-rTW/translations.xml new file mode 100644 index 0000000000..4461477da5 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-zh-rTW/translations.xml @@ -0,0 +1,13 @@ + + + "活動" + "旗幟" + "食物與飲料" + "動物與大自然" + "物品" + "表情與人物" + "旅行與景點" + "最近使用的表情符號" + "標誌" + "搜尋表情符號" + diff --git a/libraries/emoji/impl/src/main/res/values-zh/translations.xml b/libraries/emoji/impl/src/main/res/values-zh/translations.xml new file mode 100644 index 0000000000..b4e8c6c859 --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values-zh/translations.xml @@ -0,0 +1,13 @@ + + + "节假日" + "旗帜" + "饮食" + "动物和自然" + "日常物品" + "表情和人物" + "文旅景点" + "最近的 Emoji" + "符号" + "搜索 Emoji" + diff --git a/libraries/emoji/impl/src/main/res/values/localazy.xml b/libraries/emoji/impl/src/main/res/values/localazy.xml new file mode 100644 index 0000000000..f767a29ecb --- /dev/null +++ b/libraries/emoji/impl/src/main/res/values/localazy.xml @@ -0,0 +1,13 @@ + + + "Activities" + "Flags" + "Food & Drink" + "Animals & Nature" + "Objects" + "Smileys & People" + "Travel & Places" + "Recent emojis" + "Symbols" + "Search emojis" + diff --git a/libraries/emoji/impl/src/main/res/values/temporary.xml b/libraries/emoji/impl/src/main/res/values/temporary.xml deleted file mode 100644 index 34467795b9..0000000000 --- a/libraries/emoji/impl/src/main/res/values/temporary.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - "Activities" - "Flags" - "Food & Drink" - "Animals & Nature" - "Objects" - "Smileys & People" - "Travel & Places" - "Recent emojis" - "Symbols" - diff --git a/libraries/ui-strings/src/main/res/values-ca/translations.xml b/libraries/ui-strings/src/main/res/values-ca/translations.xml index 5a4c1dd516..f7798cd008 100644 --- a/libraries/ui-strings/src/main/res/values-ca/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ca/translations.xml @@ -321,7 +321,6 @@ Segur que vols continuar?" "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." 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 ccd15c10c3..11ded645d7 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -452,7 +452,6 @@ Opravdu chcete pokračovat?" "Maximální povolená velikost souboru je: %1$s" "Vyberte kvalitu videa, které chcete nahrát." "Vyberte kvalitu nahrávání videa" - "Hledat emotikony" "Na tomto zařízení jste již přihlášeni jako %1$s." "Váš domovský server je třeba upgradovat, aby podporoval službu Matrix Authentication Service a vytváření účtu." "Vytvoření trvalého odkazu se nezdařilo" 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 bed2fff573..f2fb860515 100644 --- a/libraries/ui-strings/src/main/res/values-cy/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cy/translations.xml @@ -416,7 +416,6 @@ Ydych chi\'n siŵr eich bod am barhau?" "Y maint ffeil mwyaf sy\'n cael ei ganiatáu yw: %1$s" "Dewiswch ansawdd y fideo rydych chi am ei llwytho." "Dewiswch ansawdd llwytho fideo" - "Chwilio emojis" "Rydych chi eisoes wedi mewngofnodi ar y ddyfais hon fel %1$s ." "Mae angen uwchraddio eich gweinydd cartref i gefnogi Gwasanaeth Dilysu Matrix a chreu cyfrif." "Wedi methu creu\'r ddolen barhaol" 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 41fe346190..614cec39cf 100644 --- a/libraries/ui-strings/src/main/res/values-da/translations.xml +++ b/libraries/ui-strings/src/main/res/values-da/translations.xml @@ -440,7 +440,6 @@ Er du sikker på, at du vil fortsætte?" "Den maksimalt tilladte filstørrelse er: %1$s" "Vælg den kvalitet, du ønsker at uploade videoen i." "Vælg kvalitet for video-overførsel" - "Søg emojis" "Du er allerede logget ind på denne enhed som %1$s." "Din hjemmeserver skal opgraderes for at understøtte Matrix Authentication Service og kontooprettelse." "Oprettelse af permalink mislykkedes" 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 fe1eaac312..d83fb1ee64 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -433,7 +433,6 @@ Möchtest du wirklich fortfahren?" "Die maximal erlaubte Dateigröße ist: %1$s" "Wähle die Qualität des Videos, das du hochladen möchtest." "Wähle die Video-Upload-Qualität" - "Emojis suchen" "Du bist auf diesem Gerät bereits als %1$s angemeldet." "Dein Homeserver muss aktualisiert werden, um den Matrix Authentication Services und die Erstellung von Konten zu unterstützen." "Fehler beim Erstellen des Permalinks" 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 dab809f74d..938e1a5e9a 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -477,7 +477,6 @@ Kas sa oled kindel, et soovid jätkata?" "Suurim lubatud failisuurus on: %1$s" "Vali üleslaaditava video kvaliteet." "Vali video kvaliteet." - "Otsi emojisid" "Sa juba oled sellesse seadmesse sisseloginud kasutajana %1$s." "Selleks et koos kasutajakonto loomisega toimiks Matrix Authentication Service\'i tugi, vajab sinu koduserver uuendamist." "Püsilingi loomine ei õnnestumud" 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 6d377a9652..03d1172040 100644 --- a/libraries/ui-strings/src/main/res/values-fa/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fa/translations.xml @@ -348,7 +348,6 @@ "تغییراتی ذخیره نشده دارید." "تغییراتتان ذخیره نشده‌اند. مطمئنید که می‌خواهید برگردید؟" "ذخیرهٔ تغییرات؟" - "حست‌وجوی شکلک‌ها" "شکست در ایجاد پایاپیوند" "%1$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 03e24aebd3..6ca10c229e 100644 --- a/libraries/ui-strings/src/main/res/values-hr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hr/translations.xml @@ -475,7 +475,6 @@ Jeste li sigurni da želite nastaviti?" "Maksimalna dopuštena veličina datoteke je: %1$s" "Odaberite kvalitetu videozapisa koji želite prenijeti." "Odaberi kvalitetu prijenosa videozapisa" - "Pretraživanje emotikona" "Već ste prijavljeni na ovom uređaju kao %1$s." "Vaš matični poslužitelj potrebno je nadograditi kako bi podržavao uslugu Matrix Authentication Service i stvaranje računa." "Nije uspjelo stvaranje trajne poveznice" 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 60ee544965..492268c38f 100644 --- a/libraries/ui-strings/src/main/res/values-nb/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nb/translations.xml @@ -429,7 +429,6 @@ Er du sikker på at du vil fortsette?" "Maksimal tillatt filstørrelse er: %1$s" "Velg kvaliteten på videoen du vil laste opp." "Velg kvalitet for videoopplasting" - "Søk etter emojier" "Du er allerede logget inn på denne enheten som %1$s." "Hjemmeserveren din må oppgraderes for å støtte Matrix Authentication Service og kontooppretting." "Opprettelse av permalenken mislyktes" 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 fcea19da49..e5c8755a96 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -477,7 +477,6 @@ Czy na pewno chcesz kontynuować?" "Maksymalny dozwolony rozmiar pliku to: %1$s" "Wybierz jakość filmu, który chcesz przesłać." "Wybierz jakość przesyłania wideo" - "Wyszukaj emoji" "Jesteś już zalogowany na tym urządzeniu jako %1$s." "Twój serwer domowy wymaga aktualizacji, aby uzyskać wsparcie usługi Matrix Authentication Service i tworzenia kont." "Nie udało się utworzyć linku bezpośredniego" 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 474d1c8917..49decfa49b 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 @@ -410,7 +410,6 @@ Você tem certeza de que deseja continuar?" "O tamanho máximo permitido de arquivos é: %1$s" "Selecione a qualidade do video que quer enviar." "Selecione a qualidade de envio dos vídeos" - "Pesquisar emojis" "Você já está conectado neste dispositivo como %1$s ." "Seu servidor-casa precisa ser atualizado para oferecer suporte ao Matrix Authentication Service e à criação de contas." "Falha ao criar o link permanente" 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 e8d32ee72e..617ecad2db 100644 --- a/libraries/ui-strings/src/main/res/values-pt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt/translations.xml @@ -391,7 +391,6 @@ Tens a certeza de que queres continuar?" "O tamanho máximo de ficheiro permitido é: %1$s" "Seleciona a qualidade do vídeo que pretendes carregar." "Seleciona a qualidade de carregamento do vídeo" - "Pesquisar emojis" "Já tens sessão iniciada como %1$s neste dispositivo." "Seu homeserver precisa ser atualizado para suportar o Matrix Authentication Service e a criação de conta." "Falha ao criar ligação permanente" 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 bdb220c9a0..4eba83312b 100644 --- a/libraries/ui-strings/src/main/res/values-ro/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ro/translations.xml @@ -451,7 +451,6 @@ Sunteți sigur că doriți să continuați?" "Dimensiunea maximă permisă pentru fișiere este: %1$s" "Selectați calitatea videoclipului pe care doriți să îl încărcați." "Selectați calitatea de încărcare a videoclipurilor" - "Căutați emoticoane" "Sunteți deja conectat pe acest dispozitiv ca %1$s." "Serverul dumneavoastră trebuie actualizat pentru a suporta serviciul de autentificare Matrix și crearea de conturi." "Crearea permalink-ului a eșuat" 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 cd711bf18b..892d4348c1 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -476,7 +476,6 @@ "Максимально допустимый размер файла: %1$s" "Выберите качество видео, которое Вы хотите загрузить." "Выберите качество загружаемого видео" - "Поиск эмодзи" "Вы уже вошли на данном устройстве как %1$s." "Домашний сервер необходимо обновить, чтобы он поддерживал Matrix Authentication Service и создание учётных записей." "Не удалось создать постоянную ссылку" 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 f4f03fd3b8..4fdf503c97 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -423,7 +423,6 @@ Naozaj chcete pokračovať?" "Maximálna povolená veľkosť súboru je: %1$s" "Vyberte kvalitu videa, ktoré chcete nahrať." "Vyberte kvalitu nahrávania videa" - "Hľadať emotikony" "Už ste prihlásený/á na tomto zariadení ako %1$s ." "Váš domovský server musí byť aktualizovaný tak, aby podporoval Matrix Authentication Service a vytvorenie účtu." "Nepodarilo sa vytvoriť trvalý odkaz" 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 ea7ba155c4..4e46cd4653 100644 --- a/libraries/ui-strings/src/main/res/values-sv/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sv/translations.xml @@ -379,7 +379,6 @@ Anledning:%1$s." "Den maximala tillåtna filstorleken är: %1$s" "Välj kvaliteten på videon du vill ladda upp." "Välj videouppladdningskvalitet" - "Sök emojier" "Du är redan inloggad på den här enheten som %1$s." "Din hemserver måste uppgraderas för att stödja Matrix Authentication Service och skapande av konto." "Misslyckades att skapa permalänken" 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 aabea67405..4f92b9547f 100644 --- a/libraries/ui-strings/src/main/res/values-uk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uk/translations.xml @@ -476,7 +476,6 @@ "Максимально дозволений розмір файлу: %1$s" "Виберіть якість відео, яке ви хочете вивантажити." "Виберіть якість вивантажуваного відео" - "Пошук емоджі" "Ви вже ввійшли на цьому пристрої як %1$s." "Ваш домашній сервер потрібно оновити, щоб він підтримував службу автентифікації Matrix і створення облікових записів." "Не вдалося створити постійне посилання" 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 6a21c6aea6..120de32b66 100644 --- a/libraries/ui-strings/src/main/res/values-uz/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uz/translations.xml @@ -450,7 +450,6 @@ Davom etasizmi?" "Ruxsat etilgan maksimal fayl hajmi: %1$s" "Yuklanadigan video sifatini tanlang." "Video yuklash sifatini tanlang" - "Emojilarni qidiring" "Bu qurilmada allaqachon %1$s hisobiga kirgansiz." "Matrix autentifikatsiya xizmati va hisob yaratish imkoniyatini qo‘llab-quvvatlash uchun uy serveringizni yangilash talab etiladi." "Doimiy havola yaratilmadi" 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 3da8d7f394..87baf98c47 100644 --- a/libraries/ui-strings/src/main/res/values-vi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-vi/translations.xml @@ -422,7 +422,6 @@ 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" 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 f54a9cc5a5..c2ff955eac 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 @@ -425,7 +425,6 @@ "最大允許的檔案大小為:%1$s" "選取您要上傳的視訊的品質。" "選取視訊上傳品質" - "搜尋表情符號" "您已在此裝置上以 %1$s 的身份登入。" "您的家伺服器需要升級才能支援 Matrix Authentication Service 與帳號建立。" "無法建立永久連結" 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 e91509ab3f..99f0d20b14 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -466,7 +466,6 @@ "允许的最大文件大小为:%1$s" "选择你要上传的视频的质量。" "选择视频上传质量" - "搜索 Emoji" "你已在此设备以 %1$s 的身份登录。" "你的主服务器需要升级,以支持 Matrix 认证服务和账户创建。" "永久链接创建失败" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 485b9b9d59..ed45f312e3 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -477,7 +477,6 @@ Are you sure you want to continue?" "The max file size allowed is: %1$s" "Select the quality of the video you want to upload." "Select video upload quality" - "Search emojis" "You\'re already logged in on this device as %1$s." "Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation." "Failed creating the permalink" diff --git a/tools/localazy/config.json b/tools/localazy/config.json index 5753fe5f47..ac5b1295fe 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -261,7 +261,6 @@ { "name" : ":features:messages:impl", "includeRegex" : [ - "emoji_picker_category_.*", "screen_report_content_.*", "screen_room_attachment.*", "screen_room_encrypted.*", @@ -426,6 +425,12 @@ "screen\\.share_location\\..*", "screen\\.view_location\\..*" ] + }, + { + "name" : ":libraries:emoji:impl", + "includeRegex" : [ + "emoji_picker_.*" + ] } ] } From 2f09585b813490c88ad759a913bdbb84881997d6 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 22 Jul 2026 19:22:11 +0000 Subject: [PATCH 182/383] Update screenshots --- .../features.invitepeople.impl_InvitePeopleView_Day_5_en.png | 4 ++-- ...features.invitepeople.impl_InvitePeopleView_Night_5_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_5_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_6_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_5_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_6_en.png | 4 ++-- ...embermoderation.impl_RoomMemberModerationView_Day_5_en.png | 4 ++-- ...embermoderation.impl_RoomMemberModerationView_Day_7_en.png | 4 ++-- ...bermoderation.impl_RoomMemberModerationView_Night_5_en.png | 4 ++-- ...bermoderation.impl_RoomMemberModerationView_Night_7_en.png | 4 ++-- ...eme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png | 4 ++-- ...e.components_HorizontalFloatingToolbarNoFab_Night_0_en.png | 4 ++-- ...em.theme.components_HorizontalFloatingToolbar_Day_0_en.png | 4 ++-- ....theme.components_HorizontalFloatingToolbar_Night_0_en.png | 4 ++-- ...aries.matrix.ui.components_CheckableResolvedUserRow_en.png | 4 ++-- 15 files changed, 30 insertions(+), 30 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_5_en.png index c67c062ddc..e2c64a6d5b 100644 --- a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a9237dbe1fd700357d7d073408977653a52d9f8c2ca92aad26569c10c0247a1 -size 37488 +oid sha256:686b6dbb0e54dc133a504bb56bf254c8bc6d76faf1c51e696c2b980ad67ffd35 +size 37320 diff --git a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_5_en.png index eb0e3331e0..2f41c0ac43 100644 --- a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed1399fb1ec24eddadaf91700ac446a9f76784953b8b84cf1675c979fc9aebb9 -size 38509 +oid sha256:33e7d75e2f1ebed36e05491eb27475ce74cce35a4121aaa053aff34ac6f8c0dc +size 38272 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png index 7ef9b7ae0a..270dbe6d1e 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d19e7a09114e76294a0626e5d617cf55fe7c13a0188a7d5b364f57c0d9daedc1 -size 12123 +oid sha256:195338046951366fd2345fdc8471e3e2b2786723c8bfffa9fa9057929c608afb +size 12113 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png index f831ed92a2..0ca6f66438 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7fe1f51d385bba8821dfc0f0da84990cf0d148e991d765484b343d8764abd47d -size 11724 +oid sha256:5896eb5df6f5398bdb94e74280d0d5c04b6a5a53c2378b7377c60fa58eef544b +size 12013 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index 1e04c3e7d7..fb72cafe03 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bbc8c05e6f6818d00282228f52424ebe93e6e3dca3431d742e8c652d56460d6 -size 11712 +oid sha256:4ef1b643a16b5a94c75f8bb845c36d3cbc7f7ed96a0cac32fdb9f0b09d26b4d1 +size 11747 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png index 8e1b9c99d2..ce1258d2ac 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66f6d0d6b03ee4c999cd4edc9c6ae567d31b8b537ca6f9cc8fbe436d06ce80ab -size 11643 +oid sha256:ce754ce205fd864e01828659aff42ab19dccf7c921c1c733ed1757f1b2122309 +size 11403 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png index 73b8b8e50c..5c597300e4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e8a3ad99763929d2783147814e44fa9ec7e7efb7b99949e3580f23c38fb5d971 -size 9398 +oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 +size 3853 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png index 5c597300e4..f8a1f24b34 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 -size 3853 +oid sha256:1342b6427f5b2e3075ae3ccee60bf1d3b11afaccf3e152643d6ef2d65c21b54e +size 9108 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png index d47bf90664..4ae7279fe7 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c -size 3664 +oid sha256:410a8596d4c70b9a3856d959d6d71ade8e831e8581ff410c9900957a93b3eb50 +size 8114 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png index a87d89c701..d47bf90664 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f3a0cb5d9bae6725a1c527f3d9575aabf85d3edf63a28d9faa23f4f0b65e2d0 -size 7624 +oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c +size 3664 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png index ee5c582240..58546b8522 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75de341f705bb22955f9399180519b65ad59c2e1917317d56e50ea4db78f35bc -size 12102 +oid sha256:30357bf18792db5ab20085010251170a724ffe8c00313facd04ee704e806af64 +size 10982 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png index fedead0fa8..52fd9b9693 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4811667dec0f32accc5e2c8a5dd5c0b34017fcff8d1e0376ee7a4708426bca0f -size 9838 +oid sha256:58b9491aaa5554b89d86c62a5c9c44975367538c6baa5562f8dc5768f76d8264 +size 8705 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png index 38ad0e4b56..83302d6ba4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:326d59cf768b2dbd96eb7964d54c8eda509a5cd57c6e62087625e3314da0bb4d -size 13658 +oid sha256:16dee1dfe746cd40dac9fe8f0af3ecb42cd14bab5cc490917b589beed065ed1b +size 14686 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png index 4da2a98aca..687e0d436a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef0dc4d53daeb986f378b6e4d85928b4b6729336c89cf21e642c88c53688a3ab -size 10292 +oid sha256:d57df7110371c9224e232b707d6a1b10ce14afcb56c803a78220792f2a0d4cf2 +size 11354 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 185aeb6a20..32ed8ebc5e 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:e7b042410cfc2999e599534c263abd27ef43a64444e90aeed3a45a72ec8f0a15 -size 46735 +oid sha256:ef82fb23d7da19f1c3f37c3fbd1472f138a8edb27c307072cebb3b2444c239ae +size 46245 From 14feeca2a5881938eb33b2947697fd4490080075 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 23 Jul 2026 11:25:40 +0200 Subject: [PATCH 183/383] Add some comments after PR review --- .../preferences/impl/userstatus/UserStatusPresenter.kt | 2 ++ .../emoji/impl/picker/DefaultEmojiPickerPresenter.kt | 2 ++ .../android/libraries/emoji/impl/picker/EmojiItem.kt | 10 ++++++++++ 3 files changed, 14 insertions(+) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt index 6079ae04cc..60f02ad05a 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt @@ -79,6 +79,8 @@ class UserStatusPresenter( } } + // In CustomInput mode, override the picker state's `emojiPickerSheetState` with the freshly composed emoji-picker + // sub-state so recompositions of the picker propagate up. Other modes pass through unchanged. val effectivePickerState = when (val current = pickerState) { is UserStatusPickerState.CustomInput -> { val emojiPickerState = presentEmojiPickerSheetState(isEmojiPickerVisible) diff --git a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt index 6a0c4924b3..9d7dbfdce8 100644 --- a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt @@ -93,6 +93,8 @@ class DefaultEmojiPickerPresenter( val searchQuery = queryState.text.toString() LaunchedEffect(searchQuery, data) { if (searchQuery.isEmpty() || data.allEmojis.isEmpty()) { + // `SearchBarResultState.Initial` has no `equals` override, so reassigning a new instance + // would trigger a redundant emission each time this effect re-runs while the query is empty. if (emojiResults !is SearchBarResultState.Initial) { emojiResults = SearchBarResultState.Initial() } diff --git a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiItem.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiItem.kt index 02ed46c0ae..930b42c789 100644 --- a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiItem.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/EmojiItem.kt @@ -91,6 +91,8 @@ internal fun EmojiItem( .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 { @@ -102,6 +104,7 @@ internal fun EmojiItem( .background(backgroundColor, CircleShape) .indication(interactionSource, ripple()) .pointerInput(item) { + // Always detect long press and tap gestures detectTapGestures( onPress = { pressOffset -> val press = PressInteraction.Press(pressOffset) @@ -119,6 +122,7 @@ internal fun EmojiItem( ) } .then( + // Only detect drag after long press for those items which have a skin tone picker if (hasSkinTones) { Modifier.pointerInput(item) { val slotWidthPx = with(density) { SkinToneSlotSize.toPx() } @@ -135,6 +139,8 @@ internal fun EmojiItem( 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 { @@ -146,11 +152,15 @@ internal fun EmojiItem( onDismissSkinPicker() } else { 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 + // 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 19aabd4211337c414f797d3df75626abcedb46dc Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 23 Jul 2026 13:40:08 +0200 Subject: [PATCH 184/383] review cleanup --- .../components/ActiveCallTimelineItemView.kt | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt index 34e17f8ab6..9b3702c4d3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ActiveCallTimelineItemView.kt @@ -22,11 +22,8 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableLongStateOf import androidx.compose.runtime.produceState -import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -84,15 +81,6 @@ internal fun ActiveCallTimelineItemView( onJoinCallClick: (isAudioCall: Boolean) -> Unit, modifier: Modifier = Modifier ) { - var currentTime by remember { mutableLongStateOf(System.currentTimeMillis()) } - - LaunchedEffect(Unit) { - while (true) { - delay(1.seconds) - currentTime = System.currentTimeMillis() - } - } - Column(modifier = modifier) { Row( modifier = Modifier @@ -284,6 +272,9 @@ private fun CallDurationText( startTsMillis: Long, modifier: Modifier = Modifier, ) { + fun formatElapsed(startTsMillis: Long): String = + (System.currentTimeMillis() - startTsMillis).coerceAtLeast(0).toHumanReadableDuration() + val duration by produceState( initialValue = formatElapsed(startTsMillis), startTsMillis, @@ -303,9 +294,6 @@ private fun CallDurationText( ) } -private fun formatElapsed(startTsMillis: Long): String = - (System.currentTimeMillis() - startTsMillis).coerceAtLeast(0).toHumanReadableDuration() - @PreviewsDayNight @PreviewWithLargeHeight @Composable From 0d6c35a4a2f344a35457be75ed674f6116f26e3f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Jul 2026 11:41:48 +0000 Subject: [PATCH 185/383] Update dependency org.matrix.rustcomponents:sdk-android to v26.07.23 --- 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 1aee681c47..ff1f313d9e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -185,7 +185,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.07.22" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.07.23" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From ff7f54c416462fc3ad83d410da3ae8648052bbeb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Jul 2026 11:41:57 +0000 Subject: [PATCH 186/383] Update dependency io.sentry:sentry-android to v8.49.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 1aee681c47..02309d37af 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -230,7 +230,7 @@ color_picker = "io.mhssn:colorpicker:1.0.0" # Analytics posthog = "com.posthog:posthog-android:3.51.1" -sentry = "io.sentry:sentry-android:8.48.0" +sentry = "io.sentry:sentry-android:8.49.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.37.0" From 075cca2d21c6e4eea8cf0837457e4ddf904d6f00 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 23 Jul 2026 13:56:30 +0200 Subject: [PATCH 187/383] Sync emoji picker translations from Localazy --- libraries/ui-strings/src/main/res/values-el/translations.xml | 1 - libraries/ui-strings/src/main/res/values-fi/translations.xml | 1 - libraries/ui-strings/src/main/res/values-fr/translations.xml | 1 - libraries/ui-strings/src/main/res/values-hu/translations.xml | 1 - libraries/ui-strings/src/main/res/values-in/translations.xml | 1 - libraries/ui-strings/src/main/res/values-it/translations.xml | 1 - libraries/ui-strings/src/main/res/values-ja/translations.xml | 1 - libraries/ui-strings/src/main/res/values-ko/translations.xml | 1 - 8 files changed, 8 deletions(-) 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 5bbfeb20e5..1b69bb001f 100644 --- a/libraries/ui-strings/src/main/res/values-el/translations.xml +++ b/libraries/ui-strings/src/main/res/values-el/translations.xml @@ -434,7 +434,6 @@ "Το μέγιστο επιτρεπόμενο μέγεθος αρχείου είναι: %1$s" "Επιλέξτε την ποιότητα του βίντεο που θέλετε να ανεβάσετε." "Επιλέξτε την ποιότητα μεταφόρτωσης βίντεο" - "Αναζήτηση emoji" "Έχετε ήδη συνδεθεί σε αυτή τη συσκευή ως %1$s." "Ο οικιακός διακομιστής σου πρέπει να αναβαθμιστεί για να υποστηρίζει το Matrix Authentication Service και τη δημιουργία λογαριασμού." "Αποτυχία δημιουργίας του μόνιμου συνδέσμου" 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 ef7d518779..52d3bf16e5 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -477,7 +477,6 @@ Haluatko varmasti jatkaa?" "Suurin sallittu tiedostokoko on: %1$s" "Valitse lähetettävän videon laatu." "Valitse videon lähetyslaatu" - "Etsi emojeja" "Olet jo kirjautuneena tälle laitteelle käyttäjällä %1$s." "Kotipalvelimesi on päivitettävä tukemaan Matrix Authentication Serviceä ja tilin luomista." "Pysyvän linkin luominen epäonnistui" 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 a6cbd9b48e..8d550ae51e 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -452,7 +452,6 @@ Raison : %1$s." "La taille maximale de fichier autorisée est: %1$s" "Sélectionnez la qualité des vidéos que vous souhaitez envoyer." "Sélectionnez la qualité d’envoi des vidéos" - "Chercher des emojis" "Vous êtes déjà connecté sur cet appareil en tant que %1$s." "Votre serveur d’accueil doit être mis à jour pour prendre en charge le protocole MAS (Matrix Authentication Service) et la création de compte." "Échec de la création du permalien" 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 af1c071227..0a37baf199 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -467,7 +467,6 @@ Biztos, hogy folytatja?" "A legnagyobb megengedett fájlméret: %1$s" "Válassza ki a feltöltendő videó minőségét." "Feltöltött videó minőségének kiválasztása" - "Emodzsik keresése" "Már bejelentkezett erre az eszközre, mint %1$s." "A Matrix-kiszolgálót frissíteni kell a Matrix Authentication Service és a fióklétrehozás támogatásához." "Nem sikerült létrehozni az állandó hivatkozást" 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 ac74be0e8e..5527a10802 100644 --- a/libraries/ui-strings/src/main/res/values-in/translations.xml +++ b/libraries/ui-strings/src/main/res/values-in/translations.xml @@ -439,7 +439,6 @@ Apakah Anda yakin ingin melanjutkan?" "Ukuran file maksimum yang diizinkan adalah: %1$s" "Pilih kualitas video yang ingin Anda unggah." "Pilih kualitas unggahan video" - "Cari emoji" "Anda sudah masuk ke akun di perangkat ini sebagai%1$s ." "Homeserver Anda perlu ditingkatkan untuk mendukung Matrix Authentication Service dan pembuatan akun." "Gagal membuat tautan permanen" 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 394e043e07..3b47c41665 100644 --- a/libraries/ui-strings/src/main/res/values-it/translations.xml +++ b/libraries/ui-strings/src/main/res/values-it/translations.xml @@ -467,7 +467,6 @@ Sei sicuro di voler continuare?" "La dimensione massima consentita per il file è: %1$s" "Seleziona la qualità del video che vuoi caricare." "Seleziona la qualità di caricamento del video" - "Cerca emoji" "Hai già effettuato l\'accesso su questo dispositivo come %1$s ." "Il tuo homeserver deve essere aggiornato per supportare il Matrix Authentication Service e la creazione di account." "Impossibile creare il collegamento permanente" 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 9ab50981dc..7f54e420b8 100644 --- a/libraries/ui-strings/src/main/res/values-ja/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ja/translations.xml @@ -452,7 +452,6 @@ "アップロードできる最大サイズは %1$s です。" "アップロードする画質を選択してください。" "動画のアップロード品質を選択" - "絵文字を検索" "この端末では既に %1$s としてログインしています。" "Matrix Authentication Service とアカウント作成に対応するため、このホームサーバーはアップグレードが必要です。" "固定リンクの作成に失敗しました" 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 3010ef136c..e97fe17ca5 100644 --- a/libraries/ui-strings/src/main/res/values-ko/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ko/translations.xml @@ -443,7 +443,6 @@ " "업로드할 비디오의 품질을 선택하세요." "비디오 업로드 품질 선택" - "이모지 검색" "이 기기에서 이미 %1$s님으로 로그인되어 있습니다." "Matrix Authentication Service 및 계정 생성을 지원하려면 홈서버를 업그레이드해야 합니다." "퍼머링크 생성 실패" From 93786cdcbb821f53abe7c871b2e5026c62c21cdb Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 23 Jul 2026 14:23:05 +0200 Subject: [PATCH 188/383] Use roomMember.getBestName() in SuggestionPickerView --- .../impl/messagecomposer/suggestions/SuggestionsPickerView.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 d19061d8ed..a4d8453d10 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 @@ -41,6 +41,7 @@ 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.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembershipState +import io.element.android.libraries.matrix.api.room.getBestName import io.element.android.libraries.matrix.ui.components.DisplayNameWithStatus import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.slashcommands.api.SlashCommandSuggestion @@ -115,7 +116,7 @@ private fun SuggestionItemView( } val title: String? = when (suggestion) { is ResolvedSuggestion.AtRoom -> stringResource(R.string.screen_room_mentions_at_room_title) - is ResolvedSuggestion.Member -> suggestion.roomMember.displayName ?: suggestion.roomMember.userId.value + is ResolvedSuggestion.Member -> suggestion.roomMember.getBestName() is ResolvedSuggestion.Alias -> suggestion.roomName is ResolvedSuggestion.Command -> suggestion.command.command } From 0f43b9b79a3bd62e56119bdf4c9dc96f05382ff3 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 23 Jul 2026 14:57:12 +0200 Subject: [PATCH 189/383] fix: test compilation --- .../RtcNotificationContentFormatterTest.kt | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) 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 index cd3a8df349..9a79f78413 100644 --- 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 @@ -43,8 +43,11 @@ class RtcNotificationContentFormatterTest : RobolectricTest() { 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) + callIntent = CallIntent.VIDEO, + declinedBy = listOf(A_USER_ID_2, A_USER_ID_3), + activeMembers = emptyList(), + isJoined = false, + callStartTsMillis = 0 ), false ) @@ -58,7 +61,10 @@ class RtcNotificationContentFormatterTest : RobolectricTest() { val result = formatter.format( CallNotifyContent( CallIntent.VIDEO, - declinedBy = listOf(fakeMatrixClient.sessionId) + declinedBy = listOf(fakeMatrixClient.sessionId), + activeMembers = listOf(A_USER_ID_2), + isJoined = false, + callStartTsMillis = 0 ), true ) @@ -72,7 +78,10 @@ class RtcNotificationContentFormatterTest : RobolectricTest() { val result = formatter.format( CallNotifyContent( CallIntent.VIDEO, - declinedBy = listOf(A_USER_ID_2) + declinedBy = listOf(A_USER_ID_2), + activeMembers = listOf(fakeMatrixClient.sessionId), + isJoined = true, + callStartTsMillis = 0 ), true ) @@ -86,7 +95,10 @@ class RtcNotificationContentFormatterTest : RobolectricTest() { val result = formatter.format( CallNotifyContent( CallIntent.AUDIO, - declinedBy = listOf() + declinedBy = listOf(), + activeMembers = emptyList(), + isJoined = false, + callStartTsMillis = 0 ), true ) From 72c47f7c419de51e0ff1b943aa6d8ff7f2d87e09 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 23 Jul 2026 15:38:33 +0200 Subject: [PATCH 190/383] Add warning to the 'Scan QR code' screen (#7264) * Add warning to the 'Scan QR code' screen * Update screenshots --------- Co-authored-by: ElementBot --- .../impl/screens/desktop/DesktopNoticeView.kt | 21 ++++++++++++++++--- .../impl/src/main/res/values/localazy.xml | 1 + ...ens.desktop_DesktopNoticeView_Day_0_en.png | 4 ++-- ...ens.desktop_DesktopNoticeView_Day_1_en.png | 4 ++-- ...s.desktop_DesktopNoticeView_Night_0_en.png | 4 ++-- ...s.desktop_DesktopNoticeView_Night_1_en.png | 4 ++-- 6 files changed, 27 insertions(+), 11 deletions(-) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/desktop/DesktopNoticeView.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/desktop/DesktopNoticeView.kt index c7f0bb61e7..ad2e67dbc7 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/desktop/DesktopNoticeView.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/desktop/DesktopNoticeView.kt @@ -9,21 +9,25 @@ package io.element.android.features.linknewdevice.impl.screens.desktop +import androidx.compose.foundation.background 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.padding +import androidx.compose.foundation.shape.RoundedCornerShape 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.draw.clip 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.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.organisms.NumberedListOrganism @@ -34,6 +38,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.LocalBuildMeta 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.Text import io.element.android.libraries.designsystem.utils.annotatedTextWithBold import io.element.android.libraries.permissions.api.PermissionsView import kotlinx.collections.immutable.persistentListOf @@ -71,11 +76,10 @@ fun DesktopNoticeView( } ) { Column( - Modifier.fillMaxWidth() + Modifier.fillMaxWidth(), ) { Spacer(modifier = Modifier.height(40.dp)) NumberedListOrganism( - modifier = Modifier.fillMaxSize(), items = persistentListOf( AnnotatedString(stringResource(R.string.screen_link_new_device_desktop_step1, appName)), annotatedTextWithBold( @@ -88,6 +92,17 @@ fun DesktopNoticeView( AnnotatedString(stringResource(R.string.screen_link_new_device_desktop_step3)), ) ) + Spacer(modifier = Modifier.height(32.dp)) + Text( + modifier = Modifier + .clip(RoundedCornerShape(12.dp)) + .background(ElementTheme.colors.bgCriticalSubtle) + .padding(16.dp) + .fillMaxWidth(), + text = stringResource(R.string.screen_link_new_device_desktop_warning), + style = ElementTheme.typography.fontBodyMdMedium, + color = ElementTheme.colors.textCriticalPrimary, + ) } } diff --git a/features/linknewdevice/impl/src/main/res/values/localazy.xml b/features/linknewdevice/impl/src/main/res/values/localazy.xml index 6ffcce227a..47d25cbff6 100644 --- a/features/linknewdevice/impl/src/main/res/values/localazy.xml +++ b/features/linknewdevice/impl/src/main/res/values/localazy.xml @@ -5,6 +5,7 @@ "Scan the QR code with this device" "Ready to scan" "Open %1$s on a desktop computer to get the QR code" + "Only scan a QR code after following the steps above on your own device. Never scan a code sent by another person." "The numbers don’t match" "Enter 2-digit code" "This will verify that the connection to your other device is secure." diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en.png index b1fef99b4a..a83e8f7923 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b0acb8106154715ea852d54e6a8c06dec3ed367f14cd4a6eb7ea68baab11014 -size 43495 +oid sha256:3e6d5e199d232901dfddcfaf6d2821e0a9a7bf2b98db7dcfe4d8db40ba4176f4 +size 60579 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en.png index 300ffa1122..51090926ba 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88609772b74d36b5bd1f0d192a6dd10e9c5c324e670b02932b6d2204c92cdfff -size 42846 +oid sha256:aa0ea6f6fd6ed40abd3d6a1055a2f0d034208c518bd5841e5536cb9c83dd292d +size 56366 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en.png index 01618be617..4c26bd27c9 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d8c70e27a0b88c40e6ea2a3e8b03ec3f5034eef8c25843f16677e75354eff1be -size 42244 +oid sha256:80cc35d9eea08e8ce92a1025c3432f7e10821493896b1cd5156ae5382cdac14e +size 58031 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en.png index 638fb99be6..c59e81351c 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f0b25c02e6c1c1d70e560c8d570d2a0224b2496ebcc1f782be03f247038a62f2 -size 40846 +oid sha256:9a3e89bd126e83ace147edacfa70b3ad8930d2485f3165f89e2b08ce7e94cf61 +size 53462 From 44f027514e26d6601dcd633497c33c6ee49e4372 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 23 Jul 2026 13:48:37 +0000 Subject: [PATCH 191/383] Update screenshots --- ...omponents.customreaction_EmojiItemWithPopup_Night_0_en.png | 4 ++-- ...line.components.event_ATimelineItemEventRow_Night_0_en.png | 4 ++-- ....components_TimelineItemEventRowDisambiguated_Day_0_en.png | 4 ++-- ...ents_TimelineItemEventRowWithReplyInformative_Day_0_en.png | 4 ++-- ...ts_TimelineItemEventRowWithReplyInformative_Night_0_en.png | 4 ++-- ...components_TimelineItemEventRowWithReplyOther_Day_0_en.png | 4 ++-- ...mponents_TimelineItemEventRowWithReplyOther_Night_0_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_0_en.png | 4 ++-- ...ine.components_TimelineItemEventRowWithReply_Day_10_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_2_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_4_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_6_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_8_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_0_en.png | 4 ++-- ...e.components_TimelineItemEventRowWithReply_Night_10_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_2_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_4_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_6_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_8_en.png | 4 ++-- ...references.impl.blockedusers_BlockedUsersView_Day_4_en.png | 4 ++-- ...ferences.impl.blockedusers_BlockedUsersView_Night_5_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_6_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_5_en.png | 4 ++-- ...eme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png | 4 ++-- ...em.theme.components_HorizontalFloatingToolbar_Day_0_en.png | 4 ++-- 25 files changed, 50 insertions(+), 50 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png index 45011fea4d..9c425cec6e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eede6f990a7a1dbddee1cd9e722b30600160d475ad2ae72faebcb773f52aaa7b -size 20793 +oid sha256:290a2be6838445739b0181006f9fea87337a85cfed3573c153e9f503c66624a6 +size 4994 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 index 160d58f9ec..0ccdcbb603 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c4e7b28b78cfbcbb6abf00317eea945859ac6465cecf81a3ad15801b0de721e4 -size 646216 +oid sha256:d0424685437a433b35b589668b409d55f26ab41bcae01af0121a54033c56a8c2 +size 646194 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 ab6392a424..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:94f89a37549a3f198442db467bc7d8539f0b5649d97927bfe731f090d6dfb03d -size 379505 +oid sha256:ff839731834d7d0c94fa9a2c412014ddbaeaa053c5af1c8cbd00a3f3a583f364 +size 379511 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 3ac59caeea..1f0fdabe6d 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:1a94d5198e27338675c0e15df5874ba3272ee315b8d77291dc7ccc7c754ed1f4 -size 365082 +oid sha256:b8bb5a6de6601da8d7fe59f110a054577e2e25dae4bb449f60c04e7d7a1b9551 +size 365073 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 29771235f0..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:60b9f2b920cd2a2a414805d1f0f77925232d9ae60bd607fa18d4395cda2dd73d -size 363291 +oid sha256:00fe1e676086766a3eac3e4457eff52c989789fc5d8d0df2624c019ed25ce9af +size 363322 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 94428abb56..84d9d4e5c3 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:36d7cf2510d546d2b330b1d1b1674ce58df0558c547e443794a1e7b2222add87 -size 347897 +oid sha256:7c609a633ab23eae5729ecb57a17a385bac65e81cbf0180c01e0847f1028039e +size 347890 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 22ff4965d1..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:787151f8f242a8794a804bf14831f6ca680814d617e85feb3652103e8a0f20cd -size 346565 +oid sha256:e30686c7c037ef102717e0316543faf4d3ed2671c21eca96a667150daab380d6 +size 346614 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 67490ba700..01d4dca84b 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:f4431e2d9f30123949ea5676ce60f642234adcf9b5a33f2acc3f80ebf6609a66 -size 369730 +oid sha256:ef2bf449671b652cb152b3baab92ab100eab77a54229ab49daeab156f2f484d0 +size 369724 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 1600afff71..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:273351cc9c533b2424859a0de00a8a3786628abc3a88175705c4205dedf7e9aa -size 354737 +oid sha256:f7a6302320bd1e4258e03487539bf46b0b12781dfc8a22b3f9f267017a6146fa +size 354751 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 1b99468924..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:3a9509411777f342261cab58b92a022b3c9f8f0f7a9e4d0527120a91976575f0 -size 357733 +oid sha256:02ecb903124273e24151ea2088f6b99144f7dcadba00a582b6210dd23835b5c9 +size 357743 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 14a40a5676..a332744358 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:a11044fe90227f1f316a1ade8587e545bb620e11cca76865fc2eb83cdb817fc5 -size 364655 +oid sha256:588967869cbd25ed8b82aff5618175660a8a9e45a5a861b1c7867cf1913f575b +size 364646 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 63bd9c3f6d..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:a6cd94664f89bdad2a9761ea8b20acb83fed3ed7cb5be41af8fe4852643c0bfc -size 356175 +oid sha256:a2bd77c08be705c66225f16c29fd6826decd92b41922d0f8ffc0d1a63d8c59d2 +size 356193 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 d235670def..6e83d6491d 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:a00bd766a00b7e7c6615fc53bf469b3ca5056a6c514c096431ae38d99d604306 -size 364845 +oid sha256:34152c742abc486a48234e22101833bc163cf11979890d06aac41e68e3c404d0 +size 364846 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 422c324695..77abe20982 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:a1df8d22766981fc76d6d767dc3f40d98cadc7c51be20417b067b91af604232b -size 367884 +oid sha256:5c3d87862c6d7fc88d0f23cd54c5b9f77028992fdd7c282a195b964dd17e85ac +size 367855 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 448bcec677..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:fe0daf9161bc2da194992a2fc9505bf2009c5dbed78cdb35d2eb7ed1380a7df5 -size 353037 +oid sha256:f7d9b5fc0ff5d7828ad6f4dc0c9bd9520b4920553da97ed7b4e030ee844c0208 +size 353054 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 5560c21967..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:af4a48ee80535f2c0a226c4ffa4344054fb63b7b0a88ea2c030a4eb8dd5e9644 -size 356078 +oid sha256:8e82011a72f36889c53ab61ed2b9947c7fb5f868c9b7010904fc10f4ca587082 +size 356082 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 e9d85990e8..a431a9429a 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:66d4b6ea4a697735bbb0fac936b89cde99c5077973ba828894bf50b5dae233b3 -size 362848 +oid sha256:93c2df04d65f6078ce3f7067fbae8a7317ec42ed0fc013dee962a3953269f3b7 +size 362813 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 aa322fc2e4..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:5fae87094ea13b14e2dc7c16ca96e4f8096ff39e962799468fb4ead4c666620f -size 354381 +oid sha256:08057fdc1e1184720b438ddd2a8753f00791baf2456cc30b45de8e6bdeb57e8e +size 354404 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 0cfd1dc985..1a8ea3e4e9 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:545c9e8933e420cc3f8fbba0fbd5162c946c65a20721faeb77c568596ca720cd -size 363045 +oid sha256:66aba7b4271a990fac85b0bbc7cbdc371fa1e38a4da5bb4e2f62a80b21cb3a8f +size 363012 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png index 074820e157..7cca911c45 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7caacb336793b8ae4b83e9a10a82325e25e8b3c036f881898ed28688250eb6e0 -size 55744 +oid sha256:26e14b77fa3c3aeaea58782309e6de8b9047e07945009322990ebf5f4c283309 +size 52770 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png index 36d19c6b72..616c06bf46 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7dfa2767c55a81d3f121b8fa55443b7b05f9369e91639b80e0be349863799ad7 -size 55438 +oid sha256:0ce2519906f1aaf34700ca9ba4bdeaa72030f1f5aff3f7e24352a1435ac67d98 +size 53966 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png index f831ed92a2..0ca6f66438 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7fe1f51d385bba8821dfc0f0da84990cf0d148e991d765484b343d8764abd47d -size 11724 +oid sha256:5896eb5df6f5398bdb94e74280d0d5c04b6a5a53c2378b7377c60fa58eef544b +size 12013 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index 1e04c3e7d7..fb72cafe03 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bbc8c05e6f6818d00282228f52424ebe93e6e3dca3431d742e8c652d56460d6 -size 11712 +oid sha256:4ef1b643a16b5a94c75f8bb845c36d3cbc7f7ed96a0cac32fdb9f0b09d26b4d1 +size 11747 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png index ee5c582240..58546b8522 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75de341f705bb22955f9399180519b65ad59c2e1917317d56e50ea4db78f35bc -size 12102 +oid sha256:30357bf18792db5ab20085010251170a724ffe8c00313facd04ee704e806af64 +size 10982 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png index 38ad0e4b56..83302d6ba4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:326d59cf768b2dbd96eb7964d54c8eda509a5cd57c6e62087625e3314da0bb4d -size 13658 +oid sha256:16dee1dfe746cd40dac9fe8f0af3ecb42cd14bab5cc490917b589beed065ed1b +size 14686 From 9d427077f04df37c9d8393db2d50436cb9f34293 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 23 Jul 2026 16:15:02 +0200 Subject: [PATCH 192/383] Refactor SearchBarResultState.Initial and NoResultsFound to data objects --- .../impl/DefaultInvitePeoplePresenter.kt | 8 ++++---- .../impl/DefaultInvitePeopleStateProvider.kt | 4 ++-- .../impl/DefaultInvitePeoplePresenterTest.kt | 12 ++++-------- .../impl/roles/ChangeRolesPresenter.kt | 4 ++-- .../impl/roles/ChangeRolesStateProvider.kt | 2 +- .../space/impl/addroom/AddRoomToSpacePresenter.kt | 4 ++-- .../impl/addroom/AddRoomToSpaceStateProvider.kt | 4 ++-- .../impl/userlist/DefaultUserListPresenter.kt | 8 ++++---- .../impl/userlist/UserListStateProvider.kt | 4 ++-- .../impl/userlist/DefaultUserListPresenterTest.kt | 12 ++---------- .../designsystem/theme/components/SearchBar.kt | 14 +++++++------- .../impl/picker/DefaultEmojiPickerPresenter.kt | 8 ++------ .../impl/picker/DefaultEmojiPickerStateProvider.kt | 2 +- .../roomselect/impl/RoomSelectPresenter.kt | 4 ++-- .../roomselect/impl/RoomSelectStateProvider.kt | 2 +- 15 files changed, 38 insertions(+), 54 deletions(-) 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 44627daca3..79cd0c83be 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 @@ -88,7 +88,7 @@ class DefaultInvitePeoplePresenter( override fun present(): InvitePeopleState { val roomMembers = remember { mutableStateOf>>(AsyncData.Loading()) } val selectedUsers = remember { mutableStateOf>(persistentListOf()) } - val searchResults = remember { mutableStateOf>>(SearchBarResultState.Initial()) } + val searchResults = remember { mutableStateOf>>(SearchBarResultState.Initial) } val queryState = rememberTextFieldState() var searchActive by rememberSaveable { mutableStateOf(false) } val showSearchLoader = rememberSaveable { mutableStateOf(false) } @@ -332,15 +332,15 @@ class DefaultInvitePeoplePresenter( showSearchLoader: MutableState, searchQuery: String, ) = withContext(coroutineDispatchers.io) { - searchResults.value = SearchBarResultState.Initial() + searchResults.value = SearchBarResultState.Initial showSearchLoader.value = false val joinedMembers = roomMembers.value.dataOrNull().orEmpty() userRepository.search(searchQuery).onEach { state -> showSearchLoader.value = state.isSearching searchResults.value = when { - state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial() - state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound() + state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial + state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound else -> SearchBarResultState.Results(state.results.map { result -> val existingMembership = joinedMembers.firstOrNull { j -> j.userId == result.matrixUser.userId }?.membership val isJoined = existingMembership == RoomMembershipState.JOIN 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 93a6e03bd3..1e41114406 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 @@ -33,7 +33,7 @@ internal class DefaultInvitePeopleStateProvider : PreviewParameterProvider = AsyncData.Success(Unit), canInvite: Boolean = false, searchQuery: String = "", - searchResults: SearchBarResultState> = SearchBarResultState.Initial(), + searchResults: SearchBarResultState> = SearchBarResultState.Initial, selectedUsers: ImmutableList = persistentListOf(), isSearchActive: Boolean = false, showSearchLoader: Boolean = false, 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 4e141b2c4d..922fa73060 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 @@ -95,7 +95,7 @@ internal class DefaultInvitePeoplePresenterTest { resultState.searchQuery.setTextAndPlaceCursorAtEnd("some query") assertThat(awaitItemAsDefault().searchQuery.text.toString()).isEqualTo("some query") resultState.eventSink(InvitePeopleEvents.CloseSearch) - skipItems(2) + skipItems(1) awaitItemAsDefault().also { assertThat(it.isSearchActive).isFalse() assertThat(it.searchQuery.text.toString()).isEmpty() @@ -116,7 +116,7 @@ internal class DefaultInvitePeoplePresenterTest { initialState.searchQuery.setTextAndPlaceCursorAtEnd("some query") assertThat(repository.providedQuery).isEqualTo("some query") repository.emitState(UserSearchResultState(results = emptyList(), isSearching = true)) - skipItems(3) + skipItems(2) awaitItemAsDefault().also { state -> assertThat(state.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java) assertThat(state.showSearchLoader).isTrue() @@ -145,7 +145,6 @@ internal class DefaultInvitePeoplePresenterTest { assertThat(repository.providedQuery).isEqualTo("some query") repository.emitStateWithUsers(users = aMatrixUserList()) - skipItems(1) val resultState = awaitItemAsDefault() assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java) @@ -198,7 +197,6 @@ internal class DefaultInvitePeoplePresenterTest { assertThat(repository.providedQuery).isEqualTo("some query") repository.emitStateWithUsers(users = aMatrixUserList()) - skipItems(1) val resultState = awaitItemAsDefault() assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java) @@ -265,7 +263,6 @@ internal class DefaultInvitePeoplePresenterTest { it ) }) - skipItems(1) val resultState = awaitItemAsDefault() assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java) @@ -329,7 +326,7 @@ internal class DefaultInvitePeoplePresenterTest { assertThat(repository.providedQuery).isEqualTo("some query") repository.emitStateWithUsers(users = aMatrixUserList() + selectedUser) - skipItems(2) + skipItems(1) val resultState = awaitItemAsDefault() assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java) @@ -366,7 +363,6 @@ internal class DefaultInvitePeoplePresenterTest { assertThat(repository.providedQuery).isEqualTo("some query") repository.emitStateWithUsers(users = aMatrixUserList() + selectedUser) - skipItems(1) awaitItemAsDefault().also { state -> // selectedUser is not selected assertThat(state.searchResults).isInstanceOf(SearchBarResultState.Results::class.java) @@ -732,7 +728,7 @@ internal class DefaultInvitePeoplePresenterTest { isSearching = true ) ) - skipItems(3) + skipItems(2) awaitItemAsDefault().run { assertThat(selectedUsers).containsExactly(alice, bob, charlie) diff --git a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/roles/ChangeRolesPresenter.kt b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/roles/ChangeRolesPresenter.kt index b033a5870d..848ab64f87 100644 --- a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/roles/ChangeRolesPresenter.kt +++ b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/roles/ChangeRolesPresenter.kt @@ -77,7 +77,7 @@ class ChangeRolesPresenter( val queryState = rememberTextFieldState() var searchActive by rememberSaveable { mutableStateOf(false) } var searchResults by remember { - mutableStateOf>(SearchBarResultState.Initial()) + mutableStateOf>(SearchBarResultState.Initial) } val selectedUsers = remember { mutableStateOf>(persistentListOf()) @@ -118,7 +118,7 @@ class ChangeRolesPresenter( .groupedByRole() searchResults = if (results.isEmpty()) { - SearchBarResultState.NoResultsFound() + SearchBarResultState.NoResultsFound } else { SearchBarResultState.Results(results) } diff --git a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/roles/ChangeRolesStateProvider.kt b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/roles/ChangeRolesStateProvider.kt index 1ea1662a99..e6b71ef752 100644 --- a/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/roles/ChangeRolesStateProvider.kt +++ b/features/rolesandpermissions/impl/src/main/kotlin/io/element/android/features/rolesandpermissions/impl/roles/ChangeRolesStateProvider.kt @@ -68,7 +68,7 @@ internal fun aChangeRolesState( role: RoomMember.Role = RoomMember.Role.Admin, searchQuery: String = "", isSearchActive: Boolean = false, - searchResults: SearchBarResultState = SearchBarResultState.NoResultsFound(), + searchResults: SearchBarResultState = SearchBarResultState.NoResultsFound, selectedUsers: ImmutableList = persistentListOf(), hasPendingChanges: Boolean = false, savingState: AsyncAction = AsyncAction.Uninitialized, diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpacePresenter.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpacePresenter.kt index e4f58fdff2..b8d6c08215 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpacePresenter.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpacePresenter.kt @@ -66,8 +66,8 @@ class AddRoomToSpacePresenter( derivedStateOf { when { filteredRooms.isNotEmpty() -> SearchBarResultState.Results(filteredRooms) - isSearchActive && searchQuery.text.isNotEmpty() -> SearchBarResultState.NoResultsFound>() - else -> SearchBarResultState.Initial>() + isSearchActive && searchQuery.text.isNotEmpty() -> SearchBarResultState.NoResultsFound + else -> SearchBarResultState.Initial } } } diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceStateProvider.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceStateProvider.kt index 870b72ecb7..f9036f0452 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceStateProvider.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceStateProvider.kt @@ -40,7 +40,7 @@ internal class AddRoomToSpaceStateProvider : PreviewParameterProvider> = SearchBarResultState.Initial(), + searchResults: SearchBarResultState> = SearchBarResultState.Initial, selectedRooms: ImmutableList = persistentListOf(), isSearchActive: Boolean = false, saveAction: AsyncAction = AsyncAction.Uninitialized, diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/DefaultUserListPresenter.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/DefaultUserListPresenter.kt index ce579c5b50..286f0abe68 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/DefaultUserListPresenter.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/DefaultUserListPresenter.kt @@ -67,19 +67,19 @@ class DefaultUserListPresenter( val selectedUsers by userListDataStore.selectedUsers.collectAsState(emptyList()) val queryState = rememberTextFieldState() var searchResults: SearchBarResultState> by remember { - mutableStateOf(SearchBarResultState.Initial()) + mutableStateOf(SearchBarResultState.Initial) } var showSearchLoader by remember { mutableStateOf(false) } val searchQuery = queryState.text.toString() LaunchedEffect(searchQuery) { - searchResults = SearchBarResultState.Initial() + searchResults = SearchBarResultState.Initial showSearchLoader = false userRepository.search(searchQuery).onEach { state -> showSearchLoader = state.isSearching searchResults = when { - state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial() - state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound() + state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial + state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound else -> SearchBarResultState.Results(state.results.toImmutableList()) } }.launchIn(this) diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListStateProvider.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListStateProvider.kt index 3da8bfdabe..91d047d238 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListStateProvider.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListStateProvider.kt @@ -47,7 +47,7 @@ open class UserListStateProvider : PreviewParameterProvider { aUserListState( isSearchActive = true, searchQuery = "something-with-no-results", - searchResults = SearchBarResultState.NoResultsFound() + searchResults = SearchBarResultState.NoResultsFound ), aUserListState( isSearchActive = true, @@ -63,7 +63,7 @@ open class UserListStateProvider : PreviewParameterProvider { fun aUserListState( searchQuery: String = "", isSearchActive: Boolean = false, - searchResults: SearchBarResultState> = SearchBarResultState.Initial(), + searchResults: SearchBarResultState> = SearchBarResultState.Initial, selectedUsers: List = emptyList(), showSearchLoader: Boolean = false, selectionMode: SelectionMode = SelectionMode.Single, diff --git a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/userlist/DefaultUserListPresenterTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/userlist/DefaultUserListPresenterTest.kt index 4d958011a7..55fd30a84e 100644 --- a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/userlist/DefaultUserListPresenterTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/userlist/DefaultUserListPresenterTest.kt @@ -40,7 +40,6 @@ class DefaultUserListPresenterTest { FakeMatrixClient(), ) presenter.test { - skipItems(1) val initialState = awaitItem() assertThat(initialState.searchQuery.text.toString()).isEmpty() assertThat(initialState.isMultiSelectionEnabled).isFalse() @@ -60,7 +59,6 @@ class DefaultUserListPresenterTest { FakeMatrixClient(), ) presenter.test { - skipItems(1) val initialState = awaitItem() assertThat(initialState.searchQuery.text.toString()).isEmpty() assertThat(initialState.isMultiSelectionEnabled).isTrue() @@ -80,7 +78,6 @@ class DefaultUserListPresenterTest { FakeMatrixClient(), ) presenter.test { - skipItems(1) val initialState = awaitItem() initialState.eventSink(UserListEvents.OnSearchActiveChanged(true)) @@ -90,13 +87,11 @@ class DefaultUserListPresenterTest { initialState.searchQuery.setTextAndPlaceCursorAtEnd(matrixIdQuery) assertThat(awaitItem().searchQuery.text.toString()).isEqualTo(matrixIdQuery) assertThat(userRepository.providedQuery).isEqualTo(matrixIdQuery) - skipItems(1) val notMatrixIdQuery = "name" initialState.searchQuery.setTextAndPlaceCursorAtEnd(notMatrixIdQuery) assertThat(awaitItem().searchQuery.text.toString()).isEqualTo(notMatrixIdQuery) assertThat(userRepository.providedQuery).isEqualTo(notMatrixIdQuery) - skipItems(1) initialState.eventSink(UserListEvents.OnSearchActiveChanged(false)) assertThat(awaitItem().isSearchActive).isFalse() @@ -115,13 +110,12 @@ class DefaultUserListPresenterTest { FakeMatrixClient(), ) presenter.test { - skipItems(1) val initialState = awaitItem() initialState.searchQuery.setTextAndPlaceCursorAtEnd("alice") assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java) assertThat(userRepository.providedQuery).isEqualTo("alice") - skipItems(2) + skipItems(1) // When the user repository emits a result, it's copied to the state val result = UserSearchResultState( @@ -166,13 +160,12 @@ class DefaultUserListPresenterTest { FakeMatrixClient(), ) presenter.test { - skipItems(1) val initialState = awaitItem() initialState.searchQuery.setTextAndPlaceCursorAtEnd("alice") assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java) assertThat(userRepository.providedQuery).isEqualTo("alice") - skipItems(2) + skipItems(1) // When the results list is empty, the state is set to NoResults userRepository.emitState(UserSearchResultState(results = emptyList(), isSearching = false)) @@ -190,7 +183,6 @@ class DefaultUserListPresenterTest { FakeMatrixClient(), ) presenter.test { - skipItems(1) val initialState = awaitItem() val userA = aMatrixUser("@userA:domain", "A") diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/SearchBar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/SearchBar.kt index 2e19fecced..28a62a2c36 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/SearchBar.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/SearchBar.kt @@ -59,7 +59,7 @@ fun SearchBar( modifier: Modifier = Modifier, enabled: Boolean = true, showBackButton: Boolean = true, - resultState: SearchBarResultState = SearchBarResultState.Initial(), + resultState: SearchBarResultState = SearchBarResultState.Initial, shape: Shape = SearchBarDefaults.inputFieldShape, tonalElevation: Dp = SearchBarDefaults.TonalElevation, windowInsets: WindowInsets = SearchBarDefaults.windowInsets, @@ -134,7 +134,7 @@ fun SearchBar( resultHandler(resultState.results) } - is SearchBarResultState.NoResultsFound -> { + is SearchBarResultState.NoResultsFound -> { // No results found, show a message Spacer(Modifier.size(80.dp)) @@ -200,12 +200,12 @@ object ElementSearchBarDefaults { } @Immutable -sealed interface SearchBarResultState { +sealed interface SearchBarResultState { /** No search results are available yet (e.g. because the user hasn't entered a search term). */ - class Initial : SearchBarResultState + data object Initial : SearchBarResultState /** The search has completed, but no results were found. */ - class NoResultsFound : SearchBarResultState + data object NoResultsFound : SearchBarResultState /** The search has completed, and some matching users were found. */ data class Results(val results: T) : SearchBarResultState @@ -249,7 +249,7 @@ internal fun SearchBarActiveWithNoResultsPreview() = ElementThemedPreview { ContentToPreview( initialQuery = "search term", active = true, - resultState = SearchBarResultState.NoResultsFound(), + resultState = SearchBarResultState.NoResultsFound, ) } @@ -293,7 +293,7 @@ private fun ContentToPreview( initialQuery: String = "", active: Boolean = false, showBackButton: Boolean = true, - resultState: SearchBarResultState = SearchBarResultState.Initial(), + resultState: SearchBarResultState = SearchBarResultState.Initial, contentPrefix: @Composable ColumnScope.() -> Unit = {}, contentSuffix: @Composable ColumnScope.() -> Unit = {}, resultHandler: @Composable ColumnScope.(String) -> Unit = {}, diff --git a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt index 9d7dbfdce8..d87f531e15 100644 --- a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerPresenter.kt @@ -55,7 +55,7 @@ class DefaultEmojiPickerPresenter( override fun present(): EmojiPickerState { val queryState = rememberTextFieldState() var isSearchActive by remember { mutableStateOf(false) } - var emojiResults by remember { mutableStateOf>>(SearchBarResultState.Initial()) } + var emojiResults by remember { mutableStateOf>>(SearchBarResultState.Initial) } val data by produceState(EmojiPickerData.Empty) { val storeDeferred = async { emojibaseProvider.getStore() } @@ -93,11 +93,7 @@ class DefaultEmojiPickerPresenter( val searchQuery = queryState.text.toString() LaunchedEffect(searchQuery, data) { if (searchQuery.isEmpty() || data.allEmojis.isEmpty()) { - // `SearchBarResultState.Initial` has no `equals` override, so reassigning a new instance - // would trigger a redundant emission each time this effect re-runs while the query is empty. - if (emojiResults !is SearchBarResultState.Initial) { - emojiResults = SearchBarResultState.Initial() - } + emojiResults = SearchBarResultState.Initial return@LaunchedEffect } delay(100.milliseconds) diff --git a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerStateProvider.kt b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerStateProvider.kt index 0a091a2b66..964e0f3b78 100644 --- a/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerStateProvider.kt +++ b/libraries/emoji/impl/src/main/kotlin/io/element/android/libraries/emoji/impl/picker/DefaultEmojiPickerStateProvider.kt @@ -62,7 +62,7 @@ internal fun aDefaultEmojiPickerState( }.toImmutableList(), searchQuery: String = "", isSearchActive: Boolean = false, - searchResults: SearchBarResultState> = SearchBarResultState.Initial(), + searchResults: SearchBarResultState> = SearchBarResultState.Initial, eventSink: (EmojiPickerEvent) -> Unit = {}, ) = DefaultEmojiPickerState( categories = categories, diff --git a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt index 85ecfe5ba7..618f30a3e8 100644 --- a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt +++ b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt @@ -65,8 +65,8 @@ class RoomSelectPresenter( derivedStateOf { when { roomSummaryDetailsList.isNotEmpty() -> SearchBarResultState.Results(roomSummaryDetailsList.toImmutableList()) - isSearchActive -> SearchBarResultState.NoResultsFound() - else -> SearchBarResultState.Initial() + isSearchActive -> SearchBarResultState.NoResultsFound + else -> SearchBarResultState.Initial } } } diff --git a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectStateProvider.kt b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectStateProvider.kt index 131e35429e..e57266b7e7 100644 --- a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectStateProvider.kt +++ b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectStateProvider.kt @@ -52,7 +52,7 @@ open class RoomSelectStateProvider : PreviewParameterProvider { internal fun aRoomSelectState( mode: RoomSelectMode = RoomSelectMode.Forward, maxNumberOfRooms: Int = 10, - resultState: SearchBarResultState> = SearchBarResultState.Initial(), + resultState: SearchBarResultState> = SearchBarResultState.Initial, searchQuery: String = "", isSearchActive: Boolean = false, selectedRooms: ImmutableList = persistentListOf(), From f5b05f93c17fe9d9ca64739310d95c31c4c1f39d Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 23 Jul 2026 16:07:28 +0000 Subject: [PATCH 193/383] Update screenshots --- ...line.components.event_ATimelineItemEventRow_Night_0_en.png | 4 ++-- ...references.impl.blockedusers_BlockedUsersView_Day_4_en.png | 4 ++-- ...ferences.impl.blockedusers_BlockedUsersView_Night_5_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_5_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_6_en.png | 4 ++-- ...embermoderation.impl_RoomMemberModerationView_Day_5_en.png | 4 ++-- ...embermoderation.impl_RoomMemberModerationView_Day_7_en.png | 4 ++-- ...bermoderation.impl_RoomMemberModerationView_Night_5_en.png | 4 ++-- ...bermoderation.impl_RoomMemberModerationView_Night_7_en.png | 4 ++-- ...e.components_HorizontalFloatingToolbarNoFab_Night_0_en.png | 4 ++-- ....theme.components_HorizontalFloatingToolbar_Night_0_en.png | 4 ++-- 11 files changed, 22 insertions(+), 22 deletions(-) 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 index 0ccdcbb603..160d58f9ec 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0424685437a433b35b589668b409d55f26ab41bcae01af0121a54033c56a8c2 -size 646194 +oid sha256:c4e7b28b78cfbcbb6abf00317eea945859ac6465cecf81a3ad15801b0de721e4 +size 646216 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png index 7cca911c45..074820e157 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26e14b77fa3c3aeaea58782309e6de8b9047e07945009322990ebf5f4c283309 -size 52770 +oid sha256:7caacb336793b8ae4b83e9a10a82325e25e8b3c036f881898ed28688250eb6e0 +size 55744 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png index 616c06bf46..36d19c6b72 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ce2519906f1aaf34700ca9ba4bdeaa72030f1f5aff3f7e24352a1435ac67d98 -size 53966 +oid sha256:7dfa2767c55a81d3f121b8fa55443b7b05f9369e91639b80e0be349863799ad7 +size 55438 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png index 270dbe6d1e..7ef9b7ae0a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:195338046951366fd2345fdc8471e3e2b2786723c8bfffa9fa9057929c608afb -size 12113 +oid sha256:d19e7a09114e76294a0626e5d617cf55fe7c13a0188a7d5b364f57c0d9daedc1 +size 12123 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png index ce1258d2ac..8e1b9c99d2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce754ce205fd864e01828659aff42ab19dccf7c921c1c733ed1757f1b2122309 -size 11403 +oid sha256:66f6d0d6b03ee4c999cd4edc9c6ae567d31b8b537ca6f9cc8fbe436d06ce80ab +size 11643 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png index 5c597300e4..73b8b8e50c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 -size 3853 +oid sha256:e8a3ad99763929d2783147814e44fa9ec7e7efb7b99949e3580f23c38fb5d971 +size 9398 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png index f8a1f24b34..5c597300e4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1342b6427f5b2e3075ae3ccee60bf1d3b11afaccf3e152643d6ef2d65c21b54e -size 9108 +oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 +size 3853 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png index 4ae7279fe7..d47bf90664 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:410a8596d4c70b9a3856d959d6d71ade8e831e8581ff410c9900957a93b3eb50 -size 8114 +oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c +size 3664 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png index d47bf90664..a87d89c701 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c -size 3664 +oid sha256:0f3a0cb5d9bae6725a1c527f3d9575aabf85d3edf63a28d9faa23f4f0b65e2d0 +size 7624 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png index 52fd9b9693..fedead0fa8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58b9491aaa5554b89d86c62a5c9c44975367538c6baa5562f8dc5768f76d8264 -size 8705 +oid sha256:4811667dec0f32accc5e2c8a5dd5c0b34017fcff8d1e0376ee7a4708426bca0f +size 9838 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png index 687e0d436a..4da2a98aca 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d57df7110371c9224e232b707d6a1b10ce14afcb56c803a78220792f2a0d4cf2 -size 11354 +oid sha256:ef0dc4d53daeb986f378b6e4d85928b4b6729336c89cf21e642c88c53688a3ab +size 10292 From bce559dc1b9b7441d966eef222d225d60efa645d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Jul 2026 16:52:37 +0000 Subject: [PATCH 194/383] Update actions/setup-java action to v5.6.0 --- .github/workflows/build.yml | 2 +- .github/workflows/build_enterprise.yml | 2 +- .github/workflows/generate_github_pages.yml | 2 +- .github/workflows/gradle-wrapper-update.yml | 2 +- .github/workflows/maestro-local.yml | 2 +- .github/workflows/nightly.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 +- 13 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d2f3ca18d1..cad5caf3ca 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,7 +51,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/build_enterprise.yml b/.github/workflows/build_enterprise.yml index 3ff2803bf8..b8b604dbca 100644 --- a/.github/workflows/build_enterprise.yml +++ b/.github/workflows/build_enterprise.yml @@ -56,7 +56,7 @@ jobs: - name: Clone submodules run: git submodule update --init --recursive - name: Use JDK 21 - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/generate_github_pages.yml b/.github/workflows/generate_github_pages.yml index 33fdec38a4..4f60639780 100644 --- a/.github/workflows/generate_github_pages.yml +++ b/.github/workflows/generate_github_pages.yml @@ -19,7 +19,7 @@ jobs: - name: ⏬ Checkout with LFS uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5 - name: Use JDK 21 - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/gradle-wrapper-update.yml b/.github/workflows/gradle-wrapper-update.yml index 8db2b5fb6b..33cb6b8855 100644 --- a/.github/workflows/gradle-wrapper-update.yml +++ b/.github/workflows/gradle-wrapper-update.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + - uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 name: Use JDK 21 with: distribution: 'temurin' # See 'Supported distributions' for available options diff --git a/.github/workflows/maestro-local.yml b/.github/workflows/maestro-local.yml index 99a64da5f2..ff3bdf7c49 100644 --- a/.github/workflows/maestro-local.yml +++ b/.github/workflows/maestro-local.yml @@ -44,7 +44,7 @@ jobs: # https://github.com/actions/checkout/issues/881 ref: ${{ github.ref }} persist-credentials: false - - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + - uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 name: Use JDK 21 with: distribution: 'temurin' # See 'Supported distributions' for available options diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index c32b277f5c..63816b0c30 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -36,7 +36,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml index ff2b74a753..36e7837479 100644 --- a/.github/workflows/nightlyReports.yml +++ b/.github/workflows/nightlyReports.yml @@ -37,7 +37,7 @@ jobs: uses: nschloe/action-cached-lfs-checkout@385a8ecc719e50b8c71af6ab01a624b486b7c3bc # v1.2.5 - name: Use JDK 21 - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -80,7 +80,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 4d5f568dac..b0c78a9ee8 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -69,7 +69,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -108,7 +108,7 @@ jobs: 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@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -149,7 +149,7 @@ jobs: 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@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -183,7 +183,7 @@ jobs: 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@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -228,7 +228,7 @@ jobs: 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@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -269,7 +269,7 @@ jobs: 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@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/recordScreenshots.yml b/.github/workflows/recordScreenshots.yml index 273eac3c34..00502d9612 100644 --- a/.github/workflows/recordScreenshots.yml +++ b/.github/workflows/recordScreenshots.yml @@ -54,7 +54,7 @@ jobs: with: persist-credentials: false - name: ☕️ Use JDK 21 - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e6b83a1fc3..424acab7de 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,7 +38,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -82,7 +82,7 @@ jobs: - name: Clone submodules run: git submodule update --init --recursive - name: Use JDK 21 - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' @@ -126,7 +126,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index db1cf2ecfb..fc33644b7b 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -45,7 +45,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }} persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml index bb8ead3aa3..3f72d69433 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -17,7 +17,7 @@ jobs: with: persist-credentials: false - name: Use JDK 21 - uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6edb31ce4f..72f1f7cce7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -63,7 +63,7 @@ jobs: 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@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'temurin' # See 'Supported distributions' for available options java-version: '21' From 5ee8bc2fa790892d6c851914a335302dd3a8eb3f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 24 Jul 2026 09:04:48 +0200 Subject: [PATCH 195/383] Update dependencyAnalysis to v3.17.0 (#7265) 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 e259d4f085..d1c22fa7a4 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.16.1" +dependencyAnalysis = "3.17.0" # DI metro = "1.3.2" From 15958305419a25f6534ffc20f411fc599938641e Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 24 Jul 2026 11:00:45 +0200 Subject: [PATCH 196/383] Remove no longer temporary strings (#7260) * Remove no longer temporary string These are now in localazy and the sync strings CI flow was failing because we have 2 conflicting values in `temporary.xml` and `localazy.xml` * Use the right placeholder value in `screen_local_network_opt_in_subtitle` * Update screenshots --------- Co-authored-by: ElementBot --- .../android/appnav/loggedin/LoggedInView.kt | 1 + .../login/impl/changeserver/ChangeServerView.kt | 1 + .../ChooseAccountProviderView.kt | 2 ++ .../loginwithclassic/LoginWithClassicView.kt | 2 ++ .../ConfirmAccountProviderView.kt | 2 ++ .../impl/screens/onboarding/OnBoardingView.kt | 1 + .../LocalNetworkPermissionDialogView.kt | 3 ++- .../ui-strings/src/main/res/values/localazy.xml | 14 ++++++++++++-- .../appnav.loggedin_LoggedInView_Day_4_en.png | 4 ++-- .../appnav.loggedin_LoggedInView_Day_5_en.png | 4 ++-- .../appnav.loggedin_LoggedInView_Night_4_en.png | 4 ++-- .../appnav.loggedin_LoggedInView_Night_5_en.png | 4 ++-- ...impl.changeserver_ChangeServerView_Day_6_en.png | 4 ++-- ...pl.changeserver_ChangeServerView_Night_6_en.png | 4 ++-- ...tachmentsViewScanningContentFailed_Day_0_en.png | 4 ++-- ...chmentsViewScanningContentFailed_Night_0_en.png | 4 ++-- ...imelineItemScanningContentNotFound_Day_0_en.png | 4 ++-- ...elineItemScanningContentNotFound_Night_0_en.png | 4 ++-- ...emScanningContentWithRepliesFailed_Day_0_en.png | 4 ++-- ...ScanningContentWithRepliesFailed_Night_0_en.png | 4 ++-- ...ces.impl.userstatus_UserStatusView_Day_5_en.png | 4 ++-- ...ces.impl.userstatus_UserStatusView_Day_6_en.png | 4 ++-- ...s.impl.userstatus_UserStatusView_Night_5_en.png | 4 ++-- ...s.impl.userstatus_UserStatusView_Night_6_en.png | 4 ++-- ...tion.impl_RoomMemberModerationView_Day_5_en.png | 4 ++-- ...tion.impl_RoomMemberModerationView_Day_7_en.png | 4 ++-- ...on.impl_RoomMemberModerationView_Night_5_en.png | 4 ++-- ...on.impl_RoomMemberModerationView_Night_7_en.png | 4 ++-- ...nts_HorizontalFloatingToolbarNoFab_Day_0_en.png | 4 ++-- ...s_HorizontalFloatingToolbarNoFab_Night_0_en.png | 4 ++-- ...mponents_HorizontalFloatingToolbar_Day_0_en.png | 4 ++-- ...onents_HorizontalFloatingToolbar_Night_0_en.png | 4 ++-- ...tentvalidation_NotFoundContentView_Day_0_en.png | 4 ++-- ...ntvalidation_NotFoundContentView_Night_0_en.png | 4 ++-- ...sages.reply_ReplyToNotFoundContent_Day_0_en.png | 4 ++-- ...ges.reply_ReplyToNotFoundContent_Night_0_en.png | 4 ++-- ...ewer.impl.gallery.ui_AudioItemView_Day_0_en.png | 4 ++-- ...ewer.impl.gallery.ui_AudioItemView_Day_1_en.png | 4 ++-- ...ewer.impl.gallery.ui_AudioItemView_Day_2_en.png | 4 ++-- ...er.impl.gallery.ui_AudioItemView_Night_0_en.png | 4 ++-- ...er.impl.gallery.ui_AudioItemView_Night_1_en.png | 4 ++-- ...er.impl.gallery.ui_AudioItemView_Night_2_en.png | 4 ++-- ...iewer.impl.gallery.ui_FileItemView_Day_0_en.png | 4 ++-- ...iewer.impl.gallery.ui_FileItemView_Day_1_en.png | 4 ++-- ...iewer.impl.gallery.ui_FileItemView_Day_2_en.png | 4 ++-- ...wer.impl.gallery.ui_FileItemView_Night_0_en.png | 4 ++-- ...wer.impl.gallery.ui_FileItemView_Night_1_en.png | 4 ++-- ...wer.impl.gallery.ui_FileItemView_Night_2_en.png | 4 ++-- ....impl.gallery.ui_VoiceItemViewPlay_Day_0_en.png | 4 ++-- ....impl.gallery.ui_VoiceItemViewPlay_Day_1_en.png | 4 ++-- ....impl.gallery.ui_VoiceItemViewPlay_Day_2_en.png | 4 ++-- ....impl.gallery.ui_VoiceItemViewPlay_Day_3_en.png | 4 ++-- ....impl.gallery.ui_VoiceItemViewPlay_Day_4_en.png | 4 ++-- ...mpl.gallery.ui_VoiceItemViewPlay_Night_0_en.png | 4 ++-- ...mpl.gallery.ui_VoiceItemViewPlay_Night_1_en.png | 4 ++-- ...mpl.gallery.ui_VoiceItemViewPlay_Night_2_en.png | 4 ++-- ...mpl.gallery.ui_VoiceItemViewPlay_Night_3_en.png | 4 ++-- ...mpl.gallery.ui_VoiceItemViewPlay_Night_4_en.png | 4 ++-- ...ewer.impl.gallery.ui_VoiceItemView_Day_0_en.png | 4 ++-- ...ewer.impl.gallery.ui_VoiceItemView_Day_1_en.png | 4 ++-- ...ewer.impl.gallery.ui_VoiceItemView_Day_2_en.png | 4 ++-- ...ewer.impl.gallery.ui_VoiceItemView_Day_3_en.png | 4 ++-- ...er.impl.gallery.ui_VoiceItemView_Night_0_en.png | 4 ++-- ...er.impl.gallery.ui_VoiceItemView_Night_1_en.png | 4 ++-- ...er.impl.gallery.ui_VoiceItemView_Night_2_en.png | 4 ++-- ...er.impl.gallery.ui_VoiceItemView_Night_3_en.png | 4 ++-- ...ewer.impl.gallery_MediaGalleryView_Day_7_en.png | 4 ++-- ...er.impl.gallery_MediaGalleryView_Night_7_en.png | 4 ++-- 68 files changed, 143 insertions(+), 123 deletions(-) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt index e57d378da4..3bbd640c78 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt @@ -85,6 +85,7 @@ fun LoggedInView( } LocalNetworkPermissionDialogView( + appName = state.appName, dialog = state.localNetworkPermissionDialog, onSubmit = { state.eventSink(LoggedInEvents.RequestLocationNetworkPermission) }, onDismiss = { state.eventSink(LoggedInEvents.DismissLocalNetworkPermissionPrompt) }, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt index 30ae644a70..39c167cd13 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt @@ -123,6 +123,7 @@ fun ChangeServerView( AsyncData.Uninitialized -> Unit } LocalNetworkPermissionDialogView( + appName = LocalBuildMeta.current.applicationName, dialog = state.localNetworkPermissionDialog, onSubmit = { eventSink.invoke(ChangeServerEvents.RequestLocalNetworkPermission) 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 17e7d10efb..3eb31689ff 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 @@ -41,6 +41,7 @@ import io.element.android.libraries.designsystem.components.BigIcon 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.LocalBuildMeta 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 @@ -138,6 +139,7 @@ fun ChooseAccountProviderView( } } LocalNetworkPermissionDialogView( + appName = LocalBuildMeta.current.applicationName, dialog = state.loginModeState.localNetworkPermissionDialog, onSubmit = { state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission) 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 75181a068e..02e16fca95 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 @@ -47,6 +47,7 @@ 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.LocalBuildMeta 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 @@ -207,6 +208,7 @@ fun LoginWithClassicView( onCreateAccountContinue = onCreateAccountContinue, ) LocalNetworkPermissionDialogView( + appName = LocalBuildMeta.current.applicationName, dialog = state.loginModeState.localNetworkPermissionDialog, onSubmit = { state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission) 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 95fbff25ab..a84a046e2a 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 @@ -29,6 +29,7 @@ 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.LocalBuildMeta 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.OAuthDetails @@ -112,6 +113,7 @@ fun ConfirmAccountProviderView( } LocalNetworkPermissionDialogView( + appName = LocalBuildMeta.current.applicationName, dialog = state.loginModeState.localNetworkPermissionDialog, onSubmit = { state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission) 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 bf96b2dbe0..6b3ab4043a 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 @@ -87,6 +87,7 @@ fun OnBoardingView( onCreateAccountContinue = onCreateAccountContinue, ) LocalNetworkPermissionDialogView( + appName = state.productionApplicationName, dialog = state.loginModeState.localNetworkPermissionDialog, onSubmit = { state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission) diff --git a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialogView.kt b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialogView.kt index d2337fdf5b..2fddff16b1 100644 --- a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialogView.kt +++ b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialogView.kt @@ -15,6 +15,7 @@ import io.element.android.libraries.ui.strings.CommonStrings @Composable fun LocalNetworkPermissionDialogView( + appName: String, dialog: LocalNetworkPermissionDialog, onSubmit: () -> Unit, onDismiss: () -> Unit, @@ -27,7 +28,7 @@ fun LocalNetworkPermissionDialogView( } ConfirmationDialog( title = stringResource(CommonStrings.screen_local_network_opt_in_title), - content = stringResource(CommonStrings.screen_local_network_opt_in_subtitle), + content = stringResource(CommonStrings.screen_local_network_opt_in_subtitle, appName), submitText = stringResource(submitTextRes), cancelText = stringResource(CommonStrings.action_not_now), onSubmitClick = onSubmit, diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 88fdf821de..29ca9262db 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -8,6 +8,7 @@ "Minimise message text field" "Decrease votes allowed per person" "Increase votes allowed per person" + "Custom emoji" "Delete" "%1$d digit entered" @@ -64,6 +65,7 @@ "Start a call" "Start a video call" "Start a voice call" + "Status" "Thread in %1$s" "Threads in %1$s" "Tombstoned room" @@ -445,7 +447,7 @@ Reason: %1$s." "Anyone can see history" "You" "Download not available." - "File not found" + "Something went wrong" "Scanning…" "Preview and download have been disabled." "The file is not safe" @@ -517,7 +519,7 @@ Are you sure you want to continue?" "%1$d people" "On the map" - "Your homeserver is on your local network. To connect, Element needs permission to reach devices on this network." + "Your homeserver is on your local network. To connect, %1$s needs permission to reach devices on this network." "Allow access to local network" "Failed selecting media, please try again." "Press on a message and choose “%1$s” to include here." @@ -550,6 +552,14 @@ Are you sure you want to continue?" "Loading message…" "View All" "Chat" + "Away" + "Be right back" + "Custom…" + "Custom status…" + "Focus time" + "In a meeting" + "On the road" + "What\'s your status?" "Share location" "Share my location" "Open in Apple Maps" diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png index 652703aae3..e0bfa036e8 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d9eff127b4c393418646e3874a174e807aaaeea37587b07ca2716a551fb10d8e -size 33418 +oid sha256:cdab8410501666e33f7d810376640b732e4b36255797dbf4ef09c79d896c2b3f +size 33825 diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png index 88e414ee25..eacf92c3c1 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb2dc44a39b82a4138b15214cccc945eef34b2f244b4646e925a2a62568dec37 -size 32619 +oid sha256:8100f2bdc31632af9b5894e45fa1d8b47ca992cdf7564d442ac649edb1ba8e5b +size 33022 diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png index 8dae0180a8..ab8ff08c43 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:94d9e39df7c1aba7a6ca7eb6abf073f0170469ef837c95afcb5f199f8c2bd7ec -size 31504 +oid sha256:8ebce406b2ee9354e25caee308786c7424c159cc8276f92d8d6474d07d7036cb +size 31882 diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png index 603fbef2f1..f3cdb4ff7d 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ba2563c905c2400a50f81c6d029bc9cf4a99d1cb6483ee3ee8cfe373601a0dd -size 30770 +oid sha256:e1c49dbd3cb5b4cd78d1b65a7b159d368e4a0c2734d24c7429c1f5362cf7bae9 +size 31148 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_6_en.png index 09b645e184..e088efa40f 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:487e0a1f72382c418f95d337edbf8047228e8d3b116d192ce3f8abf3cf97fbd4 -size 33063 +oid sha256:8b59f57c2a7f8577ce253d6ae4818c56c832def259895d728cb877af7dd9c36d +size 33388 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_6_en.png index 6cbd05d003..1bf7390d71 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.changeserver_ChangeServerView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:36300a7d6bd6f2529bcd72ae3f654b6ef40706e0533f54d9473a9dff23df560e -size 31406 +oid sha256:9f3a6c27cd65f81167b9e1a5037a4eed1c2cc58fbc17f2397b1ae09fb4144e72 +size 31813 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Day_0_en.png index 04c37256d4..d74b5966ce 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e801fb628e90136e1a2c83c2ec8e9ad9b75febd0fb0566a3c66aa13f42799912 -size 48113 +oid sha256:83f9f85cb577045fe9d4afa99cdd6dcf1f3a9b5f807f4827162cf89fbe9c9d34 +size 49577 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Night_0_en.png index 5925416c47..80333ddfa6 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:accb6fd85427c220b02c271316568e09f00e7307c861d75bdcd43456c7c9d892 -size 47680 +oid sha256:2599a49b27b529dc534fabe818a308ee23943ca4525d34ec38145b3d554a55a9 +size 49087 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Day_0_en.png index 3c30442331..ba25b9ae46 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d082ac0333068f5da70cf40d310d321e6304999ddb6288b680350cfc3a7f40c0 -size 31006 +oid sha256:3fb486b70a044bcb8f08ea66c0f1ed7059139f79c6bfc81fe18fb939ac9f0fc5 +size 34533 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Night_0_en.png index 688fa2736b..2411217f76 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f275ffe26e055fd8f912b7234eae39dfb9f597e23c408dcb58e46d164ce391e9 -size 31959 +oid sha256:bf8e51b771605eeed282c03457918eccc0b98af6eadffbfe9c6459a472613f17 +size 35121 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Day_0_en.png index 6a78894774..78e20f96d6 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d56fc7f2007ec4679281452b42591c0e125bcb6efe15739fd1d1d3709a5d4a2 -size 53534 +oid sha256:c1a9c829656079ca682983a0aed67db9d2c45cf64aabf4dcb1d97bba0eefdbc0 +size 60555 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Night_0_en.png index a834e8e7d2..9641251dd9 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3fc62d83354b76e3844818a63a97cac0afbf04a2992f8acb150c1976003e057 -size 54679 +oid sha256:788e79c4d88b1f20d49c1d3e669228c85e3c44cc7fd5a33dca71fb69d118f777 +size 61043 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png index 270dbe6d1e..7ef9b7ae0a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:195338046951366fd2345fdc8471e3e2b2786723c8bfffa9fa9057929c608afb -size 12113 +oid sha256:d19e7a09114e76294a0626e5d617cf55fe7c13a0188a7d5b364f57c0d9daedc1 +size 12123 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png index 0ca6f66438..f831ed92a2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5896eb5df6f5398bdb94e74280d0d5c04b6a5a53c2378b7377c60fa58eef544b -size 12013 +oid sha256:7fe1f51d385bba8821dfc0f0da84990cf0d148e991d765484b343d8764abd47d +size 11724 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index fb72cafe03..1e04c3e7d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ef1b643a16b5a94c75f8bb845c36d3cbc7f7ed96a0cac32fdb9f0b09d26b4d1 -size 11747 +oid sha256:6bbc8c05e6f6818d00282228f52424ebe93e6e3dca3431d742e8c652d56460d6 +size 11712 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png index ce1258d2ac..8e1b9c99d2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce754ce205fd864e01828659aff42ab19dccf7c921c1c733ed1757f1b2122309 -size 11403 +oid sha256:66f6d0d6b03ee4c999cd4edc9c6ae567d31b8b537ca6f9cc8fbe436d06ce80ab +size 11643 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png index 5c597300e4..73b8b8e50c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 -size 3853 +oid sha256:e8a3ad99763929d2783147814e44fa9ec7e7efb7b99949e3580f23c38fb5d971 +size 9398 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png index f8a1f24b34..5c597300e4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1342b6427f5b2e3075ae3ccee60bf1d3b11afaccf3e152643d6ef2d65c21b54e -size 9108 +oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 +size 3853 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png index 4ae7279fe7..d47bf90664 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:410a8596d4c70b9a3856d959d6d71ade8e831e8581ff410c9900957a93b3eb50 -size 8114 +oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c +size 3664 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png index d47bf90664..a87d89c701 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c -size 3664 +oid sha256:0f3a0cb5d9bae6725a1c527f3d9575aabf85d3edf63a28d9faa23f4f0b65e2d0 +size 7624 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png index 58546b8522..ee5c582240 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30357bf18792db5ab20085010251170a724ffe8c00313facd04ee704e806af64 -size 10982 +oid sha256:75de341f705bb22955f9399180519b65ad59c2e1917317d56e50ea4db78f35bc +size 12102 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png index 52fd9b9693..fedead0fa8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58b9491aaa5554b89d86c62a5c9c44975367538c6baa5562f8dc5768f76d8264 -size 8705 +oid sha256:4811667dec0f32accc5e2c8a5dd5c0b34017fcff8d1e0376ee7a4708426bca0f +size 9838 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png index 83302d6ba4..38ad0e4b56 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:16dee1dfe746cd40dac9fe8f0af3ecb42cd14bab5cc490917b589beed065ed1b -size 14686 +oid sha256:326d59cf768b2dbd96eb7964d54c8eda509a5cd57c6e62087625e3314da0bb4d +size 13658 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png index 687e0d436a..4da2a98aca 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d57df7110371c9224e232b707d6a1b10ce14afcb56c803a78220792f2a0d4cf2 -size 11354 +oid sha256:ef0dc4d53daeb986f378b6e4d85928b4b6729336c89cf21e642c88c53688a3ab +size 10292 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Day_0_en.png index db17a4bb83..bcd1c40647 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0a59033bbc70903db2251e44c92248a3d5a574a4fe0a5347f74b4ba0b065fee -size 10002 +oid sha256:14556f5fd93d2454921fbd67daeff65e954a74cde1ba842d93f89c6a006dec63 +size 11748 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Night_0_en.png index 49914a6484..ddfac119b8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d963d8b910b34a552636f4bf9a5657acef2a1507469acf136074a88cf3ff7c4 -size 9819 +oid sha256:5527dba93897d9f0c6b3a002cdf5b3c1990ab5f8058a5ddf3c0d8aeaf10f7dae +size 11397 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Day_0_en.png index a4e8be33e0..61ece7b06f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0d67a139c137d80f642f7a00b16c1e3ac916f7b82cd780cfe5ca93759ec8e96 -size 10170 +oid sha256:3ce671634b464ce25caba96b51837f3acfac6366f168766c95f221ace2b03eac +size 12010 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Night_0_en.png index 616e0cf151..e3e18bbc55 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:27303f65c849be3fed38b005cb1cf8abc6fa037e2cc9475de7c3eca53a1c6c1e -size 9791 +oid sha256:581465da26f22298b9fe3e7124f5f4ad4e951398ca3cd6d39ff6f1fa99eafe1d +size 11417 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_0_en.png index b74ae6d0fe..53a2ee8e73 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fbcb3345c0486059b8a446e0a9b904345b899e398d07f3363449e577d2c0e9fb -size 30369 +oid sha256:8ea61f7938c6ea421ed17a9453a4f678dcae62138132e10a4873a3a56376bf95 +size 32222 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_1_en.png index 8d6179571f..ed60c9f00c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d149cbbffd2698eba03f4d89de3af98fb1ad7bc37849598b95dd3f02e66965a8 -size 43742 +oid sha256:665b0d9f8459e8ff5598c99be591ab37debac8b8ee43b1899c9031c5387063d1 +size 45468 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_2_en.png index d14753f755..fb38d3a0dc 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f1abb765bc08c172adefb0ebd4c78d65b5b52791f54c15d72257b7b5a7192f0e -size 79970 +oid sha256:d8942307cebccfdab877b05e9b44280f55219973d5443856b5dcb9fcd04a7124 +size 81393 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_0_en.png index 8ead5cf497..b148eee91b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63449813a8ca880d291113834561224e2547546580cb10a1c4dd7e35a142c638 -size 29089 +oid sha256:6da76c1b723b5c5a63ed9a712797a1cffe52748bca79e8670f519e920b206e9d +size 30719 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_1_en.png index a08b41cdef..c97ab61e96 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a5efe93f94bd3f0c68adaa21043cbbf02ef1e6aebbbdd137e8e2a8e99f2f6193 -size 41850 +oid sha256:069d0cbfc6f2d76b4a8076d81d1b17a5c44fbeac1fbfcc5a361c1c386ccff2b2 +size 43385 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_2_en.png index 72b4781c79..c85c4e8fe1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c488147fde94e3c74660141125279b12435b9f037359256d70555afcd239a18 -size 77333 +oid sha256:3bbdc92089ff3f1c99883c4e65841e20f6baa00f9a785eca29dcaae792ccd217 +size 78800 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_0_en.png index 8681053839..44b84ec681 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:70aa1b155531b531ae7f7e7ac1a5123fd065a3c9080c6319435f63f8c315c4e4 -size 31421 +oid sha256:b63a1c5324150dd49b99adfcd417e8256bb3620b5adf7437540936a0d244bc95 +size 33298 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_1_en.png index b6eda3a2ad..ba18eb6000 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a5e462fa9302567a3ac90a4493e71ccb08ba8b924af686b251791c24c8b8553a -size 44108 +oid sha256:4d09ab0c7863837aca7cb06c765f404dc5cc3ac0dfd17c50c321a9d3f1701879 +size 45841 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_2_en.png index f377ff83a8..90610ad003 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ecc879f8b304ffd4b95f54d1aeda7208238352af1570be23bc9d8de4fe84677 -size 80846 +oid sha256:ee2a956897baaca40efdf0c5da43a64a3708e96ddf4c2e7f214bab03adee675e +size 82208 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_0_en.png index 1314bb6c3d..06efc78d97 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:447a27ce5bcd769a8efda39c39ef3494eaf648cbd0fa4939b6089e58b3f31ea3 -size 30107 +oid sha256:0c87c27f51cbc2afd334f0ab4669844a7c0f204843d80fbc3cc36a8d63ccb353 +size 31702 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_1_en.png index f867981bb1..015201c8df 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3946799c8c3faba3bfef028f6adba46919bda464b73d83d3dcee95383fec491b -size 42288 +oid sha256:0e6b52433616fd337dc531f7bf544565b904380427ee4e84c0c0a4ba3cc89473 +size 43825 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_2_en.png index 914059d9f1..e6164a3746 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_FileItemView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:99a5e5fa3f4e014fd1a2b127646e88d848802d24f3150c45b1fb8e4b405d45d1 -size 78217 +oid sha256:e33a8ad1b3d63141947cce850aef7920a5926652f5312dfdb5f50a7dea894cfd +size 79673 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_0_en.png index 0394b633bb..4ed385037d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:42a0dbb630480cda58746522b69f6368c9cc7295f98a865a3caa4535a8f024f3 -size 32081 +oid sha256:4e8dc41535d17bd841d6e6fa9b7a0e6a5fdc7eeea7a6f3a1f5bad26750c451bf +size 33990 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_1_en.png index fbc23c84c8..631bf2a709 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d325f7de3a1c8517e7a924de415ab8da043ae3b44eec5e46c5150b1f58f01a50 -size 32799 +oid sha256:33462425386e2a7abd05457669a614b1aa229a18722f3616b7680a25411ab408 +size 34702 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_2_en.png index 8756055e70..527f772844 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff893a90f760818bd9c4f5befabf67c90d2ecc30ce26e1f613420ec32285c588 -size 32630 +oid sha256:8ea75008929fede12fea5aba65a4004de71c51b041c066cc37f22866a2cf9455 +size 34534 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_3_en.png index 23d8c4a18e..6edbc1265b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:458bca1df07c79811b4deb874bb71bb822ae21cf85eb76ecf92c69f8ea10e84d -size 32949 +oid sha256:2466a08e0ad20bdb9b5832ad526d2dba68151e47f92b3470ae59b1c4368bd2f4 +size 34858 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_4_en.png index 1272ba5775..04866de054 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c107c8d928bb50527a24032697dee9427dd1dde5987c0c536c52163ce3b8e2a6 -size 33164 +oid sha256:68a8f8da32bf72c51a15a0095b0e5f24c6f06f4651082b1c420d14a52f1042a9 +size 35070 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_0_en.png index 8f214b76c7..7830e63421 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0cd6406db1a8309e2f524d4de88ceed6062ac0902622d16fa73d6d8ca64f780e -size 30306 +oid sha256:a125a23ba4fcee01370a7fcebc3b68612cf2e9d1099f4c6ec53de39627b2dedb +size 31929 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_1_en.png index 43098d2d33..8c00f1833f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8b63323a128da29de0ebee9104ce6473136e5e3e8a11394c61116c683c3d51a7 -size 31109 +oid sha256:35a1543f06d7256636f26f5daf557c2b2ef41b9e287b227dda5233e4cd1f1365 +size 32766 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_2_en.png index 239aea7dc1..5d0eef018a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8008dfe4f3a135203766b8107751960f159a1bb3350e1d43ede376075db8d61d -size 30978 +oid sha256:2a58694d6bba215183b308cde0c7c97dda08369be56d5d4eaab832a61c968cb9 +size 32621 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_3_en.png index 4b9fe06e2c..fa61b70639 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f642dd641bf49c51d09fcbbc6a644cf280efaf2e88d3c8f4f85ee51b37eeac2a -size 31190 +oid sha256:bc73b0110e564edf5cad792a9d6e329360103dcfd8c584c2617f8dd88fd7603a +size 32825 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_4_en.png index 165d682461..4f9f22125a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemViewPlay_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e383090f2f0f06d902b220e05434045ebdd5be781d8f076e21bdc434a83c5bde -size 31393 +oid sha256:4eb6911bab641b66a799127486cc6d66e83be232bd4c39fe079d9fb2223bf742 +size 33037 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_0_en.png index 6815b035e0..4b5365b6da 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf406dbc78412e6c4e457dfbcbabf05248f2578e938016c4a5a6b5cccf1b0c29 -size 32157 +oid sha256:86d31efa2f03952372e98c700b14a078cb043195ca382df1b03b5e122e91ecac +size 34056 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_1_en.png index a478fb4e7d..62071f235f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2506e19dfcd975a69fa533973ead95ea7923dbc67545553bad0b09ca87b3f6e9 -size 40834 +oid sha256:6eb6ad3ea6b0dc11e94f85f9348d5a345ca8b210fdde2a92520594985ee0b4c4 +size 42630 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_2_en.png index f62505f562..cabef3d7ad 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a6bc629fad6fdd5e1285cc9ac4484683b111498f989c5fe43f0b037b5619b36 -size 82000 +oid sha256:3c034af8daa917ab2cebaa935b3cc671a6c2aad2d90c8bd5ccc9aa31326d2e44 +size 83743 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_3_en.png index 37f6d667a9..367286a5ca 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:745ea9fca0277511ef197608025135387a985082367e52d52b780ba94498b7aa -size 28992 +oid sha256:4480b8f55f3ccd5d6e78d014b964efb77727f9947867b08d3d8eac774bb0aa92 +size 30915 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_0_en.png index ff3c7036a6..c01698f39c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e20e92f594ead4e2d5a0beb2f290077506322ec11eb75f8d16c1374ddb217456 -size 30375 +oid sha256:975b1dd40fe06055090bc81052757596bd7ccb1c2ddc85aea1b22a6d5975fd14 +size 31999 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_1_en.png index 166d22f9b0..36c927d7e0 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd0e274dc81bf5bfa6498922cb3a75721bb98af8fbeaf558d67b127248755543 -size 38543 +oid sha256:988d206940cc9c746cd5b3d1a0df8c11e81d3e4e3e76477fdc520a986435d2ae +size 40135 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_2_en.png index cb4cec9dda..406b599114 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e54d39cc93385c85ae9c1f8b9f5dd459811c28878f788d0e05562bfb62dfff6d -size 78927 +oid sha256:ab1bb90f13b14f91fdb17d7d6934f95995597ebbc0607ce500ea2219f6e9de56 +size 80340 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_3_en.png index 1474d94884..64b81900c1 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery.ui_VoiceItemView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4485fe9b2310bde15485f78d7dd556df6453e2567f859ab3268e36d5ec901f4f -size 27453 +oid sha256:dfac79dcfb2493a6028ab4fdf7d9f27129ef08399d7bc78ee7ec388c15feeffb +size 29093 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en.png index e1fb7f49bf..bf10ab2427 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a7f75b9cad16c26fdca283a79b871be4b4c41d8c15b1d4ea96c82dd37015761e -size 48065 +oid sha256:dd2e24e40cbf4a576c245538e3c0578c8bd3d7b44c9ff57efba5bb6f32358d0c +size 49851 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en.png index 09dc2830bb..670b03befa 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4d6f6ad2d759fd2383eed4d051880851cd3b46a03812e6ce43a372dd4542be8 -size 46007 +oid sha256:0aa19fc5903e5a35b3d8c218faa6acdae63c2fa7a45481b0ebd0cfdf7c8df0f6 +size 47550 From bfb2cc46785294dc14097ac7f29c226ea73277f1 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 24 Jul 2026 11:35:34 +0200 Subject: [PATCH 197/383] Fix CallNotifyContent constructor call in EventItemFactoryTest --- .../mediaviewer/impl/datasource/EventItemFactoryTest.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactoryTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactoryTest.kt index d00f5a3eb2..4ed89e8923 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactoryTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactoryTest.kt @@ -68,7 +68,13 @@ class EventItemFactoryTest { fun `create check all null cases`() { val factory = createEventItemFactory() val contents = listOf( - CallNotifyContent(callIntent = CallIntent.VIDEO, emptyList()), + CallNotifyContent( + callIntent = CallIntent.VIDEO, + declinedBy = emptyList(), + activeMembers = emptyList(), + isJoined = false, + callStartTsMillis = null, + ), FailedToParseMessageLikeContent("", ""), FailedToParseStateContent("", "", ""), LegacyCallInviteContent, From 892b384f0762ab5d9751b26c379ed8d83306d1aa Mon Sep 17 00:00:00 2001 From: bmarty <3940906+bmarty@users.noreply.github.com> Date: Mon, 27 Jul 2026 01:07:51 +0000 Subject: [PATCH 198/383] Sync Strings from Localazy --- .../src/main/res/values-nb/translations.xml | 4 + .../src/main/res/values-pl/translations.xml | 1 + .../src/main/res/values-zh/translations.xml | 1 + .../src/main/res/values-nb/translations.xml | 2 + .../src/main/res/values-nb/translations.xml | 7 + .../src/main/res/values-et/translations.xml | 4 + .../src/main/res/values-hr/translations.xml | 4 + .../src/main/res/values-it/translations.xml | 2 +- .../src/main/res/values-nb/translations.xml | 19 +- .../src/main/res/values-pl/translations.xml | 5 + .../src/main/res/values-zh/translations.xml | 3 + .../src/main/res/values-da/translations.xml | 2 +- .../src/main/res/values-ja/translations.xml | 2 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-et/translations.xml | 8 + .../src/main/res/values-hr/translations.xml | 8 + .../src/main/res/values-in/translations.xml | 2 + .../src/main/res/values-nb/translations.xml | 33 + .../src/main/res/values-pl/translations.xml | 8 + .../src/main/res/values-uk/translations.xml | 3 + .../src/main/res/values-zh/translations.xml | 8 + .../src/main/res/values-nb/translations.xml | 2 + .../src/main/res/values-nb/translations.xml | 1 + .../src/main/res/values-nb/translations.xml | 22 + .../src/main/res/values-nb/translations.xml | 4 +- .../src/main/res/values-nb/translations.xml | 2 +- .../src/main/res/values-nb/translations.xml | 2 + .../src/main/res/values-nb/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 6 + .../src/main/res/values-hr/translations.xml | 13 + .../src/main/res/values-nb/translations.xml | 85 +- .../src/main/res/values-pl/translations.xml | 17 + .../src/main/res/values-uk/translations.xml | 6 + .../src/main/res/values-zh/translations.xml | 14 +- .../src/main/res/values/localazy.xml | 8 - .../appnav.loggedin_LoggedInView_Day_4_de.png | 4 +- .../appnav.loggedin_LoggedInView_Day_5_de.png | 4 +- ...ens.desktop_DesktopNoticeView_Day_0_de.png | 4 +- ...ens.desktop_DesktopNoticeView_Day_1_de.png | 4 +- ...changeserver_ChangeServerView_Day_6_de.png | 4 +- ...ionlist_ActionListViewContent_Day_3_de.png | 4 +- ...estions_SuggestionsPickerView_Day_0_de.png | 4 +- ...nner_PinnedMessagesBannerView_Day_1_de.png | 4 +- ...nner_PinnedMessagesBannerView_Day_2_de.png | 4 +- ...omreaction.picker_EmojiPicker_Day_0_de.png | 3 - ...s.event_ATimelineItemEventRow_Day_0_de.png | 4 +- ...ts_ActiveCallTimelineItemView_Day_0_de.png | 3 + ...mponents_ActiveCallTimelineItemView_de.png | 3 + ...lineItemEventRowDisambiguated_Day_0_de.png | 3 - ...ineItemEventRowWithReplyOther_Day_1_de.png | 3 + ...imelineItemEventRowWithReply_Day_10_de.png | 3 - ...TimelineItemEventRowWithReply_Day_1_de.png | 3 + ...TimelineItemEventRowWithReply_Day_2_de.png | 3 - ...TimelineItemEventRowWithReply_Day_5_de.png | 3 + ...TimelineItemEventRowWithReply_Day_6_de.png | 3 - ...TimelineItemEventRowWithReply_Day_9_de.png | 3 + ...pl.topbars_MessagesViewTopBar_Day_0_de.png | 4 +- ...mpl.userstatus_UserStatusView_Day_5_de.png | 4 +- ...mpl.userstatus_UserStatusView_Day_6_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 +- ...res.space.impl.root_SpaceView_Day_4_de.png | 4 +- ...tionWithVerificationViolation_Day_0_de.png | 4 +- ...ared_UserProfileHeaderSection_Day_0_de.png | 4 +- ...rofile.shared_UserProfileView_Day_0_de.png | 4 +- ...rofile.shared_UserProfileView_Day_1_de.png | 4 +- ...rofile.shared_UserProfileView_Day_2_de.png | 4 +- ...rofile.shared_UserProfileView_Day_3_de.png | 4 +- ...rofile.shared_UserProfileView_Day_4_de.png | 4 +- ...rofile.shared_UserProfileView_Day_5_de.png | 4 +- ...rofile.shared_UserProfileView_Day_6_de.png | 4 +- ...rofile.shared_UserProfileView_Day_7_de.png | 4 +- ...rofile.shared_UserProfileView_Day_8_de.png | 4 +- ...rofile.shared_UserProfileView_Day_9_de.png | 4 +- ...ing_OutgoingVerificationView_Day_10_de.png | 4 +- ...ing_OutgoingVerificationView_Day_11_de.png | 4 +- ...nts_HorizontalFloatingToolbar_Day_0_de.png | 3 - ...i.impl.picker_EmojiPickerView_Day_0_de.png | 3 + ....impl.picker_EmojiPickerView_Day_1_de.png} | 0 ....components_SpaceRoomItemView_Day_1_de.png | 4 +- ....components_SpaceRoomItemView_Day_6_de.png | 4 +- ...impl.gallery_MediaGalleryView_Day_3_de.png | 4 +- ...impl.gallery_MediaGalleryView_Day_7_de.png | 4 +- ...l.viewer_MediaViewerViewLandscape_6_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 | 4 +- screenshots/html/data.js | 2287 +++++++++-------- ...anner_KnockRequestsBannerView_Day_5_en.png | 4 +- ...pl.list_KnockRequestsListView_Day_3_en.png | 4 +- ....impl.share_ShareLocationView_Day_3_en.png | 4 +- ....impl.share_ShareLocationView_Day_7_en.png | 4 +- ...mpl.share_ShareLocationView_Night_1_en.png | 4 +- ...mpl.share_ShareLocationView_Night_5_en.png | 4 +- ...mpl.share_ShareLocationView_Night_9_en.png | 4 +- ...essagesViewWithIdentityChange_Day_2_en.png | 4 +- ...VerifiedUserSendFailureView_Night_1_en.png | 4 +- ...s.event_ATimelineItemEventRow_Day_0_en.png | 4 +- ...mEventRowWithReplyInformative_Day_1_en.png | 4 +- ...ineItemEventRowWithReplyOther_Day_1_en.png | 4 +- ...TimelineItemEventRowWithReply_Day_1_en.png | 4 +- ...TimelineItemEventRowWithReply_Day_5_en.png | 4 +- ...TimelineItemEventRowWithReply_Day_9_en.png | 4 +- ...melineItemEventRowWithReply_Night_1_en.png | 4 +- ...melineItemEventRowWithReply_Night_5_en.png | 4 +- ...melineItemEventRowWithReply_Night_9_en.png | 4 +- ...s.messages.impl_MessagesView_Day_11_en.png | 4 +- ...es.messages.impl_MessagesView_Day_3_en.png | 4 +- ...es.messages.impl_MessagesView_Day_7_en.png | 4 +- ...messages.impl_MessagesView_Night_11_en.png | 4 +- ....messages.impl_MessagesView_Night_3_en.png | 4 +- ....messages.impl_MessagesView_Night_7_en.png | 4 +- ...ockedusers_BlockedUsersView_Night_4_en.png | 4 +- ...mpl.userstatus_UserStatusView_Day_6_en.png | 4 +- ...l.userstatus_UserStatusView_Night_5_en.png | 4 +- ...impl_RoomMemberModerationView_Day_5_en.png | 4 +- ...pl_RoomMemberModerationView_Night_7_en.png | 4 +- ...orizontalFloatingToolbarNoFab_Day_0_en.png | 4 +- ...izontalFloatingToolbarNoFab_Night_0_en.png | 4 +- ...nts_HorizontalFloatingToolbar_Day_0_en.png | 4 +- 190 files changed, 1737 insertions(+), 1460 deletions(-) delete mode 100644 screenshots/de/features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components_ActiveCallTimelineItemView_Day_0_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components_ActiveCallTimelineItemView_de.png delete mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_de.png delete mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_de.png delete mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_de.png delete mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_de.png create mode 100644 screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_de.png delete mode 100644 screenshots/de/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_de.png create mode 100644 screenshots/de/libraries.emoji.impl.picker_EmojiPickerView_Day_0_de.png rename screenshots/de/{features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_de.png => libraries.emoji.impl.picker_EmojiPickerView_Day_1_de.png} (100%) diff --git a/features/invitepeople/impl/src/main/res/values-nb/translations.xml b/features/invitepeople/impl/src/main/res/values-nb/translations.xml index 617b9271d5..81f7db3a54 100644 --- a/features/invitepeople/impl/src/main/res/values-nb/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-nb/translations.xml @@ -2,4 +2,8 @@ "Allerede medlem" "Allerede invitert" + "Du har for øyeblikket ingen samtaler med disse kontaktene. Bekreft at du vil invitere dem til dette rommet før du fortsetter." + "Du har for øyeblikket ingen samtaler med denne kontakten. Bekreft at du vil invitere vedkommende til dette rommet før du fortsetter." + "Vil du invitere nye kontakter til dette rommet?" + "Vil du invitere en ny kontakt til dette rommet?" 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 ced8955d1d..38279147f6 100644 --- a/features/linknewdevice/impl/src/main/res/values-pl/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-pl/translations.xml @@ -5,6 +5,7 @@ "Zeskanuj kod QR za pomocą tego urządzenia" "Gotowy do skanowania" "Otwórz %1$s na komputerze stacjonarnym, aby uzyskać kod QR" + "Zeskanuj kod QR dopiero po wykonaniu powyższych kroków na swoim urządzeniu. Nigdy nie skanuj kodu przesłanego przez inną osobę." "Liczby nie pasują do siebie" "Wprowadź 2-cyfrowy kod" "Pozwoli to sprawdzić, czy połączenie z drugim urządzeniem jest bezpieczne." 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 f11f60dd61..f31cf53c9c 100644 --- a/features/linknewdevice/impl/src/main/res/values-zh/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-zh/translations.xml @@ -5,6 +5,7 @@ "使用此设备扫描二维码" "准备进行扫描" "在台式电脑上打开 %1$s 以获取二维码" + "确保仅在属于你自己的设备上按上述步骤操作后再扫描二维码。绝对不要扫描来自他人的二维码。" "数字不匹配" "输入两位数字的代码" "这将验证你与其它设备的连接是否安全。" diff --git a/features/location/impl/src/main/res/values-nb/translations.xml b/features/location/impl/src/main/res/values-nb/translations.xml index 44ab657a4b..9eadb3c8e8 100644 --- a/features/location/impl/src/main/res/values-nb/translations.xml +++ b/features/location/impl/src/main/res/values-nb/translations.xml @@ -1,4 +1,6 @@ + "Din sanntids lokasjonshistorikk lagres i rommet og vil være synlig for medlemmene etter at økten er avsluttet." "Velg hvor lenge du vil dele din sanntidslokasjon." + "Du har ikke tillatelse til å dele din sanntidslokasjon i dette rommet" 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 befd26d4ce..5d4a3c1494 100644 --- a/features/login/impl/src/main/res/values-nb/translations.xml +++ b/features/login/impl/src/main/res/values-nb/translations.xml @@ -37,7 +37,14 @@ "Matrix er et åpent nettverk for sikker, desentralisert kommunikasjon." "Velkommen tilbake!" "Logg inn på %1$s" + "Åpne Element Classic" + "Åpne Element Classic på enheten din" + "Gå til Innstillinger → Sikkerhet og personvern" + "Følg instruksjonene for å aktivere nøkkellagringen din" + "Kom tilbake til %1$s" + "Aktiver nøkkellagringen din før du går videre til %1$s" "Versjon %1$s" + "Sjekker kontoen" "Logg på manuelt" "Logg inn på %1$s" "Logg inn med QR-kode" 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 aa6576fc17..ab46eeee45 100644 --- a/features/messages/impl/src/main/res/values-et/translations.xml +++ b/features/messages/impl/src/main/res/values-et/translations.xml @@ -70,6 +70,10 @@ "Näita rohkem" "Näita reageerimiste kokkuvõtet" "Uus" + + "%1$d eemaldas sõnumi" + "%1$d eemaldas sõnumid" + "%1$d jututoa muudatus" "%1$d jututoa muudatust" 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 23912aaf78..2fe73bf7de 100644 --- a/features/messages/impl/src/main/res/values-hr/translations.xml +++ b/features/messages/impl/src/main/res/values-hr/translations.xml @@ -72,6 +72,10 @@ "Prikaži više" "Prikaži sažetak reakcija" "Novo" + + "%1$d uklonjena poruka" + "%1$d uklonjene poruke" + "%1$d promjena sobe" "%1$d promjene sobe" 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 53812093ee..273efe803f 100644 --- a/features/messages/impl/src/main/res/values-it/translations.xml +++ b/features/messages/impl/src/main/res/values-it/translations.xml @@ -38,7 +38,7 @@ "Scatta foto" "Registra video" "Allegato" - "Libreria di foto e video" + "Libreria foto e video" "Condividi posizione" "Sondaggio" "Formattazione del testo" diff --git a/features/messages/impl/src/main/res/values-nb/translations.xml b/features/messages/impl/src/main/res/values-nb/translations.xml index a68aeabcdf..a510d020d6 100644 --- a/features/messages/impl/src/main/res/values-nb/translations.xml +++ b/features/messages/impl/src/main/res/values-nb/translations.xml @@ -7,6 +7,18 @@ "Kryptert av en ukjent eller slettet enhet." "Kryptert med en enhet som ikke er verifisert av eieren." "Kryptert av en ubekreftet bruker." + "Snu bildet horisontalt" + "Vendt horisontalt" + "Opprinnelig" + "Snu bildet vertikalt" + "Vendt vertikalt" + "Opprinnelig" + "Roter bildet mot venstre" + + "%1$d grad" + "%1$d grader" + + "Rediger bilde" "Teksting er kanskje ikke synlig for personer som bruker eldre apper." "Trykk for å endre kvaliteten på videoopplastingen" "Filen kunne ikke lastes opp." @@ -17,6 +29,7 @@ "Fil %1$d av %2$d" "Optimaliser bildekvaliteten" "Behandler…" + "Legg til media" "Blokker bruker" "Kryss av for om du vil skjule alle nåværende og fremtidige meldinger fra denne brukeren" "Denne meldingen vil bli rapportert til hjemmeserverens administratorer. De vil ikke kunne lese noen krypterte meldinger." @@ -26,7 +39,7 @@ "Ta opp video" "Vedlegg" "Foto- og videobibliotek" - "Del posisjon" + "Del lokasjon" "Avstemning" "Tekstformatering" "Meldingshistorikken er for øyeblikket ikke tilgjengelig." @@ -57,6 +70,10 @@ "Vis mer" "Vis sammendrag av reaksjoner" "Ny" + + "%1$d fjernet meldingen" + "%1$d fjernet meldinger" + "%1$d romendring" "%1$d romendringer" 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 651a8e460e..87ed6250c0 100644 --- a/features/messages/impl/src/main/res/values-pl/translations.xml +++ b/features/messages/impl/src/main/res/values-pl/translations.xml @@ -73,6 +73,11 @@ "Pokaż więcej" "Pokaż podsumowanie reakcji" "Nowe" + + "%1$d usunięta wiadomość" + "%1$d usunięte wiadomości" + "%1$d usuniętych wiadomości" + "%1$d zmiana pokoju" "%1$d zmiany pokoju" 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 41e55e1cce..350ade6535 100644 --- a/features/messages/impl/src/main/res/values-zh/translations.xml +++ b/features/messages/impl/src/main/res/values-zh/translations.xml @@ -67,6 +67,9 @@ "展开" "显示反应摘要" "新消息" + + "%1$d 个已移除的消息" + "%1$d 个房间变化" diff --git a/features/poll/api/src/main/res/values-da/translations.xml b/features/poll/api/src/main/res/values-da/translations.xml index 58517b3ec4..c62a1ff2d0 100644 --- a/features/poll/api/src/main/res/values-da/translations.xml +++ b/features/poll/api/src/main/res/values-da/translations.xml @@ -1,7 +1,7 @@ - "%1$d% af de samlede stemmer" + "%1$d%% af de samlede stemmer" "%1$d procent af det samlede antal stemmer" "Fjerner tidligere valg" diff --git a/features/poll/api/src/main/res/values-ja/translations.xml b/features/poll/api/src/main/res/values-ja/translations.xml index c66e27d85d..b40e58d11f 100644 --- a/features/poll/api/src/main/res/values-ja/translations.xml +++ b/features/poll/api/src/main/res/values-ja/translations.xml @@ -1,7 +1,7 @@ - "総投票数うち%1$d%" + "総投票数うち%1$d%%" "前の項目を削除します" "投票の勝者はこちらです" 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 037d6d7c85..15f71240d4 100644 --- a/features/poll/api/src/main/res/values-zh/translations.xml +++ b/features/poll/api/src/main/res/values-zh/translations.xml @@ -1,7 +1,7 @@ - "%1$d 总投票百分比" + "占总投票的 %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 3d5102fa9f..37f3348583 100644 --- a/features/preferences/impl/src/main/res/values-et/translations.xml +++ b/features/preferences/impl/src/main/res/values-et/translations.xml @@ -101,6 +101,14 @@ 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" + "Eemal" + "Tulen kohe tagasi" + "Kohandatud…" + "Kohandatud olek…" + "Keskendumisaeg" + "Koosolekul" + "Olen liikumises" + "Mis on sinu olek võrgus?" "Süsimust kujundus" "Tume" "Hele" 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 3bd09ce590..d54e3a66ff 100644 --- a/features/preferences/impl/src/main/res/values-hr/translations.xml +++ b/features/preferences/impl/src/main/res/values-hr/translations.xml @@ -102,6 +102,14 @@ Ako nastavite, neke od vaših postavki mogu se promijeniti." "postavke sustava" "Obavijesti sustava su isključene" "Obavijesti" + "Odsutan/na" + "Odmah se vraćam" + "Prilagođeno" + "Prilagođeni status…" + "Vrijeme za fokusiranje" + "Na sastanku" + "Na putu" + "Kakav je tvoj status?" "Crna" "Tamno" "Svijetlo" 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 3578db804b..11d0673606 100644 --- a/features/preferences/impl/src/main/res/values-in/translations.xml +++ b/features/preferences/impl/src/main/res/values-in/translations.xml @@ -82,6 +82,8 @@ Jika Anda melanjutkan, beberapa pengaturan Anda dapat berubah." "Beri tahu saya tentang" "Beri tahu saya pada @room" "Pengaturan Default Element" + "Suara" + "Masalah pengaturan suara peringatan" "Untuk menerima pemberitahuan, silakan ubah %1$s Anda." "pengaturan sistem" "Pemberitahuan sistem dimatikan" 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 ac67e04259..e02cc6b049 100644 --- a/features/preferences/impl/src/main/res/values-nb/translations.xml +++ b/features/preferences/impl/src/main/res/values-nb/translations.xml @@ -11,6 +11,14 @@ "Skjul avatarer i invitasjonsforespørsler til rom" "Skjul forhåndsvisninger av medier på tidslinjen" "Prøvefunksjoner" + "Avstanden du må bevege deg for å utløse en oppdatering." + "Sørg for at «Nøyaktig lokasjon» er aktivert for denne appen. For å endre tillatelsen, gå til %1$s." + "Appinnstillinger" + "Oppdateringer av lokasjon i sanntid" + + "Hver %1$d. meter" + "Hver %1$d. meter" + "Last opp bilder og videoer raskere og reduser databruken" "Optimaliser mediekvaliteten" "Moderasjon og sikkerhet" @@ -50,6 +58,7 @@ "Lyst til å prøve noe nytt?" "Prøvefunksjoner" "Ytterligere innstillinger" + "Ringetone" "Lyd- og videosamtaler" "Uoverensstemmelse i konfigurasjonen" "Vi har forenklet varslingsinnstillingene for å gjøre det lettere å finne alternativene. Noen av de egendefinerte innstillingene du har valgt tidligere, vises ikke her, men de er fortsatt aktive. @@ -68,14 +77,38 @@ Hvis du fortsetter, kan noen av innstillingene dine endres." "Invitasjoner" "Hjemmeserveren din støtter ikke dette alternativet i krypterte rom, og det kan hende at du ikke blir varslet i enkelte rom." "Omtaler" + "Velg en annen lyd…" + "Du bruker for øyeblikket %1$s" + "Meldingslyd" + "Meldingslyd" "Alle" "Omtaler" "Varsle meg om" "Gi meg varsel på @room" + "Egendefinert" + "Tilpasset lyd…" + "Feil ved sletting av fil" + "Element-standard" + "Feil ved import av fil" + "Problem med å forhåndsavspille varsellyd" + "Lyd" + "Avvis feilmelding om varsellyd" + "Problem med å angi varsellyd" + "Stille" + "Systemstandard" "For å motta varsler, vennligst endre %1$s." "systeminnstillinger" "Systemvarsler er slått av" "Varslinger" + "Borte" + "Er straks tilbake" + "Egendefinert…" + "Egendefinert status…" + "Fokustid" + "I et møte" + "På farten" + "Hva er statusen din?" + "Svart" "Mørk" "Lys" "System" 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 03be155520..fb1750e056 100644 --- a/features/preferences/impl/src/main/res/values-pl/translations.xml +++ b/features/preferences/impl/src/main/res/values-pl/translations.xml @@ -102,6 +102,14 @@ Niektóre ustawienia mogą ulec zmianie, jeśli kontynuujesz." "ustawienia systemowe" "Powiadomienia systemowe wyłączone" "Powiadomienia" + "Z dala od urządzenia" + "Zaraz wracam" + "Własny" + "Własny status…" + "Skupia się" + "Na spotkaniu" + "W trasie" + "Jaki jest Twój status?" "Czarny" "Ciemny" "Jasny" 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 28dfd799f8..9ddc896a19 100644 --- a/features/preferences/impl/src/main/res/values-uk/translations.xml +++ b/features/preferences/impl/src/main/res/values-uk/translations.xml @@ -101,6 +101,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 0b8bbd2a07..5a6e75fdd6 100644 --- a/features/preferences/impl/src/main/res/values-zh/translations.xml +++ b/features/preferences/impl/src/main/res/values-zh/translations.xml @@ -100,6 +100,14 @@ "系统设置" "系统通知已关闭" "通知" + "离开" + "马上回来" + "自定义…" + "自定义状态…" + "专注时间" + "正在开会" + "在路上" + "你的当前状态?" "纯黑" "深色" "浅色" diff --git a/features/rageshake/impl/src/main/res/values-nb/translations.xml b/features/rageshake/impl/src/main/res/values-nb/translations.xml index 996793c262..d9f01b70ac 100644 --- a/features/rageshake/impl/src/main/res/values-nb/translations.xml +++ b/features/rageshake/impl/src/main/res/values-nb/translations.xml @@ -8,6 +8,8 @@ "Beskriv problemet…" "Hvis mulig, vennligst skriv beskrivelsen på engelsk." "Beskrivelsen er for kort, vennligst gi flere detaljer om hva som skjedde. Takk skal du ha!" + "Du kan oppgi nummeret på en tilknyttet GitHub-sak, hvis det finnes." + "GitHub-sak" "Send krasjlogger" "Tillat logger" "Loggene dine er for store og kan derfor ikke inkluderes i denne rapporten. Vennligst send dem til oss på en annen måte." diff --git a/features/rolesandpermissions/impl/src/main/res/values-nb/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-nb/translations.xml index 3536e03ad5..728cac0450 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-nb/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-nb/translations.xml @@ -6,6 +6,7 @@ "Fjern meldinger" "Medlem" "Inviter folk" + "Del lokasjon i sanntid" "Administrer området" "Administrer rom" "Administrer medlemmer" diff --git a/features/securebackup/impl/src/main/res/values-nb/translations.xml b/features/securebackup/impl/src/main/res/values-nb/translations.xml index 8d643a52d0..1d6438c933 100644 --- a/features/securebackup/impl/src/main/res/values-nb/translations.xml +++ b/features/securebackup/impl/src/main/res/values-nb/translations.xml @@ -12,6 +12,7 @@ "Skriv inn gjenopprettingsnøkkel" "Nøkkellagringen din er for øyeblikket ikke synkronisert." "Hent gjenopprettingsnøkkel" + "Chattene dine sikkerhetskopieres automatisk med ende-til-ende-kryptering. For å gjenopprette denne sikkerhetskopien og beholde din digitale identitet når du mister tilgang til alle enhetene dine, trenger du gjenopprettingsnøkkelen din." "Åpne %1$s på en datamaskin" "Logg på kontoen din igjen" "Når du blir bedt om å verifisere din enhet, velger du %1$s" @@ -19,6 +20,27 @@ "Følg instruksjonene for å opprette en ny gjenopprettingsnøkkel" "Du bør lagre din nye gjenopprettingsnøkkel i en passordbehandler eller i et kryptert notat" "Tilbakestill krypteringen for kontoen din ved hjelp av en annen enhet" + "Gjenopprettingsnøkkelen du skrev inn samsvarer ikke" + "Fullfør oppsett" + "Skriv inn gjenopprettingsnøkkelen din på nytt." + "Bekreft gjenopprettingsnøkkelen din" + + "Minst %1$d tegn. Ikke bruk passordet til kontoen din" + "Minst %1$d tegn. Ikke bruk passordet til kontoen din" + + "Styrke" + "Passordstyrke: %1$s" + "Moderat" + "Sterk" + "Veldig sterk" + "Veldig svak" + "Svak" + "Velg en gjenopprettingsnøkkel som du kan huske." + "Skriv inn en gjenopprettingsnøkkel" + "Laster inn krav til gjenopprettingsnøkkel" + "For å endre gjenopprettingsnøkkelen din, gå til Innstillinger → Kryptering → Sikkerhetskopi" + "Du kan bruke gjenopprettingsnøkkelen din til å bekrefte nye enheter eller gjenopprette krypterte chatter hvis du mister tilgangen til alle enhetene dine." + "Sikkerhetskopien din er nå ferdig konfigurert" "Fortsett tilbakestillingen" "Dine kontodetaljer, kontakter, innstillinger og chatteliste vil bli beholdt" "Du mister all meldingshistorikk som bare er lagret på serveren" diff --git a/features/space/impl/src/main/res/values-nb/translations.xml b/features/space/impl/src/main/res/values-nb/translations.xml index d2b218f474..eff2588c2a 100644 --- a/features/space/impl/src/main/res/values-nb/translations.xml +++ b/features/space/impl/src/main/res/values-nb/translations.xml @@ -14,10 +14,10 @@ "Du er den eneste administratoren for %1$s" "Overfør eierskap" "Rom" - "Hvis du legger til et rom, vil det ikke påvirke tilgangen til rommet. For å endre tilgangen, gå til Rominnstillinger > Sikkerhet og personvern." + "Hvis du legger til et rom, vil det ikke påvirke tilgangen til rommet. For å endre tilgangen, gå til Rominnstillinger → Sikkerhet og personvern." "Legg til ditt første rom" "Vis medlemmer" - "Fjerning av et rom vil ikke påvirke tilgangen til rommet. For å endre tilgangen, gå til Rominformasjon > Personvern og sikkerhet." + "Fjerning av et rom vil ikke påvirke tilgangen til rommet. For å endre tilgangen, gå til Rominformasjon → Personvern og sikkerhet." "Fjern %1$d rom fra %2$s" "Fjern %1$d rommene fra %2$s" diff --git a/features/verifysession/impl/src/main/res/values-nb/translations.xml b/features/verifysession/impl/src/main/res/values-nb/translations.xml index bb448378cc..388da1f287 100644 --- a/features/verifysession/impl/src/main/res/values-nb/translations.xml +++ b/features/verifysession/impl/src/main/res/values-nb/translations.xml @@ -42,7 +42,7 @@ "Åpne appen på en annen bekreftet enhet" "For ekstra sikkerhet, verifiser denne brukeren ved å sammenligne et sett med emojier på enhetene dine. Gjør dette ved å bruke en pålitelig måte å kommunisere på." "Vil du verifisere denne brukeren?" - "For ekstra sikkerhet vil en annen bruker bekrefte identiteten din. Du får se et sett med emojier som du må sammenligne." + "For ekstra sikkerhet ønsker en annen bruker å bekrefte din digitale identitet. Du vil se et sett med emojier du kan sammenligne." "Du skal se en popup på den andre enheten. Start bekreftelsen derfra nå." "Start verifiseringen på den andre enheten" "Start verifiseringen på den andre enheten" diff --git a/libraries/matrixui/src/main/res/values-nb/translations.xml b/libraries/matrixui/src/main/res/values-nb/translations.xml index 01bea5c726..01a92ab7f8 100644 --- a/libraries/matrixui/src/main/res/values-nb/translations.xml +++ b/libraries/matrixui/src/main/res/values-nb/translations.xml @@ -3,5 +3,7 @@ "Send invitasjon" "Vil du starte en chat med %1$s?" "Vil du sende invitasjon?" + "Du har for øyeblikket ingen samtaler med denne personen. Bekreft at du vil invitere vedkommende før du fortsetter." + "Vil du starte en chat med denne nye kontakten?" "%1$s(%2$s) inviterte deg" diff --git a/libraries/mediaviewer/impl/src/main/res/values-nb/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-nb/translations.xml index 8cc6eb3c84..8f1817b067 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-nb/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-nb/translations.xml @@ -16,6 +16,7 @@ "Filnavn" "Ingen flere filer å vise" "Ikke flere mediefiler å vise" + "Filinformasjon" "Lastet opp av" "Lastet opp den" 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 938e1a5e9a..c24e8652f6 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -8,6 +8,7 @@ "Vähenda tekstivälja" "Vähenda kasutaja kohta lubatud hääletuskordi" "Suurenda kasutaja kohta lubatud hääletuskordi" + "Sinu lisatud emoji" "Kustuta" "%1$d number sisestatud" @@ -23,6 +24,7 @@ "Liitu kõnega" "Mine lõppu" "Mine lugemata sõnumite juurde" + "Suundu esimese lugemata sõnumi juurde" "Nihuta kaart minu asukohta" "Ainult mainimised" "Summutatud" @@ -63,6 +65,7 @@ "Helista" "Alusta videokõnet" "Helista" + "Olek" "Jutulõng „%1$s“ jututoas" "Jutulõngad „%1$s“ jututoas" "Lõpetatuks märgitud jututuba" @@ -143,6 +146,7 @@ "Halda kasutajakontosid ja seadmeid" "Halda seadmeid" "Halda jututuba" + "Märgi loetuks" "Saada sõnum" "Minimeeri" "Edasi" @@ -515,6 +519,8 @@ Kas sa oled kindel, et soovid jätkata?" "%1$d isikut" "Kaardil" + "Sinu koduserver asub sinu kohalikus võrgus. Ühendamiseks vajab %1$s luba selle võrgu seadmetega ühenduse loomiseks." + "Luba juurdepääs kohtvõrgule" "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" 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 6ca10c229e..3c02673a22 100644 --- a/libraries/ui-strings/src/main/res/values-hr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hr/translations.xml @@ -24,6 +24,7 @@ "Pridruži se pozivu" "Idi na dno" "Skoči na nepročitano" + "Skoči na prvu nepročitanu poruku." "Pomakni kartu na moju lokaciju" "Samo spominjanja" "Bez zvuka" @@ -144,6 +145,7 @@ "Upravljanje računom i uređajima" "Upravljanje uređajima" "Upravljaj sobama" + "Označi kao pročitano" "Poruka" "Minimiziraj" "Dalje" @@ -268,6 +270,14 @@ Razlog: %1$s ." "Proslijedi poruku" "Često korišteno" "Galerija" + + "%1$d prilog…" + "%1$d prilozi…" + + + "%1$d medijska stavka…" + "%1$d medijske stavke…" + "GIF" "Grupni poziv u tijeku" "Slika" @@ -307,6 +317,7 @@ Razlog: %1$s ." "Nema naziva prostora" "Nije šifrirano" "Izvan mreže" + "Na pozivu" "Licencije otvorenog koda" "ili" "Ostale opcije" @@ -514,6 +525,8 @@ Jeste li sigurni da želite nastaviti?" "%1$d ljudi" "Na karti" + "Vaš kućni poslužitelj je na vašoj lokalnoj mreži. Za povezivanje, %1$s je potrebno dopuštenje za pristup uređajima na ovoj mreži." + "Dopusti pristup lokalnoj mreži" "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-nb/translations.xml b/libraries/ui-strings/src/main/res/values-nb/translations.xml index 492268c38f..04199986aa 100644 --- a/libraries/ui-strings/src/main/res/values-nb/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nb/translations.xml @@ -1,22 +1,30 @@ + "Legg til avatar" "Legg til reaksjon: %1$s" "Adresse" "Profilbilde" + "Tøm søkefeltet" "Minimer meldingstekstfeltet" + "Reduser antall tillatte stemmer per person" + "Øk antall tillatte stemmer per person" "Slett" "%1$d siffer angitt" "%1$d sifre angitt" + "Varighet: %1$s" "Rediger avatar" "Den fullstendige adressen vil være %1$s" "Krypteringsdetaljer" "Utvid meldingstekstfeltet" "Skjul passord" + "Info" "Bli med i samtale" "Hopp til bunnen" - "Flytt kartet til min posisjon" + "Gå til uleste" + "Gå til første uleste melding" + "Flytt kartet til min lokasjon" "Bare omtaler" "Dempet" "Nye omtaler" @@ -26,6 +34,7 @@ "Side %1$d" "Setter på pause" "Talemelding, lengde: %1$s, nåværende posisjon: %2$s" + "Forhåndsvisning av bilde" "PIN-felt" "Festet lokasjon" "Spill av" @@ -41,18 +50,25 @@ "Forrige melding lest av %1$s og %2$d andre" "Forrige melding lest av %1$s" + "vis alle lesebekreftelser" "Fjern reaksjonen med %1$s" "Fjern reaksjonen med %1$s" "Romavatar" "Sende filer" "Avsenderens lokasjon" + "Sendt av %1$s %2$s." "Tidsbegrenset handling kreves, du har ett minutt på deg til å verifisere" + "Innstillinger, handling kreves" "Vis passord" "Start en samtale" + "Start en videosamtale" "Start et taleanrop" + "Tråd i: %1$s" + "Tråder i %1$s" "Deaktivert rom" "Brukeravatar" "Brukermeny" + "Videoforhåndsvisning" "Vis avatar" "Vis detaljer" "Talemelding, lengde: %1$s" @@ -67,6 +83,7 @@ "Ring" "Avbryt" "Avbryt for nå" + "Velg fil" "Velg bilde" "Tøm" "Lukk" @@ -86,12 +103,16 @@ "Deaktiver kontoen" "Avslå" "Avslå og blokker" + "Slett" + "Slett konto" + "Slett fil" "Slett avstemning" "Velg bort alle" "Deaktiver" "Forkast" "Avvis" "Ferdig" + "Last ned" "Rediger" "Rediger bildetekst" "Rediger avstemning" @@ -122,6 +143,7 @@ "Administrer konto og enheter" "Administrer enheter" "Administrer rom" + "Merk som lest" "Melding" "Minimer" "Neste" @@ -159,7 +181,7 @@ "Send talemelding" "Dele" "Dele lenke" - "Del posisjon i sanntid" + "Del lokasjon i sanntid" "Vis" "Logg på igjen" "Fjern denne enheten" @@ -176,9 +198,11 @@ "Oversett" "Prøv igjen" "Løsne" + "Videosamtale" "Vis" "Vis i tidslinjen" "Vis kilde" + "Taleanrop" "Ja" "Ja, prøv igjen" "Serveren din støtter nå en ny, raskere protokoll. Logg ut og logg inn igjen for å oppgradere nå. Ved å gjøre dette nå, unngår du å bli tvunget til å logge ut når den gamle protokollen fjernes senere." @@ -198,7 +222,10 @@ "Beta" "Blokkerte brukere" "Bobler" + "Anrop avvist" + "Samtale pågår" "Samtale startet" + "Du avviste en samtale" "Chat backup" "Kopiert til utklippstavlen" "Opphavsrett" @@ -223,6 +250,7 @@ "Tom fil" "Kryptering" "Kryptering aktivert" + "Slutter %1$s" "Skriv inn PIN-koden din" "Feil" "Det har oppstått en feil, og vil kanskje ikke motta varsler om nye meldinger. Vennligst feilsøk varslinger fra innstillingene. @@ -239,7 +267,17 @@ "Fil lagret i Nedlastinger" "Videresend melding" "Ofte brukt" + "Galleri" + + "%1$d-vedlegg…" + "%1$d-vedlegg…" + + + "%1$d-mediefil…" + "%1$d-mediefiler…" + "GIF" + "Gruppesamtale pågår" "Bilde" "Som svar på %1$s" "Installer APK" @@ -275,6 +313,7 @@ "Ikke noe områdenavn" "Ikke kryptert" "Frakoblet" + "I en samtale" "Åpen kildekode-lisenser" "eller" "Andre alternativer" @@ -287,6 +326,7 @@ "Vennligst vent…" "Er du sikker på at du vil avslutte denne avstemningen?" "Avstemning: %1$s" + "Avstemning" "Totalt antall stemmer: %1$s" "Resultatene vises etter at avstemningen er avsluttet" @@ -345,7 +385,7 @@ "Del område" "Nye medlemmer ser historikk" "Delt lokasjon i sanntid" - "Delt posisjon" + "Delt lokasjon" "Delt område" "Fjerner enheten" "Noe gikk galt" @@ -366,6 +406,7 @@ "Tekst" "Varsler fra tredjeparter" "Tråd" + "Tråder" "Emne" "Hva er dette rommet for?" "Kan ikke dekryptere" @@ -378,6 +419,7 @@ "Slå på lyden" "Ikke støttet anrop" "Hendelsen er ikke støttet" + "%1$s startet en samtale" "Brukernavn" "Verifisering kansellert" "Verifisering fullført" @@ -399,6 +441,11 @@ "Venter på sanntidslokasjon…" "Alle kan se historikk" "Du" + "Nedlasting ikke tilgjengelig." + "Filen ble ikke funnet" + "Skanner…" + "Forhåndsvisning og nedlasting er deaktivert." + "Filen er ikke sikker" "%1$s (%2$s) delte denne meldingen siden du ikke var i rommet da den ble sendt." "%1$s delte denne meldingen siden du ikke var i rommet da den ble sendt." "Dette rommet er konfigurert slik at nye medlemmer kan lese historikken.%1$s" @@ -434,12 +481,13 @@ Er du sikker på at du vil fortsette?" "Opprettelse av permalenken mislyktes" "%1$s kunne ikke laste inn kartet. Prøv igjen senere." "Kunne ikke laste inn meldinger" - "%1$s fikk ikke tilgang til posisjonen din. Vennligst prøv igjen senere." + "%1$s fikk ikke tilgang til lokasjonen din. Vennligst prøv igjen senere." "Kunne ikke laste opp talemeldingen din." "Rommet eksisterer ikke lenger, eller invitasjonen er ikke lenger gyldig." + "Vennligst aktiver GPSen din for å få tilgang til stedsbaserte funksjoner." "Melding ikke funnet" - "%1$s har ikke tilgang til posisjonen din. Du kan aktivere tilgang i Innstillinger." - "%1$s har ikke tilgang til posisjonen din. Aktiver tilgang nedenfor." + "%1$s har ikke tilgang til lokasjonen din. Du kan aktivere tilgang i Innstillinger." + "%1$s har ikke tilgang til lokasjonen din. Aktiver tilgang nedenfor." "%1$s har ikke tilgang til mikrofonen din. Aktiver tilgang til å ta opp en talemelding." "Dette kan skyldes nettverks- eller serverproblemer." "Denne romadressen finnes allerede. Prøv å redigere romadressefeltet eller endre romnavnet" @@ -448,6 +496,9 @@ Er du sikker på at du vil fortsette?" "Beklager, det oppstod en feil" "🔐️ Bli med meg på %1$s" "Hei, snakk med meg på %1$s: %2$s" + "Deling av lokasjon i sanntid" + "Deling av lokasjon pågår" + "%1$s sanntidslokasjon" "%1$s Android" "Rageshake for å rapportere feil" "Skjermbilde" @@ -455,6 +506,15 @@ Er du sikker på at du vil fortsette?" "Alternativer" "Fjern %1$s" "Innstillinger" + "Tillatte stemmer per person" + "Ingen deler lokasjonen sin" + "Deler lokasjon i sanntid" + + "%1$d person" + "%1$d personer" + + "På kartet" + "Gi tilgang til det lokale nettverket" "Kunne ikke velge medium, prøv igjen." "Trykk på en melding og velg “%1$s” for å inkludere her." "Fest viktige meldinger slik at de lett kan ses" @@ -479,14 +539,15 @@ Er du sikker på at du vil fortsette?" "Melding i %1$s" "Utvid" "Reduser" + "Deler lokasjon i sanntid" "Du ser allerede på dette rommet!" "%1$s av %2$s" "%1$s Festede meldinger" "Laster inn melding…" "Vis alle" "Chat" - "Del posisjon" - "Del min posisjon" + "Del lokasjon" + "Del min lokasjon" "Åpne i Apple Maps" "Åpne i Google Maps" "Åpne i OpenStreetMap" @@ -499,10 +560,14 @@ Er du sikker på at du vil fortsette?" "Områder" "Delt %1$s" "På kartet" + + "%1$d ble med" + "%1$d ble med" + "Meldingen ble ikke sendt fordi %1$s verifiserte digitale identitet ble tilbakestilt." "Meldingen ble ikke sendt fordi %1$s ikke har verifisert alle enheter." "Meldingen ble ikke sendt fordi du ikke har verifisert en eller flere av enhetene dine." - "Posisjon" + "Lokasjon" "Versjon: %1$s (%2$s)" "en" "Historiske meldinger er ikke tilgjengelige på denne enheten" @@ -510,4 +575,6 @@ Er du sikker på at du vil fortsette?" "Du har ikke tilgang til denne meldingen" "Kan ikke dekryptere meldingen" "Denne meldingen ble blokkert enten fordi du ikke verifiserte enheten din, eller fordi avsenderen må verifisere din digitale identitet." + "Enheten din er for gammel. Du trenger en enhet med Android 8 eller nyere." + "Visning av kart støttes ikke" 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 e5c8755a96..0234af883a 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -8,6 +8,7 @@ "Zmniejsz pole tekstowe wiadomości" "Zmniejsz liczbę głosów dozwolonych na osobę" "Zwiększ liczbę głosów dozwolonych na osobę" + "Własne emoji" "Usuń" "Wprowadzono %1$d cyfrę" @@ -24,6 +25,7 @@ "Dołącz do połączenia" "Przejdź na dół" "Skocz do nieprzeczytanych" + "Skocz do pierwszej nieprzeczytanej wiadomości" "Przesuń mapę do mojej lokalizacji" "Tylko wzmianki" "Wyciszone" @@ -65,6 +67,7 @@ "Rozpocznij rozmowę" "Rozpocznij rozmowę wideo" "Rozpocznij połączenie głosowe" + "Status" "Wątek w %1$s" "Wątki w %1$s" "Pokój nagrobkowy" @@ -145,6 +148,7 @@ "Zarządzaj kontem i urządzeniami" "Zarządzaj urządzeniami" "Zarządzaj pokojami" + "Oznacz jako przeczytane" "Wiadomość" "Minimalizuj" "Dalej" @@ -269,6 +273,16 @@ Powód: %1$s." "Przekaż wiadomość" "Często używane" "Galeria" + + "%1$d załącznik…" + "%1$d załączniki…" + "%1$d załączników…" + + + "%1$d przedmiot medialny…" + "%1$d przedmioty medialne…" + "%1$d przedmiotów medialnych…" + "GIF" "Trwa połączenie grupowe" "Zdjęcie" @@ -308,6 +322,7 @@ Powód: %1$s." "Brak nazwy przestrzeni" "Nieszyfrowane" "Offline" + "W trakcie rozmowy" "Licencje open-source" "lub" "Inne opcje" @@ -516,6 +531,8 @@ Czy na pewno chcesz kontynuować?" "%1$d osób" "Na mapie" + "Twój serwer domowy znajduje się w sieci lokalnej. Aby się połączyć, %1$s potrzebuje uprawnień dostępu do urządzeń w tej sieci." + "Zezwól na dostęp do sieci lokalnej" "Nie udało się wybrać multimediów. Spróbuj ponownie." "Przytrzymaj wiadomość i wybierz “%1$s”, aby umieścić ją tutaj." "Przypinaj ważne wiadomości, by łatwo je później odnaleźć" 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 4f92b9547f..d645fa7162 100644 --- a/libraries/ui-strings/src/main/res/values-uk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uk/translations.xml @@ -8,6 +8,7 @@ "Згорнути поле тексту повідомлення" "Зменшити кількість голосів, дозволених на одну особу" "Збільшити кількість голосів, дозволених на одну особу" + "Власні емоджі" "Видалити" "Введена %1$d цифра" @@ -24,6 +25,7 @@ "Приєднатися до виклику" "Перейти вниз" "Перейти до непрочитаних" + "Перейти до першого непрочитаного повідомлення" "Перемістити карту до мого місця перебування" "Тільки згадки" "Звук вимкнено" @@ -65,6 +67,7 @@ "Розпочати виклик" "Розпочати відеовиклик" "Розпочати голосовий виклик" + "Статус" "Гілка в %1$s" "Гілки в %1$s" "Кімната більше не використовується" @@ -145,6 +148,7 @@ "Керування обліковим записом і пристроями" "Керування пристроями" "Керувати кімнатами" + "Позначити прочитаним" "Написати" "Згорнути" "Далі" @@ -308,6 +312,7 @@ "Без назви простору" "Не зашифровано" "Не в мережі" + "Розмовляє" "Ліцензії відкритого коду" "або" "Інші варіанти" @@ -444,6 +449,7 @@ "Ви" "Завантаження недоступне." "Файл не знайдено" + "Сканування…" "Попередній перегляд і завантаження вимкнено." "Файл не є безпечним" "%1$s (%2$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 99f0d20b14..0ecd99f6c8 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 @@ "最小化消息文本框" "减少每人允许的投票数" "增加每人允许的投票数" + "自定义 Emoji" "删除" "已输入 %1$d 个数字" @@ -22,6 +23,7 @@ "加入通话" "跳转到底部" "跳转到未读" + "跳转到首个未读消息" "将地图移动到我的位置" "仅提及" "通知已关闭" @@ -61,6 +63,7 @@ "开始通话" "开始视频通话" "开始语音通话" + "状态" "位于 %1$s 中的消息列" "位于 %1$s 中的消息列" "已封存的房间" @@ -141,6 +144,7 @@ "管理账户与设备" "管理设备" "管理房间" + "设为已读" "发送消息" "最小化" "下一步" @@ -375,7 +379,7 @@ "设置" "共享空间" "新成员可以看到历史" - "共享实时位置" + "已共享实时位置" "共享位置" "已共享的空间" "正在移除设备" @@ -486,7 +490,7 @@ "抱歉,发生了错误" "🔐️ 在 %1$s 中与我一起" "嗨!请通过 %1$s 与我联系:%2$s" - "正在共享实时位置" + "实时位置共享" "位置共享正在进行" "%1$s 实时位置" "%1$s Android" @@ -498,11 +502,13 @@ "设置" "每人允许的投票数" "目前无人分享其位置" - "共享实时位置" + "正在共享实时位置" "%1$d 个人" "在地图上" + "你的主服务器位于本地网络。%1$s 需要获得此网络上设备的访问权才能连接。" + "允许访问本地网络" "选择媒体失败,请重试。" "按下消息并选择 “%1$s” 将其包含在此处。" "置顶重要的消息以便于发现" @@ -526,7 +532,7 @@ "%1$s 中的消息" "展开" "折叠" - "共享实时位置" + "正在共享实时位置" "已经位于此房间!" "%1$s / %2$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 29ca9262db..49dedb49e1 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -552,14 +552,6 @@ Are you sure you want to continue?" "Loading message…" "View All" "Chat" - "Away" - "Be right back" - "Custom…" - "Custom status…" - "Focus time" - "In a meeting" - "On the road" - "What\'s your status?" "Share location" "Share my location" "Open in Apple Maps" diff --git a/screenshots/de/appnav.loggedin_LoggedInView_Day_4_de.png b/screenshots/de/appnav.loggedin_LoggedInView_Day_4_de.png index 3b70c1ec3f..d0563d236e 100644 --- a/screenshots/de/appnav.loggedin_LoggedInView_Day_4_de.png +++ b/screenshots/de/appnav.loggedin_LoggedInView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:337bc943f30e9299407a8eb2522ba3b235e4ad3dd60124c6eed74d820c436e1e -size 33957 +oid sha256:7d5342cd7d81f6394ec127163668864dc9e14e05cc26999c8a9381e787067f70 +size 33738 diff --git a/screenshots/de/appnav.loggedin_LoggedInView_Day_5_de.png b/screenshots/de/appnav.loggedin_LoggedInView_Day_5_de.png index 813eabac12..dd36ce4cc0 100644 --- a/screenshots/de/appnav.loggedin_LoggedInView_Day_5_de.png +++ b/screenshots/de/appnav.loggedin_LoggedInView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:965c273b07a73a52cb3395c4ab2a6213e8927205798007c7805a00e49ccc7c75 -size 34914 +oid sha256:5c3b46bd15055a52ef9c92b49e75a042345d83826574e4bea82f6c981c8903df +size 34726 diff --git a/screenshots/de/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_de.png b/screenshots/de/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_de.png index f78c2b0313..3b08016d6e 100644 --- a/screenshots/de/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_de.png +++ b/screenshots/de/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2a85215f1eaffe17c1a32f7067bd1af2d206e554cf027e2d2393c809743debd -size 49236 +oid sha256:223554d39d768b58789951c63a7cc0fe644f618f493e5d71ae5f8e3b21fb8431 +size 61267 diff --git a/screenshots/de/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_de.png b/screenshots/de/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_de.png index 098dce745b..c4bacde16d 100644 --- a/screenshots/de/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_de.png +++ b/screenshots/de/features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da10fc1098c476b5f9d26ce4dd73310274cc48fd68899a7677623e63a539ea4b -size 44374 +oid sha256:f317b8fb7f924ed6b3f583f316663cac038887720038c560e5d4ba8db45d80d1 +size 53414 diff --git a/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_6_de.png b/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_6_de.png index b3b113479c..b6a959750e 100644 --- a/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_6_de.png +++ b/screenshots/de/features.login.impl.changeserver_ChangeServerView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0d8a20c8d08202b9f6b393345c1e4ceec0511184bb54f05386a654a492fdc791 -size 33594 +oid sha256:9fed6d5214bd9c5115a1434ee0d22b483bbbc98bffe3a38b74e1b154ba58daad +size 33314 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 995e5ead80..8a481ed3cc 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:40fa4dc8d26755ff63458009a315eebd3709b600e0a1a702d4943ce799235632 -size 51647 +oid sha256:606c1a9e29d01dd48463dbd2002f4778c1343e06ddf61c6587ac2212d292fc17 +size 51296 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 ce82506ac2..3cc4095b60 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:c5194a762cd92151c0f5de9c29d2393bb7c93137f03bcb7750f788bf449f0508 -size 36902 +oid sha256:b3084eacd8a6112e5ea6398d953209cb60ed3f4c864e6d526dd3af440b33f8f8 +size 40876 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_de.png index 373deaec9e..a640a49901 100644 --- a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_de.png +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f46be589910edf184bfbdcac39a30dbf8c9427d56e533424b6cd073200462397 -size 8834 +oid sha256:11ad85f440ba20e5b4b6974d572d05190cadb61f0a2fd42be84485d1d8a4f303 +size 8839 diff --git a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_de.png b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_de.png index 28a7af0d75..f5f1422e11 100644 --- a/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_de.png +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:091a782f3149093463760e480ffa95ee3fa1f614fe75d9388902a173e4cdf9bb -size 12542 +oid sha256:69a2947d8075a162184ea21059d2c3dd702a62fff1aa4d7a69d22c40d1b72145 +size 12549 diff --git a/screenshots/de/features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_de.png deleted file mode 100644 index 06e44d2a95..0000000000 --- a/screenshots/de/features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6ebae117696015fb8582ba579ca087bfdab8c13554c4519bd72f4f18452792c7 -size 22244 diff --git a/screenshots/de/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_de.png index 08169845d5..12bd190dd1 100644 --- a/screenshots/de/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_de.png +++ b/screenshots/de/features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86eac241e9084cc830ff13d231908da2eb0dff246aa5cac64dddaac68a5d5f13 -size 295298 +oid sha256:ce15ca9f89274620728715e3448ce671e2253f4fed22a44035460e9a3709ca0b +size 647404 diff --git a/screenshots/de/features.messages.impl.timeline.components_ActiveCallTimelineItemView_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components_ActiveCallTimelineItemView_Day_0_de.png new file mode 100644 index 0000000000..b32e163fcd --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components_ActiveCallTimelineItemView_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e00ddf0daef5c64cb855328d22b1a53786b47bff6f19d24bde3d877b3b24b8c +size 59757 diff --git a/screenshots/de/features.messages.impl.timeline.components_ActiveCallTimelineItemView_de.png b/screenshots/de/features.messages.impl.timeline.components_ActiveCallTimelineItemView_de.png new file mode 100644 index 0000000000..3943014962 --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components_ActiveCallTimelineItemView_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9623e7f442cddf1ced46e6417a5402076463570065e02380b66bd78588d5ed3a +size 50867 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_de.png deleted file mode 100644 index 0435f55de6..0000000000 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ff839731834d7d0c94fa9a2c412014ddbaeaa053c5af1c8cbd00a3f3a583f364 -size 379511 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_de.png new file mode 100644 index 0000000000..7ddac02717 --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a4ac79f3b8fb4e231244bd96b244a4f2526d6ed28d558f9d50734d83bbb74992 +size 363909 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_de.png deleted file mode 100644 index f0dfbc3321..0000000000 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f7a6302320bd1e4258e03487539bf46b0b12781dfc8a22b3f9f267017a6146fa -size 354751 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_de.png new file mode 100644 index 0000000000..68f8148879 --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ca8cf82aa8ab1bdad56a27584b27789402aeb7ad8fadd038280a376fb75a72c +size 345094 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_de.png deleted file mode 100644 index 8aa2cca147..0000000000 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:02ecb903124273e24151ea2088f6b99144f7dcadba00a582b6210dd23835b5c9 -size 357743 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_de.png new file mode 100644 index 0000000000..133fd3903f --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:426d1c844a8c88281c5fa4c61916d93278fdfd38f8cdf2dc54bf1a821f2de3eb +size 397167 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_de.png deleted file mode 100644 index 0041a870b9..0000000000 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a2bd77c08be705c66225f16c29fd6826decd92b41922d0f8ffc0d1a63d8c59d2 -size 356193 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_de.png new file mode 100644 index 0000000000..b10f9741b9 --- /dev/null +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ec1b0244dab22414c6719b3309426e13128d0c70fb67dc66cd8a60d42521fd0 +size 355411 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 5239fec1c7..482d46958a 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:5ce1d8a9e700209185e94ec2f7fb7696188d8e264a09223f7120dd9f1215a9ef -size 57721 +oid sha256:b9c76bcdde54ab7ce54ac32bc54ccfdbb07ecbc06c0924e1de296e161f08179c +size 64743 diff --git a/screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_5_de.png b/screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_5_de.png index a990081be5..d31716420a 100644 --- a/screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_5_de.png +++ b/screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6912bbfad9bbeb0e1ec60836c06f60a5d0a0c5998c5a3f4c2f94b6f9c3fa0c65 -size 13059 +oid sha256:81741b929111f37c1b062e205b8d36259807a8aadb024848f03a5e4b8562f63d +size 13056 diff --git a/screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_6_de.png b/screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_6_de.png index f26ea3b198..9c02c0eb7a 100644 --- a/screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_6_de.png +++ b/screenshots/de/features.preferences.impl.userstatus_UserStatusView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fab56595919a19506abeafc8abc93772643a63f3aae77f0619abb87df2341e18 -size 11833 +oid sha256:49bd134a83cb0c6b9b839e6145004a07bbfea3bd984f9288442a1c5cf29e0d84 +size 11846 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png index de07bf97f9..99644efa4e 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:fbd93cc28496ba6ab5073b8d0a41181dec8fadaca522d2242d35f7795dbcb2dd -size 46008 +oid sha256:363d934e082e4480345a2e1838870ae4ab92dec1d2bb0b903f4ab29e5a18d22a +size 46089 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png index 467997d3b6..ad5ae8c3a1 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:962b465563feef46eb5200c2ac06183faf62003be30c571f9a38c7b393d9ed51 -size 44089 +oid sha256:a09efd65da8dce165f383ee3c571d53ad15dece7028eb9e8eb094345795e6bf9 +size 44201 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png index d326ab1ffd..83a9cb117a 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:e80a4e54736d672b29f06e4d41d6c51ded45ebefde349f1ee27944fca0226586 -size 43439 +oid sha256:220f22926eeaa4d31a923dafa081fe3983a311bf04e15856d045b4ddbf729da0 +size 43561 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png index 916dacb45f..48b674bc28 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:3839b0a82b13e279c90f5a9f6657c37f42e830785a062056c2a2187dff96905f -size 44432 +oid sha256:1466afc2fed907b70544cccc00f5fb83dbaeb9d69e2b7986c3e9691628341af1 +size 44536 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png index caa09c00cb..69ebc6840f 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:32fbde62b59e63d0ac9ed5f18bd9d90e5cbc49ff15edd73550630e780eef3022 -size 44382 +oid sha256:b065415e13e1bdf44a9c27ba4568e6eb0d62d1b770f1b7feba2f584de937c331 +size 44468 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png index 222bdbb69b..269cfaa786 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:9425cc752cbeb63712a1a4b0ac2da47afb7137d0031e4e86654741c13a26a01f -size 45782 +oid sha256:d626fda5fdf1243976def39beaa67831011ca74f430128879b24a6e1dbd44efa +size 45907 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png index 0db1dcb516..1ea68f73ff 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:242141af976b1ff1e45dc36314b065a3e1e7669aff0a2715ea4f858556dfb706 -size 46146 +oid sha256:1edd626d24da35091f60dcd5136a27b2c4987e03d7ee6d4045bf001c4f12bcb4 +size 46268 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png index 86317ef16a..657a684d80 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:81a2d147b0216dfa3f5890fe156b9d5b3286b9eca9a4eda6f411f3973aad5d49 -size 44669 +oid sha256:ef2477e8b1a2b73694a22e7a67e580f91bb40572b4f41ded6c3022d246e5d35f +size 44766 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png index de0b76baad..b48969d333 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:7e199eacdb84d5c47d7c2a60775167c55aa83c3961ff297d0bbcf3575ff09cfe -size 44069 +oid sha256:5d67193aad54d160409572884fb43eb96eb6ce150995dd587f700a1e5f73fc63 +size 44174 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png index f1252a74c9..e8868e88f5 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:4f7e9e7b633ac41323515f71587c046cf3fbc1c41a091f1d48e2ea6a2f09a0ff -size 42864 +oid sha256:94dc77f27194f5f34ac1948226738dd5b82da88be6e75a1888f19681c81df36a +size 42836 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png index a6096d72ea..85b576cd06 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:9d197a1c9731d9422f514558f97ceb150b7e1ef696910463999b5e8b3df944f8 -size 42856 +oid sha256:e7c3a3647df677fbe63d0923c6b740f83fc5585a904c3b8e07c47e7ce7ffe4e4 +size 42837 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png index 25729f3411..4e90a09ff7 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:09a2ea1dd8fcac508e33dc773cf5bcdb2761d907133f199dbd97a72c6ca7376e -size 40443 +oid sha256:db268adf22086200cc8ebf46850f0239e8b33e1a79d1c120753a6bbd935dea39 +size 40583 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png index fb904c2bd5..9cb5a90004 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:920cfd59a2a083ba13af990feb457b70f165ccecdcb0e11c4a9cfb3455d3963b -size 44594 +oid sha256:0e86a20df92ed28a90a8b3ba4fe1aa4bdd493bade93e6737a6f6b26430a56f5c +size 44681 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png index b0c47dccd6..cca4cae93c 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:afcc12b627f86a179dcbb61417190a1c3e86f990d50fa631be38472b82d38206 -size 44531 +oid sha256:7366b272601654b4f5651cb82aaad1be08aca0cffd96a504aa857e1e4dcbe1aa +size 44629 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png index 7ff5e0c2f6..13b0440eb3 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:6bfa7e56cac57ed69d6d430075fc35e41c2b80b7a7d5d933370a5368647437f6 -size 44201 +oid sha256:a3dca96ed406e04375095792789c9e657c5d1f8e98b877c6e991d0cba70d2f33 +size 44273 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png index d72ce031a3..bb76416135 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:3cc7e47edd40cab9ed9941705590f0752b20449efc870f86abd43b54bd49dfcb -size 38465 +oid sha256:103056e52d308e044579a0e26e074f69fdadff1239ed10fbcde3088f39d26afd +size 38417 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png index d3a56873a6..7e2d491a37 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:3e11c3a17f4899077f64d7a7a90f993da912e871b4935b5e308dd9e31bac5e4c -size 34408 +oid sha256:678517d61e34de5732c3409563415fc1bc2ea8bc8571435d5adfd8cb4dd798d2 +size 34196 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png index 7afe84322f..05dbd24049 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:7a4e837ebfec6f590aacfafd7589524e7d15c970efdbd29a2b7c0e82ce81867a -size 43229 +oid sha256:45cbf2e3e00fca851864b324f349f28e63a91c01d912cc2406fba054bc325f35 +size 43053 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png index 0574322da7..4c21775d11 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:76c41c7b34d99e430c4cf5b7e76bcce3c63a59d1e346bf43ef8ae51f94efcfcb -size 42571 +oid sha256:ca1edb157db2e40136ccc898c55e88d26144f2d183030f485143d760ec1663bb +size 42543 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png index 7e7f454647..5ecc77ae3d 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:e33775515ae038a38c2c0777ab6a30b38b17cfbb9211008bf6d84f7f75da4549 -size 34952 +oid sha256:9a93a0c0243537989282dd01b26246efc5fa73cc44096364a7429f962f9c83cb +size 35001 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png index 9c036da39d..cdf3a551aa 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:1ade79185899845159fceff103119f0c811453645b63336a0315815079d116ed -size 45062 +oid sha256:e3a7897bdef6291441de8e06969f5c2781a52b5df1dcb7a0a78ca154183eca67 +size 45153 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png index 1f2b90d768..3f8a788b0e 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:df94c2469a79844306bde7021d072eee808be975e7cf9ab95d66d5278130681f -size 44585 +oid sha256:1a4e562634358362eb15165f6c3b00a66e35e187e433442a06b8f5bfbf997a34 +size 44726 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png index beeb0f0754..4c432f0485 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:f41518b33e2bac87a66d68b7a8ec1ef03d75282b191e81a89c6fb3a95534c5b6 -size 43435 +oid sha256:e171f751b3ac646550ed0d03c30af5c1a87c40bd61966109961d45e3560ea0c8 +size 43448 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png index f6bd795833..bc26f4154f 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:27c4a30fedcbdd2f87adbde9cbae6811d44e1717263afef69d94f30c62220d43 -size 47690 +oid sha256:f9a73947904a394eeef3844d70fb954d6afe99b475070e2ffd3f4d1871350fff +size 47776 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png index f925db69d4..fcead70d3d 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:1a2660554dd6866800fcf5c4cb0db71c5352ebfc8bdf8f578fbed919f1a8ea35 -size 45591 +oid sha256:9863915e647a1e379bd36a26118a27b008c91a8be834e0654c8f07f2397154b2 +size 45670 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png index 8ad1f37884..ce77255472 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:07f570ce47d91018e4c5bac7b97f02808d6f04dd45c75ecaa598f5fa015b961f -size 45030 +oid sha256:390e616bd74652cd799f44c306979cabf8e597dfa345a12ef70b734d360301e4 +size 45110 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png index 262fea0568..ac1f951a2b 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:8d83c1ad4304b03c83d355637d274ed5d7afed687d71b4584f996ba40cc8b36d -size 45999 +oid sha256:72f99b9e99f58972a241871c96b88b5a6b7c63e7936f312cc82a96e83b9df927 +size 46051 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png index 1d9b3083d3..04725afc93 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:0afc00ea3c7c01ca8d569207c67fc1e638089e02f86a799d884203743383e7fc -size 45930 +oid sha256:aaf5e26cfae6c4151d88535e3306f763cb236662a348a93486dc8d27b3844db5 +size 45997 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png index d40ba234d2..de3387c174 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:5d3c930789935491a5941dd049bf534c13eda091a3334490a930c32b7746891c -size 47431 +oid sha256:bc26686b6aa746ced27166c9a78c757351898a91440690dce39219338cd08387 +size 47558 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png index c54012fde6..611ac1df4c 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:d522792c4dccd88c57877fb1889f79e6bdee9dd46b0a69c630b4ee4c44d080fd -size 47870 +oid sha256:f3a7a3b94a0113f857083b257f5212080bea2ca6a8c45d81fa766d9be08159d4 +size 47988 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png index e7b5b4dcda..6e9d79062c 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:7c07ddb2e3c67d14161cdb50c1aeb843ed2d809c2ede25781120212c9ea8db1b -size 46245 +oid sha256:2a2a4f87070ff794d5d9b2801b00a953a2293b8ac53306f600c8fce034bccf93 +size 46309 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png index 236f7b9264..ebbeac3f02 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:6f5adab2c88707d8cfdf02afed207ed1c9dae6e079c56dafded849e69d7251ff -size 45775 +oid sha256:079136ab2f084134091d7b80e6fae5f3b4cc0bf7f15f77fba37ca2bf02f5368d +size 45831 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png index e63f91816b..cadbd5e21b 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:13de8e3d3e4fe65ded75c0bf83d35ba3d6e3fb399f6e44cf5c0dfb22a0760c8d -size 44605 +oid sha256:728d64a173548cf520b424c58cf0782efa1c7059e232d01442cdeae872bc31fd +size 44529 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png index 45f99a6437..295a526d1c 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:d7c01f6c32eb80dd6bf9b155a4a502c4fc547b75da8b4fb35fb9fdf79a74660f -size 44557 +oid sha256:a34deaf4c5e1fd72f16157623bba5a6196b198d7af8f4279810a2a530f249e73 +size 44486 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png index 7ea3b25be1..28b72b85c4 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:de5b2d0455df42d3c78ddb53af7026302bb5685cdedc95833792e056afd64a35 -size 41836 +oid sha256:8d1e0669e1bc2e8bf3ef3ad78bc5ad0d115c5ed190c324c97c50fb57c441b1c4 +size 42034 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png index 1cfd57e644..b2b4a832b3 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:ff079ace53452fdee5aa1e6bc891a20155363f9ad222a88850a940c73d4128de -size 46222 +oid sha256:670017dec6822b218b58b7ff1e9a77820bdbcb83ef8d016fdc86dc6d8424dcfb +size 46236 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png index 297290822b..b3f8165b4f 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:4aa47c73d51ec8e922cf57d70dff2ba980e2a7f7bc8a9ac879cf82c558464884 -size 46114 +oid sha256:b01fe8e863b1291d80276cbc69e90942531120ed4a55e75200537974b9c10222 +size 46175 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png index 82265039d2..4ef7cdce2d 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:b5b6a74f88e2237029aefa7958f053e8a417ce151ae15be6c9b2a23bc7cbccf0 -size 45711 +oid sha256:da295c263d2e5c5ad03114a1187f2a3839ea094a4669d81798dc44b2a9d8c639 +size 45770 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png index fdd2a706e2..74ac704623 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:f1fba8dc7f4a0aefd8a31497e503c965e944563974020549f2410d4d417e0144 -size 39952 +oid sha256:287e77c80a50f52c8f6379cb307ec87cf0ae85814229ce0794ec4485260c8b12 +size 39846 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png index ccf2aaa37e..f960fcc707 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:3afc35e14b7f3b1ff3af6661b38e6bee333f10dec623f34814e114a28a1fa61c -size 35556 +oid sha256:44272f5f1893abacabb50b6094580b3897ca8612f06ef48064f1da455b1a1359 +size 35524 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png index 6db4c29c9e..8587822a8a 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:07a8fcf6977221be7d9bda3dcc23cb3d3d22f0e46a36b282473d08d0dbfed29b -size 44735 +oid sha256:65816f3925fecc5b5f5eac06bc706c3270347103d06ad16a3c9a61cbf6a55b1b +size 44616 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png index 0360351793..0169436da7 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:be92b2bdb3d9e5778c3853391213d7f6656c06f158fd1835b8cb59fba7721bad -size 44263 +oid sha256:3b9f8b1f0b98267b2dba7918487ee7bfc432c93bb8cfab45280a014857529fcf +size 44188 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png index 60b772f6fb..fbbe4280ea 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:b2cc88fed3c7e90fd974d6d0bf047cf4cb6b16dd9697f2042d75973c5da53785 -size 36515 +oid sha256:a482b0a589b8e5fd0474e76e1292c607b3fd9232caa69ddfc4602f4eb29ba730 +size 36629 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png index c8899b5e0a..baae5fb1a5 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:6e1f82c49cb2852e455f081a1e3feeb4d89bc3066e60baffa404a0126da3db35 -size 46732 +oid sha256:9db70150e020948a92cab255b0c1b923c11f0d7f6de99d8ddd262128e9b78f6f +size 46812 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png index 84c108ea47..f0085f5849 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:267aa0d69468e5d413fa1484dd836c438d52841ec66ba47cc292c5fcbf119beb -size 46238 +oid sha256:116e23d25566ec356b2c4bae654217a1e5a38150f424f45fce91a5b4b9cc61c4 +size 46294 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png index 7f0b76d09e..a7bb6cef72 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:683a93dd5a05a3c51fc9644a0779996ff63c67b33c23df919fb142020b2f519d -size 44864 +oid sha256:0cffffdfe22cb238c6a667e4092450e27c53597f4296e35b732764e6f5b484b5 +size 44833 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 7fbe8f888d..9a73c54042 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:0578d53cd64a18056d550c9b0b8bdfbf510392b1898718efc6e753d251c21a2b -size 18557 +oid sha256:dfe598362f7bd9dd246c73cc98ac5ed34fe77e94467de94509fa0cbea9ab571b +size 21313 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 f45704af84..87471ed32e 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:0f63174a49edc5ce7f1e7d13253c1fc8449dfd3d3029a240d6d47ded6b7b20fb -size 22233 +oid sha256:86dc7f757c0f38fee531f5cc857626f5ffd993b1ff7c8830a4cdbfba4c37e501 +size 24945 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 4fbd71efb8..a2ac18ab71 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:bc661e4e10991f3810a28a69381036a8445fd44aeb27614a6ae59668c8ddcddf -size 27638 +oid sha256:58a0fbc9a1cbd6bfdb5d53d06d971fb36c666e48c14920ac10403223d87b1f4a +size 30185 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 8c6d78c1d4..1fbc980d1a 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:7c34192c1c65387e5772a9763cab97c12fffdbbc148c0d08343c211a3b8eafcb -size 28105 +oid sha256:2ea689d5607d180e37a9acdccaf3653ce20002ae1108fb6742a0624b3eb05af5 +size 30666 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 389fe3f63b..a606451f90 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:401fb9c009d48f287c649f768679d744a239cfa29f5c7dc189721a92db6c1b7a -size 61224 +oid sha256:8398f4e62d4e360f74ad19322930d3b9316c30341e8d33043e15c436962e535f +size 61207 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 b3ca4cd447..290790c30a 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:234efe683bd6bc802f2a9502faaf6969cb5ad373a1128af8dacc99969d9c10bb -size 25692 +oid sha256:933ab3d2d152a647cbea97b7068bb8186546849aab52857c62e08d763b7628e7 +size 27998 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 b7ab99464e..e2b8c8b44d 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:4b8a6428ae3624826edb3917a78e641df0704e8c21519ac003ff27387d0e37cd -size 15902 +oid sha256:b93e9986c445dd4e829a2a2be58c3954e0109b0839b63c96a12b44a093330c46 +size 18693 diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_0_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_0_de.png index 9090925f4b..de068ab838 100644 --- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_0_de.png +++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:abe095cffd60110dd69f4e51ac32b946975edfd97707ab315c9e500985b6e77b -size 25031 +oid sha256:502e23453f027c8a8e18f9fc50fb5b596cb76c7774b18dc2544fc595bd4dee44 +size 25319 diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_1_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_1_de.png index f3f7d04cd6..9ee694d882 100644 --- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_1_de.png +++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3083279a82da9a4aeeeeccb7357cd05dfc9cb9cb72ebb1b8ca6c0bb9fa4b4a8a -size 23110 +oid sha256:dc85789059bf1bbd1a5c6b2079bf306fc3929ca1f229e1caca9ab27798b0ed20 +size 23039 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 9f12c8c18d..72efdb5c37 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:0c80ae6573c4d41b14827623890cb6b211783c708d7417c3b9f1e1ab29462098 -size 25198 +oid sha256:54696ddbbe7ab2f428e0d4ea0748f0ede19eb399629edfc98b0918630dadbadb +size 25383 diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_3_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_3_de.png index dadd6c7bc4..c1f6f71e64 100644 --- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_3_de.png +++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f97f9ef5fe8deb7506d1f284b7fc9901dead7ed9a1d022752951330f7154ebe -size 43225 +oid sha256:0a37972f22a3a7b3bfd5ea412ee564c5cd8f748dea0e1430bddc09d74132fd08 +size 43226 diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_4_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_4_de.png index 5a4d3aa025..da387221dc 100644 --- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_4_de.png +++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a805d5b4c448dd24f58e3ef03c69e3d5cd37fd9f4950765c0c16d22ad868884 -size 37105 +oid sha256:6dee381ca12861805ab1839d6832299283415b113af9269e4f26d7eb9343cb2b +size 38945 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 81b5bb4a95..4486c3ea11 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:09404876c06fa55c2e01f48380f7a4767d8c55f0cd46bdec78f4d7687ba8101d -size 23150 +oid sha256:f18660504a7a2fe385f2fd261b3c61ded83a8e6afac834821aeb47c54524e7f8 +size 23356 diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_6_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_6_de.png index 707d4b7704..61f5ac6ca4 100644 --- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_6_de.png +++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:77109f43aa631a92f46c3daacf9e9eb724442bcb07608a1664cc46101785f453 -size 25112 +oid sha256:b581cdf88386d4c375cb7883a09bdb8072133ed7047a73377f98f05d040443d3 +size 24954 diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_7_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_7_de.png index 43c62ed709..b0478fe610 100644 --- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_7_de.png +++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab60966d00eabc8d73dc60185b6d36b5905cdb42204f5259c94a25e704877c5a -size 27868 +oid sha256:6d0c4cc915f588e0b08dd3d51aae1d30ec97567bf44309a227cc9ff4b247e0a8 +size 28150 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 5b11ec067d..56b138ad9c 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:35ac4bfa2e7bffba17448459c52098400f421fc3af55a7de16c24f3f293d0d42 -size 36464 +oid sha256:6e76fe613e8d078dd5d2dd3287f85c20bc4aea485fa5bd32f158082281e83535 +size 35838 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 952de3033f..9182b7c53a 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:8f5a232c60af123ef006af7ca44bf43acd21dbc8b1f4568640eb7ec78e2378e8 -size 34580 +oid sha256:d5effc46b5c1f11c7bd490362b34e29275a9611f87cced34dd12d34c062a224b +size 34517 diff --git a/screenshots/de/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_de.png b/screenshots/de/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_de.png index 8097e382a9..e162b54b55 100644 --- a/screenshots/de/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_de.png +++ b/screenshots/de/features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:404f9bfbe1e9587bc02b51eefa787b0356ca187412ce0c389f22673ee6539216 -size 27359 +oid sha256:d4063825212138532e706d4dd74426d5932c3fcd9c4ea1be0227282850d615be +size 26930 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 5673458928..92cb2eb9ad 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:3ffba2cf2bdbed63ffd3f378a9e5b2a8c08bc316c500d7c782dbca8152c07224 -size 30449 +oid sha256:11264ae11e2fb4d6a82982c9d9e64723700bd5a885d9e4351a8da4bf768a2135 +size 30041 diff --git a/screenshots/de/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_de.png b/screenshots/de/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_de.png deleted file mode 100644 index 83302d6ba4..0000000000 --- a/screenshots/de/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:16dee1dfe746cd40dac9fe8f0af3ecb42cd14bab5cc490917b589beed065ed1b -size 14686 diff --git a/screenshots/de/libraries.emoji.impl.picker_EmojiPickerView_Day_0_de.png b/screenshots/de/libraries.emoji.impl.picker_EmojiPickerView_Day_0_de.png new file mode 100644 index 0000000000..11c34216cf --- /dev/null +++ b/screenshots/de/libraries.emoji.impl.picker_EmojiPickerView_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c4016cf931ff30a3678c696c6962d0695f123aa1c7065697aab93e801a7505f8 +size 21517 diff --git a/screenshots/de/features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_de.png b/screenshots/de/libraries.emoji.impl.picker_EmojiPickerView_Day_1_de.png similarity index 100% rename from screenshots/de/features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_de.png rename to screenshots/de/libraries.emoji.impl.picker_EmojiPickerView_Day_1_de.png 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 f8cbcfc1a9..a3e8f0b16d 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:d05166fbb55144719d8f304a2055b4d586e31768e0a840539b6584a01c8a9df4 -size 14310 +oid sha256:2c1c0f9b6a4bec22adf1e39e2293f7dd5b119b6e48f6a3b9c8901d7f8207bef8 +size 14304 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 327ea308a7..7a2ce37094 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:d7dbf9bb99bd112618baff601ce3304518baf0cc8401d6b984d268264cf15007 -size 33349 +oid sha256:deff81d4c14688464b56db5c40de2c533f7cae759a6771cc09560ef7f521d4e7 +size 33333 diff --git a/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_de.png b/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_de.png index 77330acb1d..579473fada 100644 --- a/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9948daea87ec366d0d0224ea6071a00d77e2d440c923f700b8128d62b52550e -size 528896 +oid sha256:0741d04a3d5adf30805104e3b12db362d1ad09ff885bd5240c1f8eac5fb496d7 +size 449334 diff --git a/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_de.png b/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_de.png index 8928a92111..90caeae1ab 100644 --- a/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa139ab4b3399dcce1147babe4a315a5813aaeaed484796dd372c3281a6240d1 -size 33699 +oid sha256:16f6352ea69f3a8ba5b907e585d0558d7822e9cce9216ae043ba10cbf7244768 +size 50489 diff --git a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_de.png b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_de.png index d8118a67f0..f32eb72acc 100644 --- a/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_de.png +++ b/screenshots/de/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6298eeaf8442246d35fcca3b9e46755353d12bd9d6bfaa8a1e0447ee5d730e92 -size 198311 +oid sha256:71c33fbcc25360bbd32e1d895405ae1d338bbae4c815d4d216dea9038077a05d +size 198457 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_de.png index ac0cc44233..23921e4eba 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:7b8cc7c147720a5069b6dc52fd2b73fabc6ceeacb34971b6e4678fe9d3cdee7c -size 73163 +oid sha256:8fd803c53ba9e0c50ea107b3faa0e960a4499aeac9bddd6588312f35f9ed13e7 +size 73181 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_de.png index 4a128e6519..0d9af37769 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:1107d8275c397858594dae30ab60a2aaf024be42ce95c8622312c5db197fc3cd -size 59585 +oid sha256:938eb455f5d185fd3f89a45096356103fe6062ae18e17bd73f02b84ee06d1e7d +size 59607 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_de.png index 12d60e3dde..e922643412 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:a177473a350953b810a905a6d211ee2d25093df0d9f893fac1bd7f8845f180c8 -size 72685 +oid sha256:2b0840a07a87b78e8d00497f932c41d7eceea0fd931d970d074469b3c741bc55 +size 72707 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_de.png index 539b9b8dd9..587e316692 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:556bbddc7c251aaa5f4ebeba710542461c259623514f41bc2084ee84eb9a44ab -size 81452 +oid sha256:c642b990169a6a1c543e308f1cac8ad73a3e9eecc7f075ae24ea1d03d89e3219 +size 83423 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_de.png index f549e77e82..4e8012dd20 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:0abc80f87055b2389ef47dfefae1748402f31840c9f6cbe25d35c697ed8bf0e3 -size 62284 +oid sha256:57b818508094e0de0f1a94d98ab8ba0443c6f7d854d12ed855aa98073b239a17 +size 62304 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_de.png index 0fc2abd4e9..b062fff206 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:5f87522288622a68d2731dd95fa3bd0f092fffe85b707eec807be215189f5ce0 -size 61184 +oid sha256:ed2d4bc63f4731050a69ece5d58af7f6d37e806c6c47a3187a5660963372b6e9 +size 61204 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_de.png index cb2b57781d..c4676d7f32 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:0d87ab9985d4efa8bd2c430ed81e4650960ddd87a29a65cf015565853223cdde -size 66852 +oid sha256:598cdca898f332471f0e0063dfc4b01e3ac423054be47dbc631a54f52f147bb9 +size 66874 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_de.png index e94135d065..f7c935f14d 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:25b9b92e7dbf734de4e82cf7aa8122f1ead30daac6c21fb1d4fccb6a5ee2ad37 -size 89960 +oid sha256:8f5827c02a5da3f6a94ed607f0af72abeff684647a550bf097168d15ef4e60cd +size 89976 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_de.png index bfe14559db..6238b05f23 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:8c272dc0bfdd80edbc0e9804e4b0c37f9eac5191a17a3e30d4a91af8ad991e54 -size 60497 +oid sha256:99a4b449378b6b61df662f43e1e32417e8d1ecf7f76eab7fcb0f7609ef06aa4e +size 60521 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_de.png index 045576fd26..31affa15cd 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:a8c4c8e45da8d9f7cc30daa3fc451deb3880254396ac0981eda59a541b682c1e -size 60575 +oid sha256:81bcc9d662794e79998ee4a1e680abd65ee4333c1fbf597e6200d2cab9de484b +size 60598 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_de.png index cdd72552d0..84404e8803 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:3af4cb08487aca4a4c17fb1a4d4516c9d633ab581df24d28c11a88ce569bed3c -size 69191 +oid sha256:9738bf5f3078b76d3780e762556995256f6ad5a27643b487568fef7d8ea44778 +size 69214 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_de.png b/screenshots/de/libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_de.png index e287dca146..d6ec8b12c5 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:bac50948e1bde9e5bcf5d7e06a3d5c31ac598db2fb762eee9bfc243d1906d238 -size 60048 +oid sha256:acf8890ae98690403941192c7b4e2a541c299bce6a78129f84ee1fae0ae0226c +size 60068 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_0_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_0_de.png index 5d1695fefe..23459160a0 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:e938e2ee657c86a35ef80713b6851b10bbfdf81f056b84a515cb7d09d2924227 -size 72280 +oid sha256:00cf527f8c7b4666daae1874431bc4e4ed23acd2dc194c1eff4cb0d8776e5c01 +size 72220 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_10_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_10_de.png index 9139cfc084..67fe7d0095 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:ca96ca3115b7630e87e67c1f65aae89348f9ab6386f6bbdfe6706bb498e29df1 -size 56098 +oid sha256:7e368d4bed293ab020355ad99c7ec8aeaa29cc8d49e789c23c9a2c5020bb8fbd +size 56060 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_11_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_11_de.png index d4e1216279..d492a13bfa 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:343644a8d2d9db799de9169a8e2feebb71f535dd18ca03460a774aeb230f473e -size 70592 +oid sha256:f74eedd9e5ff22d3b2689fc3a794c74f0c1b36eb79941098a34f84ccc25e23c3 +size 70527 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_1_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_1_de.png index 43013eaa67..5719875b39 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:22010f59f1eecd415b1053bfc39433a1fab5c7dc9fc91ae7d58677bafd818ff2 -size 81892 +oid sha256:86ca47745f52ce69247f231c10321e852be493922f300786167262944c6e4589 +size 84162 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_2_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_2_de.png index d60e5a8065..1cfa5959ad 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:f8456372d40c2812ca55bb65be6cb2d84fbeec5108d33b9f6670887c95089184 -size 59224 +oid sha256:cb74b0cc66cf73d64dad42b8bfd36e31c081d5e17425d44a966786b30e736cf7 +size 59206 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_3_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_3_de.png index 19f0bfef1e..f25038075a 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:90957d3d22f355d00813010758d4c2cff75a58bd5446fd8e4a9e07aa5b815e23 -size 58221 +oid sha256:40c72b83b4bdebeef1012e4503471979e4c665eeb34f2300250fbc777a1dfae6 +size 58210 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_4_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_4_de.png index a33b90da60..27c85c1f18 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:386ca75ca2695fce27cba64e3dc7350f0fc13291a842b8ed75987abe4165a82f -size 65990 +oid sha256:7ddc4b824eb3e6d1576d82b20f674be3d02937d5652ff2ca2acdddf4be3e842e +size 65967 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_5_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_5_de.png index 1bd9e7c1ef..821efef0ef 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:3edb8f82e829c80cae739460d75967e10de58c5cd18f75dba90daf1fc61c2f20 -size 101215 +oid sha256:6ef123f742c10b05079f64fdd39425420eabe963beb30e42d3ddf5fc494b1210 +size 101189 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_6_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_6_de.png index ffcd9cad1e..2df6b6f26c 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:af83e91f7fa2b45d7e70af1784873b3584c2313b35fd0e861bdce7e3d33b63ab -size 57426 +oid sha256:394bbe03228817a62d63d2bab5eddc3890c77f71cb8d071b640d9de9a260f281 +size 57389 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_7_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_7_de.png index a80bc423e3..2bee54c74d 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:c48965981c80bf46726ec3fe33e3307e213726f002ba18263600d4cd07a92b4e -size 57282 +oid sha256:d77ca9b7f40967b9255236c28e810dd7df515afe8d3ea32213c183048707d172 +size 57259 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_8_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_8_de.png index c1de8eb3b9..e13695ee39 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:86e8e15959f4e9a29a1320b9a586fb1877d7703e554ca730ea58c1f4c0b56e47 -size 67720 +oid sha256:092c6b66d3a324f0f55c549b1a06859eeeea220db76f3f800dc2d1c7cde0d537 +size 67693 diff --git a/screenshots/de/libraries.textcomposer_TextComposerReply_Day_9_de.png b/screenshots/de/libraries.textcomposer_TextComposerReply_Day_9_de.png index 90b9927d64..cfffdc9727 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:92b0771d88f7e428e99fd8393d4c1e03da059403408ab5deec02a9e35df0f946 -size 56821 +oid sha256:04e5fbe07c868e8032b734706244f5b24b91c070c0b04abfcd0e65f0599c22e5 +size 56780 diff --git a/screenshots/de/libraries.textcomposer_TextComposerScaledDensityWithReply_de.png b/screenshots/de/libraries.textcomposer_TextComposerScaledDensityWithReply_de.png index eaa36d2c24..b598ca869d 100644 --- a/screenshots/de/libraries.textcomposer_TextComposerScaledDensityWithReply_de.png +++ b/screenshots/de/libraries.textcomposer_TextComposerScaledDensityWithReply_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:181ce0a2bf5e6eb95a7726bdf26540f2320e5fb6bc4d86b17f9e027314d79f0c -size 16262 +oid sha256:0dc96d71b7356682ff66e6b0c2b4780a7c29df451c100391889e019490ccfcda +size 16822 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 759f39cb02..d9e43a5274 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,107 +1,109 @@ // Generated file, do not edit 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",20647,], -["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20644,], +["features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components.event_ATimelineItemEventRow_Night_0_en",20658,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20658,], ["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",20644,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20644,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20644,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20644,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20644,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20644,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20644,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20644,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20644,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20644,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20644,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20658,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20658,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20658,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20658,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20658,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20658,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20658,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20658,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20658,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20658,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20658,], ["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",20644,], -["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20644,], +["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20658,], +["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20658,], ["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",20644,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20644,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20644,], +["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20658,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20658,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20658,], ["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",20644,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20644,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20644,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20644,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20644,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20644,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20644,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20644,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20644,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20644,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20644,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20644,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20644,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20644,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20644,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20644,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20644,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20644,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20644,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20644,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20644,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20644,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20658,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20658,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20658,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20658,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20658,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20658,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20658,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20658,], +["features.messages.impl.timeline.components_ActiveCallTimelineItemView_Day_0_en","features.messages.impl.timeline.components_ActiveCallTimelineItemView_Night_0_en",20661,], +["features.messages.impl.timeline.components_ActiveCallTimelineItemView_en","",20661,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20658,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20658,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20658,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20658,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20658,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20658,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20658,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20658,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20658,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20658,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20658,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20658,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20658,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20658,], ["libraries.designsystem.theme.components_AllIcons_Icons_en","",0,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20644,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20644,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20644,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20644,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20644,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20658,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20658,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20658,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20658,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20658,], ["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",20644,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20644,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20644,], -["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20644,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20658,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20658,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20658,], +["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20658,], ["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",20644,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20658,], ["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",20644,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20658,], ["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",20644,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20658,], ["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","",20644,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_en","",20644,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en","",20644,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_en","",20644,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_en","",20644,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_en","",20644,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_6_en","",20644,], -["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_7_en","",20644,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_0_en","",20658,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_1_en","",20658,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_2_en","",20658,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_3_en","",20658,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_4_en","",20658,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_5_en","",20658,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_6_en","",20658,], +["features.messages.impl.attachments.preview.imageeditor_AttachmentImageEditorView_7_en","",20658,], ["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,], @@ -111,22 +113,22 @@ 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.messagecomposer_AttachmentsBottomSheet_Day_0_en","features.messages.impl.messagecomposer_AttachmentsBottomSheet_Night_0_en",20647,], -["features.messages.impl.attachments.preview_AttachmentsPreviewGalleryView_en","",20647,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20644,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20644,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20644,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20644,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20644,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20644,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20644,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20644,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20644,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_9_en","",20644,], +["features.messages.impl.messagecomposer_AttachmentsBottomSheet_Day_0_en","features.messages.impl.messagecomposer_AttachmentsBottomSheet_Night_0_en",20658,], +["features.messages.impl.attachments.preview_AttachmentsPreviewGalleryView_en","",20658,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20658,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20658,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20658,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20658,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20658,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20658,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20658,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20658,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20658,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_9_en","",20658,], ["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",20644,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20658,], ["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,], @@ -156,22 +158,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",20644,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20658,], ["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",20644,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20644,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20644,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20644,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20644,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20644,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20644,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20658,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20658,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20658,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20658,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20658,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20658,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20658,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20644,], -["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20644,], -["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20644,], -["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20644,], -["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20644,], +["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20658,], +["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20658,], +["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20658,], +["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20658,], +["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20658,], ["features.rageshake.impl.bugreport_BugReportViewNight_0_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_1_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_2_en","",0,], @@ -182,142 +184,142 @@ 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",20644,], -["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20644,], +["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20658,], +["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20658,], ["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",20644,], +["features.messages.impl.timeline.components_CallMenuItem_Day_6_en","features.messages.impl.timeline.components_CallMenuItem_Night_6_en",20658,], ["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",20644,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20644,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20644,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20644,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20644,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20644,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20644,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20644,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20644,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20644,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20644,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20644,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20644,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20644,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20644,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20658,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20658,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20658,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20658,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20658,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20658,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20658,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20658,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20658,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20658,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20658,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20658,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20658,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20658,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20658,], ["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",20644,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20644,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20644,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20644,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20644,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20644,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20644,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20644,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20644,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20644,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20644,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20658,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20658,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20658,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20658,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20658,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20658,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20658,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20658,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20658,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20658,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20658,], ["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",20644,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20644,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20644,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20644,], -["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20644,], -["features.login.impl.changeserver_ChangeServerView_Day_6_en","features.login.impl.changeserver_ChangeServerView_Night_6_en",20647,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20658,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20658,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20658,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20658,], +["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20658,], +["features.login.impl.changeserver_ChangeServerView_Day_6_en","features.login.impl.changeserver_ChangeServerView_Night_6_en",20658,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20644,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20658,], ["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",20644,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20644,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20644,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20644,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20644,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20644,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20644,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20644,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20658,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20658,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20658,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20658,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20658,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20658,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20658,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20658,], ["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",20644,], +["features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en","features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en",20658,], ["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",20644,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20644,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20644,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20644,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20644,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20644,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20644,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20658,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20658,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20658,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20658,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20658,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20658,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20658,], ["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","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20644,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20644,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20644,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20644,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20644,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20644,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20658,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20658,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20658,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20658,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20658,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20658,], ["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",20644,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20644,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20644,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20644,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20644,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20644,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20644,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20644,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20644,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20644,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20644,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20644,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20644,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20644,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20644,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20644,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20644,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20644,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20644,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20644,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20658,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20658,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20658,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20658,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20658,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20658,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20658,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20658,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20658,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20658,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20658,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20658,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20658,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20658,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20658,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20658,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20658,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20658,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20658,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20658,], ["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","",20644,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20644,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20644,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20644,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20644,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20644,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20644,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20658,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20658,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20658,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20658,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20658,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20658,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20658,], ["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",20644,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20644,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20644,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20658,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20658,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20658,], ["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",20644,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20658,], ["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",20644,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20644,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20644,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20644,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20644,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20644,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20644,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20644,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20644,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20658,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20658,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20658,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20658,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20658,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20658,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20658,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20658,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20658,], ["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,], @@ -330,51 +332,51 @@ 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",20644,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20644,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20644,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20644,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20644,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20644,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20644,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20644,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20644,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20644,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20644,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20644,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20644,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20644,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20658,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20658,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20658,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20658,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20658,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20658,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20658,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20658,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20658,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20658,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20658,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20658,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20658,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20658,], ["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,], ["libraries.designsystem.atomic.atoms_ElementLogoAtomLarge_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomLarge_Night_0_en",0,], ["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_EmojiItemWithPopup_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItemWithPopup_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",20644,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20644,], -["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.emoji.impl.picker_EmojiItemWithPopup_Day_0_en","libraries.emoji.impl.picker_EmojiItemWithPopup_Night_0_en",0,], +["libraries.emoji.impl.picker_EmojiItem_Day_0_en","libraries.emoji.impl.picker_EmojiItem_Night_0_en",0,], +["libraries.emoji.impl.picker_EmojiPickerView_Day_0_en","libraries.emoji.impl.picker_EmojiPickerView_Night_0_en",20661,], +["libraries.emoji.impl.picker_EmojiPickerView_Day_1_en","libraries.emoji.impl.picker_EmojiPickerView_Night_1_en",20661,], +["libraries.emoji.impl.picker_EmojiPickerView_Day_2_en","libraries.emoji.impl.picker_EmojiPickerView_Night_2_en",0,], +["libraries.emoji.impl.picker_EmojiPickerView_Day_3_en","libraries.emoji.impl.picker_EmojiPickerView_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",20644,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20644,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20644,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20644,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20644,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20644,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20644,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20644,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20644,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20644,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20644,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20644,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20644,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20644,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20644,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20644,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20644,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20644,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en",20658,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20658,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20658,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20658,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20658,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20658,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20658,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20658,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20658,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20658,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20658,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20658,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20658,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20658,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20658,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20658,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20658,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20658,], ["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,], @@ -394,52 +396,52 @@ 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",20644,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20644,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20644,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20658,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20658,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20658,], ["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",20644,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20644,], +["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20658,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20658,], ["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",20644,], +["features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_en","features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_1_en",20658,], ["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",20644,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20644,], -["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20644,], -["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20644,], -["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20644,], +["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20658,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20658,], +["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20658,], +["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20658,], +["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20658,], ["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",20644,], -["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20644,], +["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20658,], +["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20658,], ["features.home.impl_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20644,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20644,], +["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20658,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20658,], ["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",20644,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20644,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20644,], -["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20644,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20644,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20644,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20644,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20644,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20644,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20644,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20644,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20644,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20644,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20658,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20658,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20658,], +["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20658,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20658,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20658,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20658,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20658,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20658,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20658,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20658,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20658,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20658,], ["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",20644,], +["libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en","libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en",0,], ["libraries.designsystem.ruler_HorizontalRuler_Day_0_en","libraries.designsystem.ruler_HorizontalRuler_Night_0_en",0,], ["libraries.designsystem.theme.components_IconButton_Buttons_en","",0,], ["libraries.designsystem.theme.components_IconColorButton_Day_0_en","libraries.designsystem.theme.components_IconColorButton_Night_0_en",0,], @@ -451,8 +453,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",20644,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20644,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20658,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20658,], ["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,], @@ -460,117 +462,118 @@ 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",20644,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20658,], ["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",20644,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20658,], ["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",20644,], -["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20644,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20658,], +["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20658,], ["features.verifysession.impl.incoming_IncomingVerificationViewA11y_en","",0,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20644,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20644,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20644,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20644,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20644,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20644,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20644,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20644,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20644,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20644,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20644,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20644,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20644,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20644,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20658,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20658,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20658,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20658,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20658,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20658,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20658,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20658,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20658,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20658,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20658,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20658,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20658,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20658,], ["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",20644,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20644,], -["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20644,], +["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20658,], +["libraries.matrix.ui.media.contentvalidation_InvalidContentView_Day_0_en","libraries.matrix.ui.media.contentvalidation_InvalidContentView_Night_0_en",0,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20658,], +["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20658,], ["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",20644,], +["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20658,], ["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",20644,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20644,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20644,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20644,], +["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20658,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20658,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20658,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20658,], ["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",20644,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20644,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20644,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20644,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20644,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20644,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20644,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20644,], +["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20658,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20658,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20658,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20658,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20658,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20658,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20658,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20658,], ["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",20644,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20644,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20644,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20644,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20644,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20644,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20644,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20644,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20644,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20644,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20644,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20644,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20644,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20644,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20644,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20644,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20644,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20644,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20644,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20644,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20644,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20644,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20644,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20644,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20644,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20644,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20644,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20644,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20644,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20644,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20644,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20644,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20644,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20644,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20658,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20658,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20658,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20658,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20658,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20658,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20658,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20658,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20658,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20658,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20658,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20658,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20658,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20658,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20658,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20658,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20658,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20658,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20658,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20658,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20658,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20658,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20658,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20658,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20658,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20658,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20658,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20658,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20658,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20658,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20658,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20658,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20658,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20658,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], -["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20644,], -["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20644,], +["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20658,], +["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20658,], ["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",20644,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20644,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20644,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20644,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20644,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20644,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20644,], -["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20644,], -["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20644,], -["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20644,], -["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20644,], -["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20644,], -["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20644,], -["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20644,], -["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20644,], -["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20644,], -["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20644,], -["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20644,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20658,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20658,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20658,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20658,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20658,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20658,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20658,], +["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20658,], +["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20658,], +["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20658,], +["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20658,], +["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20658,], +["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20658,], +["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20658,], +["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20658,], +["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20658,], +["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20658,], +["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20658,], ["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",20644,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20644,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20644,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20644,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20644,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20644,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en",20658,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20658,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20658,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20658,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20658,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20658,], ["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",20644,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20658,], ["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,], @@ -623,50 +626,50 @@ 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",20644,], +["features.location.api_LiveLocationSharingBanner_Day_0_en","features.location.api_LiveLocationSharingBanner_Night_0_en",20658,], ["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",20644,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20658,], ["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",20644,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20644,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20644,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20658,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20658,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20658,], ["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",20644,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20644,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20644,], -["appnav.loggedin_LoggedInView_Day_4_en","appnav.loggedin_LoggedInView_Night_4_en",20647,], -["appnav.loggedin_LoggedInView_Day_5_en","appnav.loggedin_LoggedInView_Night_5_en",20647,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20644,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20644,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20644,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20644,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20644,], -["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20644,], -["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20644,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20644,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20644,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20644,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20644,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20644,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20644,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20644,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20644,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20644,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20644,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20644,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20644,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20644,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20644,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20644,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20644,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20644,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20658,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20658,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20658,], +["appnav.loggedin_LoggedInView_Day_4_en","appnav.loggedin_LoggedInView_Night_4_en",20658,], +["appnav.loggedin_LoggedInView_Day_5_en","appnav.loggedin_LoggedInView_Night_5_en",20658,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20658,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20658,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20658,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20658,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20658,], +["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20658,], +["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20658,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20658,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20658,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20658,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20658,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20658,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20658,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20658,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20658,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20658,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20658,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20658,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20658,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20658,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20658,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20658,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20658,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20658,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20644,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20644,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20644,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20644,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20658,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20658,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20658,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20658,], ["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,], @@ -675,33 +678,35 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomPositive_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomPositive_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_MatrixUserHeader_Day_2_en","libraries.matrix.ui.components_MatrixUserHeader_Night_2_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.matrix.ui.components_MatrixUserRow_Day_2_en","libraries.matrix.ui.components_MatrixUserRow_Night_2_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",20644,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20644,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20644,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20644,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20644,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20644,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_4_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_4_en",20644,], -["libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en",20644,], -["libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en",20644,], -["libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_2_en",20644,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20644,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20644,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20644,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20644,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20644,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20644,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20644,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20644,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20644,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20644,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20644,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20644,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20644,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20658,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20658,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20658,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20658,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20658,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20658,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_4_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_4_en",20658,], +["libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en",20658,], +["libraries.mediaviewer.impl.local.file_MediaFileView_Day_1_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_1_en",20658,], +["libraries.mediaviewer.impl.local.file_MediaFileView_Day_2_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_2_en",20658,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20658,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20658,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20658,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20658,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20658,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20658,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20658,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20658,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20658,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20658,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20658,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20658,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20658,], ["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,], @@ -709,10 +714,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","",20644,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20644,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20658,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20658,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20644,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20658,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en","",0,], @@ -722,20 +727,22 @@ 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","",20644,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_23_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_24_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",20658,], ["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","",20644,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en","",20644,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en","",20658,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en","",20658,], ["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","",20644,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20644,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20658,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20658,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20644,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20658,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_17_en","",0,], @@ -745,12 +752,14 @@ 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","",20644,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_23_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_24_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20658,], ["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","",20644,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_7_en","",20644,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_6_en","",20658,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_7_en","",20658,], ["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,], @@ -759,7 +768,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",20644,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20658,], ["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,], @@ -768,7 +777,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",20644,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20658,], ["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,], @@ -777,24 +786,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",20644,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20644,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20644,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20644,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20644,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20644,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20644,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20644,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20644,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20644,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20644,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20644,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20644,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20644,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20644,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20644,], +["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20658,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20658,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20658,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20658,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20658,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20658,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",20658,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20658,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20658,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20658,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20658,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20658,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20658,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20658,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20658,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20658,], ["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",20644,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20658,], ["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,], @@ -805,128 +814,129 @@ 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",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_14_en","features.preferences.impl.notifications_NotificationSettingsView_Night_14_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_15_en","features.preferences.impl.notifications_NotificationSettingsView_Night_15_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_16_en","features.preferences.impl.notifications_NotificationSettingsView_Night_16_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_17_en","features.preferences.impl.notifications_NotificationSettingsView_Night_17_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_18_en","features.preferences.impl.notifications_NotificationSettingsView_Night_18_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_19_en","features.preferences.impl.notifications_NotificationSettingsView_Night_19_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_20_en","features.preferences.impl.notifications_NotificationSettingsView_Night_20_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20644,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20644,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20644,], +["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20658,], +["libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Day_0_en","libraries.matrix.ui.media.contentvalidation_NotFoundContentView_Night_0_en",0,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_14_en","features.preferences.impl.notifications_NotificationSettingsView_Night_14_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_15_en","features.preferences.impl.notifications_NotificationSettingsView_Night_15_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_16_en","features.preferences.impl.notifications_NotificationSettingsView_Night_16_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_17_en","features.preferences.impl.notifications_NotificationSettingsView_Night_17_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_18_en","features.preferences.impl.notifications_NotificationSettingsView_Night_18_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_19_en","features.preferences.impl.notifications_NotificationSettingsView_Night_19_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_20_en","features.preferences.impl.notifications_NotificationSettingsView_Night_20_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20658,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20658,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20658,], ["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",20644,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20644,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20644,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20644,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20644,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20644,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20644,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20644,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20644,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20658,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20658,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20658,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20658,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20658,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20658,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20658,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20658,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20658,], ["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",20644,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20644,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20644,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20644,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20658,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20658,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20658,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20658,], ["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",20644,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20644,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20644,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20644,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20644,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20644,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20644,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20644,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20644,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20658,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20658,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20658,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20658,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20658,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20658,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20658,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20658,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20658,], ["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",20644,], -["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20644,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20644,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20644,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20644,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20644,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20658,], +["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20658,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20658,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20658,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20658,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20658,], ["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_PinUnlockViewCompact_0_en","",20644,], -["features.lockscreen.impl.unlock_PinUnlockViewCompact_1_en","",20644,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_10_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_10_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_10_en","features.lockscreen.impl.unlock_PinUnlockView_Night_10_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_8_en","features.lockscreen.impl.unlock_PinUnlockView_Night_8_en",20644,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_9_en","features.lockscreen.impl.unlock_PinUnlockView_Night_9_en",20644,], +["features.lockscreen.impl.unlock_PinUnlockViewCompact_0_en","",20658,], +["features.lockscreen.impl.unlock_PinUnlockViewCompact_1_en","",20658,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_10_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_10_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_10_en","features.lockscreen.impl.unlock_PinUnlockView_Night_10_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_8_en","features.lockscreen.impl.unlock_PinUnlockView_Night_8_en",20658,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_9_en","features.lockscreen.impl.unlock_PinUnlockView_Night_9_en",20658,], ["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",20644,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20644,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20644,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20644,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20644,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20644,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20644,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20644,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20644,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20644,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20644,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20644,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20644,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20644,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20658,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20658,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20658,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20658,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20658,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20658,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20658,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20658,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20658,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20658,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20658,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20658,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20658,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20658,], ["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",20644,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20644,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20644,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20644,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20644,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20658,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20658,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20658,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20658,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20658,], ["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",20644,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20644,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20644,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20644,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20644,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20644,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20644,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20644,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20644,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20644,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20644,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20658,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20658,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20658,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20658,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20658,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20658,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20658,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20658,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20658,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20658,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20658,], ["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,], @@ -940,229 +950,231 @@ 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","",20644,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20644,], -["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20644,], -["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20644,], -["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20644,], -["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20644,], -["features.preferences.impl.root_PreferencesRootViewDark_6_en","",20647,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20644,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20644,], -["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20644,], -["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20644,], -["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20644,], -["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20644,], -["features.preferences.impl.root_PreferencesRootViewLight_6_en","",20647,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20658,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20658,], +["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20658,], +["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20658,], +["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20658,], +["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20658,], +["features.preferences.impl.root_PreferencesRootViewDark_6_en","",20658,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20658,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20658,], +["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20658,], +["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20658,], +["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20658,], +["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20658,], +["features.preferences.impl.root_PreferencesRootViewLight_6_en","",20658,], ["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","",20644,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20644,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20658,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20658,], ["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",20644,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20644,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20644,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20644,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20644,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20644,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20644,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20644,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20644,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20644,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20644,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20644,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20644,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20644,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20644,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20644,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20644,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20644,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20644,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20644,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20644,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20644,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20644,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20644,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20644,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20644,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20644,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20658,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20658,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20658,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20658,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20658,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20658,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20658,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20658,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20658,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20658,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20658,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20658,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20658,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20658,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20658,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20658,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20658,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20658,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20658,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20658,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20658,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20658,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20658,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20658,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20658,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20658,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20658,], ["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",20644,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20644,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20658,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20658,], ["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",20644,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20644,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20644,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20644,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20644,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20644,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20644,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20644,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20644,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20644,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20644,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20644,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20644,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20644,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20644,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20644,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20644,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20644,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20644,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20644,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20644,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20658,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20658,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20658,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20658,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20658,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20658,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20658,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20658,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20658,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20658,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20658,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20658,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20658,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20658,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20658,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20658,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20658,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20658,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20658,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20658,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20658,], ["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",20644,], +["features.location.api_RenderingMapsNotSupportedDialog_Day_0_en","features.location.api_RenderingMapsNotSupportedDialog_Night_0_en",20658,], ["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",20644,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20644,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20644,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20644,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20644,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20644,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20644,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20644,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20644,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20644,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20644,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20644,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20644,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20644,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20644,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20644,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20644,], +["libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Day_0_en","libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Night_0_en",0,], +["libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Day_0_en","libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Night_0_en",0,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20658,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20658,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20658,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20658,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20658,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20658,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20658,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20658,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20658,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20658,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20658,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20658,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20658,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20658,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20658,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20658,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20658,], ["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",20644,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20644,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20644,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20644,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20644,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20644,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20644,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20644,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20644,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20644,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20644,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20644,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20644,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20658,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20658,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20658,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20658,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20658,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20658,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20658,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20658,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20658,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20658,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20658,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20658,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20658,], ["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",20644,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20644,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20658,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20658,], ["features.roomdetails.impl_RoomDetailsA11y_en","",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_20_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_21_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_22_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20644,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20644,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20644,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20644,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20644,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20644,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20644,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20644,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20644,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20644,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20644,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20644,], -["features.roomdetails.impl_RoomDetails_0_en","",20644,], -["features.roomdetails.impl_RoomDetails_10_en","",20644,], -["features.roomdetails.impl_RoomDetails_11_en","",20644,], -["features.roomdetails.impl_RoomDetails_12_en","",20644,], -["features.roomdetails.impl_RoomDetails_13_en","",20644,], -["features.roomdetails.impl_RoomDetails_14_en","",20644,], -["features.roomdetails.impl_RoomDetails_15_en","",20644,], -["features.roomdetails.impl_RoomDetails_16_en","",20644,], -["features.roomdetails.impl_RoomDetails_17_en","",20644,], -["features.roomdetails.impl_RoomDetails_18_en","",20644,], -["features.roomdetails.impl_RoomDetails_19_en","",20644,], -["features.roomdetails.impl_RoomDetails_1_en","",20644,], -["features.roomdetails.impl_RoomDetails_20_en","",20644,], -["features.roomdetails.impl_RoomDetails_21_en","",20644,], -["features.roomdetails.impl_RoomDetails_22_en","",20644,], -["features.roomdetails.impl_RoomDetails_2_en","",20644,], -["features.roomdetails.impl_RoomDetails_3_en","",20644,], -["features.roomdetails.impl_RoomDetails_4_en","",20644,], -["features.roomdetails.impl_RoomDetails_5_en","",20644,], -["features.roomdetails.impl_RoomDetails_6_en","",20644,], -["features.roomdetails.impl_RoomDetails_7_en","",20644,], -["features.roomdetails.impl_RoomDetails_8_en","",20644,], -["features.roomdetails.impl_RoomDetails_9_en","",20644,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20644,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20644,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20644,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20644,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20644,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20644,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20644,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20644,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20644,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_20_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_21_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_22_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20658,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20658,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20658,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20658,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20658,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20658,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20658,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20658,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20658,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20658,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20658,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20658,], +["features.roomdetails.impl_RoomDetails_0_en","",20658,], +["features.roomdetails.impl_RoomDetails_10_en","",20658,], +["features.roomdetails.impl_RoomDetails_11_en","",20658,], +["features.roomdetails.impl_RoomDetails_12_en","",20658,], +["features.roomdetails.impl_RoomDetails_13_en","",20658,], +["features.roomdetails.impl_RoomDetails_14_en","",20658,], +["features.roomdetails.impl_RoomDetails_15_en","",20658,], +["features.roomdetails.impl_RoomDetails_16_en","",20658,], +["features.roomdetails.impl_RoomDetails_17_en","",20658,], +["features.roomdetails.impl_RoomDetails_18_en","",20658,], +["features.roomdetails.impl_RoomDetails_19_en","",20658,], +["features.roomdetails.impl_RoomDetails_1_en","",20658,], +["features.roomdetails.impl_RoomDetails_20_en","",20658,], +["features.roomdetails.impl_RoomDetails_21_en","",20658,], +["features.roomdetails.impl_RoomDetails_22_en","",20658,], +["features.roomdetails.impl_RoomDetails_2_en","",20658,], +["features.roomdetails.impl_RoomDetails_3_en","",20658,], +["features.roomdetails.impl_RoomDetails_4_en","",20658,], +["features.roomdetails.impl_RoomDetails_5_en","",20658,], +["features.roomdetails.impl_RoomDetails_6_en","",20658,], +["features.roomdetails.impl_RoomDetails_7_en","",20658,], +["features.roomdetails.impl_RoomDetails_8_en","",20658,], +["features.roomdetails.impl_RoomDetails_9_en","",20658,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20658,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20658,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20658,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20658,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20658,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20658,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20658,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20658,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20658,], ["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",20644,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20644,], -["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20644,], -["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20644,], -["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20644,], -["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20644,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20644,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20644,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20644,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20644,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20644,], +["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20658,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20658,], +["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20658,], +["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20658,], +["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20658,], +["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20658,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20658,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20658,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20658,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20658,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20658,], ["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",20644,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20644,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20644,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20644,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20644,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20644,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20644,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20644,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20644,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20644,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20644,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20644,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20644,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20644,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20644,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20644,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20644,], +["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20658,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20658,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20658,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20658,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20658,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20658,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20658,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20658,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20658,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20658,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20658,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20658,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20658,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20658,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20658,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20658,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20658,], ["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",20644,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20644,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20644,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20644,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20644,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20644,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20644,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20644,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20658,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20658,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20658,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20658,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20658,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20658,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20658,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20658,], ["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",20644,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20644,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20644,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20644,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20644,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20644,], -["libraries.roomselect.impl_RoomSelectView_Day_6_en","libraries.roomselect.impl_RoomSelectView_Night_6_en",20644,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20658,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20658,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20658,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20658,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20658,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20658,], +["libraries.roomselect.impl_RoomSelectView_Day_6_en","libraries.roomselect.impl_RoomSelectView_Night_6_en",20658,], ["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,], @@ -1185,16 +1197,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",20644,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20644,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20644,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20644,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20644,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20644,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20644,], -["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20644,], +["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20658,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20658,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20658,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20658,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20658,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20658,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20658,], +["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20658,], ["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",20644,], +["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20658,], ["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,], @@ -1203,119 +1215,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",20644,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20658,], ["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",20644,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20644,], -["appicon.element_RoundIcon_en","",0,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20658,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20658,], ["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",20644,], -["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20644,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20644,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20644,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20644,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20644,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20644,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20644,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20658,], +["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20658,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20658,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20658,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20658,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20658,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20658,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20658,], ["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","",20644,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20658,], ["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","",20644,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20644,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20644,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20644,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20644,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20644,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20644,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20644,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20644,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20644,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20644,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20644,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20644,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20644,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20644,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20644,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20644,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20644,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20644,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20644,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20644,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20644,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20644,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20644,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20644,], -["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20644,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20658,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20658,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20658,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20658,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20658,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20658,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20658,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20658,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20658,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20658,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20658,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20658,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20658,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20658,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20658,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20658,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20658,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20658,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20658,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20658,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20658,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20658,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20658,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20658,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20658,], +["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20658,], ["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,], @@ -1338,39 +1350,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",20644,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20644,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20644,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20644,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20644,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20644,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20644,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20644,], -["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20644,], -["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20644,], -["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20644,], -["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20644,], -["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20644,], -["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20644,], -["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20644,], -["features.location.impl.share_ShareLocationView_Day_7_en","features.location.impl.share_ShareLocationView_Night_7_en",20644,], -["features.location.impl.share_ShareLocationView_Day_8_en","features.location.impl.share_ShareLocationView_Night_8_en",20644,], -["features.location.impl.share_ShareLocationView_Day_9_en","features.location.impl.share_ShareLocationView_Night_9_en",20644,], +["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20658,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20658,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20658,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20658,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20658,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20658,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20658,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20658,], +["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20658,], +["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20658,], +["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20658,], +["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20658,], +["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20658,], +["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20658,], +["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20658,], +["features.location.impl.share_ShareLocationView_Day_7_en","features.location.impl.share_ShareLocationView_Night_7_en",20658,], +["features.location.impl.share_ShareLocationView_Day_8_en","features.location.impl.share_ShareLocationView_Night_8_en",20658,], +["features.location.impl.share_ShareLocationView_Day_9_en","features.location.impl.share_ShareLocationView_Night_9_en",20658,], ["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",20644,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20644,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20644,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20644,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20644,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20644,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20644,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20644,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20644,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20644,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_1_en",20644,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20644,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20658,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20658,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20658,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20658,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20658,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20658,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20658,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20658,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20658,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20658,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_1_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_1_en",20658,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20658,], ["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,], @@ -1379,108 +1391,108 @@ export const screenshots = [ ["libraries.designsystem.components.list_SingleSelectionListItemSelectedInTrailingContent_Single_selection_List_item_-_selection_in_trailing_content_List_items_en","",0,], ["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,], -["features.messages.impl.timeline.components.customreaction.picker_SkinTonePicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_SkinTonePicker_Night_0_en",0,], +["libraries.emoji.impl.picker_SkinTonePicker_Day_0_en","libraries.emoji.impl.picker_SkinTonePicker_Night_0_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",20644,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20658,], ["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",20644,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20644,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20644,], -["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20644,], -["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20644,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20658,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20658,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20658,], +["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20658,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20658,], ["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",20644,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20644,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20644,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20644,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20644,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20644,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20644,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20644,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20644,], -["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20644,], -["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20644,], -["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20644,], -["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20644,], -["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20644,], -["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20644,], -["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20644,], -["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20644,], -["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20644,], -["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20644,], -["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20644,], -["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20644,], -["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20644,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20658,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20658,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20658,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20658,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20658,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20658,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20658,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20658,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20658,], +["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20658,], +["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20658,], +["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20658,], +["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20658,], +["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20658,], +["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20658,], +["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20658,], +["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20658,], +["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20658,], +["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20658,], +["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20658,], +["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20658,], +["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20658,], ["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",20644,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20644,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20644,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20644,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20644,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20644,], +["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20658,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20658,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20658,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20658,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20658,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20658,], ["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",20644,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20658,], ["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",20644,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20658,], ["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",20644,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20644,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20644,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20644,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20644,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20644,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20644,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20644,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20644,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20644,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20644,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20644,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20644,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20644,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20644,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20644,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20644,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20644,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20644,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20644,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20644,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20644,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20644,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20644,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20644,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20644,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20644,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20644,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20644,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20644,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20644,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20644,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20644,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20644,], -["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20644,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20644,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20644,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20644,], +["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20658,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20658,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20658,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20658,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20658,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20658,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20658,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20658,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20658,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20658,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20658,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20658,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20658,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20658,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20658,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20658,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20658,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20658,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20658,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20658,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20658,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20658,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20658,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20658,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20658,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20658,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20658,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20658,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20658,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20658,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20658,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20658,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20658,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20658,], +["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20658,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20658,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20658,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20658,], ["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",20644,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20644,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20658,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20658,], ["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,], @@ -1493,54 +1505,53 @@ 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",20644,], -["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20644,], +["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20658,], +["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20658,], ["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","",20644,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20644,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20644,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20658,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20658,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20658,], ["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",20644,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20644,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20658,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20658,], ["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,], -["features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemAttachmentsListView_Night_1_en",0,], +["features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Day_0_en","features.messages.impl.timeline.components_TimelineItemAttachmentsViewScanningContentFailed_Night_0_en",0,], +["features.messages.impl.timeline.components_TimelineItemAudioViewScanningContent_Day_0_en","features.messages.impl.timeline.components_TimelineItemAudioViewScanningContent_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_1_en",0,], ["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",20644,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20658,], ["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",20644,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20644,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20644,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20644,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20644,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20644,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20644,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20644,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20644,], -["features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20658,], +["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,], -["features.messages.impl.timeline.components_TimelineItemEventRowRtlContent_en","",20647,], +["features.messages.impl.timeline.components_TimelineItemEventRowRtlContent_en","",20658,], ["features.messages.impl.timeline.components_TimelineItemEventRowShield_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowShield_Night_0_en",0,], ["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",20644,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20644,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20658,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20658,], ["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",20644,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20644,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20658,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20658,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_2_en",0,], @@ -1550,34 +1561,34 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_6_en","features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_6_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_7_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithGallery_Night_8_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20644,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20658,], ["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",20644,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20644,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en",20644,], -["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",20644,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en",20644,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en",20647,], -["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",20644,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",20647,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20644,], -["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",20644,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en",20647,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20644,], -["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",20644,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20658,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20658,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en",20658,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en",20661,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en",20658,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_10_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_10_en",0,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_11_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_11_en",20658,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",20661,], +["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",20658,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20658,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en",20661,], +["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",20658,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20658,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",20661,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20658,], ["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","",20644,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20658,], +["features.messages.impl.timeline.components_TimelineItemFileViewScanningContent_Day_0_en","features.messages.impl.timeline.components_TimelineItemFileViewScanningContent_Night_0_en",0,], ["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_TimelineItemGalleryViewScanningContentFailed_Day_0_en","features.messages.impl.timeline.components_TimelineItemGalleryViewScanningContentFailed_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_2_en",0,], @@ -1588,30 +1599,31 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_7_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_8_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemGalleryView_Day_9_en","features.messages.impl.timeline.components.event_TimelineItemGalleryView_Night_9_en",0,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20644,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20644,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20644,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20658,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20658,], +["features.messages.impl.timeline.components_TimelineItemImageViewScanningContent_Day_0_en","features.messages.impl.timeline.components_TimelineItemImageViewScanningContent_Night_0_en",0,], ["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",20644,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20658,], ["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",20644,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20644,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20644,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20644,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20644,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20644,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20644,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20644,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20658,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20658,], ["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",20644,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20644,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20658,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20658,], ["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",20644,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20658,], ["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,], @@ -1620,10 +1632,16 @@ 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",20644,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20644,], +["features.messages.impl.timeline.components_TimelineItemRedactedMessagesGroup_Day_0_en","features.messages.impl.timeline.components_TimelineItemRedactedMessagesGroup_Night_0_en",0,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20658,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20658,], +["features.messages.impl.timeline.components_TimelineItemScanningContentFailed_Day_0_en","features.messages.impl.timeline.components_TimelineItemScanningContentFailed_Night_0_en",0,], +["features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Day_0_en","features.messages.impl.timeline.components_TimelineItemScanningContentNotFound_Night_0_en",0,], +["features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Day_0_en","features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Night_0_en",0,], +["features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Day_0_en","features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Night_0_en",0,], ["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_TimelineItemStickerViewScanningContent_Day_0_en","features.messages.impl.timeline.components_TimelineItemStickerViewScanningContent_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,], ["features.messages.impl.timeline.components.event_TimelineItemStickerView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemStickerView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemStickerView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemStickerView_Night_2_en",0,], @@ -1636,12 +1654,15 @@ 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",20644,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20644,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20658,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20658,], +["features.messages.impl.timeline.components_TimelineItemVideoViewScanningContent_Day_0_en","features.messages.impl.timeline.components_TimelineItemVideoViewScanningContent_Night_0_en",0,], ["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,], ["features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_3_en",0,], +["features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_4_en",0,], +["features.messages.impl.timeline.components_TimelineItemVoiceViewScanningContent_Day_0_en","features.messages.impl.timeline.components_TimelineItemVoiceViewScanningContent_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemVoiceViewUnified_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVoiceViewUnified_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemVoiceView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVoiceView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemVoiceView_Day_10_en","features.messages.impl.timeline.components.event_TimelineItemVoiceView_Night_10_en",0,], @@ -1659,94 +1680,94 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemVoiceView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemVoiceView_Night_8_en",0,], ["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",20644,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20658,], ["features.messages.impl.timeline_TimelineViewWithReadMarkerBothIndicators_Day_0_en","features.messages.impl.timeline_TimelineViewWithReadMarkerBothIndicators_Night_0_en",0,], ["features.messages.impl.timeline_TimelineViewWithReadMarkerJumpToUnreadIndicatorOnly_Day_0_en","features.messages.impl.timeline_TimelineViewWithReadMarkerJumpToUnreadIndicatorOnly_Night_0_en",0,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20644,], -["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20644,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20644,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20644,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20644,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20644,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20644,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20644,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20644,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20644,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20658,], +["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20658,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20658,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20658,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20658,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20658,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20658,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20658,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20658,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20658,], ["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",20644,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20658,], ["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",20644,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20658,], ["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",20644,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20644,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20644,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20644,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20644,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20644,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20644,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20644,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20658,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20658,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20658,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20658,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20658,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20658,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20658,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20658,], ["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",20644,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20644,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20644,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20644,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20644,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20644,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20658,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20658,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20658,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20658,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20658,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20658,], ["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","",20644,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20658,], ["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",20644,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20644,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20644,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20644,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20658,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20658,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20658,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20658,], ["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",20644,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20658,], ["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",20644,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20658,], ["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",20644,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20644,], -["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20644,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20644,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20644,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20644,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20644,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20644,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20644,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20644,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20644,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20644,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20644,], +["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",20658,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20658,], +["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20658,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20658,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20658,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20658,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20658,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20658,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20658,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20658,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20658,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20658,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20658,], ["features.preferences.impl.userstatus_UserStatusView_Day_0_en","features.preferences.impl.userstatus_UserStatusView_Night_0_en",0,], ["features.preferences.impl.userstatus_UserStatusView_Day_1_en","features.preferences.impl.userstatus_UserStatusView_Night_1_en",0,], ["features.preferences.impl.userstatus_UserStatusView_Day_2_en","features.preferences.impl.userstatus_UserStatusView_Night_2_en",0,], ["features.preferences.impl.userstatus_UserStatusView_Day_3_en","features.preferences.impl.userstatus_UserStatusView_Night_3_en",0,], ["features.preferences.impl.userstatus_UserStatusView_Day_4_en","features.preferences.impl.userstatus_UserStatusView_Night_4_en",0,], -["features.preferences.impl.userstatus_UserStatusView_Day_5_en","features.preferences.impl.userstatus_UserStatusView_Night_5_en",20647,], -["features.preferences.impl.userstatus_UserStatusView_Day_6_en","features.preferences.impl.userstatus_UserStatusView_Night_6_en",20647,], +["features.preferences.impl.userstatus_UserStatusView_Day_5_en","features.preferences.impl.userstatus_UserStatusView_Night_5_en",20658,], +["features.preferences.impl.userstatus_UserStatusView_Day_6_en","features.preferences.impl.userstatus_UserStatusView_Night_6_en",20658,], ["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",20644,], -["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20644,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20658,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20658,], ["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",20644,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20658,], ["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.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en.png index ae365f5143..5fe8e62f96 100644 --- a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:645349979f0789dd674b9efcaee305a35955725c5c4d24599984aefc3a61b18f -size 32005 +oid sha256:b2e211a700dfcefab1927926ecd2ab1eee2ceaed6980657e1bad1e70bbc69dd5 +size 29522 diff --git a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_3_en.png index 93d24c8613..d002a79378 100644 --- a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3cd12ed914f8c161ef845feaaec416eec9ef1ae6d23d71fb444c93d1388738ea -size 41736 +oid sha256:ab30267a07b1ceb43c1a7f854e758c68123812d99054f6e94db4cccf3214a2b4 +size 41479 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png index 3f99f935c9..aa9893db72 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccb0deee31506379cfa76f8d39d37639b6b1f03d7eb2e7d5e8c6ceff300b1978 -size 30397 +oid sha256:e88b079d9e8633d0c46aa18074f728fce8deb792451d3db982c2918ade3af474 +size 32505 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 index e8ae396119..664a1fac0f 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ddaf978cdf3e70b01fbee75e7e7290fa390e749b48ae192fe7da0dcaa9a1d4dc -size 38417 +oid sha256:1a3763a54a079f3f0724ab896b07b2cd29449d23a2c963f3fd4b5b9d3d92aa4b +size 42359 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png index bf0e1594e1..3b13f8bfa5 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:001bcd1755e837c0c05e493f964ee5c71fba81e811bdaf91effba257743bdacb -size 34836 +oid sha256:1fb1e95c7a6ef163c2ca4c07f11ca06e83b828f2e59873743fd76176441eef78 +size 36921 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 d79bfca142..e1d6b96687 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:69bcf19161f70c27256c1bf0e5b99c993c86dd3e77a42d0e87061730a5c0c752 -size 21649 +oid sha256:ae7f05084edddddacc2d996e73fe7a5a3a575e5b07558428a8adbbf8c3855132 +size 21619 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 index 213a75dce9..5d663d4072 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5198742a388a2bd04985fe6b9f035de3878125607fe3b554209b0eb5c4590db3 -size 19935 +oid sha256:d2bf5dfabb925d2e94a3f17337e72c502e4bfb2e228487f81b4d67d920247266 +size 19929 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png index 4185f46b51..5289eaca63 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:085963fcb425147d35a9ad947a7a3e4ba4712bd3d2f32e93099ff15cffe83b88 -size 64761 +oid sha256:65f9ee083a73669a0d3f9d88141a610ea53f3c39e89d8f706d414b04555b4764 +size 59321 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png index 0cf6c10c4e..bd73e322ab 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49f0bb16d3d57b59242e704e3dd4e8885c59721a42129837ff6a4f0d7d02de11 -size 54433 +oid sha256:12020ba97720f2374f9ace172693f08be01522e4ca30d3970efa91d802581e81 +size 3657 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 index 12bd190dd1..0ab00359b7 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce15ca9f89274620728715e3448ce671e2253f4fed22a44035460e9a3709ca0b -size 647404 +oid sha256:7b5e6f4c5ec97e67bb20f03f25f18d9f32d5d1aed5ff30d161b331894ad03443 +size 647384 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 86018764ac..195aa04fe2 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:8344427a0fe87cbf0883ff53a9ee4dcf90976a7011f6618d85961df48b2c53a9 -size 370228 +oid sha256:76e5ae44362792d570cd82f3910c8bd0acde509b8418c5892e0385e7d636f042 +size 370223 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 7ddac02717..73b7e674e2 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:a4ac79f3b8fb4e231244bd96b244a4f2526d6ed28d558f9d50734d83bbb74992 -size 363909 +oid sha256:991deacdfb7bc371a2df960a2364ae3b2187e588aa5afe7f39409e367040dd9c +size 363893 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 68f8148879..b5dac8434c 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:6ca8cf82aa8ab1bdad56a27584b27789402aeb7ad8fadd038280a376fb75a72c -size 345094 +oid sha256:1a92f8af94682facac66d4aacb6e49f345561c15be2f8b689041b78aeaaae831 +size 345062 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 133fd3903f..d7b969fd5b 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:426d1c844a8c88281c5fa4c61916d93278fdfd38f8cdf2dc54bf1a821f2de3eb -size 397167 +oid sha256:2528df873713755f542f61cd794080929586c1bd5f316c0378ce9e837c21d50b +size 397145 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 b10f9741b9..0021619c44 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:3ec1b0244dab22414c6719b3309426e13128d0c70fb67dc66cd8a60d42521fd0 -size 355411 +oid sha256:7b23d3a37774283067a8919b8c332b1bb5a79e90dceb7216b484b985491282e5 +size 355389 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 b6d1f07279..47a9a6b630 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:4bee12a6bdb18fea5ac6997671bfcb903296da7278cf69b2456330066ca31dfb -size 342870 +oid sha256:54372845e922d047408dd960d048b9b5eae2263d589117d8e7d197741aa34f32 +size 342827 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 0eb106f4a9..b51a89586b 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:217ac95bf476c53d2dc6d3d0143b21312bf38b8ab86c8dfd4f9360582b584f9d -size 395476 +oid sha256:e642229c58169775fe702769a306bbef22698516ae6f7ac75a761213c3f195fa +size 395446 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 c8306263a0..c9227ebf94 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:756f0cff90ddd61adce2f467c0384d74d430f6d51c091e4980e45bcc9ee6f0fd -size 353705 +oid sha256:e614f4a8657637c584a283d69124236d00fe1251c2b8d739c5688a57a6fd152e +size 353693 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 adabb6dde5..ee23a7111d 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:9b071ba6e99b68dcc75f5aaed3a879f2e30614c954b88c6dc05e1dfec57f1079 -size 65771 +oid sha256:38ae233a128e887efc48da73be3d6ce50a7095601315ed49a3c9cb209ffdda26 +size 58352 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 479d07ae5f..f6456f0ec1 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:0d4f03ac10bbb676d272dba906e758b25d633a1da1e249fe23ba825f8d2f4901 -size 55298 +oid sha256:22153168f6f3e84ab789faea29c94fffbc1a5e4c1b9a98deccb0460192fdde23 +size 57213 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 2209fcb54f..b3af9d831a 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:bd0de7412503e93c33cf92dde0cff38bb68555ef176080d913320af5e4942e7a -size 58642 +oid sha256:ce795c4e32a1be3d57f6b1c87588d8c7ed0442996ab9d8a96f1ec5a07627e598 +size 59663 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 b3109663f2..6e8468054f 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:10bce6df962a5198f019f509b1cdb55e28195587de4b74742ddc29833f1333a4 -size 69216 +oid sha256:262e8d4b8daa2d25593834fd0ab5d7019b0a3dd13707aa96e0701bf9240c6525 +size 59809 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 b0cd5bc6d4..3974618f39 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:5e900ff75d02c9db4200e2032444dd7e2f8635973cca3389dd96d7d2bb734061 -size 50757 +oid sha256:718d5c9f24c114f3bf88e000b637ea19598d7bb9b97001ba137fc12a6a1285e4 +size 52608 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 952751a962..7261c9b671 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:ed13a2778b8ced86ee41d5460d274b42b714a87f59749e3b26bf75114ef40dd9 -size 58265 +oid sha256:7cf3d727da78b39ecf24d4df7db0884af9008db67cc92274849c1b0978f87726 +size 59252 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png index a68f886f73..616c06bf46 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5a2e306087a967849f61872b56a83f194d1a76df5723f0bbae6e6e2f4a98c63 -size 55725 +oid sha256:0ce2519906f1aaf34700ca9ba4bdeaa72030f1f5aff3f7e24352a1435ac67d98 +size 53966 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png index f831ed92a2..0ca6f66438 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7fe1f51d385bba8821dfc0f0da84990cf0d148e991d765484b343d8764abd47d -size 11724 +oid sha256:5896eb5df6f5398bdb94e74280d0d5c04b6a5a53c2378b7377c60fa58eef544b +size 12013 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index 1e04c3e7d7..fb72cafe03 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bbc8c05e6f6818d00282228f52424ebe93e6e3dca3431d742e8c652d56460d6 -size 11712 +oid sha256:4ef1b643a16b5a94c75f8bb845c36d3cbc7f7ed96a0cac32fdb9f0b09d26b4d1 +size 11747 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png index 73b8b8e50c..5c597300e4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e8a3ad99763929d2783147814e44fa9ec7e7efb7b99949e3580f23c38fb5d971 -size 9398 +oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 +size 3853 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png index a87d89c701..d47bf90664 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f3a0cb5d9bae6725a1c527f3d9575aabf85d3edf63a28d9faa23f4f0b65e2d0 -size 7624 +oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c +size 3664 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png index ee5c582240..58546b8522 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75de341f705bb22955f9399180519b65ad59c2e1917317d56e50ea4db78f35bc -size 12102 +oid sha256:30357bf18792db5ab20085010251170a724ffe8c00313facd04ee704e806af64 +size 10982 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png index fedead0fa8..52fd9b9693 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4811667dec0f32accc5e2c8a5dd5c0b34017fcff8d1e0376ee7a4708426bca0f -size 9838 +oid sha256:58b9491aaa5554b89d86c62a5c9c44975367538c6baa5562f8dc5768f76d8264 +size 8705 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png index 38ad0e4b56..83302d6ba4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:326d59cf768b2dbd96eb7964d54c8eda509a5cd57c6e62087625e3314da0bb4d -size 13658 +oid sha256:16dee1dfe746cd40dac9fe8f0af3ecb42cd14bab5cc490917b589beed065ed1b +size 14686 From 91ec8185224c9af2f21d11c8664feb45fbf2b277 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Jul 2026 09:23:13 +0200 Subject: [PATCH 199/383] Update dependency org.jetbrains.kotlinx:kover-gradle-plugin to v0.9.9 (#7273) * Update dependency org.jetbrains.kotlinx:kover-gradle-plugin to v0.9.9 --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: ElementBot --- gradle/libs.versions.toml | 2 +- ...es.preferences.impl.userstatus_UserStatusView_Day_6_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_5_en.png | 4 ++-- ...eme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png | 4 ++-- ...em.theme.components_HorizontalFloatingToolbar_Day_0_en.png | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d1c22fa7a4..6a9019bc74 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -66,7 +66,7 @@ detekt_compose_rules = "0.4.28" # See https://github.com/pinterest/ktlint/releases/ ktlint = "1.8.0" androidx-test-ext-junit = "1.3.0" -kover = "0.9.8" +kover = "0.9.9" [libraries] # Project diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png index f831ed92a2..0ca6f66438 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7fe1f51d385bba8821dfc0f0da84990cf0d148e991d765484b343d8764abd47d -size 11724 +oid sha256:5896eb5df6f5398bdb94e74280d0d5c04b6a5a53c2378b7377c60fa58eef544b +size 12013 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index 1e04c3e7d7..fb72cafe03 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bbc8c05e6f6818d00282228f52424ebe93e6e3dca3431d742e8c652d56460d6 -size 11712 +oid sha256:4ef1b643a16b5a94c75f8bb845c36d3cbc7f7ed96a0cac32fdb9f0b09d26b4d1 +size 11747 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png index ee5c582240..58546b8522 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75de341f705bb22955f9399180519b65ad59c2e1917317d56e50ea4db78f35bc -size 12102 +oid sha256:30357bf18792db5ab20085010251170a724ffe8c00313facd04ee704e806af64 +size 10982 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png index 38ad0e4b56..83302d6ba4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:326d59cf768b2dbd96eb7964d54c8eda509a5cd57c6e62087625e3314da0bb4d -size 13658 +oid sha256:16dee1dfe746cd40dac9fe8f0af3ecb42cd14bab5cc490917b589beed065ed1b +size 14686 From 4d9bbd67c3edac04dc94d512bcedfef56b1b2172 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Jul 2026 10:56:07 +0200 Subject: [PATCH 200/383] Update actions/setup-python action to v7 (#7278) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/generate_github_pages.yml | 2 +- .github/workflows/quality.yml | 4 ++-- .github/workflows/sync-localazy.yml | 2 +- .github/workflows/sync-sas-strings.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/generate_github_pages.yml b/.github/workflows/generate_github_pages.yml index 4f60639780..45e886f904 100644 --- a/.github/workflows/generate_github_pages.yml +++ b/.github/workflows/generate_github_pages.yml @@ -28,7 +28,7 @@ jobs: with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Set up Python 3.12 - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: 3.14 - name: Run World screenshots generation script diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index b0c78a9ee8..73836c472f 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -55,7 +55,7 @@ jobs: with: persist-credentials: false - name: Set up Python 3.12 - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: 3.14 - name: Search for invalid screenshot files @@ -78,7 +78,7 @@ jobs: with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Set up Python 3.12 - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: 3.14 - name: Search for invalid dependencies diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml index 3f72d69433..6ab2dd3ac3 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -26,7 +26,7 @@ jobs: with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - name: Set up Python 3.12 - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: 3.14 - name: Setup Localazy diff --git a/.github/workflows/sync-sas-strings.yml b/.github/workflows/sync-sas-strings.yml index f84b1596cb..3811b41f88 100644 --- a/.github/workflows/sync-sas-strings.yml +++ b/.github/workflows/sync-sas-strings.yml @@ -18,7 +18,7 @@ jobs: with: persist-credentials: false - name: Set up Python 3.12 - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: 3.14 - name: Install Prerequisite dependencies From 0e3d4794909631d25a7dfef963bf5c03cd8beaf9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Jul 2026 10:56:30 +0200 Subject: [PATCH 201/383] Update roborazzi to v1.70.0 (#7274) 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 6a9019bc74..e92757182f 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.68.0" +roborazzi = "1.70.0" # Jetbrain datetime = "0.8.0" From bbb83c2ff02e9d990b75fe248aec0d272869cce9 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 27 Jul 2026 15:12:53 +0200 Subject: [PATCH 202/383] Localazy: improve search, parallelize checks (#7261) * Remove no longer temporary string These are now in localazy and the sync strings CI flow was failing because we have 2 conflicting values in `temporary.xml` and `localazy.xml` * Use the right placeholder value in `screen_local_network_opt_in_subtitle` * Localazy: improve search, parallelize checks The search for XML files has been narrowed down and it's several times faster now, and processing the files is now done in parallel * Improve script to also find and delete previous files Also add the option of having a `-v|--verbose` flag to print which files we're modifying * Use `LocalBuildMeta` to get the app name inside `LocalNetworkPermissionDialogView` * Allow finding all the forbidden terms in the strings and translations and then return an error exit code instead of a success one --------- Co-authored-by: ElementBot --- .../android/appnav/loggedin/LoggedInView.kt | 1 - .../impl/changeserver/ChangeServerView.kt | 1 - .../ChooseAccountProviderView.kt | 2 - .../loginwithclassic/LoginWithClassicView.kt | 2 - .../ConfirmAccountProviderView.kt | 2 - .../impl/screens/onboarding/OnBoardingView.kt | 1 - .../LocalNetworkPermissionDialogView.kt | 4 +- .../appnav.loggedin_LoggedInView_Day_4_en.png | 4 +- .../appnav.loggedin_LoggedInView_Day_5_en.png | 4 +- ...ppnav.loggedin_LoggedInView_Night_4_en.png | 4 +- ...ppnav.loggedin_LoggedInView_Night_5_en.png | 4 +- tools/localazy/checkForbiddenTerms.py | 5 + tools/localazy/downloadStrings.sh | 106 ++++++++++++++++-- 13 files changed, 110 insertions(+), 30 deletions(-) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt index 3bbd640c78..e57d378da4 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInView.kt @@ -85,7 +85,6 @@ fun LoggedInView( } LocalNetworkPermissionDialogView( - appName = state.appName, dialog = state.localNetworkPermissionDialog, onSubmit = { state.eventSink(LoggedInEvents.RequestLocationNetworkPermission) }, onDismiss = { state.eventSink(LoggedInEvents.DismissLocalNetworkPermissionPrompt) }, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt index 39c167cd13..30ae644a70 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerView.kt @@ -123,7 +123,6 @@ fun ChangeServerView( AsyncData.Uninitialized -> Unit } LocalNetworkPermissionDialogView( - appName = LocalBuildMeta.current.applicationName, dialog = state.localNetworkPermissionDialog, onSubmit = { eventSink.invoke(ChangeServerEvents.RequestLocalNetworkPermission) 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 3eb31689ff..17e7d10efb 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 @@ -41,7 +41,6 @@ import io.element.android.libraries.designsystem.components.BigIcon 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.LocalBuildMeta 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 @@ -139,7 +138,6 @@ fun ChooseAccountProviderView( } } LocalNetworkPermissionDialogView( - appName = LocalBuildMeta.current.applicationName, dialog = state.loginModeState.localNetworkPermissionDialog, onSubmit = { state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission) 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 02e16fca95..75181a068e 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 @@ -47,7 +47,6 @@ 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.LocalBuildMeta 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 @@ -208,7 +207,6 @@ fun LoginWithClassicView( onCreateAccountContinue = onCreateAccountContinue, ) LocalNetworkPermissionDialogView( - appName = LocalBuildMeta.current.applicationName, dialog = state.loginModeState.localNetworkPermissionDialog, onSubmit = { state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission) 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 a84a046e2a..95fbff25ab 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 @@ -29,7 +29,6 @@ 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.LocalBuildMeta 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.OAuthDetails @@ -113,7 +112,6 @@ fun ConfirmAccountProviderView( } LocalNetworkPermissionDialogView( - appName = LocalBuildMeta.current.applicationName, dialog = state.loginModeState.localNetworkPermissionDialog, onSubmit = { state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission) 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 6b3ab4043a..bf96b2dbe0 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 @@ -87,7 +87,6 @@ fun OnBoardingView( onCreateAccountContinue = onCreateAccountContinue, ) LocalNetworkPermissionDialogView( - appName = state.productionApplicationName, dialog = state.loginModeState.localNetworkPermissionDialog, onSubmit = { state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission) diff --git a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialogView.kt b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialogView.kt index 2fddff16b1..66616c197e 100644 --- a/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialogView.kt +++ b/libraries/permissions/api/src/main/kotlin/io/element/android/libraries/permissions/api/localnetwork/LocalNetworkPermissionDialogView.kt @@ -11,11 +11,11 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog +import io.element.android.libraries.designsystem.theme.LocalBuildMeta import io.element.android.libraries.ui.strings.CommonStrings @Composable fun LocalNetworkPermissionDialogView( - appName: String, dialog: LocalNetworkPermissionDialog, onSubmit: () -> Unit, onDismiss: () -> Unit, @@ -28,7 +28,7 @@ fun LocalNetworkPermissionDialogView( } ConfirmationDialog( title = stringResource(CommonStrings.screen_local_network_opt_in_title), - content = stringResource(CommonStrings.screen_local_network_opt_in_subtitle, appName), + content = stringResource(CommonStrings.screen_local_network_opt_in_subtitle, LocalBuildMeta.current.applicationName), submitText = stringResource(submitTextRes), cancelText = stringResource(CommonStrings.action_not_now), onSubmitClick = onSubmit, diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png index e0bfa036e8..5adfe35003 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cdab8410501666e33f7d810376640b732e4b36255797dbf4ef09c79d896c2b3f -size 33825 +oid sha256:965cd4692e88a413e5e0a83e16a190386e8f199716fdd7288f4e05b8c623a8b2 +size 33756 diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png index eacf92c3c1..bf9aed6830 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8100f2bdc31632af9b5894e45fa1d8b47ca992cdf7564d442ac649edb1ba8e5b -size 33022 +oid sha256:771c01d4563687aff208b0f279c9fb98192b0cd2b2ba56d43627f6c785e92b90 +size 32956 diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png index ab8ff08c43..75fdd8172d 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ebce406b2ee9354e25caee308786c7424c159cc8276f92d8d6474d07d7036cb -size 31882 +oid sha256:8f2d01f11bcca2ba3465b6308f7368797c6fd9712bf90f4e9493b30dbece8277 +size 31907 diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png index f3cdb4ff7d..28fd0cfc21 100644 --- a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e1c49dbd3cb5b4cd78d1b65a7b159d368e4a0c2734d24c7429c1f5362cf7bae9 -size 31148 +oid sha256:484173d52fcb0acff42f62d28f88cd544e205bde49370ccc8230c30b193e1959 +size 31173 diff --git a/tools/localazy/checkForbiddenTerms.py b/tools/localazy/checkForbiddenTerms.py index 123246ffd0..48bf7030b8 100755 --- a/tools/localazy/checkForbiddenTerms.py +++ b/tools/localazy/checkForbiddenTerms.py @@ -34,6 +34,11 @@ forbiddenTerms = { # Contains "Element Classic" "screen_missing_key_backup_open_element_classic", "screen_missing_key_backup_step_1", + # These are notification sound names + "screen_notification_settings_sound_element_default", + "screen_notification_settings_sound_element_fade", + # This contains the word 'element' in some languages + "screen_media_upload_preview_item_count", ] } diff --git a/tools/localazy/downloadStrings.sh b/tools/localazy/downloadStrings.sh index 5a60656f35..5560aa002d 100755 --- a/tools/localazy/downloadStrings.sh +++ b/tools/localazy/downloadStrings.sh @@ -8,23 +8,51 @@ set -e -if [[ $1 == "--all" ]]; then +allFiles=0 + +while [[ $# -gt 0 ]]; do + case $1 in + -a|--all) + allFiles=1 + shift + ;; + -v|--verbose) + verbose=1 + shift + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done + +if [[ $allFiles == 1 ]]; then echo "Note: I will update all the files." - allFiles=1 else echo "Note: I will update only the English files." - allFiles=0 fi echo "Generating the configuration file for localazy..." python3 ./tools/localazy/generateLocalazyConfig.py $allFiles +# Search for existing string files first so we can remove them +localazyXmlFiles=$(find . \ + -type d \( -name build -o -name .git \) -prune -o \ + -type f -path '*/src/*/res/values/localazy.xml' -print | sort) + +if [[ $allFiles == 1 ]]; then + translationXmlFiles=$(find . \ + -type d \( -name build -o -name .git \) -prune -o \ + -type f -path '*/src/*/res/values-*/translations.xml' -print | sort) +fi + echo "Deleting all existing localazy.xml files..." -find . -name 'localazy.xml' -delete +echo "$localazyXmlFiles" | xargs -L1 -P0 rm if [[ $allFiles == 1 ]]; then echo "Deleting all existing translations.xml files..." - find . -name 'translations.xml' -delete + echo "$translationXmlFiles" | xargs -L1 -P0 rm fi echo "Importing the strings..." @@ -33,16 +61,72 @@ localazy download --config ./tools/localazy/localazy.json echo "Removing the generated config" rm ./tools/localazy/localazy.json -echo "Formatting the resources files..." -find . -name 'localazy.xml' -exec ./tools/localazy/formatXmlResourcesFile.py {} \; +# Now list the newly generated files so we can format them and check for forbidden terms +localazyXmlFiles=$(find . \ + -type d \( -name build -o -name .git \) -prune -o \ + -type f -path '*/src/*/res/values/localazy.xml' -print | sort) + if [[ $allFiles == 1 ]]; then - find . -name 'translations.xml' -exec ./tools/localazy/formatXmlResourcesFile.py {} \; + translationXmlFiles=$(find . \ + -type d \( -name build -o -name .git \) -prune -o \ + -type f -path '*/src/*/res/values-*/translations.xml' -print | sort) fi -echo "Checking forbidden terms..." -find . -name 'localazy.xml' -exec ./tools/localazy/checkForbiddenTerms.py {} \; +formatXmlFiles() { + local xml="$1" + if [[ $verbose == 1 ]]; then + echo "Formatting $xml" + fi + ./tools/localazy/formatXmlResourcesFile.py "$xml" +} + +checkForbiddenTerms() { + set +e + local xml="$1" + if [[ $verbose == 1 ]]; then + echo "Checking forbidden terms in $xml" + fi + ./tools/localazy/checkForbiddenTerms.py "$xml" + + # If the script finds a forbidden term, it will exit with a non-zero status code and interrupt the execution, but we don't want that. + # Instead we want to capture that exit code and write it to a global variable so we can check later if any forbidden terms were found. + status=$? + if [[ $status != 0 ]]; then + forbiddenTermsResult=$((forbiddenTermsResult || status)) + fi +} + +export -f formatXmlFiles +export -f checkForbiddenTerms + +echo "Formatting the resources files..." + +echo "Formatting original localazy.xml files..." +# Format the original localazy.xml files in parallel +echo "$localazyXmlFiles" | xargs -L1 -P0 bash -c 'formatXmlFiles "$@"' _ + if [[ $allFiles == 1 ]]; then - find . -name 'translations.xml' -exec ./tools/localazy/checkForbiddenTerms.py {} \; + if [[ $verbose == 1 ]]; then + echo "Formatting translation files..." + fi + + echo "$translationXmlFiles" | xargs -L1 -P0 bash -c 'formatXmlFiles "$@"' _ +fi + +# This stores whether any forbidden terms were found in any of the files. If any forbidden terms are found, this will be set to a non-zero value. +export forbiddenTermsResult=0 + +echo "Checking forbidden terms..." +echo "$localazyXmlFiles" | xargs -L1 -P0 bash -c 'checkForbiddenTerms "$@"' _ + +if [[ $allFiles == 1 ]]; then + echo "Checking forbidden terms in translation files..." + echo "$translationXmlFiles" | xargs -L1 -P0 bash -c 'checkForbiddenTerms "$@"' _ +fi + +if [[ $forbiddenTermsResult != 0 ]]; then + echo "Error: Forbidden terms found in the resources files. Please check the output above." + exit 1 fi echo "Success!" From d8b01cf3e7a4b3c5d70a6194e0e23121c0d823fe Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 27 Jul 2026 18:15:33 +0200 Subject: [PATCH 203/383] Fix `ContentErrorView` not calculating its text size synchronously (#7281) It was using a `LaunchedEffect` instead of relying on the `Text(onTextLayout)` parameter. --- .../contentvalidation/ContentErrorView.kt | 43 +++---------------- 1 file changed, 6 insertions(+), 37 deletions(-) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentErrorView.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentErrorView.kt index 85753246d3..24f4a15200 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentErrorView.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentErrorView.kt @@ -9,26 +9,17 @@ package io.element.android.libraries.matrix.ui.media.contentvalidation import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues 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.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.movableContentOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.TextLayoutResult -import androidx.compose.ui.text.rememberTextMeasurer -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 @@ -41,7 +32,6 @@ internal fun ContentErrorView( contentPadding: PaddingValues = PaddingValues.Zero, onTextLayout: ((TextLayoutResult) -> Unit)? = null, ) { - val updatedOnTextLayout by rememberUpdatedState(onTextLayout) Row( modifier = modifier .background(color = ElementTheme.colors.bgCriticalSubtle) @@ -61,33 +51,12 @@ internal fun ContentErrorView( color = ElementTheme.colors.textCriticalPrimary, style = ElementTheme.typography.fontBodyMdMedium, ) - val textMeasurer = rememberTextMeasurer() - val textContent = remember(message) { - movableContentOf( - @Composable { - Text( - text = message, - color = ElementTheme.colors.textSecondary, - style = ElementTheme.typography.fontBodySmRegular, - ) - } - ) - } - - // BoxWithConstraints is needed to be able to calculate the text layout in the current constraints, so we can pass it to the onTextLayout callback. - // However, this can't be used inside a SubComposeLayout (like the one in the text composer), so we only use it when the onTextLayout callback - // is provided. - if (updatedOnTextLayout != null) { - BoxWithConstraints(modifier = Modifier.fillMaxWidth()) { - LaunchedEffect(message) { - updatedOnTextLayout?.invoke(textMeasurer.measure(message, overflow = TextOverflow.Visible, constraints = constraints)) - } - - textContent() - } - } else { - textContent() - } + Text( + text = message, + color = ElementTheme.colors.textSecondary, + style = ElementTheme.typography.fontBodySmRegular, + onTextLayout = onTextLayout, + ) } } } From 0442fbd307e499561196cc707fd36d57c92637da Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 27 Jul 2026 18:16:35 +0200 Subject: [PATCH 204/383] Fix media viewer for medias not related to events displaying invalid state (#7280) * When no URL is provided to `ContentValidationState.collectMediaState`, assume it's valid That way we can do: `if (validationState.isValid() && state.collectMediaState(possiblyNullUrl).isValid()) ...` * Remove the `eventId` param from `ContentScannerService.scan` It's not really used, since we then provide a state that can be mutated, and fetching that is what the previous parameter was used for * Make sure to always validate the medias in the viewer, both the actual media and the thumbnail * Update screenshots --------- Co-authored-by: ElementBot --- .../api/ContentScannerService.kt | 5 +-- .../impl/DefaultContentScannerService.kt | 3 +- .../di/AlwaysValidContentScannerService.kt | 3 +- .../impl/DefaultContentScannerServiceTest.kt | 9 ----- .../MessageComposerPresenter.kt | 2 +- .../impl/timeline/TimelinePresenter.kt | 2 +- .../protection/TimelineProtectionEvent.kt | 1 - .../protection/TimelineProtectionPresenter.kt | 2 +- ...essageComposerPresenterSlashCommandTest.kt | 2 +- .../MessageComposerPresenterTest.kt | 2 +- .../TimelineProtectionPresenterTest.kt | 6 +-- .../ContentValidationState.kt | 2 +- .../impl/gallery/MediaGalleryPresenter.kt | 9 ++--- .../impl/viewer/MediaViewerDataSource.kt | 9 ++--- .../impl/viewer/MediaViewerEvent.kt | 2 +- .../impl/viewer/MediaViewerPresenter.kt | 2 +- .../impl/viewer/MediaViewerView.kt | 38 ++++++++++-------- .../impl/DefaultMediaViewerEntryPointTest.kt | 4 +- .../impl/gallery/MediaGalleryPresenterTest.kt | 2 +- .../impl/viewer/MediaViewerDataSourceTest.kt | 2 +- .../impl/viewer/MediaViewerPresenterTest.kt | 2 +- .../impl/viewer/MediaViewerViewTest.kt | 40 +++++++++++++++++++ ....viewer_MediaViewerViewLandscape_23_en.png | 4 +- ...ewer.impl.viewer_MediaViewerView_23_en.png | 4 +- 24 files changed, 92 insertions(+), 65 deletions(-) diff --git a/features/contentscanner/api/src/main/kotlin/io/element/android/features/contentscanner/api/ContentScannerService.kt b/features/contentscanner/api/src/main/kotlin/io/element/android/features/contentscanner/api/ContentScannerService.kt index cc5fca38a0..68f7af28f1 100644 --- a/features/contentscanner/api/src/main/kotlin/io/element/android/features/contentscanner/api/ContentScannerService.kt +++ b/features/contentscanner/api/src/main/kotlin/io/element/android/features/contentscanner/api/ContentScannerService.kt @@ -7,17 +7,16 @@ package io.element.android.features.contentscanner.api -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.scanner.ContentScanner import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState /** - * Service to perform security scans in the contents for a given event and media source. + * Service to perform security scans in the contents for a given media source. * * The default implementation (FOSS) always returns a valid state. * This will only process media when a [ContentScanner] is provided when building the client in Pro. */ fun interface ContentScannerService { - fun scan(eventId: EventId, mediaSources: List, contentValidationState: ContentValidationState) + fun scan(mediaSources: List, contentValidationState: ContentValidationState) } diff --git a/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.kt b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.kt index c809179552..8b75a79d2c 100644 --- a/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.kt +++ b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerService.kt @@ -9,7 +9,6 @@ package io.element.android.features.contentscanner.impl import io.element.android.features.contentscanner.api.ContentScannerService import io.element.android.libraries.core.coroutine.CoroutineDispatchers -import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.exception.ClientException import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.scanner.ContentScanner @@ -29,7 +28,7 @@ class DefaultContentScannerService( ) : ContentScannerService { private val dispatcher = coroutineDispatchers.io.limitedParallelism(4) - override fun scan(eventId: EventId, mediaSources: List, contentValidationState: ContentValidationState) { + override fun scan(mediaSources: List, contentValidationState: ContentValidationState) { for (mediaSource in mediaSources) { val url = mediaSource.safeUrl val currentState = contentValidationState.getCurrentMediaState(url) diff --git a/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/di/AlwaysValidContentScannerService.kt b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/di/AlwaysValidContentScannerService.kt index 6170f3e153..cd96433ce4 100644 --- a/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/di/AlwaysValidContentScannerService.kt +++ b/features/contentscanner/impl/src/main/kotlin/io/element/android/features/contentscanner/impl/di/AlwaysValidContentScannerService.kt @@ -8,7 +8,6 @@ package io.element.android.features.contentscanner.impl.di import io.element.android.features.contentscanner.api.ContentScannerService -import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationState import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue @@ -19,7 +18,7 @@ import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentVal * This is used when the content scanner feature is not enabled or available. */ class AlwaysValidContentScannerService : ContentScannerService { - override fun scan(eventId: EventId, mediaSources: List, contentValidationState: ContentValidationState) { + override fun scan(mediaSources: List, contentValidationState: ContentValidationState) { // Always return success for the noop implementation for (mediaSource in mediaSources) { val url = mediaSource.safeUrl diff --git a/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerServiceTest.kt b/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerServiceTest.kt index 4bd20ebaf8..ecfdd9715d 100644 --- a/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerServiceTest.kt +++ b/features/contentscanner/impl/src/test/kotlin/io/element/android/features/contentscanner/impl/DefaultContentScannerServiceTest.kt @@ -11,7 +11,6 @@ import com.google.common.truth.Truth.assertThat import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.scanner.ContentScanner -import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.media.aMediaSource import io.element.android.libraries.matrix.test.scanner.FakeContentScanner import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue @@ -39,7 +38,6 @@ class DefaultContentScannerServiceTest { createDefaultContentScannerService( contentScanner = scanner, ).scan( - eventId = AN_EVENT_ID, mediaSources = emptyList(), contentValidationState = contentValidationState, ) @@ -58,7 +56,6 @@ class DefaultContentScannerServiceTest { createDefaultContentScannerService( contentScanner = scanner, ).scan( - eventId = AN_EVENT_ID, mediaSources = listOf(mediaSource), contentValidationState = contentValidationState, ) @@ -87,7 +84,6 @@ class DefaultContentScannerServiceTest { createDefaultContentScannerService( contentScanner = scanner, ).scan( - eventId = AN_EVENT_ID, mediaSources = listOf(mediaSourceA, mediaSourceB), contentValidationState = contentValidationState, ) @@ -113,14 +109,12 @@ class DefaultContentScannerServiceTest { // First scan attempt service.scan( - eventId = AN_EVENT_ID, mediaSources = listOf(mediaSource), contentValidationState = contentValidationState, ) // Immediately after, a new scan attempt is made for the same media source service.scan( - eventId = AN_EVENT_ID, mediaSources = listOf(mediaSource), contentValidationState = contentValidationState, ) @@ -144,7 +138,6 @@ class DefaultContentScannerServiceTest { ) service.scan( - eventId = AN_EVENT_ID, mediaSources = listOf(mediaSource), contentValidationState = contentValidationState, ) @@ -166,7 +159,6 @@ class DefaultContentScannerServiceTest { ) service.scan( - eventId = AN_EVENT_ID, mediaSources = listOf(mediaSource), contentValidationState = contentValidationState, ) @@ -191,7 +183,6 @@ class DefaultContentScannerServiceTest { ) service.scan( - eventId = AN_EVENT_ID, mediaSources = listOf(mediaSource), contentValidationState = contentValidationState, ) 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 80dd21b7b3..18252ee17d 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 @@ -858,7 +858,7 @@ class MessageComposerPresenter( if (currentComposerMode is MessageComposerMode.Reply) { val mediaSources = currentComposerMode.replyToDetails.content()?.mediaSources() ?: return@launch val contentValidationState = contentValidationCache[currentComposerMode.replyToDetails.eventId()] - contentScannerService.scan(currentComposerMode.replyToDetails.eventId(), mediaSources, contentValidationState) + contentScannerService.scan(mediaSources, contentValidationState) } // When coming from edit, just clear the composer as it'd be weird to reset a volatile draft in this scenario. if (currentComposerMode.isEditing) { 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 9a33299cd0..7cd0d018d2 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 @@ -259,7 +259,7 @@ class TimelinePresenter( ) } is TimelineEvent.ValidateMedia -> { - timelineProtectionState.eventSink(TimelineProtectionEvent.ValidateContent(event.eventId, event.mediaSources, event.validationState)) + timelineProtectionState.eventSink(TimelineProtectionEvent.ValidateContent(event.mediaSources, event.validationState)) } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionEvent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionEvent.kt index 75a676cdb7..72c5eb7a30 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionEvent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionEvent.kt @@ -15,7 +15,6 @@ import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentVal sealed interface TimelineProtectionEvent { data class ShowContent(val eventId: EventId?) : TimelineProtectionEvent data class ValidateContent( - val eventId: EventId, val mediaSources: List, val validationState: ContentValidationState, ) : TimelineProtectionEvent diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenter.kt index dc70b63f32..22be4acb2d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenter.kt @@ -59,7 +59,7 @@ class TimelineProtectionPresenter( allowedEvents += setOfNotNull(event.eventId) } is TimelineProtectionEvent.ValidateContent -> { - contentScannerService.scan(event.eventId, event.mediaSources, event.validationState) + contentScannerService.scan(event.mediaSources, event.validationState) } } } 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 0ac8c3be1f..faf0bbe6ed 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 @@ -316,7 +316,7 @@ class MessageComposerPresenterSlashCommandTest { notificationConversationService = notificationConversationService, slashCommandService = slashCommandService, featureFlagService = featureFlagService, - contentScannerService = { _, _, _ -> }, + contentScannerService = { _, _ -> }, contentValidationCache = InMemoryEventContentValidationCache(), ).apply { isTesting = true 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 c164a30160..fda8621087 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 @@ -1650,7 +1650,7 @@ class MessageComposerPresenterTest : RobolectricTest() { notificationConversationService = notificationConversationService, slashCommandService = slashCommandService, featureFlagService = featureFlagService, - contentScannerService = { _, _, _ -> }, + contentScannerService = { _, _ -> }, contentValidationCache = InMemoryEventContentValidationCache(), ).apply { isTesting = true diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenterTest.kt index 11093bd74f..11142cc9a2 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/protection/TimelineProtectionPresenterTest.kt @@ -10,7 +10,6 @@ package io.element.android.features.messages.impl.timeline.protection import com.google.common.truth.Truth.assertThat import io.element.android.features.contentscanner.api.ContentScannerService -import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.media.MediaPreviewConfig import io.element.android.libraries.matrix.api.media.MediaPreviewService import io.element.android.libraries.matrix.api.media.MediaPreviewValue @@ -104,7 +103,7 @@ class TimelineProtectionPresenterTest { val mediaPreviewConfig = MediaPreviewConfig(mediaPreviewValue = MediaPreviewValue.Private, hideInviteAvatar = false) val mediaPreviewService = FakeMediaPreviewService(mediaPreviewConfigFlow = MutableStateFlow(mediaPreviewConfig)) val room = FakeBaseRoom(initialRoomInfo = aRoomInfo(joinRule = JoinRule.Invite), roomCoroutineScope = backgroundScope) - val contentScannerService = lambdaRecorder { _: EventId, _: List, state: ContentValidationState -> + val contentScannerService = lambdaRecorder { _: List, state: ContentValidationState -> state.update(url, ContentValidationValue.Valid) } val presenter = createPresenter( @@ -119,7 +118,6 @@ class TimelineProtectionPresenterTest { val initialState = awaitItem() initialState.eventSink( TimelineProtectionEvent.ValidateContent( - eventId = AN_EVENT_ID, mediaSources = listOf(MediaSource(url)), validationState = validationState ) @@ -135,7 +133,7 @@ class TimelineProtectionPresenterTest { private fun createPresenter( room: BaseRoom = FakeBaseRoom(), mediaPreviewService: MediaPreviewService = FakeMediaPreviewService(), - contentScannerService: ContentScannerService = ContentScannerService { _: EventId, _: List, _: ContentValidationState -> }, + contentScannerService: ContentScannerService = ContentScannerService { _: List, _: ContentValidationState -> }, ) = TimelineProtectionPresenter( mediaPreviewService = mediaPreviewService, room = room, diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentValidationState.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentValidationState.kt index bbaf52f5b0..bfc01c4255 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentValidationState.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/media/contentvalidation/ContentValidationState.kt @@ -189,7 +189,7 @@ fun ContentValidationState.collectOverallState(): State @Composable fun ContentValidationState.collectMediaState(url: String?): State { if (url == null) { - return remember { mutableStateOf(ContentValidationValue.Unknown) } + return remember { mutableStateOf(ContentValidationValue.Valid) } } return produceState(getCurrentMediaState(url), key1 = url) { 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 2add4630e7..e909c5367c 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 @@ -84,9 +84,8 @@ class MediaGalleryPresenter( if (groupedItems is AsyncData.Success) { val items = groupedItems.data.getItems(mode) items.forEach { item -> - if (item is MediaItem.Event) { - val eventId = item.eventId() ?: return@forEach - coroutineScope.validateMedia(eventId, item) + if (item is MediaItem.Event && item.eventId() != null) { + coroutineScope.validateMedia(item) } } } @@ -237,7 +236,7 @@ class MediaGalleryPresenter( } } - private fun CoroutineScope.validateMedia(eventId: EventId, mediaItem: MediaItem.Event) { + private fun CoroutineScope.validateMedia(mediaItem: MediaItem.Event) { launch { val thumbnailSource = mediaItem.thumbnailSource() val mediaSource = mediaItem.mediaSource() @@ -248,7 +247,7 @@ class MediaGalleryPresenter( return@launch } - contentScannerService.scan(eventId, listOfNotNull(thumbnailSource, mediaSource).distinct(), contentValidationState) + contentScannerService.scan(listOfNotNull(thumbnailSource, mediaSource).distinct(), contentValidationState) } } 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 8b48955502..e1be702c9c 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 @@ -242,18 +242,15 @@ class MediaViewerDataSource( } } - fun validateMedia( - eventId: EventId, - mediaSource: MediaSource, - ) { + fun validateMedia(mediaSource: MediaSource, thumbnailMediaSource: MediaSource?) { val validationState = mediaValidationState[mediaSource.safeUrl] ?: return - val currentState = validationState.getCurrentMediaState(mediaSource.safeUrl) + val currentState = validationState.getCurrentOverallState() if (currentState.isLoading() || currentState.isValid()) { return } - contentScannerService.scan(eventId, listOf(mediaSource), validationState) + contentScannerService.scan(listOfNotNull(mediaSource, thumbnailMediaSource), validationState) } fun cancelLoadingMedia(data: MediaViewerPageData.MediaViewerData) { 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 21769f81be..8374294075 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 @@ -31,5 +31,5 @@ sealed interface MediaViewerEvent { data class OnNavigateTo(val index: Int) : MediaViewerEvent data class LoadMore(val direction: Timeline.PaginationDirection) : MediaViewerEvent data class CancelLoadingMedia(val data: MediaViewerPageData.MediaViewerData) : MediaViewerEvent - data class ValidateMedia(val eventId: EventId, val mediaSource: MediaSource) : MediaViewerEvent + data class ValidateMedia(val mediaSource: MediaSource, val thumbnailMediaSource: MediaSource?) : 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 60c14f562e..35dc4d97ba 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 @@ -194,7 +194,7 @@ class MediaViewerPresenter( is MediaViewerEvent.LoadMore -> coroutineScope.launch { dataSource.loadMore(event.direction) } - is MediaViewerEvent.ValidateMedia -> dataSource.validateMedia(event.eventId, event.mediaSource) + is MediaViewerEvent.ValidateMedia -> dataSource.validateMedia(event.mediaSource, event.thumbnailMediaSource) } } 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 c05bcb6bf6..1083f26685 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 @@ -95,6 +95,7 @@ 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 import io.element.android.libraries.matrix.ui.media.MediaRequestData +import io.element.android.libraries.matrix.ui.media.contentvalidation.collectMediaState import io.element.android.libraries.mediaviewer.api.MediaInfo import io.element.android.libraries.mediaviewer.api.local.LocalMedia import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState @@ -217,20 +218,24 @@ fun MediaViewerView( ) } is MediaViewerPageData.MediaViewerData -> { - val eventId = dataForPage.eventId - - val isMediaValid = dataForPage.validationState.getCurrentMediaState(dataForPage.mediaSource.safeUrl).isValid() + // We need to check the 2 validation states and can't use the overall state because these might be part of a gallery event + // If that was the case, the overall state would be invalid if any of the sources for any media in the gallery was invalid, e.g.: + // Media 1: mediaSource = valid, thumbnailSource = valid + // Media 2: mediaSource = invalid, thumbnailSource = valid + // The overall state would be invalid, so the whole gallery event and all its medias would be considered invalid. + val mediaValidationState by dataForPage.validationState.collectMediaState(dataForPage.mediaSource.safeUrl) + val thumbnailValidationState by dataForPage.validationState.collectMediaState(dataForPage.thumbnailSource?.safeUrl) // Check if the media to display is valid or dangerous - LaunchedEffect(eventId) { - if (eventId != null) { - state.eventSink(MediaViewerEvent.ValidateMedia(eventId, dataForPage.mediaSource)) - } + LaunchedEffect(Unit) { + state.eventSink( + MediaViewerEvent.ValidateMedia(mediaSource = dataForPage.mediaSource, thumbnailMediaSource = dataForPage.thumbnailSource) + ) } var bottomPaddingInPixels by remember { mutableIntStateOf(defaultBottomPaddingInPixels) } - val loadMediaOnVisibilityChangedModifier = remember(isMediaValid) { - if (isMediaValid == true) { + val loadMediaOnVisibilityChangedModifier = remember(mediaValidationState) { + if (mediaValidationState.isValid() && thumbnailValidationState.isValid()) { Modifier.onVisibilityChanged(minDurationMs = 200L) { isVisible -> if (isVisible) { state.eventSink(MediaViewerEvent.LoadMedia(dataForPage)) @@ -383,6 +388,8 @@ private fun MediaViewerPage( ) { val downloadedMedia by data.downloadedMedia val showProgress = rememberShowProgress(downloadedMedia) + val mediaValidationState by data.validationState.collectMediaState(data.mediaSource.safeUrl) + val thumbnailValidationState by data.validationState.collectMediaState(data.thumbnailSource?.safeUrl) Box( modifier = Modifier @@ -390,7 +397,7 @@ private fun MediaViewerPage( .navigationBarsPadding() ) { AnimatedVisibility( - visible = data.validationState.getCurrentMediaState(data.mediaSource.safeUrl).isLoading(), + visible = mediaValidationState.isLoading(), modifier = Modifier.padding(top = containerPadding.calculateTopPadding()).align(Alignment.TopCenter), enter = fadeIn(spring(stiffness = 500F)), exit = fadeOut(spring(stiffness = 500F)), @@ -423,20 +430,18 @@ private fun MediaViewerPage( } } - val isMediaValid = data.validationState.getCurrentMediaState(data.mediaSource.safeUrl).isValid() - - if (isMediaValid == false) { + if (mediaValidationState.isInvalid() || thumbnailValidationState.isInvalid()) { Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, ) { IconTitleSubtitleMolecule( iconStyle = BigIcon.Style.AlertSolid, - title = "The file is not safe", - subTitle = "Preview and download have been disabled.", + title = stringResource(CommonStrings.content_scanner_unsafe_title), + subTitle = stringResource(CommonStrings.content_scanner_unsafe_message), ) } - } else { + } else if (mediaValidationState.isValid() && thumbnailValidationState.isValid()) { LocalMediaView( modifier = Modifier.fillMaxSize(), isDisplayed = isDisplayed, @@ -462,6 +467,7 @@ private fun MediaViewerPage( ) } } + if (showError) { ErrorView( errorMessage = stringResource(id = CommonStrings.error_unknown), 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 1691ed9995..3ca702a47f 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 @@ -74,7 +74,7 @@ class DefaultMediaViewerEntryPointTest { sessionId = A_SESSION_ID, enterpriseService = FakeEnterpriseService(), contentValidationCache = NoopEventContentValidationCache(), - contentScannerService = ContentScannerService { _, _, _ -> }, + contentScannerService = ContentScannerService { _, _ -> }, ) } val callback = object : MediaViewerEntryPoint.Callback { @@ -123,7 +123,7 @@ class DefaultMediaViewerEntryPointTest { sessionId = A_SESSION_ID, enterpriseService = FakeEnterpriseService(), contentValidationCache = NoopEventContentValidationCache(), - contentScannerService = ContentScannerService { _, _, _ -> }, + contentScannerService = ContentScannerService { _, _ -> }, ) } val callback = object : MediaViewerEntryPoint.Callback { 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 1ce9b6ff19..a6e7e6b201 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 @@ -534,7 +534,7 @@ class MediaGalleryPresenterTest { mediaLoader = matrixMediaLoader, localMediaActions = localMediaActions, snackbarDispatcher = snackbarDispatcher, - contentScannerService = { _, _, _ -> }, + contentScannerService = { _, _ -> }, ) } } 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 95052e29a0..bc8e3f1a50 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 @@ -291,7 +291,7 @@ class MediaViewerDataSourceTest { localMediaFactory = localMediaFactory, systemClock = FakeSystemClock(), pagerKeysHandler = PagerKeysHandler(), - contentScannerService = { _, _, _ -> }, + contentScannerService = { _, _ -> }, contentValidationCache = NoopEventContentValidationCache(), ) } 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 0ca6534a6c..be577362bd 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 @@ -970,7 +970,7 @@ internal fun TestScope.createMediaViewerPresenter( localMediaFactory = localMediaFactory, systemClock = FakeSystemClock(), pagerKeysHandler = PagerKeysHandler(), - contentScannerService = { _, _, _ -> }, + contentScannerService = { _, _ -> }, contentValidationCache = NoopEventContentValidationCache(), ), room = room, 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 d2780bb408..ef668849d7 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 @@ -47,6 +47,24 @@ import kotlin.time.Duration.Companion.milliseconds class MediaViewerViewTest : RobolectricTest() { private val mockMediaUrl: Uri = mockk("localMediaUri") + @Test + fun `displaying a media will automatically validate it`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder() + val pagerData = aMediaViewerPageData(downloadedMedia = AsyncData.Success(aLocalMedia(uri = mockMediaUrl))) + val state = aMediaViewerState( + listData = listOf(pagerData), + eventSink = eventsRecorder + ) + setMediaViewerView( + state = state, + ) + eventsRecorder.assertList( + listOf( + MediaViewerEvent.ValidateMedia(mediaSource = pagerData.mediaSource, thumbnailMediaSource = pagerData.thumbnailSource), + ) + ) + } + @Test fun `clicking on back invokes expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder() @@ -59,6 +77,9 @@ class MediaViewerViewTest : RobolectricTest() { onBackClick = callback, ) + // Remove the `ValidateMedia` event that is emitted when the media is loaded, since we are not testing it here. + eventsRecorder.clear() + // Wait for enough time for the onVisibilityChanged modifier to trigger mainClock.advanceTimeBy(200) @@ -120,6 +141,9 @@ class MediaViewerViewTest : RobolectricTest() { ), ) + // Remove the `ValidateMedia` event that is emitted when the media is loaded, since we are not testing it here. + eventsRecorder.clear() + // Wait for enough time for the onVisibilityChanged modifier to trigger mainClock.advanceTimeBy(200) @@ -157,9 +181,11 @@ class MediaViewerViewTest : RobolectricTest() { eventSink = eventsRecorder ), ) + clickOn(textRes) eventsRecorder.assertList( listOf( + MediaViewerEvent.ValidateMedia(mediaSource = data.mediaSource, thumbnailMediaSource = data.thumbnailSource), MediaViewerEvent.LoadMedia(data), expectedEvent, ) @@ -175,6 +201,10 @@ class MediaViewerViewTest : RobolectricTest() { setMediaViewerView( state = state, ) + + // Remove the `ValidateMedia` event that is emitted when the media is loaded, since we are not testing it here. + eventsRecorder.clear() + // Ensure that the action are visible val resources = activity!!.resources val contentDescription = resources.getString(CommonStrings.action_share) @@ -205,6 +235,10 @@ class MediaViewerViewTest : RobolectricTest() { state = state, onBackClick = callback, ) + + // Remove the `ValidateMedia` event that is emitted when the media is loaded, since we are not testing it here. + eventsRecorder.clear() + val imageContentDescription = activity!!.getString(CommonStrings.common_image) onNodeWithContentDescription(imageContentDescription).performTouchInput { swipeDown(startY = centerY) } mainClock.advanceTimeBy(1_000) @@ -229,6 +263,9 @@ class MediaViewerViewTest : RobolectricTest() { ), ) + // Remove the `ValidateMedia` event that is emitted when the media is loaded, since we are not testing it here. + eventsRecorder.clear() + // Wait for enough time for the onVisibilityChanged modifier to trigger mainClock.advanceTimeBy(200) @@ -254,6 +291,9 @@ class MediaViewerViewTest : RobolectricTest() { ), ) + // Remove the `ValidateMedia` event that is emitted when the media is loaded, since we are not testing it here. + eventsRecorder.clear() + // Wait for enough time for the onVisibilityChanged modifier to trigger mainClock.advanceTimeBy(200) diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_23_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_23_en.png index 704d3432cf..96ee2aa0dc 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_23_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_23_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:47779722cc50bb7181d300e5738d10c32824c87122faef5939c4774e1b6530d8 -size 23583 +oid sha256:fa4e4a853c228493b0b2f65bfb903d471756ca669446cd62395fc0afa3ee47e8 +size 11997 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_23_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_23_en.png index 98cca36417..e5ac12f739 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_23_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_23_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fc42702e3ee2b646b4763fef985568f03d3d1ad971fd426328a1d9820045cbb8 -size 24235 +oid sha256:8e85ebc527d837aa3eba64e14b39cf7d7bdc9e08eff6b1c473e5698f879ea0eb +size 12389 From 77edfec61af4e17b0ea0724fa16e9029b8dcdc81 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 27 Jul 2026 18:17:14 +0200 Subject: [PATCH 205/383] Use the right insets in the home screen UI (#7271) * Use the right insets in the home screen UI That's `WindowInsets.statusBar` for the `Scaffold` component, then `WindowInsets.navigationBar` for the `LazyColum.contentPadding` * Apply it to other screens with long lists of items too * Apply the insets to `PreferencePage` too * Apply inset changes to other screens with scrollable content * Add helper insets/padding values based on review suggestions. * Use the newly added insets/padding values in several scaffold and scrollable columns --------- Co-authored-by: ElementBot --- .../android/features/home/impl/HomeView.kt | 29 ++++++++------ .../home/impl/search/RoomListSearchView.kt | 10 ++++- .../impl/spacefilters/SpaceFiltersView.kt | 15 +++---- .../impl/list/KnockRequestsListView.kt | 8 +++- .../impl/details/DependenciesDetailsView.kt | 7 +++- .../impl/list/DependencyLicensesListView.kt | 10 ++++- .../ChangeAccountProviderView.kt | 6 ++- .../ChooseAccountProviderView.kt | 6 ++- .../features/messages/impl/MessagesView.kt | 5 +-- .../pinned/list/PinnedMessagesListView.kt | 11 ++++- .../impl/threads/list/ThreadsListView.kt | 8 +++- .../api/ui/ConnectivityIndicatorContainer.kt | 5 +-- .../roomdetails/impl/RoomDetailsView.kt | 4 ++ .../impl/members/RoomMemberListView.kt | 11 ++++- .../impl/root/RoomDirectoryView.kt | 10 ++++- .../impl/RoomMemberModerationView.kt | 3 +- .../impl/root/SecurityAndPrivacyView.kt | 8 +++- .../space/impl/addroom/AddRoomToSpaceView.kt | 9 ++++- .../features/space/impl/root/SpaceView.kt | 8 +++- .../space/impl/settings/SpaceSettingsView.kt | 4 ++ .../startchat/impl/components/UserListView.kt | 7 +++- .../startchat/impl/root/StartChatView.kt | 4 +- .../components/preferences/PreferencePage.kt | 15 ++++--- .../libraries/designsystem/utils/Insets.kt | 40 +++++++++++++++++++ .../impl/gallery/MediaGalleryView.kt | 7 ++++ .../roomselect/impl/RoomSelectView.kt | 10 ++++- .../impl/history/PushHistoryView.kt | 5 +-- ...mpl.userstatus_UserStatusView_Day_6_en.png | 4 +- ...l.userstatus_UserStatusView_Night_5_en.png | 4 +- ...orizontalFloatingToolbarNoFab_Day_0_en.png | 4 +- ...nts_HorizontalFloatingToolbar_Day_0_en.png | 4 +- 31 files changed, 208 insertions(+), 73 deletions(-) create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/Insets.kt 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 6956ba6ba5..e306af0e9c 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 @@ -19,6 +19,7 @@ import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.plus import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @@ -65,6 +66,8 @@ import io.element.android.libraries.designsystem.theme.components.HorizontalFloa import io.element.android.libraries.designsystem.theme.components.HorizontalFloatingToolbarSeparator import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Scaffold +import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets 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.RoomId @@ -234,7 +237,15 @@ private fun HomeScaffold( ) }, floatingActionButtonPosition = FabPosition.Center, + contentWindowInsets = scaffoldScrollableContentInsets, content = { padding -> + val outerPadding = PaddingValues( + start = padding.calculateStartPadding(LocalLayoutDirection.current), + end = padding.calculateEndPadding(LocalLayoutDirection.current), + // Remove these two lines once https://issuetracker.google.com/issues/436432313 has been fixed + bottom = padding.calculateBottomPadding(), + top = padding.calculateTopPadding() + ) val contentPadding = PaddingValues( bottom = 96.dp, ) @@ -251,18 +262,10 @@ private fun HomeScaffold( onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick, onRoomClick = ::onRoomClick, onCreateRoomClick = onStartChatClick, - contentPadding = contentPadding, + contentPadding = lazyColumnContentPadding + contentPadding, modifier = Modifier - .padding( - PaddingValues( - start = padding.calculateStartPadding(LocalLayoutDirection.current), - end = padding.calculateEndPadding(LocalLayoutDirection.current), - // Remove these two lines once https://issuetracker.google.com/issues/436432313 has been fixed - bottom = padding.calculateBottomPadding(), - top = padding.calculateTopPadding() - ) - ) - .consumeWindowInsets(padding) + .padding(outerPadding) + .consumeWindowInsets(outerPadding) .hazeSource(state = hazeState) ) SpaceFiltersView(roomListState.spaceFiltersState) @@ -271,8 +274,8 @@ private fun HomeScaffold( HomeSpacesView( modifier = Modifier .fillMaxSize() - .padding(padding) - .consumeWindowInsets(padding) + .padding(outerPadding) + .consumeWindowInsets(outerPadding) .hazeSource(state = hazeState), contentPadding = contentPadding, state = state.homeSpacesState, diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/search/RoomListSearchView.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/search/RoomListSearchView.kt index f67338ef21..0535ded5c5 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/search/RoomListSearchView.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/search/RoomListSearchView.kt @@ -13,9 +13,15 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState @@ -153,7 +159,8 @@ private fun RoomListSearchContent( } }, ) - } + }, + contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Bottom), ) { padding -> Column( modifier = Modifier @@ -167,6 +174,7 @@ private fun RoomListSearchContent( LazyColumn( state = lazyListState, modifier = Modifier.weight(1f), + contentPadding = WindowInsets.navigationBars.asPaddingValues(), ) { items( items = state.results, 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 c8d710fced..280f41b909 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 @@ -15,9 +15,7 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight 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.systemBarsPadding import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -45,6 +43,8 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet import io.element.android.libraries.designsystem.theme.components.SearchField import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets 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 @@ -75,9 +75,7 @@ fun SpaceFiltersView( } if (sheetState.isVisible || isSelecting) { ModalBottomSheet( - modifier = modifier - .systemBarsPadding() - .navigationBarsPadding(), + modifier = modifier, sheetState = sheetState, onDismissRequest = { if (state is SpaceFiltersState.Selecting) { @@ -85,6 +83,7 @@ fun SpaceFiltersView( } }, scrollable = false, + contentWindowInsets = { scaffoldScrollableContentInsets }, ) { Box( modifier = Modifier @@ -113,7 +112,7 @@ private fun SpaceFiltersBottomSheetContent( modifier: Modifier = Modifier ) { Column( - modifier = modifier.padding(vertical = 16.dp) + modifier = modifier.padding(top = 16.dp) ) { Text( text = stringResource(R.string.screen_roomlist_your_spaces), @@ -131,7 +130,9 @@ private fun SpaceFiltersBottomSheetContent( placeholder = stringResource(CommonStrings.action_search), ) Spacer(modifier = Modifier.height(16.dp)) - LazyColumn { + LazyColumn( + contentPadding = lazyColumnContentPadding, + ) { items(filters) { filter -> SpaceFilterItem( filter = filter, diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListView.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListView.kt index 1ccc0742d6..db40596892 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListView.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListView.kt @@ -23,6 +23,7 @@ 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.plus import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn @@ -73,6 +74,8 @@ 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.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList @@ -94,7 +97,8 @@ fun KnockRequestsListView( .padding(padding) .consumeWindowInsets(padding), ) - } + }, + contentWindowInsets = scaffoldScrollableContentInsets, ) } @@ -132,7 +136,7 @@ private fun KnockRequestsListContent( onAcceptClick = ::onAcceptClick, onDeclineClick = ::onDeclineClick, onBanClick = ::onBanClick, - contentPadding = PaddingValues(bottom = bottomPaddingInPixels.toDp()), + contentPadding = lazyColumnContentPadding + PaddingValues(bottom = bottomPaddingInPixels.toDp()), ) } } diff --git a/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/details/DependenciesDetailsView.kt b/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/details/DependenciesDetailsView.kt index f463a6b8d1..e1d445ea1f 100644 --- a/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/details/DependenciesDetailsView.kt +++ b/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/details/DependenciesDetailsView.kt @@ -9,7 +9,7 @@ package io.element.android.features.licenses.impl.details import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.plus import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.ExperimentalMaterial3Api @@ -25,6 +25,8 @@ 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.Scaffold import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -41,9 +43,10 @@ fun DependenciesDetailsView( navigationIcon = { BackButton(onClick = onBack) }, ) }, + contentWindowInsets = scaffoldScrollableContentInsets, ) { contentPadding -> LazyColumn( - modifier = Modifier.padding(contentPadding), + contentPadding = contentPadding + lazyColumnContentPadding, ) { val licenses = licenseItem.licenses.orEmpty() + licenseItem.unknownLicenses.orEmpty() diff --git a/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/list/DependencyLicensesListView.kt b/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/list/DependencyLicensesListView.kt index f60c28ef2b..b732588217 100644 --- a/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/list/DependencyLicensesListView.kt +++ b/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/list/DependencyLicensesListView.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.plus import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.ExperimentalMaterial3Api @@ -34,6 +35,8 @@ 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 import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets import io.element.android.libraries.ui.strings.CommonStrings @OptIn(ExperimentalMaterial3Api::class) @@ -52,10 +55,11 @@ fun DependencyLicensesListView( navigationIcon = { BackButton(onClick = onBackClick) }, ) }, + contentWindowInsets = scaffoldScrollableContentInsets, ) { contentPadding -> Column( modifier = Modifier - .padding(contentPadding) + .padding(contentPadding + lazyColumnContentPadding) .padding(horizontal = 16.dp) ) { if (state.licenses.isSuccess()) { @@ -72,7 +76,9 @@ fun DependencyLicensesListView( modifier = Modifier.fillMaxWidth(), ) } - LazyColumn { + LazyColumn( + contentPadding = lazyColumnContentPadding, + ) { when (state.licenses) { is AsyncData.Failure -> item { Text( diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderView.kt index 4f6c87ac73..212bab515d 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/changeaccountprovider/ChangeAccountProviderView.kt @@ -39,6 +39,8 @@ 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.TopAppBar +import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets /** * https://www.figma.com/file/o9p34zmiuEpZRyvZXJZAYL/FTUE?type=design&node-id=604-60817 @@ -59,7 +61,8 @@ fun ChangeAccountProviderView( title = {}, navigationIcon = { BackButton(onClick = onBackClick) } ) - } + }, + contentWindowInsets = scaffoldScrollableContentInsets, ) { padding -> Box( modifier = Modifier @@ -71,6 +74,7 @@ fun ChangeAccountProviderView( Column( modifier = Modifier .verticalScroll(state = rememberScrollState()) + .padding(lazyColumnContentPadding) ) { IconTitleSubtitleMolecule( modifier = Modifier.padding(top = 16.dp, bottom = 32.dp, start = 16.dp, end = 16.dp), 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 17e7d10efb..e858789bb4 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 @@ -44,6 +44,8 @@ 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.designsystem.utils.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets import io.element.android.libraries.matrix.api.auth.OAuthDetails import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialogView import io.element.android.libraries.ui.strings.CommonStrings @@ -71,7 +73,8 @@ fun ChooseAccountProviderView( title = {}, navigationIcon = { BackButton(onClick = onBackClick) } ) - } + }, + contentWindowInsets = scaffoldScrollableContentInsets, ) { padding -> Box( modifier = Modifier @@ -84,6 +87,7 @@ fun ChooseAccountProviderView( modifier = Modifier .fillMaxSize() .verticalScroll(state = rememberScrollState()) + .padding(lazyColumnContentPadding) ) { IconTitleSubtitleMolecule( modifier = Modifier.padding(top = 16.dp, bottom = 32.dp, start = 16.dp, end = 16.dp), 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 358eba9c25..1d5cb9c67f 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 @@ -19,7 +19,6 @@ 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 import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -27,7 +26,6 @@ import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.imePadding 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 @@ -112,6 +110,7 @@ import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.HideKeyboardWhenDisposed import io.element.android.libraries.designsystem.utils.KeepScreenOn import io.element.android.libraries.designsystem.utils.OnLifecycleEvent +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets 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.EventId @@ -226,7 +225,7 @@ fun MessagesView( }, content = { Scaffold( - contentWindowInsets = WindowInsets.statusBars, + contentWindowInsets = scaffoldScrollableContentInsets, topBar = { if (state.timelineState.timelineMode is Timeline.Mode.Thread) { ThreadTopBar( 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 dae2ceb836..d35cda87bc 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 @@ -10,9 +10,13 @@ package io.element.android.features.messages.impl.pinned.list import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.plus import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState @@ -47,6 +51,7 @@ 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.Scaffold import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets 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 @@ -90,7 +95,8 @@ fun PinnedMessagesListView( .padding(padding) .consumeWindowInsets(padding), ) - } + }, + contentWindowInsets = scaffoldScrollableContentInsets, ) } @@ -206,11 +212,12 @@ private fun PinnedMessagesListLoaded( onEmojiReactionClick = { _, _ -> }, onVerifiedUserSendFailureClick = {} ) + LazyColumn( modifier = modifier.fillMaxSize(), state = rememberLazyListState(), reverseLayout = true, - contentPadding = PaddingValues(vertical = 8.dp), + contentPadding = WindowInsets.navigationBars.asPaddingValues() + PaddingValues(vertical = 8.dp), ) { items( items = state.timelineItems, 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 dd44fe0af3..6480dacfcf 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 @@ -16,6 +16,7 @@ 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.plus import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn @@ -54,6 +55,8 @@ 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.designsystem.utils.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets 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 @@ -129,14 +132,15 @@ fun ThreadsListView( }, navigationIcon = { BackButton(onBackClick) - } + }, + windowInsets = scaffoldScrollableContentInsets, ) } ) { padding -> val lazyListState = rememberLazyListState() LazyColumn( modifier = Modifier.fillMaxSize(), - contentPadding = padding, + contentPadding = padding + lazyColumnContentPadding, state = lazyListState, ) { itemsIndexed(state.threads, key = { _, row -> row.item.threadId }) { index, row -> diff --git a/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorContainer.kt b/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorContainer.kt index 7c3ff4a988..7d05fa7298 100644 --- a/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorContainer.kt +++ b/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorContainer.kt @@ -19,16 +19,15 @@ import androidx.compose.animation.fadeOut import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.consumeWindowInsets -import androidx.compose.foundation.layout.statusBars import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets private val INDICATOR_VERTICAL_PADDING = 6.dp @@ -47,7 +46,7 @@ fun ConnectivityIndicatorContainer( // Needed to get valid UI previews 24.dp } else { - WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + INDICATOR_VERTICAL_PADDING + scaffoldScrollableContentInsets.asPaddingValues().calculateTopPadding() + INDICATOR_VERTICAL_PADDING } val target = if (isIndicatorVisible.targetState) statusBarTopPadding else 0.dp val topWindowInset by animateDpAsState( 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 e55144985a..412006feae 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 @@ -78,6 +78,8 @@ import io.element.android.libraries.designsystem.theme.components.ListItemStyle 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.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets 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.RoomAlias @@ -135,12 +137,14 @@ fun RoomDetailsView( ) }, snackbarHost = { SnackbarHost(snackbarHostState) }, + contentWindowInsets = scaffoldScrollableContentInsets, ) { padding -> Column( modifier = Modifier .padding(padding) .verticalScroll(rememberScrollState()) .consumeWindowInsets(padding) + .padding(lazyColumnContentPadding) ) { leaveRoomView() diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt index 0e6f5b6c88..35150f42af 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt @@ -50,6 +50,8 @@ import io.element.android.libraries.designsystem.theme.components.SegmentedButto 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.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets 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 @@ -78,7 +80,8 @@ fun RoomMemberListView( onBackClick = navigator::exitRoomMemberList, onInviteClick = navigator::openInviteMembers, ) - } + }, + contentWindowInsets = scaffoldScrollableContentInsets, ) { padding -> Column( modifier = Modifier @@ -115,7 +118,11 @@ private fun RoomMemberList( onSelectedSectionChange: (SelectedSection) -> Unit, onSelectUser: (RoomMember) -> Unit, ) { - LazyColumn(modifier = Modifier.fillMaxWidth(), state = rememberLazyListState()) { + LazyColumn( + modifier = Modifier.fillMaxWidth(), + state = rememberLazyListState(), + contentPadding = lazyColumnContentPadding, + ) { stickyHeader { Column { AnimatedVisibility(visible = showBannedSection) { diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt index f2e4ae44fa..dd9098b7ad 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryView.kt @@ -52,6 +52,8 @@ 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.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList @@ -76,7 +78,8 @@ fun RoomDirectoryView( .padding(padding) .consumeWindowInsets(padding) ) - } + }, + contentWindowInsets = scaffoldScrollableContentInsets, ) } @@ -127,7 +130,10 @@ private fun RoomDirectoryRoomList( onReachedLoadMore: () -> Unit, modifier: Modifier = Modifier, ) { - LazyColumn(modifier = modifier) { + LazyColumn( + modifier = modifier, + contentPadding = lazyColumnContentPadding, + ) { items(roomDescriptions) { roomDescription -> RoomDirectoryRoomRow( roomDescription = roomDescription, 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 9b0686a64f..22f7439b2a 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 @@ -18,7 +18,6 @@ import androidx.compose.foundation.layout.height 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 @@ -228,7 +227,7 @@ private fun RoomMemberActionsBottomSheet( enabledValues = setOf(SheetValue.Hidden, SheetValue.Expanded), ) ModalBottomSheet( - modifier = Modifier.systemBarsPadding(), + modifier = Modifier.statusBarsPadding(), sheetState = bottomSheetState, onDismissRequest = { coroutineScope.launch { diff --git a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyView.kt b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyView.kt index f4207ae3af..45fce0ca01 100644 --- a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyView.kt +++ b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyView.kt @@ -54,6 +54,8 @@ 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.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList @@ -78,14 +80,16 @@ fun SecurityAndPrivacyView( state.eventSink(SecurityAndPrivacyEvent.Save) }, ) - } + }, + contentWindowInsets = scaffoldScrollableContentInsets, ) { padding -> Column( modifier = Modifier .padding(padding) .imePadding() .verticalScroll(rememberScrollState()) - .consumeWindowInsets(padding), + .consumeWindowInsets(padding) + .padding(lazyColumnContentPadding), verticalArrangement = Arrangement.spacedBy(32.dp), ) { if (state.showRoomAccessSection) { 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 47c78e6fb8..eb485f11b5 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 @@ -47,6 +47,8 @@ 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.OnVisibleRangeChangeEffect +import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets import io.element.android.libraries.matrix.ui.components.SelectedRoom import io.element.android.libraries.matrix.ui.model.SelectRoomInfo import io.element.android.libraries.matrix.ui.model.getAvatarData @@ -101,7 +103,8 @@ fun AddRoomToSpaceView( ) } ) - } + }, + contentWindowInsets = scaffoldScrollableContentInsets, ) { paddingValues -> Column( Modifier @@ -130,7 +133,9 @@ fun AddRoomToSpaceView( OnVisibleRangeChangeEffect(lazyListState) { visibleRange -> state.eventSink(AddRoomToSpaceEvent.UpdateSearchVisibleRange(visibleRange)) } - LazyColumn { + LazyColumn( + contentPadding = lazyColumnContentPadding, + ) { items(rooms, key = { it.roomId }) { roomInfo -> RoomListItem( roomInfo = roomInfo, 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 29898a1f63..fe971091f5 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 @@ -82,6 +82,8 @@ 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.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets 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.spaces.SpaceRoom @@ -157,6 +159,7 @@ fun SpaceView( } } }, + contentWindowInsets = scaffoldScrollableContentInsets, content = { padding -> Box( modifier = Modifier.padding(padding) @@ -251,7 +254,10 @@ private fun SpaceViewContent( onAddRoomClick: () -> Unit, modifier: Modifier = Modifier, ) { - LazyColumn(modifier.fillMaxSize()) { + LazyColumn( + modifier = modifier.fillMaxSize(), + contentPadding = lazyColumnContentPadding, + ) { val spaceInfo = state.spaceInfo item(key = "space_header") { AnimatedVisibility( diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/settings/SpaceSettingsView.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/settings/SpaceSettingsView.kt index 63b83516ac..ace3a1f670 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/settings/SpaceSettingsView.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/settings/SpaceSettingsView.kt @@ -43,6 +43,8 @@ import io.element.android.libraries.designsystem.theme.components.ListItemStyle 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.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.ui.strings.CommonStrings @@ -62,11 +64,13 @@ fun SpaceSettingsView( topBar = { SpaceSettingsTopBar(onBackClick = onBackClick) }, + contentWindowInsets = scaffoldScrollableContentInsets, ) { padding -> Column( modifier = Modifier .padding(padding) .verticalScroll(rememberScrollState()) + .padding(lazyColumnContentPadding) ) { SpaceInfoSection( roomId = state.roomId, diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/UserListView.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/UserListView.kt index cab1c57015..d33bd10856 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/UserListView.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/UserListView.kt @@ -10,7 +10,10 @@ package io.element.android.features.startchat.impl.components import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -76,7 +79,9 @@ fun UserListView( ) } if (!state.isSearchActive && state.recentDirectRooms.isNotEmpty()) { - LazyColumn { + LazyColumn( + contentPadding = WindowInsets.navigationBars.asPaddingValues(), + ) { item { ListSectionHeader( title = stringResource(id = CommonStrings.common_suggestions), 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 7537fee524..1878c6688e 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 @@ -45,6 +45,7 @@ import io.element.android.libraries.designsystem.theme.components.ListSectionHea 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.scaffoldScrollableContentInsets import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.ui.components.CreateDmConfirmationBottomSheet import io.element.android.libraries.matrix.ui.components.MatrixUserRow @@ -71,7 +72,8 @@ fun StartChatView( if (!state.userListState.isSearchActive) { CreateRoomRootViewTopBar(onCloseClick = onCloseClick) } - } + }, + contentWindowInsets = scaffoldScrollableContentInsets, ) { paddingValues -> Column( modifier = Modifier diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferencePage.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferencePage.kt index 24477b4339..61dff418b1 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferencePage.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferencePage.kt @@ -10,13 +10,11 @@ package io.element.android.libraries.designsystem.components.preferences import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.statusBars -import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.foundation.layout.plus import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api @@ -34,6 +32,8 @@ import io.element.android.libraries.designsystem.theme.aliasScreenTitle 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.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets @Composable fun PreferencePage( @@ -46,9 +46,8 @@ fun PreferencePage( Scaffold( modifier = modifier .fillMaxSize() - .systemBarsPadding() .imePadding(), - contentWindowInsets = WindowInsets.statusBars, + contentWindowInsets = scaffoldScrollableContentInsets, topBar = { PreferenceTopAppBar( title = title, @@ -56,12 +55,12 @@ fun PreferencePage( ) }, snackbarHost = snackbarHost, - content = { + content = { contentPadding -> Column( modifier = Modifier - .padding(it) - .consumeWindowInsets(it) .verticalScroll(state = rememberScrollState()) + .padding(contentPadding + lazyColumnContentPadding) + .consumeWindowInsets(contentPadding + lazyColumnContentPadding) ) { content() } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/Insets.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/Insets.kt new file mode 100644 index 0000000000..69160c902e --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/Insets.kt @@ -0,0 +1,40 @@ +/* + * 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.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.only +import androidx.compose.foundation.layout.safeDrawing +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.runtime.Composable +import io.element.android.libraries.designsystem.theme.components.Scaffold + +/** + * Content insets meant to be used for [Column] or [LazyColumn] components that are used as the main content of a screen, + * to avoid overlapping with navigation bars, IME or cut-out display parts, but ignoring the status bar. + * + * Counterpart of [scaffoldScrollableContentInsets] for [Column] or [LazyColumn] components. + */ +val lazyColumnContentPadding @Composable + get() = WindowInsets.safeDrawing + .only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom) + .asPaddingValues() + +/** + * Content insets meant to be used for [Scaffold] components that contain some content that is scrollable like [Column] or [LazyColumn], + * and this content should handle its own content padding. The insets will only apply the top padding to avoid overlapping with the status bar, + * while ignoring navigation bars, IME or cut-out display parts. + * + * Counterpart of [lazyColumnContentPadding] for [Scaffold] components. + */ +val scaffoldScrollableContentInsets @Composable + get() = WindowInsets.safeDrawing + .only(WindowInsetsSides.Top) 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 046a487502..2cddde495e 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 @@ -14,11 +14,14 @@ 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.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn @@ -67,6 +70,7 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.SegmentedButton 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.scaffoldScrollableContentInsets 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.timeline.Timeline @@ -125,6 +129,7 @@ fun MediaGalleryView( }, ) }, + contentWindowInsets = scaffoldScrollableContentInsets, ) { paddingValues -> Column( modifier = Modifier @@ -320,6 +325,7 @@ private fun MediaGalleryFilesList( val presenterFactories = LocalMediaItemPresenterFactories.current LazyColumn( modifier = Modifier.fillMaxSize(), + contentPadding = WindowInsets.navigationBars.asPaddingValues(), ) { items( items = files, @@ -396,6 +402,7 @@ private fun MediaGalleryImageGrid( columns = GridCells.Adaptive(80.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), verticalArrangement = Arrangement.spacedBy(4.dp), + contentPadding = WindowInsets.navigationBars.asPaddingValues(), ) { items( items = imagesAndVideos, diff --git a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt index 508fcd4fc2..7153306746 100644 --- a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt +++ b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt @@ -53,6 +53,8 @@ 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.OnVisibleRangeChangeEffect +import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.ui.components.SelectedRoom import io.element.android.libraries.matrix.ui.model.SelectRoomInfo @@ -133,7 +135,8 @@ fun RoomSelectView( ) } ) - } + }, + contentWindowInsets = scaffoldScrollableContentInsets, ) { paddingValues -> Column( Modifier @@ -149,7 +152,10 @@ fun RoomSelectView( resultState = state.resultState, showBackButton = false, ) { summaries -> - LazyColumn(state = lazyListState) { + LazyColumn( + state = lazyListState, + contentPadding = lazyColumnContentPadding, + ) { item { SelectedRoomsHelper( selectedRooms = state.selectedRooms, diff --git a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/history/PushHistoryView.kt b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/history/PushHistoryView.kt index 9105653516..7dfb8419dd 100644 --- a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/history/PushHistoryView.kt +++ b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/history/PushHistoryView.kt @@ -11,14 +11,12 @@ package io.element.android.libraries.troubleshoot.impl.history import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.consumeWindowInsets 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.layout.size -import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -50,6 +48,7 @@ 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.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets import io.element.android.libraries.push.api.history.PushHistoryItem import io.element.android.libraries.troubleshoot.impl.R import io.element.android.libraries.ui.strings.CommonStrings @@ -68,7 +67,7 @@ fun PushHistoryView( .fillMaxSize() .systemBarsPadding() .imePadding(), - contentWindowInsets = WindowInsets.statusBars, + contentWindowInsets = scaffoldScrollableContentInsets, topBar = { TopAppBar( navigationIcon = { diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png index 0ca6f66438..f831ed92a2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5896eb5df6f5398bdb94e74280d0d5c04b6a5a53c2378b7377c60fa58eef544b -size 12013 +oid sha256:7fe1f51d385bba8821dfc0f0da84990cf0d148e991d765484b343d8764abd47d +size 11724 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index fb72cafe03..1e04c3e7d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ef1b643a16b5a94c75f8bb845c36d3cbc7f7ed96a0cac32fdb9f0b09d26b4d1 -size 11747 +oid sha256:6bbc8c05e6f6818d00282228f52424ebe93e6e3dca3431d742e8c652d56460d6 +size 11712 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png index 58546b8522..ee5c582240 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30357bf18792db5ab20085010251170a724ffe8c00313facd04ee704e806af64 -size 10982 +oid sha256:75de341f705bb22955f9399180519b65ad59c2e1917317d56e50ea4db78f35bc +size 12102 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png index 83302d6ba4..38ad0e4b56 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:16dee1dfe746cd40dac9fe8f0af3ecb42cd14bab5cc490917b589beed065ed1b -size 14686 +oid sha256:326d59cf768b2dbd96eb7964d54c8eda509a5cd57c6e62087625e3314da0bb4d +size 13658 From 03639caa75875d89f3cf142679c43357c47eb16a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Jul 2026 16:18:01 +0000 Subject: [PATCH 206/383] Update actions/checkout action to v7.0.1 --- .github/workflows/build.yml | 2 +- .github/workflows/build_enterprise.yml | 2 +- .github/workflows/danger.yml | 2 +- .github/workflows/gradle-wrapper-update.yml | 2 +- .github/workflows/maestro-local.yml | 4 ++-- .github/workflows/nightly.yml | 2 +- .github/workflows/nightlyReports.yml | 2 +- .github/workflows/quality.yml | 24 ++++++++++----------- .github/workflows/release.yml | 6 +++--- .github/workflows/sonar.yml | 2 +- .github/workflows/sync-localazy.yml | 2 +- .github/workflows/sync-sas-strings.yml | 2 +- 12 files changed, 26 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cad5caf3ca..69152b7e2d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,7 +44,7 @@ jobs: docker-images: true swap-storage: false - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 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/build_enterprise.yml b/.github/workflows/build_enterprise.yml index b8b604dbca..f2658bb342 100644 --- a/.github/workflows/build_enterprise.yml +++ b/.github/workflows/build_enterprise.yml @@ -43,7 +43,7 @@ jobs: docker-images: true swap-storage: false - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 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/danger.yml b/.github/workflows/danger.yml index 287492bce5..531771e0b1 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -11,7 +11,7 @@ jobs: # Skip in forks, it doesn't work even with the fallback token if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Add SSH private keys for submodule repositories diff --git a/.github/workflows/gradle-wrapper-update.yml b/.github/workflows/gradle-wrapper-update.yml index 33cb6b8855..6b64a731d7 100644 --- a/.github/workflows/gradle-wrapper-update.yml +++ b/.github/workflows/gradle-wrapper-update.yml @@ -13,7 +13,7 @@ jobs: # Skip in forks if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 diff --git a/.github/workflows/maestro-local.yml b/.github/workflows/maestro-local.yml index ff3bdf7c49..cdc6fd3330 100644 --- a/.github/workflows/maestro-local.yml +++ b/.github/workflows/maestro-local.yml @@ -38,7 +38,7 @@ jobs: docker-images: true swap-storage: false - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 @@ -78,7 +78,7 @@ jobs: concurrency: group: maestro-test steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 if: (github.event_name == 'pull_request' && github.event.pull_request.fork == null) || github.event_name == 'workflow_dispatch' with: # Ensure we are building the branch and not the branch after being merged on develop diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 63816b0c30..9beab4e01c 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -32,7 +32,7 @@ jobs: docker-images: true swap-storage: false - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Use JDK 21 diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml index 36e7837479..23cfffc265 100644 --- a/.github/workflows/nightlyReports.yml +++ b/.github/workflows/nightlyReports.yml @@ -76,7 +76,7 @@ jobs: name: Dependency analysis runs-on: ubuntu-latest steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Use JDK 21 diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 73836c472f..cf74a9e396 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -33,7 +33,7 @@ jobs: docker-images: true swap-storage: false - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Add SSH private keys for submodule repositories @@ -51,7 +51,7 @@ jobs: name: Search for invalid screenshot files runs-on: ubuntu-latest steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Set up Python 3.12 @@ -65,7 +65,7 @@ jobs: name: Search for invalid dependencies runs-on: ubuntu-latest steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Use JDK 21 @@ -93,7 +93,7 @@ jobs: group: ${{ github.ref == 'refs/heads/main' && format('check-konsist-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-konsist-develop-{0}', github.sha) || format('check-konsist-{0}', github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 @@ -134,7 +134,7 @@ jobs: group: ${{ github.ref == 'refs/heads/main' && format('check-compose-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-compose-develop-{0}', github.sha) || format('check-compose-{0}', github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 @@ -168,7 +168,7 @@ jobs: group: ${{ github.ref == 'refs/heads/main' && format('check-lint-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-lint-develop-{0}', github.sha) || format('check-lint-{0}', github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 @@ -213,7 +213,7 @@ jobs: group: ${{ github.ref == 'refs/heads/main' && format('check-detekt-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-detekt-develop-{0}', github.sha) || format('check-detekt-{0}', github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 @@ -254,7 +254,7 @@ jobs: group: ${{ github.ref == 'refs/heads/main' && format('check-ktlint-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-ktlint-develop-{0}', github.sha) || format('check-ktlint-{0}', github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 @@ -295,7 +295,7 @@ jobs: group: ${{ github.ref == 'refs/heads/main' && format('check-docs-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-docs-develop-{0}', github.sha) || format('check-docs-{0}', github.ref) }} cancel-in-progress: true steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: # Ensure we are building the branch and not the branch after being merged on develop # https://github.com/actions/checkout/issues/881 @@ -319,7 +319,7 @@ jobs: name: Check shell scripts runs-on: ubuntu-latest steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Run shellcheck @@ -333,7 +333,7 @@ jobs: permissions: security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files. steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - uses: zizmorcore/zizmor-action@6599ee8b7a49aef6a770f63d261d214911a7ce02 # v0.6.0 @@ -344,7 +344,7 @@ jobs: needs: [konsist, lint, ktlint, detekt] if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 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/release.yml b/.github/workflows/release.yml index 424acab7de..4bc71a02ff 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -34,7 +34,7 @@ jobs: docker-images: true swap-storage: false - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Use JDK 21 @@ -71,7 +71,7 @@ jobs: group: ${{ format('build-release-main-enterprise-{0}', github.sha) }} cancel-in-progress: true steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Add SSH private keys for submodule repositories @@ -122,7 +122,7 @@ jobs: docker-images: true swap-storage: false - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Use JDK 21 diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index fc33644b7b..6d9a62a2d1 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -38,7 +38,7 @@ jobs: docker-images: true swap-storage: false - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 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/sync-localazy.yml b/.github/workflows/sync-localazy.yml index 6ab2dd3ac3..61b4a8d521 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -13,7 +13,7 @@ jobs: # Skip in forks if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }} steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Use JDK 21 diff --git a/.github/workflows/sync-sas-strings.yml b/.github/workflows/sync-sas-strings.yml index 3811b41f88..7ed0b60243 100644 --- a/.github/workflows/sync-sas-strings.yml +++ b/.github/workflows/sync-sas-strings.yml @@ -14,7 +14,7 @@ jobs: 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@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Set up Python 3.12 From cc3c68411e65b8a8e7c3bf8e858dbf76e09afbd3 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 28 Jul 2026 09:38:56 +0200 Subject: [PATCH 207/383] Try making `HeaderFooterView` more robust (#7267) * Try making `HeaderFooterView` more robust Create `HeaderFooterLayout` to properly calculate the content size when the component is scrollable so it's at least the size of the available space. * Make `DesktopNoticeView` scrollable For this, `NumberedListOrganism` can't be a `LazyColumn`, since that's a lazy layout with no intrinsic height and Compose doesn't know how to size it. * Fix the case where no header or content composables are supplied * Fix insets in non-scrollable UI * Remove `movableContentOf`, suppress the warning instead since the `isScrollable` parameter should never toggle this behavior * Update screenshots --------- Co-authored-by: ElementBot --- .../impl/screens/desktop/DesktopNoticeView.kt | 1 + .../atomic/organisms/NumberedListOrganism.kt | 7 +- .../atomic/pages/HeaderFooterLayout.kt | 106 ++++++++++++++++++ .../atomic/pages/HeaderFooterPage.kt | 56 +++------ ...screens.qrcode_ShowQrCodeView_Day_0_en.png | 4 +- ...screens.qrcode_ShowQrCodeView_Day_1_en.png | 4 +- ...reens.qrcode_ShowQrCodeView_Night_0_en.png | 4 +- ...reens.qrcode_ShowQrCodeView_Night_1_en.png | 4 +- ...eybackup_MissingKeyBackupView_Day_0_en.png | 4 +- ...backup_MissingKeyBackupView_Night_0_en.png | 4 +- ...es_HeaderFooterPageScrollable_Day_0_en.png | 4 +- ..._HeaderFooterPageScrollable_Night_0_en.png | 4 +- 12 files changed, 141 insertions(+), 61 deletions(-) create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterLayout.kt diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/desktop/DesktopNoticeView.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/desktop/DesktopNoticeView.kt index ad2e67dbc7..a66ea7b391 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/desktop/DesktopNoticeView.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/screens/desktop/DesktopNoticeView.kt @@ -67,6 +67,7 @@ fun DesktopNoticeView( title = stringResource(R.string.screen_link_new_device_desktop_title, appName), iconStyle = BigIcon.Style.Default(CompoundIcons.Computer()), modifier = modifier, + isScrollable = true, buttons = { Button( text = stringResource(R.string.screen_link_new_device_desktop_submit), diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/NumberedListOrganism.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/NumberedListOrganism.kt index df841dad9b..03a5258b78 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/NumberedListOrganism.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/NumberedListOrganism.kt @@ -9,8 +9,7 @@ package io.element.android.libraries.designsystem.atomic.organisms import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.text.AnnotatedString @@ -23,11 +22,11 @@ fun NumberedListOrganism( items: ImmutableList, modifier: Modifier = Modifier, ) { - LazyColumn( + Column( modifier = modifier, verticalArrangement = Arrangement.spacedBy(24.dp), ) { - itemsIndexed(items) { index, item -> + for ((index, item) in items.withIndex()) { NumberedListMolecule(index = index + 1, text = item) } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterLayout.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterLayout.kt new file mode 100644 index 0000000000..af707ec251 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterLayout.kt @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.designsystem.atomic.pages + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +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 androidx.compose.ui.Modifier +import androidx.compose.ui.layout.Layout +import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.unit.Constraints +import kotlin.math.max + +/** + * A layout with a [header], a [footer] and a [content] composables. + * The component can be scrollable or not, which will modify which layout is used internally to arrange the UI. + * In both cases, the [content] will use all the available space between the [header] and the [footer]. + * The [footer] is always visible, the [header] and the [content] can be scrolled if [isScrollable] is true. + * + * @param header the header composable. + * @param footer the footer composable. + * @param isScrollable if the content should be scrollable. + * @param contentInsetsPadding padding values to apply to the content. This is useful to handle system insets. + * @param modifier Compose modifier. + * @param content the main content composable. + */ +@Suppress("ContentSlotReused") +@Composable +fun HeaderFooterLayout( + header: @Composable () -> Unit, + footer: @Composable () -> Unit, + isScrollable: Boolean, + contentInsetsPadding: PaddingValues, + modifier: Modifier = Modifier, + content: @Composable () -> Unit, +) { + Column(modifier = modifier) { + if (isScrollable) { + // This is a hack to make the content at least 1px high, otherwise the layout will crash + var newHeight by remember { mutableIntStateOf(1) } + Box( + modifier = Modifier + .padding(contentInsetsPadding) + .weight(1f, fill = true) + .onSizeChanged { + newHeight = it.height + } + ) { + Layout( + content = { + header() + content() + }, + modifier = Modifier.verticalScroll(rememberScrollState()), + measurePolicy = { measurables, constraints -> + val actualConstraints = constraints.copy(minWidth = 0, minHeight = 0, maxHeight = newHeight) + val headerPlaceable = measurables.firstOrNull()?.measure(actualConstraints) + + val contentPlaceable = if (headerPlaceable != null && measurables.size > 1) { + val availableContentHeight = max(1, actualConstraints.maxHeight - headerPlaceable.height) + val contentConstraints = actualConstraints.copy(minHeight = availableContentHeight, maxHeight = Constraints.Infinity) + measurables[1].measure(contentConstraints) + } else { + null + } + + val headerHeight = headerPlaceable?.height ?: 0 + val contentHeight = contentPlaceable?.height ?: 0 + layout(actualConstraints.maxWidth, headerHeight + contentHeight) { + var yPosition = 0 + + headerPlaceable?.let { + it.placeRelative(0, yPosition) + yPosition += it.height + } + + contentPlaceable?.placeRelative(0, yPosition) + } + } + ) + } + } else { + Box(Modifier.padding(contentInsetsPadding)) { + header() + } + Box(Modifier.weight(1f, fill = true)) { + content() + } + } + + footer() + } +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt index f09dc895e9..5ca601baae 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/HeaderFooterPage.kt @@ -9,19 +9,14 @@ package io.element.android.libraries.designsystem.atomic.pages import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.calculateEndPadding import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.consumeWindowInsets 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.rememberScrollState -import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment @@ -82,48 +77,27 @@ fun HeaderFooterPage( Box { background() - // Render in a Column - Column( + HeaderFooterLayout( modifier = Modifier .fillMaxSize() .padding(paddingValues = contentPadding) .consumeWindowInsets(insetsPadding) .imePadding(), - ) { - // Content - Column( - modifier = Modifier - .fillMaxWidth() - .run { - if (isScrollable) { - verticalScroll(rememberScrollState()) - // Make sure the scrollable content takes the full available height - .height(IntrinsicSize.Max) - } else { - Modifier - } - } - // Apply insets here so if the content is scrollable it can get below the top app bar if needed - .padding(contentInsetsPadding) - .weight(1f, fill = true), - ) { - // Header - header() - Box { - content() + isScrollable = isScrollable, + contentInsetsPadding = contentInsetsPadding, + header = header, + content = content, + footer = { + Box( + modifier = Modifier + .padding(start = 16.dp, end = 16.dp, top = 16.dp) + .fillMaxWidth() + .padding(footerInsetsPadding) + ) { + footer() } - } - - // Footer - Box( - modifier = Modifier - .padding(start = 16.dp, end = 16.dp, top = 16.dp) - .fillMaxWidth() - .padding(footerInsetsPadding) - ) { - footer() - } - } + }, + ) } } } diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en.png index 5bc0a7e57a..48598e410f 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da71297e7073c5c592dc154af7f137c4eb500bf528e1509b95da869a2c61cbd2 -size 30488 +oid sha256:5c79c83bde346bec65f67c34805407e46b351b2c91772c13e0a6c23ae09bf7e8 +size 30345 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 index d2ab2dcb1e..da85b85089 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:48cafd6b98791b64e4cc6a16c602f17e3a886659698c3c93bc4acaf875337e0f -size 31102 +oid sha256:e666d896f715b1e6a165514acbe603fc879c0495a2d7215ac7cabe7a8d165e09 +size 30961 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en.png index fac34cc904..d22d7f98cf 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8bbb94fdb717b2bcda3683d5833181c59d00e4c03a1860af66de6225c8df0756 -size 32482 +oid sha256:ff17ff66d5c92ab19ce8064e2e14326e9f2921c1b7313a3974547b2932cb7fb1 +size 32295 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 index c4593656d1..05d8692fb0 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f6f8d1282ae47a5240aec2b2c63a137b8e3e25ec8b746cf2d82d0fa7e0c0a34 -size 30287 +oid sha256:6a7786eecdd8f9f8ee2c7edb0d76a2fc09a960f6ca457445b35dc428539e5be6 +size 30102 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 3314252e26..ac8d5e8611 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:6e97cab70b9ee3e870154ad4ae4cf1bf0bb413facf8253f5f9fe9429eddf76b1 -size 60303 +oid sha256:d70106c0e4d800aa34faa380d79b65ac29c6bc43e41cf874f31517f138e252f9 +size 60126 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 d58e079ced..4d93016dd4 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:caaa2a0f4de455704a6b5c78e19c2f723be7deaeec470c77ff1e87df194dd95c -size 58620 +oid sha256:75670dcefa55cf863d2c0dd608704d465b5c9ac74f4798b3503ce9a2d8e74417 +size 58518 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Day_0_en.png index 6bcc250b5c..e435ce728f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b3874d6fa6ad92eac4ccfbbc2ea76cf8b1fbc869a725eb5e8131af52e78be7a4 -size 12427 +oid sha256:5d8630310d2c2f08aae23fe2e98b9b7b6dec253cbc0528804c999aa3d2d40658 +size 12439 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Night_0_en.png index 5eaa6da79f..d816e772f4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60d3361163e9a846d0686e696ba25e35b6a8ca9b691d711ff0f5fdd3b1d5578d -size 12091 +oid sha256:99e36471b02eedc24bf1a07ffc720fe18ca5482e7fc0f35316ab407fd485cb34 +size 12105 From 9042b4be4f776817f149e46767292c498bda9ad3 Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Tue, 28 Jul 2026 00:51:15 -0700 Subject: [PATCH 208/383] Make settings section separators visible in black theme (#7039) * Make settings section separators visible in black theme In the Black (OLED) theme the canvas is forced to pure black while the section-separator divider keeps its standard-dark colour (outlineVariant, ~10% alpha white), leaving dividers in Settings and related screens almost invisible. Add an OLED-aware listSectionDivider alias that lightens the divider only when the black theme is active, and use it for the ListSectionHeader divider. Light and standard-dark themes are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> * Set separatorSecondary for Black theme instead of a custom divider alias Following review feedback: now that the global HorizontalDivider uses separatorSecondary (#7054), give the Black/OLED theme a visible separatorSecondary value in ElementTheme instead of carrying a bespoke listSectionDivider alias. This fixes all separators on pure black, not just section headers. The exact color is pending design confirmation. * chore(theme): remove in-code design discussion comment Move design discussion out of the code per review; the divider color decision lives in the PR thread. * Update screenshots Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> --------- Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) Co-authored-by: ElementBot Co-authored-by: Jorge Martin Espinosa --- .../io/element/android/compound/theme/ElementTheme.kt | 8 +++++++- ...ences.impl.advanced_AdvancedSettingsViewBlack_0_en.png | 2 +- ...ences.impl.advanced_AdvancedSettingsViewBlack_1_en.png | 2 +- ...ences.impl.advanced_AdvancedSettingsViewBlack_2_en.png | 2 +- ...ences.impl.advanced_AdvancedSettingsViewBlack_3_en.png | 4 ++-- ...ences.impl.advanced_AdvancedSettingsViewBlack_4_en.png | 2 +- ...ences.impl.advanced_AdvancedSettingsViewBlack_5_en.png | 2 +- ...ences.impl.advanced_AdvancedSettingsViewBlack_6_en.png | 4 ++-- ...ences.impl.advanced_AdvancedSettingsViewBlack_7_en.png | 2 +- ...ences.impl.advanced_AdvancedSettingsViewBlack_8_en.png | 4 ++-- 10 files changed, 19 insertions(+), 13 deletions(-) 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 34cea4f856..ff9fe2a959 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 @@ -33,11 +33,13 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp +import io.element.android.compound.annotations.CoreColorToken import io.element.android.compound.tokens.compoundTypography import io.element.android.compound.tokens.generated.SemanticColors import io.element.android.compound.tokens.generated.TypographyTokens import io.element.android.compound.tokens.generated.compoundColorsDark import io.element.android.compound.tokens.generated.compoundColorsLight +import io.element.android.compound.tokens.generated.internal.DarkColorTokens /** * Inspired from https://medium.com/@lucasyujideveloper/54cbcbde1ace @@ -94,6 +96,7 @@ internal val LocalCompoundColors = staticCompositionLocalOf { compoundColorsLigh * @param typography the Material 3 [Typography] tokens to use. It'll use [compoundTypography] by default. * @param content the content to apply the theme to. */ +@OptIn(CoreColorToken::class) @Composable fun ElementTheme( theme: Theme = if (isSystemInDarkTheme()) Theme.Dark else Theme.Light, @@ -111,7 +114,10 @@ fun ElementTheme( val darkTheme = theme.isDark() val currentCompoundColor = when { darkTheme -> if (theme == Theme.Black) { - compoundDark.copy(bgCanvasDefault = Color.Black) + compoundDark.copy( + bgCanvasDefault = Color.Black, + separatorSecondary = DarkColorTokens.colorGray400, + ) } else { compoundDark } 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 b86c69a702..e0f36af121 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:fb6e775ab09eb127cd56db6831f8bb125d3ce8b2403bd986487e9ee2c628fe03 +oid sha256:b7243c65196024fb3d5ff2d0e281adb21cbed44405d0ca3ac30c7c91ca7414d2 size 59750 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 efb0ba0a05..836b0f5742 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:2cde83c54e65dac37f42d162758d0bb075eecfdaae5508b7790eb2aacc36f4a2 +oid sha256:027d59e8fc57b0e599dd1386368189ce193ddb6d77d95116af4574f96ce11988 size 59615 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 6d10e6b029..5f406a44aa 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:56e19e11105421fee374e36f824761ddff1e160f3c6f505d7c66241a81430612 +oid sha256:64fdf9939053f75434e17dd74aadd60ee21b2254bb0fe2dc70090bb2e6678938 size 59600 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 2b3acbef75..3ac454c6de 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:27d1cff6cdb23657a1d65855589efbd4a1640370f081c2a492f28fcb624f8bf9 -size 59611 +oid sha256:9f3a90f5ae1cfb76187e86d298392ae0bc126fa2e8e691b3625fe61cfe90070b +size 59612 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 87e3f5d778..473582bbe5 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:c383308325ff9b683a9b001ace0601c04e3ae71b2bbbf3e07aae1917e7bf6e15 +oid sha256:f8e8c7f85c81245686e69c5886c8cb88760a159806387a3b69c8d746186b2a2d size 59498 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 f4c1154539..11588b5e7c 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:7b634c94a7c36c771c7c7cf7b42f05151aa03479448e2c10ae22bf7e058eb28c +oid sha256:29723fc3ce6d24ae89dad4c3b5705d062db29bbdc16b6c0e4bff9193b683915b size 59746 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 738db2b489..fa9697e195 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:4e27c596d0e2462b5a469d27bcfe9073c09cfe51a91cf280599919ef25b74395 -size 59292 +oid sha256:c81d7887430494d111ffa6ba109dcc81b96d6b9ee788d73e008448acda2d9517 +size 59293 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 5092ac3e94..8133c30321 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:596e9308895c9a8fec14ed26af4ef348f8c3f5772eb7f296b437579c59dabda6 +oid sha256:cbeae364251d54a8089821e9286a8a10bf97cdfcb3382664b912032a38091c1f size 58804 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 aa72afe58b..07d47f573f 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:644204d979bb19ec5a002ae246814098af05e8750316d52910f649ff62eb8b6f -size 62866 +oid sha256:a2dfd70af3fa004f7edfc46f32bc42925d64829875d6dc852245d2d5fab3f88f +size 62867 From adc1b50492c3dbe71b96a0448c911db6cc18f640 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 28 Jul 2026 10:29:42 +0200 Subject: [PATCH 209/383] Fix insets in several screens (#7285) * Fix insets in several screens UI components in the room list, room member list, etc. now have better insets based on `WindowInsets.safeDrawing` * Update screenshots --------- Co-authored-by: ElementBot --- .../android/features/home/impl/HomeView.kt | 2 +- .../home/impl/components/HomeTopBar.kt | 10 ++++++++-- .../features/messages/impl/MessagesView.kt | 20 ++++++++++++++----- .../pinned/banner/PinnedMessagesBannerView.kt | 8 +++++++- .../pinned/list/PinnedMessagesListView.kt | 6 ++---- .../messages/impl/timeline/TimelineView.kt | 8 +++++++- .../impl/topbars/MessagesViewTopBar.kt | 6 +++++- .../impl/members/RoomMemberListView.kt | 8 +++++++- .../startchat/impl/components/UserListView.kt | 15 ++++++++++---- .../startchat/impl/root/StartChatView.kt | 5 ++++- .../impl/gallery/MediaGalleryView.kt | 12 +++++++---- .../impl/viewer/MediaViewerView.kt | 7 ++++++- ...mpl.userstatus_UserStatusView_Day_6_en.png | 4 ++-- ...l.userstatus_UserStatusView_Night_5_en.png | 4 ++-- ...orizontalFloatingToolbarNoFab_Day_0_en.png | 4 ++-- ...nts_HorizontalFloatingToolbar_Day_0_en.png | 4 ++-- 16 files changed, 89 insertions(+), 34 deletions(-) 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 e306af0e9c..50cfc00a78 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 @@ -277,7 +277,7 @@ private fun HomeScaffold( .padding(outerPadding) .consumeWindowInsets(outerPadding) .hazeSource(state = hazeState), - contentPadding = contentPadding, + contentPadding = lazyColumnContentPadding + contentPadding, state = state.homeSpacesState, lazyListState = spacesLazyListState, onSpaceClick = { spaceId -> 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 a563520e09..8163d29d92 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 @@ -12,8 +12,12 @@ 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.WindowInsetsSides +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.pager.VerticalPager import androidx.compose.foundation.pager.rememberPagerState @@ -96,13 +100,15 @@ fun HomeTopBar( spaceFiltersState: SpaceFiltersState, modifier: Modifier = Modifier, ) { + val contentPadding = WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal).asPaddingValues() Column(modifier) { TopAppBar( modifier = Modifier .backgroundVerticalGradient( isVisible = !areSearchResultsDisplayed, ) - .statusBarsPadding(), + .statusBarsPadding() + .padding(contentPadding), colors = TopAppBarDefaults.topAppBarColors( containerColor = Color.Transparent, scrolledContainerColor = Color.Transparent, @@ -153,7 +159,7 @@ fun HomeTopBar( TopAppBarScrollBehaviorLayout(scrollBehavior = scrollBehavior) { RoomListFiltersView( state = filtersState, - modifier = Modifier.padding(bottom = 16.dp) + modifier = Modifier.padding(bottom = 16.dp).padding(contentPadding) ) } } 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 1d5cb9c67f..5911de7372 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 @@ -19,13 +19,18 @@ 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.WindowInsetsSides +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.foundation.layout.width import androidx.compose.material3.MaterialTheme @@ -581,12 +586,17 @@ private fun MessagesViewComposerBottomSheetContents( onRoomSuccessorClick: (RoomId) -> Unit, onLinkClick: (String, Boolean) -> Unit, ) { + val contentPadding = WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal).asPaddingValues() when { state.successorRoom != null -> { - SuccessorRoomBanner(roomSuccessor = state.successorRoom, onRoomSuccessorClick = onRoomSuccessorClick) + SuccessorRoomBanner( + modifier = Modifier.fillMaxWidth().padding(contentPadding), + roomSuccessor = state.successorRoom, + onRoomSuccessorClick = onRoomSuccessorClick + ) } state.userEventPermissions.canSendMessage -> { - Column(modifier = Modifier.fillMaxWidth()) { + Column(modifier = Modifier.fillMaxWidth().padding(contentPadding)) { // Do not show the identity change if user is composing a Rich message or is seeing suggestion(s). if (state.composerState.suggestions.isEmpty() && state.composerState.textEditorState is TextEditorState.Markdown) { @@ -610,15 +620,15 @@ private fun MessagesViewComposerBottomSheetContents( } } else -> { - CantSendMessageBanner() + CantSendMessageBanner(Modifier.padding(contentPadding)) } } } @Composable -private fun CantSendMessageBanner() { +private fun CantSendMessageBanner(modifier: Modifier = Modifier) { Row( - modifier = Modifier + modifier = modifier .fillMaxWidth() .background(ElementTheme.colors.bgSubtleSecondary) .padding(16.dp), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt index 21b89da5d1..bc80d6b014 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt @@ -16,10 +16,15 @@ 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.WindowInsetsSides +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.runtime.Composable @@ -98,7 +103,8 @@ private fun PinnedMessagesBannerRow( onClick(state.currentPinnedMessage.eventId) state.eventSink(PinnedMessagesBannerEvent.MoveToNextPinned) } - }, + } + .padding(WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal).asPaddingValues()), verticalAlignment = Alignment.CenterVertically, ) { Spacer(modifier = Modifier.width(26.dp)) 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 d35cda87bc..4f69bacd28 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 @@ -10,11 +10,8 @@ package io.element.android.features.messages.impl.pinned.list import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.plus import androidx.compose.foundation.lazy.LazyColumn @@ -51,6 +48,7 @@ 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.Scaffold import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.user.MatrixUser @@ -217,7 +215,7 @@ private fun PinnedMessagesListLoaded( modifier = modifier.fillMaxSize(), state = rememberLazyListState(), reverseLayout = true, - contentPadding = WindowInsets.navigationBars.asPaddingValues() + PaddingValues(vertical = 8.dp), + contentPadding = lazyColumnContentPadding + PaddingValues(vertical = 8.dp), ) { items( items = state.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 7db220dd01..78c067eed1 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 @@ -27,9 +27,15 @@ 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.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.plus +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn @@ -193,7 +199,7 @@ fun TimelineView( .testTag(TestTags.timeline), state = lazyListState, reverseLayout = true, - contentPadding = PaddingValues(top = 64.dp, bottom = 8.dp), + contentPadding = WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal).asPaddingValues() + PaddingValues(top = 64.dp, bottom = 8.dp), ) { items( items = state.timelineItems, 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 2daa90af53..6aabf97f2c 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 @@ -14,7 +14,11 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ExperimentalMaterial3Api @@ -72,7 +76,7 @@ internal fun MessagesViewTopBar( menuActions: @Composable RowScope.() -> Unit, ) { TopAppBar( - modifier = modifier, + modifier = modifier.padding(WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal).asPaddingValues()), navigationIcon = { BackButton(onClick = onBackClick) }, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt index 35150f42af..659d8ed0e0 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListView.kt @@ -14,9 +14,14 @@ 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.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListScope @@ -94,7 +99,8 @@ fun RoomMemberListView( state = state.searchQuery, modifier = Modifier .fillMaxWidth() - .padding(horizontal = 16.dp), + .padding(horizontal = 16.dp) + .padding(WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal).asPaddingValues()), placeholder = stringResource(CommonStrings.common_search_for_someone), ) RoomMemberList( diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/UserListView.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/UserListView.kt index d33bd10856..c8587d9784 100644 --- a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/UserListView.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/UserListView.kt @@ -11,9 +11,13 @@ package io.element.android.features.startchat.impl.components import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.only +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.plus +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -28,6 +32,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.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.ListSectionHeader +import io.element.android.libraries.designsystem.utils.lazyColumnContentPadding import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.components.CheckableUserRow import io.element.android.libraries.matrix.ui.components.CheckableUserRowData @@ -47,8 +52,10 @@ fun UserListView( Column( modifier = modifier, ) { + val contentPaddingValues = WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal).asPaddingValues() SearchUserBar( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.fillMaxWidth() + .padding(contentPaddingValues), queryState = state.searchQuery, resultState = state.searchResults, selectedUsers = state.selectedUsers, @@ -69,7 +76,7 @@ fun UserListView( if (state.isMultiSelectionEnabled && !state.isSearchActive && state.selectedUsers.isNotEmpty()) { SelectedUsersRowList( - contentPadding = PaddingValues(16.dp), + contentPadding = contentPaddingValues + PaddingValues(16.dp), selectedUsers = state.selectedUsers, autoScroll = true, onUserRemove = { @@ -80,7 +87,7 @@ fun UserListView( } if (!state.isSearchActive && state.recentDirectRooms.isNotEmpty()) { LazyColumn( - contentPadding = WindowInsets.navigationBars.asPaddingValues(), + contentPadding = lazyColumnContentPadding, ) { item { ListSectionHeader( 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 1878c6688e..104a8cecf7 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 @@ -45,6 +45,7 @@ import io.element.android.libraries.designsystem.theme.components.ListSectionHea 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.lazyColumnContentPadding import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.ui.components.CreateDmConfirmationBottomSheet @@ -170,7 +171,9 @@ private fun CreateRoomActionButtonsList( onRoomDirectorySearchClick: () -> Unit, onDmClick: (RoomId) -> Unit, ) { - LazyColumn { + LazyColumn( + contentPadding = lazyColumnContentPadding, + ) { item { CreateRoomActionButton( iconRes = CompoundDrawables.ic_compound_plus, 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 2cddde495e..441b6082dd 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 @@ -15,14 +15,16 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.grid.GridCells @@ -70,6 +72,7 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.SegmentedButton 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.lazyColumnContentPadding import io.element.android.libraries.designsystem.utils.scaffoldScrollableContentInsets import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState @@ -141,7 +144,8 @@ fun MediaGalleryView( SingleChoiceSegmentedButtonRow( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 16.dp), + .padding(horizontal = 16.dp) + .padding(WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal).asPaddingValues()), ) { MediaGalleryMode.entries.forEach { mode -> SegmentedButton( @@ -325,7 +329,7 @@ private fun MediaGalleryFilesList( val presenterFactories = LocalMediaItemPresenterFactories.current LazyColumn( modifier = Modifier.fillMaxSize(), - contentPadding = WindowInsets.navigationBars.asPaddingValues(), + contentPadding = lazyColumnContentPadding, ) { items( items = files, @@ -402,7 +406,7 @@ private fun MediaGalleryImageGrid( columns = GridCells.Adaptive(80.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), verticalArrangement = Arrangement.spacedBy(4.dp), - contentPadding = WindowInsets.navigationBars.asPaddingValues(), + contentPadding = lazyColumnContentPadding, ) { items( items = imagesAndVideos, 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 1083f26685..6eca5e9dbc 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 @@ -21,13 +21,17 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.asPaddingValues 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.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState @@ -655,7 +659,8 @@ private fun MediaViewerBottomBar( Box( modifier = Modifier .fillMaxWidth() - .heightIn(max = if (hasCompactHeightWindowSize()) maxCaptionHeightLandscape else maxCaptionHeightPortrait), + .heightIn(max = if (hasCompactHeightWindowSize()) maxCaptionHeightLandscape else maxCaptionHeightPortrait) + .padding(WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal).asPaddingValues()), ) { val textToRender = when { formattedCaption != null -> formattedCaption diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png index f831ed92a2..0ca6f66438 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7fe1f51d385bba8821dfc0f0da84990cf0d148e991d765484b343d8764abd47d -size 11724 +oid sha256:5896eb5df6f5398bdb94e74280d0d5c04b6a5a53c2378b7377c60fa58eef544b +size 12013 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index 1e04c3e7d7..fb72cafe03 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bbc8c05e6f6818d00282228f52424ebe93e6e3dca3431d742e8c652d56460d6 -size 11712 +oid sha256:4ef1b643a16b5a94c75f8bb845c36d3cbc7f7ed96a0cac32fdb9f0b09d26b4d1 +size 11747 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png index ee5c582240..58546b8522 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75de341f705bb22955f9399180519b65ad59c2e1917317d56e50ea4db78f35bc -size 12102 +oid sha256:30357bf18792db5ab20085010251170a724ffe8c00313facd04ee704e806af64 +size 10982 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png index 38ad0e4b56..83302d6ba4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:326d59cf768b2dbd96eb7964d54c8eda509a5cd57c6e62087625e3314da0bb4d -size 13658 +oid sha256:16dee1dfe746cd40dac9fe8f0af3ecb42cd14bab5cc490917b589beed065ed1b +size 14686 From 0cd163a680162bb0aaf3a805791a142225d162c1 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 28 Jul 2026 11:07:24 +0200 Subject: [PATCH 210/383] Import Compound tokens from `v10.2.3` (#7272) * Import Compound tokens from `v10.2.3` * Remove manually added `bgSubtleTertiary` semantic color: it's in Compound now * Bump enterprise module to a compatible commit --- .idea/kotlinc.xml | 4 ++-- enterprise | 2 +- .../event/TimelineItemGalleryView.kt | 1 - gradle.properties | 3 +++ .../compound/src/main/assets/theme.iife.js | 2 +- .../tokens/generated/SemanticColors.kt | 22 +++++++++++++++++-- .../tokens/generated/SemanticColorsDark.kt | 9 ++++++++ .../tokens/generated/SemanticColorsDarkHc.kt | 9 ++++++++ .../tokens/generated/SemanticColorsLight.kt | 9 ++++++++ .../tokens/generated/SemanticColorsLightHc.kt | 9 ++++++++ .../designsystem/theme/ColorAliases.kt | 5 ----- .../ElementRichTextEditorStyle.kt | 1 - 12 files changed, 63 insertions(+), 13 deletions(-) diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index 089816d5c8..cc87bc5140 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -2,6 +2,6 @@ - + \ No newline at end of file diff --git a/enterprise b/enterprise index 60de13ffd7..7bbf7db013 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit 60de13ffd7dea97fd4fec6fb6af49b5288e67ff2 +Subproject commit 7bbf7db0135c6a537ce360abb482922e6582d879 diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryView.kt index c7426f6f8d..3212d789f9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemGalleryView.kt @@ -43,7 +43,6 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.libraries.designsystem.components.blurhash.blurHashBackground import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight -import io.element.android.libraries.designsystem.theme.bgSubtleTertiary import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.ui.media.contentvalidation.ContentValidationValue diff --git a/gradle.properties b/gradle.properties index 4ffc90776d..4323d20107 100644 --- a/gradle.properties +++ b/gradle.properties @@ -65,3 +65,6 @@ roborazzi.test.verify=true # Needed after enabling proguard on AGP 8.13.1 android.r8.gradual.support=true + +# Enabled parallel sync for Gradle 9.4+ +org.gradle.tooling.parallel=true diff --git a/libraries/compound/src/main/assets/theme.iife.js b/libraries/compound/src/main/assets/theme.iife.js index 41e18ba6a0..d1629a95bb 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()};return`#${o(0)}${o(8)}${o(4)}${Math.round(((e,t,n)=>Math.min(Math.max(e,t),n))(r,0,1)*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/SemanticColors.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/tokens/generated/SemanticColors.kt index 6bc6c89a63..339179bbb2 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 @@ -29,6 +29,8 @@ data class SemanticColors( val bgAccentRest: Color, /** Background colour for accent or brand actions. State: Selected */ val bgAccentSelected: Color, + /** Accent colour, subtle shade for Text buttons Hover/press */ + val bgAccentSubtle: Color, /** Background colour for primary actions. State: Disabled. */ val bgActionPrimaryDisabled: Color, /** Background colour for primary actions. State: Hover. */ @@ -83,12 +85,20 @@ data class SemanticColors( val bgDecorative6: Color, /** Subtle background colour for informational elements. State: Rest. */ val bgInfoSubtle: Color, - /** Medium contrast surfaces. Elevation: Default (Level 2). */ + /** Medium contrast surfaces. Elevation: Default (Level 3). */ val bgSubtlePrimary: Color, - /** Low contrast surfaces. Elevation: Default (Level 1). */ + /** Low contrast surfaces. Elevation: Default (Level 2). */ val bgSubtleSecondary: Color, /** Lower contrast surfaces. Elevation: Level 0. */ val bgSubtleSecondaryLevel0: Color, + /** Lowest contrast surfaces. Elevation: Default (Level 1). */ + val bgSubtleTertiary: Color, + /** Hovered Background for success states */ + val bgSuccessHovered: Color, + /** Pressed Background for success states */ + val bgSuccessPressed: Color, + /** Default Background for success states */ + val bgSuccessRest: Color, /** Subtle background colour for success state elements. State: Rest. */ val bgSuccessSubtle: Color, /** Accent borders for containers */ @@ -113,6 +123,8 @@ data class SemanticColors( val borderInteractivePrimary: Color, /** ⚠️ Lowest contrast for non-accessible interactive element borders, <3:1. Only use for non-essential borders. Do not rely exclusively on them. State: Rest. */ val borderInteractiveSecondary: Color, + /** Border success state */ + val borderSuccessPrimary: Color, /** Subtle border colour for success state elements. */ val borderSuccessSubtle: Color, /** Background gradient stop for super and send buttons */ @@ -173,6 +185,8 @@ data class SemanticColors( val iconTertiary: Color, /** Translucent version of tertiary icon. Refer to it for intended use. */ val iconTertiaryAlpha: Color, + /** Warning icon */ + val iconWarningPrimary: 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 */ @@ -181,6 +195,8 @@ data class SemanticColors( val textActionAccent: Color, /** Default text colour for plain actions. */ val textActionPrimary: Color, + /** Text label success state */ + val textActionSuccess: Color, /** Badge accent text colour */ val textBadgeAccent: Color, /** Badge info text colour */ @@ -213,6 +229,8 @@ data class SemanticColors( val textSecondary: Color, /** Accent text colour for success state elements. */ val textSuccessPrimary: Color, + /** Warning text */ + val textWarningPrimary: Color, /** True for light theme, false for dark theme. */ val isLight: Boolean, ) 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 e9334de0e7..4f2ee4c93f 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 @@ -27,6 +27,7 @@ val compoundColorsDark = SemanticColors( bgAccentPressed = DarkColorTokens.colorGreen1100, bgAccentRest = DarkColorTokens.colorGreen900, bgAccentSelected = DarkColorTokens.colorAlphaGreen300, + bgAccentSubtle = DarkColorTokens.colorGreen200, bgActionPrimaryDisabled = DarkColorTokens.colorGray700, bgActionPrimaryHovered = DarkColorTokens.colorGray1200, bgActionPrimaryPressed = DarkColorTokens.colorGray1100, @@ -60,6 +61,10 @@ val compoundColorsDark = SemanticColors( bgSubtlePrimary = DarkColorTokens.colorGray400, bgSubtleSecondary = DarkColorTokens.colorGray300, bgSubtleSecondaryLevel0 = DarkColorTokens.colorThemeBg, + bgSubtleTertiary = DarkColorTokens.colorGray100, + bgSuccessHovered = DarkColorTokens.colorGreen1000, + bgSuccessPressed = DarkColorTokens.colorGreen1100, + bgSuccessRest = DarkColorTokens.colorGreen900, bgSuccessSubtle = DarkColorTokens.colorGreen200, borderAccentPrimary = DarkColorTokens.colorGreen900, borderAccentSubtle = DarkColorTokens.colorGreen700, @@ -72,6 +77,7 @@ val compoundColorsDark = SemanticColors( borderInteractiveHovered = DarkColorTokens.colorGray1100, borderInteractivePrimary = DarkColorTokens.colorGray800, borderInteractiveSecondary = DarkColorTokens.colorGray600, + borderSuccessPrimary = DarkColorTokens.colorGreen900, borderSuccessSubtle = DarkColorTokens.colorGreen500, gradientActionStop1 = DarkColorTokens.colorGreen1100, gradientActionStop2 = DarkColorTokens.colorGreen900, @@ -102,10 +108,12 @@ val compoundColorsDark = SemanticColors( iconSuccessPrimary = DarkColorTokens.colorGreen900, iconTertiary = DarkColorTokens.colorGray800, iconTertiaryAlpha = DarkColorTokens.colorAlphaGray800, + iconWarningPrimary = DarkColorTokens.colorOrange900, separatorPrimary = DarkColorTokens.colorGray400, separatorSecondary = DarkColorTokens.colorGray300, textActionAccent = DarkColorTokens.colorGreen900, textActionPrimary = DarkColorTokens.colorGray1400, + textActionSuccess = DarkColorTokens.colorGreen900, textBadgeAccent = DarkColorTokens.colorGreen1100, textBadgeInfo = DarkColorTokens.colorBlue1100, textCriticalPrimary = DarkColorTokens.colorRed900, @@ -122,5 +130,6 @@ val compoundColorsDark = SemanticColors( textPrimary = DarkColorTokens.colorGray1400, textSecondary = DarkColorTokens.colorGray900, textSuccessPrimary = DarkColorTokens.colorGreen900, + textWarningPrimary = DarkColorTokens.colorOrange900, isLight = false, ) 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 a3ef51cff1..21c5ccb482 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 @@ -27,6 +27,7 @@ val compoundColorsHcDark = SemanticColors( bgAccentPressed = DarkHcColorTokens.colorGreen1100, bgAccentRest = DarkHcColorTokens.colorGreen900, bgAccentSelected = DarkHcColorTokens.colorAlphaGreen300, + bgAccentSubtle = DarkHcColorTokens.colorGreen200, bgActionPrimaryDisabled = DarkHcColorTokens.colorGray700, bgActionPrimaryHovered = DarkHcColorTokens.colorGray1200, bgActionPrimaryPressed = DarkHcColorTokens.colorGray1100, @@ -60,6 +61,10 @@ val compoundColorsHcDark = SemanticColors( bgSubtlePrimary = DarkHcColorTokens.colorGray400, bgSubtleSecondary = DarkHcColorTokens.colorGray300, bgSubtleSecondaryLevel0 = DarkHcColorTokens.colorThemeBg, + bgSubtleTertiary = DarkHcColorTokens.colorGray100, + bgSuccessHovered = DarkHcColorTokens.colorGreen1000, + bgSuccessPressed = DarkHcColorTokens.colorGreen1100, + bgSuccessRest = DarkHcColorTokens.colorGreen900, bgSuccessSubtle = DarkHcColorTokens.colorGreen200, borderAccentPrimary = DarkHcColorTokens.colorGreen900, borderAccentSubtle = DarkHcColorTokens.colorGreen700, @@ -72,6 +77,7 @@ val compoundColorsHcDark = SemanticColors( borderInteractiveHovered = DarkHcColorTokens.colorGray1100, borderInteractivePrimary = DarkHcColorTokens.colorGray800, borderInteractiveSecondary = DarkHcColorTokens.colorGray600, + borderSuccessPrimary = DarkHcColorTokens.colorGreen900, borderSuccessSubtle = DarkHcColorTokens.colorGreen500, gradientActionStop1 = DarkHcColorTokens.colorGreen1100, gradientActionStop2 = DarkHcColorTokens.colorGreen900, @@ -102,10 +108,12 @@ val compoundColorsHcDark = SemanticColors( iconSuccessPrimary = DarkHcColorTokens.colorGreen900, iconTertiary = DarkHcColorTokens.colorGray800, iconTertiaryAlpha = DarkHcColorTokens.colorAlphaGray800, + iconWarningPrimary = DarkHcColorTokens.colorOrange900, separatorPrimary = DarkHcColorTokens.colorGray400, separatorSecondary = DarkHcColorTokens.colorGray300, textActionAccent = DarkHcColorTokens.colorGreen900, textActionPrimary = DarkHcColorTokens.colorGray1400, + textActionSuccess = DarkHcColorTokens.colorGreen900, textBadgeAccent = DarkHcColorTokens.colorGreen1100, textBadgeInfo = DarkHcColorTokens.colorBlue1100, textCriticalPrimary = DarkHcColorTokens.colorRed900, @@ -122,5 +130,6 @@ val compoundColorsHcDark = SemanticColors( textPrimary = DarkHcColorTokens.colorGray1400, textSecondary = DarkHcColorTokens.colorGray900, textSuccessPrimary = DarkHcColorTokens.colorGreen900, + textWarningPrimary = DarkHcColorTokens.colorOrange900, isLight = false, ) 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 75153cb66b..17fa8d0875 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 @@ -27,6 +27,7 @@ val compoundColorsLight = SemanticColors( bgAccentPressed = LightColorTokens.colorGreen1100, bgAccentRest = LightColorTokens.colorGreen900, bgAccentSelected = LightColorTokens.colorAlphaGreen300, + bgAccentSubtle = LightColorTokens.colorGreen200, bgActionPrimaryDisabled = LightColorTokens.colorGray700, bgActionPrimaryHovered = LightColorTokens.colorGray1200, bgActionPrimaryPressed = LightColorTokens.colorGray1100, @@ -60,6 +61,10 @@ val compoundColorsLight = SemanticColors( bgSubtlePrimary = LightColorTokens.colorGray400, bgSubtleSecondary = LightColorTokens.colorGray300, bgSubtleSecondaryLevel0 = LightColorTokens.colorGray300, + bgSubtleTertiary = LightColorTokens.colorGray100, + bgSuccessHovered = LightColorTokens.colorGreen1000, + bgSuccessPressed = LightColorTokens.colorGreen1100, + bgSuccessRest = LightColorTokens.colorGreen900, bgSuccessSubtle = LightColorTokens.colorGreen200, borderAccentPrimary = LightColorTokens.colorGreen900, borderAccentSubtle = LightColorTokens.colorGreen700, @@ -72,6 +77,7 @@ val compoundColorsLight = SemanticColors( borderInteractiveHovered = LightColorTokens.colorGray1100, borderInteractivePrimary = LightColorTokens.colorGray800, borderInteractiveSecondary = LightColorTokens.colorGray600, + borderSuccessPrimary = LightColorTokens.colorGreen900, borderSuccessSubtle = LightColorTokens.colorGreen500, gradientActionStop1 = LightColorTokens.colorGreen500, gradientActionStop2 = LightColorTokens.colorGreen700, @@ -102,10 +108,12 @@ val compoundColorsLight = SemanticColors( iconSuccessPrimary = LightColorTokens.colorGreen900, iconTertiary = LightColorTokens.colorGray800, iconTertiaryAlpha = LightColorTokens.colorAlphaGray800, + iconWarningPrimary = LightColorTokens.colorOrange900, separatorPrimary = LightColorTokens.colorGray400, separatorSecondary = LightColorTokens.colorGray300, textActionAccent = LightColorTokens.colorGreen900, textActionPrimary = LightColorTokens.colorGray1400, + textActionSuccess = LightColorTokens.colorGreen900, textBadgeAccent = LightColorTokens.colorGreen1100, textBadgeInfo = LightColorTokens.colorBlue1100, textCriticalPrimary = LightColorTokens.colorRed900, @@ -122,5 +130,6 @@ val compoundColorsLight = SemanticColors( textPrimary = LightColorTokens.colorGray1400, textSecondary = LightColorTokens.colorGray900, textSuccessPrimary = LightColorTokens.colorGreen900, + textWarningPrimary = LightColorTokens.colorOrange900, isLight = true, ) 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 fa40a2e2ab..1f8ddc2f85 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 @@ -27,6 +27,7 @@ val compoundColorsHcLight = SemanticColors( bgAccentPressed = LightHcColorTokens.colorGreen1100, bgAccentRest = LightHcColorTokens.colorGreen900, bgAccentSelected = LightHcColorTokens.colorAlphaGreen300, + bgAccentSubtle = LightHcColorTokens.colorGreen200, bgActionPrimaryDisabled = LightHcColorTokens.colorGray700, bgActionPrimaryHovered = LightHcColorTokens.colorGray1200, bgActionPrimaryPressed = LightHcColorTokens.colorGray1100, @@ -60,6 +61,10 @@ val compoundColorsHcLight = SemanticColors( bgSubtlePrimary = LightHcColorTokens.colorGray400, bgSubtleSecondary = LightHcColorTokens.colorGray300, bgSubtleSecondaryLevel0 = LightHcColorTokens.colorGray300, + bgSubtleTertiary = LightHcColorTokens.colorGray100, + bgSuccessHovered = LightHcColorTokens.colorGreen1000, + bgSuccessPressed = LightHcColorTokens.colorGreen1100, + bgSuccessRest = LightHcColorTokens.colorGreen900, bgSuccessSubtle = LightHcColorTokens.colorGreen200, borderAccentPrimary = LightHcColorTokens.colorGreen900, borderAccentSubtle = LightHcColorTokens.colorGreen700, @@ -72,6 +77,7 @@ val compoundColorsHcLight = SemanticColors( borderInteractiveHovered = LightHcColorTokens.colorGray1100, borderInteractivePrimary = LightHcColorTokens.colorGray800, borderInteractiveSecondary = LightHcColorTokens.colorGray600, + borderSuccessPrimary = LightHcColorTokens.colorGreen900, borderSuccessSubtle = LightHcColorTokens.colorGreen500, gradientActionStop1 = LightHcColorTokens.colorGreen500, gradientActionStop2 = LightHcColorTokens.colorGreen700, @@ -102,10 +108,12 @@ val compoundColorsHcLight = SemanticColors( iconSuccessPrimary = LightHcColorTokens.colorGreen900, iconTertiary = LightHcColorTokens.colorGray800, iconTertiaryAlpha = LightHcColorTokens.colorAlphaGray800, + iconWarningPrimary = LightHcColorTokens.colorOrange900, separatorPrimary = LightHcColorTokens.colorGray400, separatorSecondary = LightHcColorTokens.colorGray300, textActionAccent = LightHcColorTokens.colorGreen900, textActionPrimary = LightHcColorTokens.colorGray1400, + textActionSuccess = LightHcColorTokens.colorGreen900, textBadgeAccent = LightHcColorTokens.colorGreen1100, textBadgeInfo = LightHcColorTokens.colorBlue1100, textCriticalPrimary = LightHcColorTokens.colorRed900, @@ -122,5 +130,6 @@ val compoundColorsHcLight = SemanticColors( textPrimary = LightHcColorTokens.colorGray1400, textSecondary = LightHcColorTokens.colorGray900, textSuccessPrimary = LightHcColorTokens.colorGreen900, + textWarningPrimary = LightHcColorTokens.colorOrange900, isLight = true, ) 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 8973e312ce..80ef3b9b26 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 @@ -53,11 +53,6 @@ val SemanticColors.messageFromOtherBackground val SemanticColors.progressIndicatorTrackColor get() = if (isLight) LightColorTokens.colorAlphaGray500 else DarkColorTokens.colorAlphaGray500 -// This color is not present in Semantic color, so put hard-coded value for now -@OptIn(CoreColorToken::class) -val SemanticColors.bgSubtleTertiary - get() = if (isLight) LightColorTokens.colorGray100 else DarkColorTokens.colorGray100 - // Temporary color, which is not in the token right now val SemanticColors.temporaryColorBgSpecial get() = if (isLight) Color(0xFFE4E8F0) else Color(0xFF3A4048) diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ElementRichTextEditorStyle.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ElementRichTextEditorStyle.kt index 8f6421b654..7300430c41 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ElementRichTextEditorStyle.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/ElementRichTextEditorStyle.kt @@ -15,7 +15,6 @@ import androidx.compose.ui.graphics.isSpecified import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme -import io.element.android.libraries.designsystem.theme.bgSubtleTertiary import io.element.android.wysiwyg.compose.RichTextEditorDefaults import io.element.android.wysiwyg.compose.RichTextEditorStyle From fe24aeb2ce6ee230c6792ac26423b5ec57f6e177 Mon Sep 17 00:00:00 2001 From: Jenna Vassar Date: Tue, 28 Jul 2026 03:30:06 -0700 Subject: [PATCH 211/383] Add a password strength estimator wrapping the SDK zxcvbn API (#7186) * Add a password strength estimator wrapping the SDK zxcvbn API * Add tests for the password strength estimator SDK mapping --------- Co-authored-by: ElementBot --- .../encryption/PasswordStrengthEstimator.kt | 59 +++++++++++++++++++ .../RustPasswordStrengthEstimator.kt | 43 ++++++++++++++ .../RustPasswordStrengthEstimatorTest.kt | 52 ++++++++++++++++ .../FakePasswordStrengthEstimator.kt | 30 ++++++++++ 4 files changed, 184 insertions(+) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/PasswordStrengthEstimator.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustPasswordStrengthEstimator.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RustPasswordStrengthEstimatorTest.kt create mode 100644 libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakePasswordStrengthEstimator.kt diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/PasswordStrengthEstimator.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/PasswordStrengthEstimator.kt new file mode 100644 index 0000000000..62322781d5 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/PasswordStrengthEstimator.kt @@ -0,0 +1,59 @@ +/* + * 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.encryption + +/** + * Estimates the strength of a password or passphrase using the zxcvbn algorithm, + * as exposed by the Rust SDK. Backed by pattern matching (dictionary words, + * keyboard walks, repeats, dates, l33t speak, …) rather than naive per-character + * entropy, so it agrees with the iOS client for cross-platform parity. + * + * App-scoped: obtain an instance via dependency injection rather than constructing one. + */ +interface PasswordStrengthEstimator { + /** + * Estimate the strength of [password]. + * + * @param password the password or passphrase to evaluate. + * @param userInputs optional context (e.g. user ID, display name, email) that the + * estimator penalises when it appears inside the password, so personal information + * does not inflate the score. + */ + fun estimate(password: String, userInputs: List = emptyList()): PasswordStrengthEstimate +} + +/** + * The result of a [PasswordStrengthEstimator.estimate] call. + */ +data class PasswordStrengthEstimate( + /** Overall ranking, from [PasswordStrengthRanking.VeryWeak] to [PasswordStrengthRanking.VeryStrong]. */ + val ranking: PasswordStrengthRanking, + /** + * `log10` of the estimated number of guesses needed to crack the password. Grows without an + * upper bound and is independent of any threshold configuration. + */ + val score: Double, + /** + * [score] normalized to `0.0..1.0` against the estimator's `VeryStrong` threshold + * (`score / veryStrong`), suitable for driving a strength meter. Scores above the `VeryStrong` + * threshold can exceed `1.0`, so clamp before use. + */ + val normalScore: Double, +) + +/** + * A ranking of estimated password strength. Derived by the SDK from [PasswordStrengthEstimate.score] + * against a fixed set of thresholds tuned for modern hardware. + */ +enum class PasswordStrengthRanking { + VeryWeak, + Weak, + Fair, + Strong, + VeryStrong, +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustPasswordStrengthEstimator.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustPasswordStrengthEstimator.kt new file mode 100644 index 0000000000..13cba9d759 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustPasswordStrengthEstimator.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.encryption + +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.matrix.api.encryption.PasswordStrengthEstimate +import io.element.android.libraries.matrix.api.encryption.PasswordStrengthEstimator +import io.element.android.libraries.matrix.api.encryption.PasswordStrengthRanking +import org.matrix.rustcomponents.sdk.PasswordStrengthEstimate as SdkPasswordStrengthEstimate +import org.matrix.rustcomponents.sdk.PasswordStrengthEstimator as SdkPasswordStrengthEstimator +import org.matrix.rustcomponents.sdk.PasswordStrengthRanking as SdkPasswordStrengthRanking + +@ContributesBinding(AppScope::class) +class RustPasswordStrengthEstimator : PasswordStrengthEstimator { + // The SDK ranking is derived from caller-supplied thresholds. We use the "modern hardware (2025)" + // preset so Android and iOS rank passphrases identically. The zxcvbn estimator holds no per-password + // state, so a single app-scoped instance is reused for every keystroke rather than reconstructed. + private val estimator by lazy { SdkPasswordStrengthEstimator.withModernDefaults2025() } + + override fun estimate(password: String, userInputs: List): PasswordStrengthEstimate { + return estimator.estimate(password, userInputs).toApiModel() + } +} + +internal fun SdkPasswordStrengthEstimate.toApiModel() = PasswordStrengthEstimate( + ranking = ranking.toApiModel(), + score = score, + normalScore = normalScore, +) + +internal fun SdkPasswordStrengthRanking.toApiModel() = when (this) { + SdkPasswordStrengthRanking.VERY_WEAK -> PasswordStrengthRanking.VeryWeak + SdkPasswordStrengthRanking.WEAK -> PasswordStrengthRanking.Weak + SdkPasswordStrengthRanking.FAIR -> PasswordStrengthRanking.Fair + SdkPasswordStrengthRanking.STRONG -> PasswordStrengthRanking.Strong + SdkPasswordStrengthRanking.VERY_STRONG -> PasswordStrengthRanking.VeryStrong +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RustPasswordStrengthEstimatorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RustPasswordStrengthEstimatorTest.kt new file mode 100644 index 0000000000..affe8195d9 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RustPasswordStrengthEstimatorTest.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.libraries.matrix.impl.encryption + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.encryption.PasswordStrengthRanking +import io.element.android.libraries.matrix.test.encryption.FakePasswordStrengthEstimator +import io.element.android.libraries.matrix.test.encryption.aPasswordStrengthEstimate +import org.junit.Test +import org.matrix.rustcomponents.sdk.PasswordStrengthEstimate as SdkPasswordStrengthEstimate +import org.matrix.rustcomponents.sdk.PasswordStrengthRanking as SdkPasswordStrengthRanking + +class RustPasswordStrengthEstimatorTest { + @Test + fun `each SDK ranking maps to the matching api ranking`() { + assertThat(SdkPasswordStrengthRanking.VERY_WEAK.toApiModel()).isEqualTo(PasswordStrengthRanking.VeryWeak) + assertThat(SdkPasswordStrengthRanking.WEAK.toApiModel()).isEqualTo(PasswordStrengthRanking.Weak) + assertThat(SdkPasswordStrengthRanking.FAIR.toApiModel()).isEqualTo(PasswordStrengthRanking.Fair) + assertThat(SdkPasswordStrengthRanking.STRONG.toApiModel()).isEqualTo(PasswordStrengthRanking.Strong) + assertThat(SdkPasswordStrengthRanking.VERY_STRONG.toApiModel()).isEqualTo(PasswordStrengthRanking.VeryStrong) + } + + @Test + fun `an SDK estimate forwards its ranking, score and normalScore to the api model`() { + val sdkEstimate = SdkPasswordStrengthEstimate( + ranking = SdkPasswordStrengthRanking.FAIR, + guesses = 1_000_000uL, + score = 6.0, + normalScore = 0.35, + feedback = null, + ) + assertThat(sdkEstimate.toApiModel()).isEqualTo( + aPasswordStrengthEstimate( + ranking = PasswordStrengthRanking.Fair, + score = 6.0, + normalScore = 0.35, + ) + ) + } + + @Test + fun `the fake estimator returns its configured estimate`() { + val estimate = aPasswordStrengthEstimate(ranking = PasswordStrengthRanking.Strong) + val fake = FakePasswordStrengthEstimator { _, _ -> estimate } + assertThat(fake.estimate("hunter2")).isEqualTo(estimate) + } +} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakePasswordStrengthEstimator.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakePasswordStrengthEstimator.kt new file mode 100644 index 0000000000..b74e021a2e --- /dev/null +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakePasswordStrengthEstimator.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.test.encryption + +import io.element.android.libraries.matrix.api.encryption.PasswordStrengthEstimate +import io.element.android.libraries.matrix.api.encryption.PasswordStrengthEstimator +import io.element.android.libraries.matrix.api.encryption.PasswordStrengthRanking + +class FakePasswordStrengthEstimator( + private val estimateResult: (password: String, userInputs: List) -> PasswordStrengthEstimate = + { _, _ -> aPasswordStrengthEstimate() }, +) : PasswordStrengthEstimator { + override fun estimate(password: String, userInputs: List): PasswordStrengthEstimate = + estimateResult(password, userInputs) +} + +fun aPasswordStrengthEstimate( + ranking: PasswordStrengthRanking = PasswordStrengthRanking.Strong, + score: Double = 18.0, + normalScore: Double = 0.7, +) = PasswordStrengthEstimate( + ranking = ranking, + score = score, + normalScore = normalScore, +) From ea3788abd13759fa70d9edfe72b064e50800c51a Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 28 Jul 2026 14:51:37 +0200 Subject: [PATCH 212/383] Sync Strings from Localazy --- .../src/main/res/values-uk/translations.xml | 1 + .../src/main/res/values-nb/translations.xml | 2 +- .../src/main/res/values-uk/translations.xml | 5 +++++ .../src/main/res/values-uk/translations.xml | 6 ++++++ .../src/main/res/values-uk/translations.xml | 1 + .../src/main/res/values-zh/translations.xml | 1 + .../push/impl/src/main/res/values/localazy.xml | 1 + .../src/main/res/values-uk/translations.xml | 17 +++++++++++++++++ 8 files changed, 33 insertions(+), 1 deletion(-) 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 752b5ead3f..6f0fc7f3e0 100644 --- a/features/linknewdevice/impl/src/main/res/values-uk/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-uk/translations.xml @@ -5,6 +5,7 @@ "Зіскануйте QR-код цим пристроєм" "Готовий до сканування" "Відкрийте %1$s на комп\'ютері, щоб отримати QR-код" + "Скануйте QR-код лише після виконання наведених вище кроків на своєму власному пристрої. Ніколи не скануйте код, надісланий іншою особою." "Цифри не збігаються" "Введіть 2-значний код" "Це підтвердить, що з\'єднання з іншим пристроєм захищене." diff --git a/features/messages/impl/src/main/res/values-nb/translations.xml b/features/messages/impl/src/main/res/values-nb/translations.xml index a510d020d6..9faf74130c 100644 --- a/features/messages/impl/src/main/res/values-nb/translations.xml +++ b/features/messages/impl/src/main/res/values-nb/translations.xml @@ -29,7 +29,7 @@ "Fil %1$d av %2$d" "Optimaliser bildekvaliteten" "Behandler…" - "Legg til media" + "Legg til medier" "Blokker bruker" "Kryss av for om du vil skjule alle nåværende og fremtidige meldinger fra denne brukeren" "Denne meldingen vil bli rapportert til hjemmeserverens administratorer. De vil ikke kunne lese noen krypterte meldinger." 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 c5f5ddde91..1e35a2eee1 100644 --- a/features/messages/impl/src/main/res/values-uk/translations.xml +++ b/features/messages/impl/src/main/res/values-uk/translations.xml @@ -73,6 +73,11 @@ "Показати більше" "Показати підсумок реакцій" "Нове" + + "%1$d вилучене повідомлення" + "%1$d вилучені повідомлення" + "%1$d вилучених повідомлень" + "%1$d зміна в кімнаті" "%1$d зміни в кімнаті" 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 9ddc896a19..db42d153aa 100644 --- a/features/preferences/impl/src/main/res/values-uk/translations.xml +++ b/features/preferences/impl/src/main/res/values-uk/translations.xml @@ -94,6 +94,7 @@ "Помилка імпорту файлу" "Проблема з попереднім прослуховуванням звуку сповіщення" "Звук" + "Відхилити помилку звукового сповіщення" "Проблема налаштовування звуку сповіщення" "Без звуку" "Як у системі" @@ -101,6 +102,11 @@ "системні налаштування" "Системні сповіщення вимкнені" "Сповіщення" + "Не на місці" + "Зараз повернуся" + "Власний…" + "Власний статус…" + "Зосереджений(а)" "На зустрічі" "У дорозі" "Який у вас статус?" 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 345fe6a7be..253bebda78 100644 --- a/libraries/push/impl/src/main/res/values-uk/translations.xml +++ b/libraries/push/impl/src/main/res/values-uk/translations.xml @@ -34,6 +34,7 @@ "Запрошує вас до бесіди" "%1$s запрошує вас до бесіди" + "Починає ділитися своїм поточним місцем розташування" "Вас згадує: %1$s" "Нові повідомлення" 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 7532f16ba0..155c9d8ce6 100644 --- a/libraries/push/impl/src/main/res/values-zh/translations.xml +++ b/libraries/push/impl/src/main/res/values-zh/translations.xml @@ -26,6 +26,7 @@ "已邀请你聊天" "%1$s 已邀请你聊天" + "已开始共享其实时位置" "提到了你:%1$s" "新消息" diff --git a/libraries/push/impl/src/main/res/values/localazy.xml b/libraries/push/impl/src/main/res/values/localazy.xml index d680ffeb5a..1620408c15 100644 --- a/libraries/push/impl/src/main/res/values/localazy.xml +++ b/libraries/push/impl/src/main/res/values/localazy.xml @@ -30,6 +30,7 @@ "Invited you to chat" "%1$s invited you to chat" + "Started sharing their live location" "Mentioned you: %1$s" "New Messages" 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 d645fa7162..9e93cdb891 100644 --- a/libraries/ui-strings/src/main/res/values-uk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uk/translations.xml @@ -273,6 +273,16 @@ "Переслати повідомлення" "Частовживані" "Галерея" + + "%1$d вкладення…" + "%1$d вкладення…" + "%1$d вкладень…" + + + "%1$d медіаелемент…" + "%1$d медіаелементи…" + "%1$d медіаелементів…" + "GIF" "Триває груповий виклик" "Зображення" @@ -521,6 +531,8 @@ "%1$d осіб" "На карті" + "Ваш домашній сервер перебуває у вашій локальній мережі. Щоб приєднатися, %1$s повинен мати право доступу до пристроїв у цій мережі." + "Дозволити доступ до локальної мережі" "Не вдалося вибрати медіафайл, спробуйте ще раз." "Натисніть на повідомлення і виберіть \"%1$s\", щоб додати його сюди." "Закріпіть важливі повідомлення, щоб їх можна було легко знайти" @@ -567,6 +579,11 @@ "Простори" "Надано доступ %1$s" "На карті" + + "%1$d приєднується" + "%1$d приєдналися" + "%1$d приєдналися" + "Повідомлення не надіслано, оскільки звірена цифрова ідентичність %1$s була скинута." "Повідомлення не надіслано, оскільки %1$s перевірив не всі пристрої." "Повідомлення не надіслано, оскільки ви не звірили один або кілька своїх пристроїв." From f5b01958523e8490ff9f887982d1777c637de147 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 28 Jul 2026 13:17:45 +0000 Subject: [PATCH 213/383] Update screenshots --- ...krequests.impl.banner_KnockRequestsBannerView_Day_5_en.png | 4 ++-- ...knockrequests.impl.list_KnockRequestsListView_Day_3_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_3_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_7_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_1_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_5_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_9_en.png | 4 ++-- ...rypto.identity_MessagesViewWithIdentityChange_Day_2_en.png | 4 ++-- ....resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png | 4 ++-- ...meline.components.event_ATimelineItemEventRow_Day_0_en.png | 4 ++-- ...ents_TimelineItemEventRowWithReplyInformative_Day_1_en.png | 4 ++-- ...components_TimelineItemEventRowWithReplyOther_Day_1_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_1_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_5_en.png | 4 ++-- ...line.components_TimelineItemEventRowWithReply_Day_9_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_1_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_5_en.png | 4 ++-- ...ne.components_TimelineItemEventRowWithReply_Night_9_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_11_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_3_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Day_7_en.png | 4 ++-- .../features.messages.impl_MessagesView_Night_11_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_3_en.png | 4 ++-- .../images/features.messages.impl_MessagesView_Night_7_en.png | 4 ++-- ...ferences.impl.blockedusers_BlockedUsersView_Night_4_en.png | 4 ++-- ...embermoderation.impl_RoomMemberModerationView_Day_5_en.png | 4 ++-- ...bermoderation.impl_RoomMemberModerationView_Night_7_en.png | 4 ++-- ...e.components_HorizontalFloatingToolbarNoFab_Night_0_en.png | 4 ++-- 28 files changed, 56 insertions(+), 56 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en.png index 5fe8e62f96..ae365f5143 100644 --- a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2e211a700dfcefab1927926ecd2ab1eee2ceaed6980657e1bad1e70bbc69dd5 -size 29522 +oid sha256:645349979f0789dd674b9efcaee305a35955725c5c4d24599984aefc3a61b18f +size 32005 diff --git a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_3_en.png index d002a79378..93d24c8613 100644 --- a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab30267a07b1ceb43c1a7f854e758c68123812d99054f6e94db4cccf3214a2b4 -size 41479 +oid sha256:3cd12ed914f8c161ef845feaaec416eec9ef1ae6d23d71fb444c93d1388738ea +size 41736 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png index aa9893db72..3f99f935c9 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e88b079d9e8633d0c46aa18074f728fce8deb792451d3db982c2918ade3af474 -size 32505 +oid sha256:ccb0deee31506379cfa76f8d39d37639b6b1f03d7eb2e7d5e8c6ceff300b1978 +size 30397 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 index 664a1fac0f..e8ae396119 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a3763a54a079f3f0724ab896b07b2cd29449d23a2c963f3fd4b5b9d3d92aa4b -size 42359 +oid sha256:ddaf978cdf3e70b01fbee75e7e7290fa390e749b48ae192fe7da0dcaa9a1d4dc +size 38417 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png index 3b13f8bfa5..bf0e1594e1 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1fb1e95c7a6ef163c2ca4c07f11ca06e83b828f2e59873743fd76176441eef78 -size 36921 +oid sha256:001bcd1755e837c0c05e493f964ee5c71fba81e811bdaf91effba257743bdacb +size 34836 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 e1d6b96687..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:ae7f05084edddddacc2d996e73fe7a5a3a575e5b07558428a8adbbf8c3855132 -size 21619 +oid sha256:69bcf19161f70c27256c1bf0e5b99c993c86dd3e77a42d0e87061730a5c0c752 +size 21649 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 index 5d663d4072..213a75dce9 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2bf5dfabb925d2e94a3f17337e72c502e4bfb2e228487f81b4d67d920247266 -size 19929 +oid sha256:5198742a388a2bd04985fe6b9f035de3878125607fe3b554209b0eb5c4590db3 +size 19935 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png index 5289eaca63..4185f46b51 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:65f9ee083a73669a0d3f9d88141a610ea53f3c39e89d8f706d414b04555b4764 -size 59321 +oid sha256:085963fcb425147d35a9ad947a7a3e4ba4712bd3d2f32e93099ff15cffe83b88 +size 64761 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png index bd73e322ab..0cf6c10c4e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12020ba97720f2374f9ace172693f08be01522e4ca30d3970efa91d802581e81 -size 3657 +oid sha256:49f0bb16d3d57b59242e704e3dd4e8885c59721a42129837ff6a4f0d7d02de11 +size 54433 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 index 0ab00359b7..12bd190dd1 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b5e6f4c5ec97e67bb20f03f25f18d9f32d5d1aed5ff30d161b331894ad03443 -size 647384 +oid sha256:ce15ca9f89274620728715e3448ce671e2253f4fed22a44035460e9a3709ca0b +size 647404 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 195aa04fe2..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:76e5ae44362792d570cd82f3910c8bd0acde509b8418c5892e0385e7d636f042 -size 370223 +oid sha256:8344427a0fe87cbf0883ff53a9ee4dcf90976a7011f6618d85961df48b2c53a9 +size 370228 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 73b7e674e2..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:991deacdfb7bc371a2df960a2364ae3b2187e588aa5afe7f39409e367040dd9c -size 363893 +oid sha256:a4ac79f3b8fb4e231244bd96b244a4f2526d6ed28d558f9d50734d83bbb74992 +size 363909 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 b5dac8434c..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:1a92f8af94682facac66d4aacb6e49f345561c15be2f8b689041b78aeaaae831 -size 345062 +oid sha256:6ca8cf82aa8ab1bdad56a27584b27789402aeb7ad8fadd038280a376fb75a72c +size 345094 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 d7b969fd5b..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:2528df873713755f542f61cd794080929586c1bd5f316c0378ce9e837c21d50b -size 397145 +oid sha256:426d1c844a8c88281c5fa4c61916d93278fdfd38f8cdf2dc54bf1a821f2de3eb +size 397167 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 0021619c44..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:7b23d3a37774283067a8919b8c332b1bb5a79e90dceb7216b484b985491282e5 -size 355389 +oid sha256:3ec1b0244dab22414c6719b3309426e13128d0c70fb67dc66cd8a60d42521fd0 +size 355411 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 47a9a6b630..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:54372845e922d047408dd960d048b9b5eae2263d589117d8e7d197741aa34f32 -size 342827 +oid sha256:4bee12a6bdb18fea5ac6997671bfcb903296da7278cf69b2456330066ca31dfb +size 342870 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 b51a89586b..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:e642229c58169775fe702769a306bbef22698516ae6f7ac75a761213c3f195fa -size 395446 +oid sha256:217ac95bf476c53d2dc6d3d0143b21312bf38b8ab86c8dfd4f9360582b584f9d +size 395476 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 c9227ebf94..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:e614f4a8657637c584a283d69124236d00fe1251c2b8d739c5688a57a6fd152e -size 353693 +oid sha256:756f0cff90ddd61adce2f467c0384d74d430f6d51c091e4980e45bcc9ee6f0fd +size 353705 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 ee23a7111d..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:38ae233a128e887efc48da73be3d6ce50a7095601315ed49a3c9cb209ffdda26 -size 58352 +oid sha256:9b071ba6e99b68dcc75f5aaed3a879f2e30614c954b88c6dc05e1dfec57f1079 +size 65771 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 f6456f0ec1..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:22153168f6f3e84ab789faea29c94fffbc1a5e4c1b9a98deccb0460192fdde23 -size 57213 +oid sha256:0d4f03ac10bbb676d272dba906e758b25d633a1da1e249fe23ba825f8d2f4901 +size 55298 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 b3af9d831a..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:ce795c4e32a1be3d57f6b1c87588d8c7ed0442996ab9d8a96f1ec5a07627e598 -size 59663 +oid sha256:bd0de7412503e93c33cf92dde0cff38bb68555ef176080d913320af5e4942e7a +size 58642 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 6e8468054f..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:262e8d4b8daa2d25593834fd0ab5d7019b0a3dd13707aa96e0701bf9240c6525 -size 59809 +oid sha256:10bce6df962a5198f019f509b1cdb55e28195587de4b74742ddc29833f1333a4 +size 69216 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 3974618f39..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:718d5c9f24c114f3bf88e000b637ea19598d7bb9b97001ba137fc12a6a1285e4 -size 52608 +oid sha256:5e900ff75d02c9db4200e2032444dd7e2f8635973cca3389dd96d7d2bb734061 +size 50757 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 7261c9b671..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:7cf3d727da78b39ecf24d4df7db0884af9008db67cc92274849c1b0978f87726 -size 59252 +oid sha256:ed13a2778b8ced86ee41d5460d274b42b714a87f59749e3b26bf75114ef40dd9 +size 58265 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png index 616c06bf46..a68f886f73 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ce2519906f1aaf34700ca9ba4bdeaa72030f1f5aff3f7e24352a1435ac67d98 -size 53966 +oid sha256:e5a2e306087a967849f61872b56a83f194d1a76df5723f0bbae6e6e2f4a98c63 +size 55725 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png index 5c597300e4..73b8b8e50c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 -size 3853 +oid sha256:e8a3ad99763929d2783147814e44fa9ec7e7efb7b99949e3580f23c38fb5d971 +size 9398 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png index d47bf90664..a87d89c701 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c -size 3664 +oid sha256:0f3a0cb5d9bae6725a1c527f3d9575aabf85d3edf63a28d9faa23f4f0b65e2d0 +size 7624 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png index 52fd9b9693..fedead0fa8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58b9491aaa5554b89d86c62a5c9c44975367538c6baa5562f8dc5768f76d8264 -size 8705 +oid sha256:4811667dec0f32accc5e2c8a5dd5c0b34017fcff8d1e0376ee7a4708426bca0f +size 9838 From c2e86767739fc2ea497bc59869c4349912f9d349 Mon Sep 17 00:00:00 2001 From: Jenna Vassar Date: Tue, 28 Jul 2026 06:35:27 -0700 Subject: [PATCH 214/383] Update keyboard visibility to track hasFocus (#7284) --- .../modifiers/BringIntoViewOnImeVisible.kt | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/modifiers/BringIntoViewOnImeVisible.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/modifiers/BringIntoViewOnImeVisible.kt index 155172c96f..90dd40c891 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/modifiers/BringIntoViewOnImeVisible.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/modifiers/BringIntoViewOnImeVisible.kt @@ -25,25 +25,28 @@ import kotlinx.coroutines.delay import kotlin.time.Duration.Companion.milliseconds /** - * Keeps the focused field visible above the keyboard. Intended for a field inside a scrollable - * container: the field is never clipped by a pinned footer, but the IME is shown only after focus - * arrives, so we re-request bringIntoView once it is visible to scroll the field back into the - * reduced viewport. + * Keeps a focused field visible above the keyboard. Intended for a field — or a group that wraps + * one — inside a scrollable container: the content is never clipped by a pinned footer, but the IME + * is shown only after focus arrives, so we re-request bringIntoView once it is visible to scroll the + * content back into the reduced viewport. + * + * Tracks focus via `hasFocus` rather than `isFocused`, so it also works when applied to a wrapper + * whose child — rather than the wrapper itself — takes focus. */ @OptIn(ExperimentalLayoutApi::class) @Composable fun Modifier.bringIntoViewOnImeVisible(): Modifier { val bringIntoViewRequester = remember { BringIntoViewRequester() } - var isFocused by remember { mutableStateOf(false) } + var hasFocus by remember { mutableStateOf(false) } val isImeVisible = WindowInsets.isImeVisible - LaunchedEffect(isImeVisible, isFocused) { - if (isImeVisible && isFocused) { - // Delay to ensure the keyboard is fully shown before scrolling the field into view. + LaunchedEffect(isImeVisible, hasFocus) { + if (isImeVisible && hasFocus) { + // Delay to ensure the keyboard is fully shown before scrolling the content into view. delay(100.milliseconds) bringIntoViewRequester.bringIntoView() } } return this .bringIntoViewRequester(bringIntoViewRequester) - .onFocusChanged { isFocused = it.isFocused } + .onFocusChanged { hasFocus = it.hasFocus } } From 154d79d4b53efe2338ec3b7e1687b32ee295ff68 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 28 Jul 2026 13:45:07 +0000 Subject: [PATCH 215/383] Update dependency org.matrix.rustcomponents:sdk-android to v26.07.28 --- 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 e92757182f..b9c7fb1c98 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -185,7 +185,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.07.23" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.07.28" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From bd4d0cb02b68f55f4149dc5f412644f1cc33d389 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 28 Jul 2026 16:44:07 +0200 Subject: [PATCH 216/383] Fix compilation for QR login continuation error variants added in SDK 26.07.28 --- .../android/features/login/impl/qrcode/QrCodeLoginFlowNode.kt | 2 ++ .../libraries/matrix/api/auth/qrlogin/QrLoginException.kt | 2 ++ .../android/libraries/matrix/impl/auth/qrlogin/QrErrorMapper.kt | 2 ++ 3 files changed, 6 insertions(+) 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 03264551a5..6d46cdea0f 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 @@ -141,6 +141,8 @@ class QrCodeLoginFlowNode( } QrLoginException.CheckCodeAlreadySent, QrLoginException.CheckCodeCannotBeSent, + QrLoginException.ContinuationAlreadySent, + QrLoginException.ContinuationCannotBeSent, QrLoginException.UnsupportedQrCodeType, QrLoginException.Unknown -> { Timber.e(error, "Unknown error found") 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 3f22244405..11c646650e 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 @@ -20,6 +20,8 @@ sealed class QrLoginException : Exception() { data object OtherDeviceNotSignedIn : QrLoginException() data object CheckCodeAlreadySent : QrLoginException() data object CheckCodeCannotBeSent : QrLoginException() + data object ContinuationAlreadySent : QrLoginException() + data object ContinuationCannotBeSent : QrLoginException() data object UnsupportedQrCodeType : QrLoginException() data object Unknown : QrLoginException() } 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 23b9c6be5e..ed00db82e4 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 @@ -46,6 +46,8 @@ object QrErrorMapper { is RustHumanQrLoginException.SlidingSyncNotAvailable -> QrLoginException.SlidingSyncNotAvailable is RustHumanQrLoginException.CheckCodeAlreadySent -> QrLoginException.CheckCodeAlreadySent is RustHumanQrLoginException.CheckCodeCannotBeSent -> QrLoginException.CheckCodeCannotBeSent + is RustHumanQrLoginException.ContinuationAlreadySent -> QrLoginException.ContinuationAlreadySent + is RustHumanQrLoginException.ContinuationCannotBeSent -> QrLoginException.ContinuationCannotBeSent is RustHumanQrLoginException.UnsupportedQrCodeType -> QrLoginException.UnsupportedQrCodeType } } From 3fc89724640b32b3a2738191c276edc44cbd0555 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 28 Jul 2026 18:08:10 +0200 Subject: [PATCH 217/383] Fix unit test compilation for new continuationSender param on WaitingForAuth --- .../fakes/FakeFfiContinuationMessageSender.kt | 24 +++++++++++++++++++ .../RustLinkDesktopHandlerTest.kt | 3 ++- .../RustLinkMobileHandlerTest.kt | 3 ++- 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiContinuationMessageSender.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiContinuationMessageSender.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiContinuationMessageSender.kt new file mode 100644 index 0000000000..7c504003f0 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiContinuationMessageSender.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + */ + +package io.element.android.libraries.matrix.impl.fixtures.fakes + +import io.element.android.tests.testutils.lambda.lambdaError +import org.matrix.rustcomponents.sdk.ContinuationMessageSender +import org.matrix.rustcomponents.sdk.NoHandle + +class FakeFfiContinuationMessageSender( + private val confirmResult: () -> Unit = { lambdaError() }, + private val cancelResult: () -> Unit = { lambdaError() }, +) : ContinuationMessageSender(NoHandle) { + override suspend fun confirm() { + confirmResult() + } + + override suspend fun cancel() { + cancelResult() + } +} 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 fd635e2da6..c0781972ac 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 @@ -13,6 +13,7 @@ import app.cash.turbine.test import com.google.common.truth.Truth.assertThat 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.FakeFfiContinuationMessageSender import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiGrantLoginWithQrCodeHandler import io.element.android.libraries.matrix.test.QR_CODE_DATA import kotlinx.coroutines.CompletableDeferred @@ -51,7 +52,7 @@ class RustLinkDesktopHandlerTest { listOf( GrantQrLoginProgress.Starting to LinkDesktopStep.Starting, GrantQrLoginProgress.SyncingSecrets to LinkDesktopStep.SyncingSecrets, - GrantQrLoginProgress.WaitingForAuth("aVerificationUri") + GrantQrLoginProgress.WaitingForAuth("aVerificationUri", FakeFfiContinuationMessageSender()) to LinkDesktopStep.WaitingForAuth("aVerificationUri"), GrantQrLoginProgress.EstablishingSecureChannel(1.toUByte(), "1") to LinkDesktopStep.EstablishingSecureChannel(1.toUByte(), "1"), 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 3d84e34f45..8c0306c8ad 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 @@ -14,6 +14,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.linknewdevice.ErrorType import io.element.android.libraries.matrix.api.linknewdevice.LinkMobileStep import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiCheckCodeSender +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiContinuationMessageSender 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 @@ -52,7 +53,7 @@ class RustLinkMobileHandlerTest { listOf( GrantGeneratedQrLoginProgress.Starting to LinkMobileStep.Starting::class.java, GrantGeneratedQrLoginProgress.SyncingSecrets to LinkMobileStep.SyncingSecrets::class.java, - GrantGeneratedQrLoginProgress.WaitingForAuth("aVerificationUri") + GrantGeneratedQrLoginProgress.WaitingForAuth("aVerificationUri", FakeFfiContinuationMessageSender()) to LinkMobileStep.WaitingForAuth::class.java, GrantGeneratedQrLoginProgress.QrScanned(FakeFfiCheckCodeSender()) to LinkMobileStep.QrScanned::class.java, From 8b970fb2f14fd0e1f2420cc2fb49eb95c789fce5 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 29 Jul 2026 01:02:03 +0200 Subject: [PATCH 218/383] Fix license header on FakeFfiContinuationMessageSender --- .../impl/fixtures/fakes/FakeFfiContinuationMessageSender.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiContinuationMessageSender.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiContinuationMessageSender.kt index 7c504003f0..4f5358658f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiContinuationMessageSender.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiContinuationMessageSender.kt @@ -1,7 +1,8 @@ /* - * Copyright (c) 2025 Element Creations 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.matrix.impl.fixtures.fakes From 00dcf48f2822341f44dba972707a22d187cf4678 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 29 Jul 2026 09:53:27 +0200 Subject: [PATCH 219/383] Update dependency org.maplibre.gl:android-sdk to v13.4.0 (#7290) 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 b9c7fb1c98..5256827918 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -215,7 +215,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.3.1" +maplibre = "org.maplibre.gl:android-sdk:13.4.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 eb18770378c5b8f4f5f0acaee59e5723af6522f8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 29 Jul 2026 07:55:56 +0000 Subject: [PATCH 220/383] Update dependency org.maplibre.compose:maplibre-compose 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 5256827918..9679d592c9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -217,7 +217,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.4.0" maplibre_ktx = "org.maplibre.gl:android-sdk-ktx-v7:3.0.2" -maplibre_compose = "org.maplibre.compose:maplibre-compose:0.13.0" +maplibre_compose = "org.maplibre.compose:maplibre-compose:0.13.1" 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.1.0" From 674354b1a69257ad6e6f70d6d31cd0158df3c50e Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 29 Jul 2026 11:17:41 +0200 Subject: [PATCH 221/383] Enforce HS disabling E2EE in DM creation too (Element Pro) (#7292) This part was missing from the implementation of this Element Pro feature, which incorrectly only applied to rooms. --- features/startchat/impl/build.gradle.kts | 2 ++ .../startchat/impl/DefaultStartDMAction.kt | 8 ++++- .../impl/DefaultStartDMActionTest.kt | 31 +++++++++++++++++++ .../libraries/matrix/api/MatrixClient.kt | 2 +- .../libraries/matrix/api/room/StartDM.kt | 3 +- .../libraries/matrix/impl/RustMatrixClient.kt | 4 +-- .../matrix/impl/RustMatrixClientTest.kt | 2 +- .../libraries/matrix/test/FakeMatrixClient.kt | 8 ++--- 8 files changed, 50 insertions(+), 10 deletions(-) diff --git a/features/startchat/impl/build.gradle.kts b/features/startchat/impl/build.gradle.kts index 805dcc742b..fe7bfa9ae2 100644 --- a/features/startchat/impl/build.gradle.kts +++ b/features/startchat/impl/build.gradle.kts @@ -43,6 +43,7 @@ dependencies { implementation(libs.coil.compose) implementation(projects.libraries.featureflag.api) implementation(projects.features.createroom.api) + implementation(projects.features.enterprise.api) api(projects.features.startchat.api) testCommonDependencies(libs, true) @@ -55,4 +56,5 @@ dependencies { testImplementation(projects.features.createroom.test) testImplementation(projects.features.startchat.test) testImplementation(projects.libraries.featureflag.test) + testImplementation(projects.features.enterprise.test) } 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 6821005c67..0e6b3faf1c 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 @@ -11,6 +11,7 @@ package io.element.android.features.startchat.impl import androidx.compose.runtime.MutableState import dev.zacsweers.metro.ContributesBinding import im.vector.app.features.analytics.plan.CreatedRoom +import io.element.android.features.enterprise.api.SessionEnterpriseService import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser import io.element.android.features.startchat.api.StartDMAction import io.element.android.libraries.architecture.AsyncAction @@ -26,6 +27,7 @@ import io.element.android.services.analytics.api.AnalyticsService class DefaultStartDMAction( private val matrixClient: MatrixClient, private val analyticsService: AnalyticsService, + private val sessionEnterpriseService: SessionEnterpriseService, ) : StartDMAction { override suspend fun execute( matrixUser: MatrixUser, @@ -33,7 +35,11 @@ class DefaultStartDMAction( actionState: MutableState>, ) { actionState.value = AsyncAction.Loading - when (val result = matrixClient.startDM(matrixUser.userId, createIfDmDoesNotExist)) { + when (val result = matrixClient.startDM( + userId = matrixUser.userId, + createIfDmDoesNotExist = createIfDmDoesNotExist, + isEncryped = !sessionEnterpriseService.isEncryptionDisabledByHomeserver(), + )) { is StartDMResult.Success -> { if (result.isNew) { analyticsService.capture(CreatedRoom(isDM = true)) 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 2c1fd1aa2b..16b59f35df 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 @@ -11,6 +11,8 @@ package io.element.android.features.startchat.impl import androidx.compose.runtime.mutableStateOf import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.CreatedRoom +import io.element.android.features.enterprise.api.SessionEnterpriseService +import io.element.android.features.enterprise.test.FakeSessionEnterpriseService import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.MatrixClient @@ -25,6 +27,7 @@ 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 io.element.android.tests.testutils.lambda.value import kotlinx.coroutines.test.runTest import org.junit.Test @@ -122,13 +125,41 @@ class DefaultStartDMActionTest { assertThat(state.value).isEqualTo(ConfirmingStartDmWithMatrixUser(aMatrixUser(), isUserIdentityUnknown = true)) } + @Test + fun `when SessionEnterpriseService disables encryption the DM is created without encryption`() = runTest { + val createDmLambda = lambdaRecorder> { _, _ -> Result.success(A_ROOM_ID) } + val matrixClient = FakeMatrixClient().apply { + givenFindDmResult(Result.success(null)) + createDmResult = createDmLambda + } + + val action = createStartDMAction( + matrixClient = matrixClient, + sessionEnterpriseService = FakeSessionEnterpriseService(isEncryptionDisabledResult = { true }) + ) + val state = mutableStateOf>(AsyncAction.Uninitialized) + + val matrixUser = aMatrixUser() + action.execute(matrixUser = matrixUser, createIfDmDoesNotExist = true, actionState = state) + + createDmLambda.assertions().isCalledOnce().with( + value(matrixUser.userId), + // isEncrypted should be false because encryption is disabled + value(false), + ) + + assertThat(state.value).isEqualTo(AsyncAction.Success(A_ROOM_ID)) + } + private fun createStartDMAction( matrixClient: MatrixClient = FakeMatrixClient(), analyticsService: AnalyticsService = FakeAnalyticsService(), + sessionEnterpriseService: SessionEnterpriseService = FakeSessionEnterpriseService(isEncryptionDisabledResult = { false }), ): DefaultStartDMAction { return DefaultStartDMAction( matrixClient = matrixClient, analyticsService = analyticsService, + sessionEnterpriseService = sessionEnterpriseService, ) } } 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 f38b175b7e..0c26d87acb 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 @@ -84,7 +84,7 @@ interface MatrixClient { suspend fun ignoreUser(userId: UserId): Result suspend fun unignoreUser(userId: UserId): Result suspend fun createRoom(createRoomParams: CreateRoomParameters): Result - suspend fun createDM(userId: UserId): Result + suspend fun createDM(userId: UserId, isEncrypted: Boolean): Result suspend fun getProfile(userId: UserId): Result suspend fun searchUsers(searchTerm: String, limit: Long): Result suspend fun setDisplayName(displayName: String): Result diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/StartDM.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/StartDM.kt index 057c5838e5..59a6aaa2fe 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/StartDM.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/StartDM.kt @@ -18,6 +18,7 @@ import io.element.android.libraries.matrix.api.core.UserId suspend fun MatrixClient.startDM( userId: UserId, createIfDmDoesNotExist: Boolean, + isEncryped: Boolean, ): StartDMResult { return findDM(userId) .fold( @@ -25,7 +26,7 @@ suspend fun MatrixClient.startDM( if (existingDM != null) { StartDMResult.Success(existingDM, isNew = false) } else if (createIfDmDoesNotExist) { - createDM(userId).fold( + createDM(userId, isEncryped).fold( { StartDMResult.Success(it, isNew = true) }, { StartDMResult.Failure(it) } ) 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 0a59547631..33ed6610d3 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 @@ -430,10 +430,10 @@ class RustMatrixClient( } } - override suspend fun createDM(userId: UserId): Result { + override suspend fun createDM(userId: UserId, isEncrypted: Boolean): Result { val createRoomParams = CreateRoomParameters( name = null, - isEncrypted = true, + isEncrypted = isEncrypted, isDirect = true, visibility = RoomVisibility.Private, preset = RoomPreset.TRUSTED_PRIVATE_CHAT, diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt index 49cf59a954..0039f16ed9 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt @@ -132,7 +132,7 @@ class RustMatrixClientTest { client = FakeFfiClient(createRoomResult = createRoomLambda) ) - client.createDM(A_USER_ID) + client.createDM(userId = A_USER_ID, isEncrypted = true) createRoomLambda.assertions().isCalledOnce() assertThat(createParameters?.historyVisibilityOverride).isEqualTo(RoomHistoryVisibility.Invited) 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 1c9fcfa482..0933239c93 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 @@ -145,7 +145,7 @@ class FakeMatrixClient( override val userProfile: StateFlow = _userProfile var createRoomResult: (CreateRoomParameters) -> Result = { Result.success(A_ROOM_ID) } - private var createDmResult: Result = Result.success(A_ROOM_ID) + var createDmResult: (UserId, Boolean) -> Result = { _, _ -> Result.success(A_ROOM_ID) } private var findDmResult: Result = Result.success(A_ROOM_ID) private val getRoomResults = mutableMapOf() private val searchUserResults = mutableMapOf>() @@ -196,8 +196,8 @@ class FakeMatrixClient( return createRoomResult(createRoomParams) } - override suspend fun createDM(userId: UserId): Result = simulateLongTask { - return createDmResult + override suspend fun createDM(userId: UserId, isEncrypted: Boolean): Result = simulateLongTask { + return createDmResult(userId, isEncrypted) } override suspend fun getProfile(userId: UserId): Result { @@ -301,7 +301,7 @@ class FakeMatrixClient( } fun givenCreateDmResult(result: Result) { - createDmResult = result + createDmResult = { _, _ -> result } } fun givenFindDmResult(result: Result) { From 49692794f9ea93c2ed3ef3f028354149fc52995b Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 29 Jul 2026 11:29:44 +0200 Subject: [PATCH 222/383] Allow adding a path suffix to the OAuth client URI (#7286) * Allow adding a path suffix to the OAuth client URI --- libraries/matrix/api/build.gradle.kts | 5 +++++ .../element/android/libraries/matrix/api/auth/OAuthConfig.kt | 5 ++++- plugins/src/main/kotlin/config/BuildTimeConfig.kt | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/matrix/api/build.gradle.kts b/libraries/matrix/api/build.gradle.kts index 2a326527df..d0790a6905 100644 --- a/libraries/matrix/api/build.gradle.kts +++ b/libraries/matrix/api/build.gradle.kts @@ -24,6 +24,11 @@ android { } defaultConfig { + buildConfigField( + name = "OAUTH_CLIENT_URI_PATH", + type = "String", + value = BuildTimeConfig.OAUTH_CLIENT_URL_PATH?.let { "\"$it\"" } ?: "null", + ) buildConfigFieldStr( name = "CLIENT_URI", value = BuildTimeConfig.URL_WEBSITE ?: "https://element.io" diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthConfig.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthConfig.kt index d3a42f42b9..3256d0545c 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthConfig.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/OAuthConfig.kt @@ -11,7 +11,10 @@ package io.element.android.libraries.matrix.api.auth import io.element.android.libraries.matrix.api.BuildConfig object OAuthConfig { - const val CLIENT_URI = BuildConfig.CLIENT_URI + val CLIENT_URI = BuildConfig.OAUTH_CLIENT_URI_PATH?.let { + // Concatenate the base URI and the path, ensuring there is exactly one '/' between them + "${BuildConfig.CLIENT_URI.trimEnd('/')}/${it.trimStart('/')}" + } ?: BuildConfig.CLIENT_URI // Note: host must match with the host of CLIENT_URI const val LOGO_URI = BuildConfig.LOGO_URI diff --git a/plugins/src/main/kotlin/config/BuildTimeConfig.kt b/plugins/src/main/kotlin/config/BuildTimeConfig.kt index 8cfa533609..9c8c5c986a 100644 --- a/plugins/src/main/kotlin/config/BuildTimeConfig.kt +++ b/plugins/src/main/kotlin/config/BuildTimeConfig.kt @@ -22,6 +22,7 @@ object BuildTimeConfig { val URL_ACCEPTABLE_USE: String? = null val URL_PRIVACY: String? = null val URL_POLICY: String? = null + val OAUTH_CLIENT_URL_PATH: String? = null val SERVICES_MAPTILER_BASE_URL: String? = null val SERVICES_MAPTILER_APIKEY: String? = null val SERVICES_MAPTILER_LIGHT_MAPID: String? = null From ddc972a3656b1b2815e963841bb6c756bc0b11dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 29 Jul 2026 13:28:22 +0200 Subject: [PATCH 223/383] Run `Konsist` tests sequentially It's sadly faster that way: Every time we run a test class in parallel a new JVM is started, and the `KoScope` contents can't be shared between them. This scope can take a few minutes to load, so having several instances of this happening at the same time is a terrible idea. It's actually faster to run the tests sequentially, at least locally. --- tests/konsist/build.gradle.kts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/konsist/build.gradle.kts b/tests/konsist/build.gradle.kts index 5558b1a564..ccd354db89 100644 --- a/tests/konsist/build.gradle.kts +++ b/tests/konsist/build.gradle.kts @@ -29,6 +29,11 @@ dependencies { // - Add every single module as a dependency of this one. // - Move the Konsist tests to the `app` module, but the `app` module does not need to know about Konsist. tasks.withType().configureEach { + // Disable parallel tests: every time we run a test class in parallel a new JVM is started, and the `KoScope` contents can't be shared between them. + // This scope can take 1-2min to load, so having several instances of this happening is a terrible idea. + // It's actually faster to run the tests sequentially, at least locally. + maxParallelForks = 1 + val isNotCheckTask = gradle.startParameter.taskNames.any { it.contains("check", ignoreCase = true).not() } outputs.upToDateWhen { isNotCheckTask } } From d711922325a12e3374a08d2e8e92df3414841ca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Wed, 29 Jul 2026 13:28:57 +0200 Subject: [PATCH 224/383] Remove test for detecting `m` prefix for fields I'm not sure anyone will actually use `m` prefixes on Kotlin anymore --- .../android/tests/konsist/KonsistFieldTest.kt | 28 ------------------- 1 file changed, 28 deletions(-) delete mode 100644 tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistFieldTest.kt diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistFieldTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistFieldTest.kt deleted file mode 100644 index bfbe76d358..0000000000 --- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistFieldTest.kt +++ /dev/null @@ -1,28 +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.tests.konsist - -import com.lemonappdev.konsist.api.Konsist -import com.lemonappdev.konsist.api.ext.list.properties -import com.lemonappdev.konsist.api.verify.assertFalse -import org.junit.Test - -class KonsistFieldTest { - @Test - fun `no field should have 'm' prefix`() { - Konsist - .scopeFromProject() - .classes() - .properties() - .assertFalse { - val secondCharacterIsUppercase = it.name.getOrNull(1)?.isUpperCase() ?: false - it.name.startsWith('m') && secondCharacterIsUppercase - } - } -} From ae74546ee470f4d40d70e508df03f08473aded5a Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 29 Jul 2026 17:44:12 +0200 Subject: [PATCH 225/383] Setting version for the release 26.08.0 --- plugins/src/main/kotlin/Versions.kt | 4 ++-- tools/manifest/gplay/release/aaptDump.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index a1e25e8180..179ff7ac90 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 = 7 +private const val versionMonth = 8 /** * 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 = 0 object Versions { /** diff --git a/tools/manifest/gplay/release/aaptDump.txt b/tools/manifest/gplay/release/aaptDump.txt index be6bcdaf8a..23f4acfb38 100644 --- a/tools/manifest/gplay/release/aaptDump.txt +++ b/tools/manifest/gplay/release/aaptDump.txt @@ -1,4 +1,4 @@ -package: name='io.element.android.x' versionCode='202607010' versionName='26.07.1' platformBuildVersionName='17' platformBuildVersionCode='37' compileSdkVersion='37' compileSdkVersionCodename='17' +package: name='io.element.android.x' versionCode='202608000' versionName='26.08.0' platformBuildVersionName='17' platformBuildVersionCode='37' compileSdkVersion='37' compileSdkVersionCodename='17' sdkVersion:'24' targetSdkVersion:'37' uses-permission: name='android.permission.POST_NOTIFICATIONS' From 0770ff04c7b8d7930d548cba9550b0d4c81b8c3e Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 29 Jul 2026 17:44:30 +0200 Subject: [PATCH 226/383] Adding fastlane file for version 26.08.0 --- fastlane/metadata/android/en-US/changelogs/202608000.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/202608000.txt diff --git a/fastlane/metadata/android/en-US/changelogs/202608000.txt b/fastlane/metadata/android/en-US/changelogs/202608000.txt new file mode 100644 index 0000000000..a4b397f1bb --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202608000.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 67b5bddf4e0a425ac5a96a7befe6d824af8acfad Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 29 Jul 2026 18:31:11 +0200 Subject: [PATCH 227/383] Changelog for version 26.08.0 --- CHANGES.md | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 07ffafd3d6..3f7360a338 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,86 @@ +Changes in Element X v26.08.0 +============================= + + + +## What's Changed +### ✨ Features +* feat(call): Active call timeline rendering by @BillCarsonFr in https://github.com/element-hq/element-x-android/pull/7051 +### 🙌 Improvements +* Announce expanded/collapsed state on the timeline group header by @unclejay80 in https://github.com/element-hq/element-x-android/pull/7226 +* Allow adding extra elements to the developer settings from external modules by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7230 +* Update keyboard visibility to track hasFocus by @jennaharris7 in https://github.com/element-hq/element-x-android/pull/7284 +### 🐛 Bugfixes +* Live location sharing timeout by @ganfra in https://github.com/element-hq/element-x-android/pull/7184 +* Fix logging via QR code when using MDM-configured homeserver by @mxandreas in https://github.com/element-hq/element-x-android/pull/7228 +* Fix #7181: Remove back arrow from device verified screen and use 'Done' text by @thirumani-vihaan in https://github.com/element-hq/element-x-android/pull/7222 +* Fix padding for captions of media in 'not found' state by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7247 +* Fix banned mime type errors in `DefaultContentScannerService` by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7255 +* Fix `ContentErrorView` not calculating its text size synchronously by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7281 +* Fix media viewer for medias not related to events displaying invalid state by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7280 +* Try making `HeaderFooterView` more robust by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7267 +* Fix insets in several screens by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7285 +### ⚠️ API Changes +* Add a password strength estimator wrapping the SDK zxcvbn API by @jennaharris7 in https://github.com/element-hq/element-x-android/pull/7186 +### 🗣 Translations +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/7277 +### 🧱 Build +* CI: fix 'Update Gradle Wrapper' by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7238 +* Update Gradle Wrapper from 9.5.1 to 9.6.1 by @ElementBot in https://github.com/element-hq/element-x-android/pull/7240 +* Localazy: improve search, parallelize checks by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7261 +* Run `Konsist` tests sequentially by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7293 +### 📄 Documentation +* Group Element Pro changes into a dedicated release notes section by @manuroe in https://github.com/element-hq/element-x-android/pull/7236 +### 🚧 In development 🚧 +* Plug emoji picker for custom user status by @ganfra in https://github.com/element-hq/element-x-android/pull/7257 +* WIP : display user status by @ganfra in https://github.com/element-hq/element-x-android/pull/7232 +### Dependency upgrades +* Update roborazzi to v1.67.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7188 +* Update dependency io.sentry:sentry-android to v8.48.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7217 +* Update dependency com.google.crypto.tink:tink-android to v1.23.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7229 +* Update kotlin to v2.3.10 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7234 +* Update dependency net.zetetic:sqlcipher-android to v4.17.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7218 +* Update dependency com.google.firebase:firebase-bom to v34.16.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7237 +* Update dependencyAnalysis to v3.16.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7212 +* Update actions/setup-java action to v5.5.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7214 +* Update dependency io.element.android:element-call-embedded to v0.22.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7161 +* Update kotlin to v2.4.10 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7244 +* Update roborazzi to v1.68.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7245 +* Update metro to v1.3.2 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7243 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.07.22 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7258 +* Update zizmorcore/zizmor-action action to v0.6.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7256 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.07.23 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7262 +* Update dependency io.sentry:sentry-android to v8.49.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7263 +* Update dependencyAnalysis to v3.17.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7265 +* Update actions/setup-java action to v5.6.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7268 +* Update dependency org.jetbrains.kotlinx:kover-gradle-plugin to v0.9.9 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7273 +* Update actions/setup-python action to v7 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7278 +* Update roborazzi to v1.70.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7274 +* Update actions/checkout action to v7.0.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7282 +* Import Compound tokens from `v10.2.3` by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7272 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.07.28 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7287 +* Update dependency org.maplibre.gl:android-sdk to v13.4.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/7290 +### 💼 Element Pro +* Content scanner (Element Pro): scan timeline events for unsafe content by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7159 +* Add content scanner support to media gallery and viewer (Element Pro) by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7233 +* Enforce HS disabling E2EE in DM creation too (Element Pro) by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7292 +* Allow adding a path suffix to the OAuth client URI by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7286 +### Others +* [A11y] Improve rendering on focused UI items by @bmarty in https://github.com/element-hq/element-x-android/pull/7182 +* Add a button role to clickable icons and text on the login/onboarding screens by @unclejay80 in https://github.com/element-hq/element-x-android/pull/7225 +* Expose formatting toggle state to TalkBack by @unclejay80 in https://github.com/element-hq/element-x-android/pull/7227 +* Add warning to the 'Scan QR code' screen by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7264 +* Refactor SearchBarResultState.Initial/NoResultsFound to data objects by @ganfra in https://github.com/element-hq/element-x-android/pull/7266 +* Remove no longer temporary strings by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7260 +* Use the right insets in the home screen UI by @jmartinesp in https://github.com/element-hq/element-x-android/pull/7271 +* Make settings section separators visible in black theme by @mvanhorn in https://github.com/element-hq/element-x-android/pull/7039 + +## New Contributors +* @thirumani-vihaan made their first contribution in https://github.com/element-hq/element-x-android/pull/7222 +* @mvanhorn made their first contribution in https://github.com/element-hq/element-x-android/pull/7039 + +**Full Changelog**: https://github.com/element-hq/element-x-android/compare/v26.07.1...v26.08.0 + Changes in Element X v26.07.1 ============================= From e46d36ec6469802cb0c12385320cb1e2c389ac8a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 Jul 2026 09:40:09 +0200 Subject: [PATCH 228/383] Update android.gradle.plugin to v9.3.0 (#7248) 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 9679d592c9..ae83600cc3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ [versions] # Project -android_gradle_plugin = "9.2.1" +android_gradle_plugin = "9.3.0" # When updating this, please also update the version in the file ./idea/kotlinc.xml kotlin = "2.4.10" kotlinpoet = "2.3.0" From bac77b7645ae17b691d99ef4141b9fe3f00cfb1f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 Jul 2026 09:43:45 +0200 Subject: [PATCH 229/383] Update dependency io.sentry:sentry-android to v8.50.0 (#7298) 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 ae83600cc3..23dc990beb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -230,7 +230,7 @@ color_picker = "io.mhssn:colorpicker:1.0.0" # Analytics posthog = "com.posthog:posthog-android:3.51.1" -sentry = "io.sentry:sentry-android:8.49.0" +sentry = "io.sentry:sentry-android:8.50.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.37.0" From 9ab679566d57cbca8f29b18d8d884be53993ba48 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 30 Jul 2026 10:29:43 +0200 Subject: [PATCH 230/383] Don't check enterprise previews in `KonsistPreviewTest` (#7297) Don't check enterprise previews in `KonsistPreviewTest` --- .../android/tests/konsist/KonsistPreviewTest.kt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 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 deaa903e25..e2a387eede 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 @@ -11,6 +11,7 @@ package io.element.android.tests.konsist import androidx.compose.ui.tooling.preview.PreviewLightDark import com.google.common.truth.Truth.assertThat import com.lemonappdev.konsist.api.Konsist +import com.lemonappdev.konsist.api.declaration.KoFunctionDeclaration import com.lemonappdev.konsist.api.ext.list.withAllAnnotationsOf import com.lemonappdev.konsist.api.ext.list.withName import com.lemonappdev.konsist.api.ext.list.withNameEndingWith @@ -61,6 +62,8 @@ class KonsistPreviewTest { .scopeFromProject() .functions() .withAllAnnotationsOf(PreviewsDayNight::class) + // We can't check Enterprise previews because they are in a different repo, and they aren't present for FOSS + .withoutEnterpriseFunctions() .assertTrue { it.text.contains("ElementPreview") || it.text.contains("ElementTimelineItemPreview") @@ -88,8 +91,6 @@ class KonsistPreviewTest { "BackgroundVerticalGradientPreview", "ColorAliasesPreview", "EmojiItemWithPopupPreview", - "EnterpriseExtraDeveloperOptionsRendererBottomSheetPreview", - "EnterpriseExtraDeveloperOptionsRendererListItemPreview", "FocusedEventPreview", "GradientFloatingActionButtonCircleShapePreview", "HeaderFooterPageScrollablePreview", @@ -189,7 +190,8 @@ class KonsistPreviewTest { @Test fun `previewNameExceptions only contains existing functions`() { - val names = previewNameExceptions.toMutableSet() + val names = previewNameExceptions + .toMutableSet() Konsist .scopeFromProject() .functions() @@ -210,6 +212,8 @@ class KonsistPreviewTest { .functions() .withAllAnnotationsOf(PreviewsDayNight::class) .withoutName(previewNameExceptions) + // We can't check Enterprise previews because they are in a different repo, and they aren't present for FOSS + .withoutEnterpriseFunctions() .assertTrue( additionalMessage = "Functions for Preview should be named like this: Preview. " + "Exception can be added to the test, for multiple Previews of the same view", @@ -237,3 +241,7 @@ class KonsistPreviewTest { ) } } + +private fun List.withoutEnterpriseFunctions() = filter { function -> + function.packagee?.hasNameStartingWith("io.element.android.enterprise") != true +} From af9db20f4f31286dde02894460e28353af27dea9 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 30 Jul 2026 10:30:22 +0200 Subject: [PATCH 231/383] Add extra vertical padding to `ReplyToInvalidContent` and `ReplyToNotFoundContent` (#7288) * Add extra vertical padding to `ReplyToInvalidContent` and `ReplyToNotFoundContent` * Update screenshots --------- Co-authored-by: ElementBot --- .../libraries/matrix/ui/messages/reply/InReplyToView.kt | 4 ++-- ...TimelineItemScanningContentWithInvalidReplies_Day_0_en.png | 4 ++-- ...melineItemScanningContentWithInvalidReplies_Night_0_en.png | 4 ++-- ..._TimelineItemScanningContentWithRepliesFailed_Day_0_en.png | 4 ++-- ...imelineItemScanningContentWithRepliesFailed_Night_0_en.png | 4 ++-- ...atrix.ui.messages.reply_ReplyToInvalidContent_Day_0_en.png | 4 ++-- ...rix.ui.messages.reply_ReplyToInvalidContent_Night_0_en.png | 4 ++-- ...trix.ui.messages.reply_ReplyToNotFoundContent_Day_0_en.png | 4 ++-- ...ix.ui.messages.reply_ReplyToNotFoundContent_Night_0_en.png | 4 ++-- 9 files changed, 18 insertions(+), 18 deletions(-) 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 7ff41abcd3..3072c81a15 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 @@ -227,7 +227,7 @@ private fun ReplyToInvalidContent( ) { InvalidContentView( modifier = modifier, - contentPadding = PaddingValues(horizontal = 8.dp), + contentPadding = PaddingValues(vertical = 4.dp, horizontal = 8.dp), onTextLayout = null, ) } @@ -238,7 +238,7 @@ private fun ReplyToNotFoundContent( ) { NotFoundContentView( modifier = modifier, - contentPadding = PaddingValues(horizontal = 8.dp), + contentPadding = PaddingValues(vertical = 4.dp, horizontal = 8.dp), onTextLayout = null, ) } diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Day_0_en.png index 8f65bb19fd..0de3c37538 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:020f44e2c54b1449ea4b4f3608073433133ebb3d3cae3be20dab121a103d2f65 -size 66749 +oid sha256:c5af2ef73b410ed9debbd981547300109a7b821e2d013f8d423c098d12051e8a +size 67130 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Night_0_en.png index cc10efcb15..942b61ed59 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithInvalidReplies_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:75b14fa771f05ebd3ab6a6d57068c59259ac6a7c3891e9cbdb96d4a025e6491a -size 66992 +oid sha256:c47105fc400a2abc58c1614e3071521445995914c85447a0cd408779640ed2ae +size 67475 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Day_0_en.png index 78e20f96d6..8bc3d3bc38 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1a9c829656079ca682983a0aed67db9d2c45cf64aabf4dcb1d97bba0eefdbc0 -size 60555 +oid sha256:4c7c357c58d519ef4eb2003b70a3ede6b00394be77c067867798e11597310133 +size 60757 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Night_0_en.png index 9641251dd9..25a06ab957 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemScanningContentWithRepliesFailed_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:788e79c4d88b1f20d49c1d3e669228c85e3c44cc7fd5a33dca71fb69d118f777 -size 61043 +oid sha256:f9d2fe78d4e6bac6a9c66b56ef51be188d4d8a9b8cd38f8f253eb5c33e47fdcf +size 61101 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Day_0_en.png index 7a941824b1..939a1e2e3b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:779d234f352bcd163ad792b858dc832c0e01c0598766c5cd636e2767ce10b30f -size 13153 +oid sha256:369112147d73da7987e671e5c4ad60312946d6a2e580132c0618a343f1feec85 +size 13280 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Night_0_en.png index b79f27aaae..41de211740 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToInvalidContent_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12a4056aeda90fbe1d54cc6d5fb7c01b54c5c97eb9aab2d49b665da49860f3e3 -size 12540 +oid sha256:5375bd98bf7060ba1c522b6abb7cbcbd1a75beb6957f6049b11c87f81fb06536 +size 12691 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Day_0_en.png index 61ece7b06f..7f01c64831 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ce671634b464ce25caba96b51837f3acfac6366f168766c95f221ace2b03eac -size 12010 +oid sha256:08ed7f23b4987ef02f10127bd124d05bad7fb786df99a096646ed8632c45fbc7 +size 12009 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Night_0_en.png index e3e18bbc55..3e040f8c1d 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.messages.reply_ReplyToNotFoundContent_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:581465da26f22298b9fe3e7124f5f4ad4e951398ca3cd6d39ff6f1fa99eafe1d -size 11417 +oid sha256:282f703a34243c3d4d0aa6ae09cb230ba376c8fa56a3a062ecfa730ea13e9ed6 +size 11414 From e6d4472c0cef46b3f302ba45c403dd7db3bdc880 Mon Sep 17 00:00:00 2001 From: hayyaksi <193020925+hayaksi1@users.noreply.github.com> Date: Thu, 30 Jul 2026 12:17:40 +0300 Subject: [PATCH 232/383] Index messages locally in an encrypted on-device store so encrypted rooms can be searched at all (#7249) * Add a message search abstraction over the Rust SDK's local index Wraps the SDK's search service so the rest of the app never sees MatrixRustSDK types, following the existing convention in libraries/matrix. - MessageSearch, MessageSearchService, MessageSearchResult and MessageSearchPaginationState describe the surface in the api module. - RustMessageSearch and RustMessageSearchService implement it, with MessageSearchResultMapper and MessageSearchResultsProcessor turning SDK results into Kotlin data classes. - TantivyQueryEscaper escapes the query so a user typing ":)" or "AND" searches for that literal text rather than tripping the tantivy parser, and joins every word as a Must clause. - Fakes and unit tests cover the mapping, the processor and the escaper, the last checked against a real tantivy 0.26.1 parser. * Attach the encrypted search index behind a disabled feature flag Gives the client an on-device tantivy index encrypted with the session's client secret, so encrypted rooms can be searched at all. - The index store is attached at ClientBuilder time via withSearchIndexStore, in a search-index directory alongside the session, keyed on the client secret. A session without one gets no index. - MatrixClient exposes isMessageSearchAvailable so callers gate on the real indexing capability rather than on the raw flag, and getCacheSize() counts the index directory so it stays visible in the settings figures. - FeatureFlags.MessageSearch (feature.message_search) is off by default and isFinished = false. It is read once at ClientBuilder time, so develop stays releasable and nothing reaches a user. * Simplify search index wiring following review Tie search availability to the MessageSearch feature flag alone and let the index be created without a client secret, encrypting it only when the session has one, matching the SDK's SQLite stores. Make getBaseClientBuilder take the flag as a required parameter and return ClientBuilder directly again, dropping the BaseClientBuilder wrapper and the mid-restore snapshot parameter. Check the flag through FeatureFlagService in RustMatrixAuthenticationService instead of caching it in a field, and revert the extra matrix_sdk_search tracing target, which belongs in the SDK's defaults. --- .../libraries/featureflag/api/FeatureFlags.kt | 7 + .../libraries/matrix/api/MatrixClient.kt | 5 + .../matrix/api/search/MessageSearch.kt | 41 ++++ .../search/MessageSearchPaginationState.kt | 24 +++ .../matrix/api/search/MessageSearchResult.kt | 27 +++ .../matrix/api/search/MessageSearchService.kt | 31 +++ .../libraries/matrix/impl/RustMatrixClient.kt | 13 +- .../matrix/impl/RustMatrixClientFactory.kt | 43 +++- .../auth/RustMatrixAuthenticationService.kt | 16 +- .../impl/search/MessageSearchResultMapper.kt | 39 ++++ .../search/MessageSearchResultsProcessor.kt | 84 ++++++++ .../matrix/impl/search/RustMessageSearch.kt | 153 +++++++++++++ .../impl/search/RustMessageSearchService.kt | 33 +++ .../matrix/impl/search/TantivyQueryEscaper.kt | 85 ++++++++ .../matrix/impl/RustMatrixClientTest.kt | 1 + .../RustMatrixAuthenticationServiceTest.kt | 2 + .../fixtures/factories/SearchServiceResult.kt | 31 +++ .../fixtures/fakes/FakeFfiSearchService.kt | 45 ++++ .../MessageSearchResultsProcessorTest.kt | 176 +++++++++++++++ .../impl/search/RustMessageSearchTest.kt | 204 ++++++++++++++++++ .../impl/search/TantivyQueryEscaperTest.kt | 169 +++++++++++++++ .../libraries/matrix/test/FakeMatrixClient.kt | 4 + .../matrix/test/search/FakeMessageSearch.kt | 98 +++++++++ .../test/search/FakeMessageSearchService.kt | 30 +++ 24 files changed, 1353 insertions(+), 8 deletions(-) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearch.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearchPaginationState.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearchResult.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearchService.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/MessageSearchResultMapper.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/MessageSearchResultsProcessor.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearch.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearchService.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/TantivyQueryEscaper.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchServiceResult.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSearchService.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/MessageSearchResultsProcessorTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearchTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/TantivyQueryEscaperTest.kt create mode 100644 libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/search/FakeMessageSearch.kt create mode 100644 libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/search/FakeMessageSearchService.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 ab7454e72f..79b63f4455 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 @@ -159,4 +159,11 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), + MessageSearch( + key = "feature.message_search", + title = "Message search", + description = "Index messages locally so they can be searched. Only messages received while enabled are indexed.", + defaultValue = { false }, + isFinished = false, + ), } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index 0c26d87acb..0dd8821a4f 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 @@ -39,6 +39,7 @@ 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.scanner.ContentScanner +import io.element.android.libraries.matrix.api.search.MessageSearchService import io.element.android.libraries.matrix.api.spaces.SpaceService import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion import io.element.android.libraries.matrix.api.sync.SyncService @@ -70,6 +71,10 @@ interface MatrixClient { val notificationSettingsService: NotificationSettingsService val encryptionService: EncryptionService val roomDirectoryService: RoomDirectoryService + + /** Whether this live client was built with a message search index attached. */ + val isMessageSearchAvailable: Boolean + val messageSearchService: MessageSearchService val mediaPreviewService: MediaPreviewService val matrixMediaLoader: MatrixMediaLoader val sessionCoroutineScope: CoroutineScope diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearch.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearch.kt new file mode 100644 index 0000000000..002be8c7f8 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearch.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.matrix.api.search + +import kotlinx.collections.immutable.ImmutableList +import kotlinx.coroutines.flow.StateFlow + +/** + * A single, stateful message search cursor: one query at a time, with paginated results. + * + * Obtain an instance via [MessageSearchService.createMessageSearch]. The instance is tied to the + * [kotlinx.coroutines.CoroutineScope] it was created with; cancelling that scope releases the + * underlying SDK resources, so there is no `close()` to call. + */ +interface MessageSearch { + /** + * The current result set for the active query, in the order supplied by the SDK. + */ + val results: StateFlow> + + /** + * Whether a page is currently loading, and whether the end has been reached. + */ + val paginationState: StateFlow + + /** + * Set (or update) the search query. Clears the current results, restarts pagination from + * scratch and loads the first page. Call [paginate] to load any further pages. + */ + suspend fun setQuery(query: String): Result + + /** + * Load the next page of results. No-ops if a page is already loading or the end was reached. + */ + suspend fun paginate(): Result +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearchPaginationState.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearchPaginationState.kt new file mode 100644 index 0000000000..c55b8cd80b --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearchPaginationState.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.matrix.api.search + +/** + * Whether the search is currently loading a page of results. + */ +sealed interface MessageSearchPaginationState { + /** + * Not currently paginating. [endReached] is true once every source has been + * exhausted for the current query. + */ + data class Idle(val endReached: Boolean) : MessageSearchPaginationState + + /** + * A page of results is currently being loaded. + */ + data object Loading : MessageSearchPaginationState +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearchResult.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearchResult.kt new file mode 100644 index 0000000000..c4ae315c32 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearchResult.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.matrix.api.search + +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.timeline.item.event.EventContent +import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetails + +/** + * A single message matching a search query, with its content and sender resolved. + */ +data class MessageSearchResult( + val roomId: RoomId, + val eventId: EventId, + val senderId: UserId, + val senderProfile: ProfileDetails, + val content: EventContent, + /** Origin server timestamp, in milliseconds since the epoch. */ + val timestamp: Long, +) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearchService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearchService.kt new file mode 100644 index 0000000000..3e20b163f2 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/search/MessageSearchService.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.matrix.api.search + +import io.element.android.libraries.matrix.api.core.RoomId +import kotlinx.coroutines.CoroutineScope + +interface MessageSearchService { + /** + * Create a new, independent search cursor. + * + * The underlying SDK service is stateful (one query at a time), so create one per search + * screen — never one per keystroke, and never a shared singleton. + * + * @param scope the lifetime of the search session. The returned [MessageSearch] observes and + * emits results on this scope, and the underlying SDK service is closed once the scope + * completes, so there is nothing to release by hand. Pass the scope of the screen that owns the + * search, not a longer-lived one. + * @param roomId when null, the search is session-wide and results from every room the user is + * in are exposed; when non-null, only results from that room are. Note that the SDK searches + * and ranks across every room regardless, so this is a client-side filter, not a pushdown: a + * room with few matches may need several [MessageSearch.paginate] calls before any of its + * results surface. + */ + fun createMessageSearch(scope: CoroutineScope, roomId: RoomId? = null): MessageSearch +} 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 33ed6610d3..88b1f05909 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 @@ -81,6 +81,7 @@ import io.element.android.libraries.matrix.impl.roomdirectory.map import io.element.android.libraries.matrix.impl.roomlist.RoomListFactory import io.element.android.libraries.matrix.impl.roomlist.RustRoomListService import io.element.android.libraries.matrix.impl.roomlist.roomOrNull +import io.element.android.libraries.matrix.impl.search.RustMessageSearchService import io.element.android.libraries.matrix.impl.spaces.RustSpaceService import io.element.android.libraries.matrix.impl.sync.RustSyncService import io.element.android.libraries.matrix.impl.sync.map @@ -155,6 +156,7 @@ class RustMatrixClient( private val analyticsService: AnalyticsService, private val workManagerScheduler: WorkManagerScheduler, override val contentScanner: ContentScanner?, + override val isMessageSearchAvailable: Boolean, ) : MatrixClient { override val sessionId: UserId = UserId(innerClient.userId()) override val deviceId: DeviceId = DeviceId(innerClient.deviceId()) @@ -194,6 +196,11 @@ class RustMatrixClient( sessionDispatcher = sessionDispatcher, ) + override val messageSearchService = RustMessageSearchService( + client = innerClient, + sessionDispatcher = sessionDispatcher, + ) + private val roomSyncSubscriber: RoomSyncSubscriber = RoomSyncSubscriber(innerRoomListService, dispatchers) override val roomListService: RoomListService = RustRoomListService( @@ -876,7 +883,11 @@ class RustMatrixClient( File(sessionPaths.fileDirectory, fileName) }.sumOf { file -> file.length() - } + } + + // The message search index. Like the state database above it lives in the file + // directory and so survives a cache clear, but it can grow without bound and must + // not be invisible in the storage figures. Returns 0 when the index is disabled. + File(sessionPaths.fileDirectory, SEARCH_INDEX_DIRECTORY).getSizeOfFiles() } } 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 b4a9272166..de2c5c0141 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 @@ -81,10 +81,23 @@ 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 sessionPaths = sessionData.getSessionPaths() + val isMessageSearchAvailable = featureFlagService.isFeatureEnabled(FeatureFlags.MessageSearch) + val indexDirectory = File(sessionPaths.fileDirectory, SEARCH_INDEX_DIRECTORY) + + if (!isMessageSearchAvailable && indexDirectory.exists()) { + // With search off, events reach the event cache unindexed and the index can never + // catch up on them. Delete it so the next enable rebuilds it from a state where + // coverage can actually be guaranteed, instead of resuming a silently stale index. + Timber.tag("RustMatrixClient").i("Message search is disabled, deleting the stale search index") + indexDirectory.deleteRecursively() + } + val client = getBaseClientBuilder( - sessionPaths = sessionData.getSessionPaths(), + sessionPaths = sessionPaths, clientSecret = clientSecret, slidingSyncType = ClientBuilderSlidingSync.Restored, + isMessageSearchAvailable = isMessageSearchAvailable, ) .homeserverUrl(sessionData.homeserverUrl) .username(sessionData.userId) @@ -105,10 +118,14 @@ class RustMatrixClientFactory( client.restoreSession(sessionData.toSession()) - create(client, sessionData) + create(client, sessionData, isMessageSearchAvailable) } - suspend fun create(client: Client, sessionData: SessionData): RustMatrixClient { + suspend fun create( + client: Client, + sessionData: SessionData, + isMessageSearchAvailable: Boolean, + ): RustMatrixClient { val (anonymizedAccessToken, anonymizedRefreshToken) = client.session().anonymizedTokens() // Must be called before creating the sync service, timelines etc. @@ -155,6 +172,7 @@ class RustMatrixClientFactory( analyticsService = analyticsService, workManagerScheduler = workManagerScheduler, contentScanner = contentScanner, + isMessageSearchAvailable = isMessageSearchAvailable, ).also { Timber.tag("RustMatrixClient").i("Creating Client with access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'") } @@ -164,6 +182,7 @@ class RustMatrixClientFactory( sessionPaths: SessionPaths, clientSecret: ClientSecret?, slidingSyncType: ClientBuilderSlidingSync, + isMessageSearchAvailable: Boolean, ): ClientBuilder { return clientBuilderProvider.provide() .run { @@ -193,6 +212,18 @@ class RustMatrixClientFactory( ) .enableShareHistoryOnInvite(true) .threadsEnabled(featureFlagService.isFeatureEnabled(FeatureFlags.Threads), threadSubscriptions = false) + .run { + if (isMessageSearchAvailable) { + // The index is encrypted at rest with the same secret the SDK's SQLite stores + // use, or left unencrypted for sessions without one, matching those stores. + withSearchIndexStore( + path = File(sessionPaths.fileDirectory, SEARCH_INDEX_DIRECTORY).absolutePath, + password = clientSecret?.formattedAsString(), + ) + } else { + this + } + } .dmRoomDefinition(DmRoomDefinition.TWO_MEMBERS) .requestConfig( RequestConfig( @@ -221,6 +252,12 @@ class RustMatrixClientFactory( } } +/** + * Directory holding the local message search index, under the session's file directory. + * Not the cache directory: the index is not disposable, and a cache wipe should not destroy it. + */ +internal const val SEARCH_INDEX_DIRECTORY = "search-index" + sealed interface ClientBuilderSlidingSync { // The proxy will be supplied when restoring the Session. data object Restored : ClientBuilderSlidingSync 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 639031334e..dd9f73c381 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,8 @@ 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 +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.auth.AuthenticationException import io.element.android.libraries.matrix.api.auth.ElementClassicSession @@ -69,6 +71,7 @@ class RustMatrixAuthenticationService( private val secretGenerator: SecretGenerator, private val oAuthConfigurationProvider: OAuthConfigurationProvider, private val enterpriseService: EnterpriseService, + private val featureFlagService: FeatureFlagService, ) : MatrixAuthenticationService { // Any existing Element Classic session that we want to try to import secrets from during login. private var elementClassicSession: ElementClassicSession? = null @@ -160,7 +163,7 @@ class RustMatrixAuthenticationService( passphrase = pendingKey.formattedAsString(), sessionPaths = currentSessionPaths, ) - val matrixClient = rustMatrixClientFactory.create(client, sessionData) + val matrixClient = rustMatrixClientFactory.create(client, sessionData, isMessageSearchAvailable()) newMatrixClientObservers.forEach { it.invoke(matrixClient) } sessionStore.addSession(sessionData) @@ -235,7 +238,7 @@ class RustMatrixAuthenticationService( // We restore the client using the just retrieved session data client.restoreSession(sessionData.toSession()) - val matrixClient = rustMatrixClientFactory.create(client, sessionData) + val matrixClient = rustMatrixClientFactory.create(client, sessionData, isMessageSearchAvailable()) // We wait for the verification state to be known matrixClient.waitForKnownVerificationState() @@ -325,7 +328,7 @@ class RustMatrixAuthenticationService( passphrase = pendingKey.formattedAsString(), sessionPaths = currentSessionPaths, ) - val matrixClient = rustMatrixClientFactory.create(client, sessionData) + val matrixClient = rustMatrixClientFactory.create(client, sessionData, isMessageSearchAvailable()) matrixClient.waitForKnownVerificationState() newMatrixClientObservers.forEach { it.invoke(matrixClient) } @@ -390,7 +393,7 @@ class RustMatrixAuthenticationService( passphrase = pendingKey.formattedAsString(), sessionPaths = emptySessionPaths, ) - val matrixClient = rustMatrixClientFactory.create(client, sessionData) + val matrixClient = rustMatrixClientFactory.create(client, sessionData, isMessageSearchAvailable()) newMatrixClientObservers.forEach { it.invoke(matrixClient) } sessionStore.addSession(sessionData) @@ -422,6 +425,7 @@ class RustMatrixAuthenticationService( sessionPaths = sessionPaths, clientSecret = pendingKey, slidingSyncType = ClientBuilderSlidingSync.Discovered, + isMessageSearchAvailable = isMessageSearchAvailable(), ) .config() .build() @@ -454,6 +458,7 @@ class RustMatrixAuthenticationService( sessionPaths = sessionPaths, clientSecret = pendingKey, slidingSyncType = ClientBuilderSlidingSync.Discovered, + isMessageSearchAvailable = isMessageSearchAvailable(), ) .serverNameOrHomeserverUrl(baseUrlOrServerName) .build() @@ -464,6 +469,9 @@ class RustMatrixAuthenticationService( currentClient = null } + private suspend fun isMessageSearchAvailable(): Boolean = + featureFlagService.isFeatureEnabled(FeatureFlags.MessageSearch) + private suspend fun MatrixClient.waitForKnownVerificationState() { withTimeoutOrNull(10.seconds) { Timber.d("Waiting for a known verification status...") diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/MessageSearchResultMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/MessageSearchResultMapper.kt new file mode 100644 index 0000000000..033d0fc911 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/MessageSearchResultMapper.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.matrix.impl.search + +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.search.MessageSearchResult +import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper +import io.element.android.libraries.matrix.impl.timeline.item.event.map +import org.matrix.rustcomponents.sdk.SearchServiceResult + +class MessageSearchResultMapper( + private val contentMapper: TimelineEventContentMapper = TimelineEventContentMapper(), +) { + /** + * Note: [TimelineEventContentMapper.map] consumes (and destroys) the content, so each result + * must be mapped exactly once. + */ + fun map(result: SearchServiceResult): MessageSearchResult { + // Exhaustive on purpose, with no `else`: a new SDK result kind must fail compilation here + // rather than being silently dropped, which would desync our list from the SDK's indices. + return when (result) { + is SearchServiceResult.Message -> MessageSearchResult( + roomId = RoomId(result.roomId), + eventId = EventId(result.result.eventId), + senderId = UserId(result.result.sender), + senderProfile = result.result.senderProfile.map(), + content = contentMapper.map(result.result.content), + timestamp = result.result.timestamp.toLong(), + ) + } + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/MessageSearchResultsProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/MessageSearchResultsProcessor.kt new file mode 100644 index 0000000000..58c5f6b01c --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/MessageSearchResultsProcessor.kt @@ -0,0 +1,84 @@ +/* + * 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.search + +import io.element.android.libraries.matrix.api.search.MessageSearchResult +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import kotlinx.coroutines.withContext +import org.matrix.rustcomponents.sdk.SearchServiceResultsUpdate +import kotlin.coroutines.CoroutineContext + +/** + * Applies the SDK's diff stream to a local list of search results. + * + * The local list is kept strictly index-parallel to the SDK's: every result is mapped, nothing is + * filtered or dropped, so the positional updates ([SearchServiceResultsUpdate.Insert], + * [SearchServiceResultsUpdate.Set], [SearchServiceResultsUpdate.Remove], + * [SearchServiceResultsUpdate.Truncate]) always address the slot the SDK meant. Filtering for + * display, if ever needed, belongs at render time — not here. + */ +class MessageSearchResultsProcessor( + private val results: MutableSharedFlow>, + private val coroutineContext: CoroutineContext, + private val mapper: MessageSearchResultMapper = MessageSearchResultMapper(), +) { + private val mutex = Mutex() + + suspend fun postUpdates(updates: List) = withContext(coroutineContext) { + mutex.withLock { + val current = results.replayCache.lastOrNull().orEmpty().toMutableList() + updates.forEach { update -> + current.applyUpdate(update) + } + results.emit(current) + } + } + + private fun MutableList.applyUpdate(update: SearchServiceResultsUpdate) { + // Exhaustive on purpose, with no `else`: a future SDK bump adding a variant must fail + // compilation rather than silently dropping updates and corrupting the list. + when (update) { + is SearchServiceResultsUpdate.Append -> { + addAll(update.values.map(mapper::map)) + } + is SearchServiceResultsUpdate.PushBack -> { + add(mapper.map(update.value)) + } + is SearchServiceResultsUpdate.PushFront -> { + add(0, mapper.map(update.value)) + } + is SearchServiceResultsUpdate.Set -> { + this[update.index.toInt()] = mapper.map(update.value) + } + is SearchServiceResultsUpdate.Insert -> { + add(update.index.toInt(), mapper.map(update.value)) + } + is SearchServiceResultsUpdate.Remove -> { + removeAt(update.index.toInt()) + } + is SearchServiceResultsUpdate.Truncate -> { + subList(update.length.toInt(), size).clear() + } + is SearchServiceResultsUpdate.Reset -> { + clear() + addAll(update.values.map(mapper::map)) + } + SearchServiceResultsUpdate.PopBack -> { + removeLastOrNull() + } + SearchServiceResultsUpdate.PopFront -> { + removeFirstOrNull() + } + SearchServiceResultsUpdate.Clear -> { + clear() + } + } + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearch.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearch.kt new file mode 100644 index 0000000000..9116c88cc7 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearch.kt @@ -0,0 +1,153 @@ +/* + * 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.search + +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.search.MessageSearch +import io.element.android.libraries.matrix.api.search.MessageSearchPaginationState +import io.element.android.libraries.matrix.api.search.MessageSearchResult +import io.element.android.libraries.matrix.impl.util.TaskHandleBag +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.channels.Channel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.consumeAsFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.job +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import kotlinx.coroutines.withContext +import org.matrix.rustcomponents.sdk.SearchServiceInterface +import org.matrix.rustcomponents.sdk.SearchServicePaginationStateListener +import org.matrix.rustcomponents.sdk.SearchServiceResultsListener +import org.matrix.rustcomponents.sdk.SearchServiceResultsUpdate +import uniffi.matrix_sdk_ui.SearchServicePaginationState + +/** + * Wraps the SDK's stateful [SearchServiceInterface] as a single search cursor. + * + * Lifecycle: the caller's [CoroutineScope] owns this instance. When that scope completes, both + * subscription [org.matrix.rustcomponents.sdk.TaskHandle]s are cancelled and [onClose] releases the + * underlying service — the handles must be retained until then, or the Rust side drops the + * subscription. + * + * PII: search queries and message bodies are never logged. + */ +class RustMessageSearch( + private val inner: SearchServiceInterface, + private val onClose: () -> Unit, + scope: CoroutineScope, + private val dispatcher: CoroutineDispatcher, + private val roomId: RoomId? = null, +) : MessageSearch { + private val innerResults = MutableStateFlow>(emptyList()) + private val processor = MessageSearchResultsProcessor( + results = innerResults, + coroutineContext = dispatcher, + ) + private val taskHandles = TaskHandleBag() + private val subscriptionMutex = Mutex() + private var subscribedToResults = false + + /** + * The SDK listener is not a suspend function, so batches are handed to a single consumer + * coroutine. An unlimited channel keeps them strictly in arrival order — applying diffs out of + * order would corrupt the list just as surely as dropping them. + */ + private val updates = Channel>(Channel.UNLIMITED) + + override val results: StateFlow> = innerResults + .map { results -> + // Room scoping is applied HERE, at the exposure boundary, and nowhere else. + // [innerResults] must stay index-parallel to the SDK's own list, because the positional + // diffs (Insert/Set/Remove/Truncate) address the SDK's indices. Filtering inside + // MessageSearchResultsProcessor instead is precisely the element-x-ios desync bug. + when (roomId) { + null -> results.toImmutableList() + else -> results.filter { it.roomId == roomId }.toImmutableList() + } + } + .stateIn(scope, SharingStarted.Eagerly, persistentListOf()) + + private val mutablePaginationState = MutableStateFlow(inner.paginationState().map()) + override val paginationState: StateFlow = mutablePaginationState.asStateFlow() + + init { + updates.consumeAsFlow() + .onEach { processor.postUpdates(it) } + .launchIn(scope) + + taskHandles += inner.subscribeToPaginationStateUpdates( + object : SearchServicePaginationStateListener { + override fun onUpdate(paginationState: SearchServicePaginationState) { + mutablePaginationState.value = paginationState.map() + } + } + ) + + scope.coroutineContext.job.invokeOnCompletion { + taskHandles.dispose() + updates.close() + onClose() + } + } + + override suspend fun setQuery(query: String): Result = withContext(dispatcher) { + runCatchingExceptions { + // Subscribe lazily, so a search screen that is opened but never used costs nothing. + subscribeToResultsIfNeeded() + // The SDK contract for setQuery is "clears the current results, restarts pagination from + // scratch". Whatever endReached we are holding describes the PREVIOUS query — or, on the + // very first search, a cursor that was never queried at all and reports endReached=true + // because there is nothing to page through yet. Carrying it over makes every search look + // finished before it starts, so callers never paginate and an empty result is reported as + // a definitive "no results". Reset before handing the query over; the subscription + // corrects this the moment the SDK reports its real state. + mutablePaginationState.value = MessageSearchPaginationState.Idle(endReached = false) + // The SDK parses this with tantivy's strict query parser, where `:` and friends are + // syntax rather than text — a pasted URL fails the whole search. Escape so the query is + // searched literally. The caller keeps the raw string; only the SDK sees the escaped one. + inner.setQuery(query.escapeForTantivy()) + } + } + + override suspend fun paginate(): Result = withContext(dispatcher) { + runCatchingExceptions { + inner.paginate() + } + } + + private suspend fun subscribeToResultsIfNeeded() { + subscriptionMutex.withLock { + if (subscribedToResults) return@withLock + taskHandles += inner.subscribeToResults( + object : SearchServiceResultsListener { + override fun onUpdate(updates: List) { + this@RustMessageSearch.updates.trySend(updates) + } + } + ) + subscribedToResults = true + } + } +} + +internal fun SearchServicePaginationState.map(): MessageSearchPaginationState = when (this) { + is SearchServicePaginationState.Idle -> MessageSearchPaginationState.Idle(endReached = endReached) + SearchServicePaginationState.Loading -> MessageSearchPaginationState.Loading +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearchService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearchService.kt new file mode 100644 index 0000000000..43f22333ac --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearchService.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.search + +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.search.MessageSearch +import io.element.android.libraries.matrix.api.search.MessageSearchService +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import org.matrix.rustcomponents.sdk.Client + +class RustMessageSearchService( + private val client: Client, + private val sessionDispatcher: CoroutineDispatcher, +) : MessageSearchService { + override fun createMessageSearch(scope: CoroutineScope, roomId: RoomId?): MessageSearch { + // Each searchService() call mints a new Rust object, so this instance owns the one it + // creates and closes it when the caller's scope completes. + val searchService = client.searchService() + return RustMessageSearch( + inner = searchService, + onClose = { searchService.close() }, + scope = scope, + dispatcher = sessionDispatcher, + roomId = roomId, + ) + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/TantivyQueryEscaper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/TantivyQueryEscaper.kt new file mode 100644 index 0000000000..e375bdf9f6 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/search/TantivyQueryEscaper.kt @@ -0,0 +1,85 @@ +/* + * 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.search + +/** + * Characters that terminate a bare word wherever they appear in it. Escaping them keeps the token a + * single literal word. `\` is included so a backslash the user typed cannot escape one of ours, and + * `*` is the prefix/all-documents operator rather than a word breaker. + */ +private val ESCAPED_ANYWHERE = charArrayOf('\\', '^', '`', ':', '{', '}', '"', '\'', '[', ']', '(', ')', '*') + +/** + * Characters that are operators only in the first position of a term: `-`/`+` occurrence, `/` regex, + * `>`/`<` elastic range, `!` field separator, `~` slop. Inside a word they are ordinary text, so + * escaping them there would be over-broad — `C++` and `1/2/2024` must survive untouched. + */ +private val ESCAPED_WHEN_LEADING = charArrayOf('-', '+', '/', '>', '<', '!', '~') + +/** + * Bare-word operators, neutralised so the query stays literal text end to end: `a AND b` searches + * for the three words rather than silently switching to a boolean AND. Mid-query these change + * meaning rather than failing; only a dangling operator is a syntax error. + */ +private val OPERATOR_WORDS = setOf("AND", "OR", "NOT", "IN", "TO") + +private val WHITESPACE_REGEX = Regex("\\s+") + +private const val ESCAPE_HEADROOM = 8 + +/** + * Escapes a user-typed search string so tantivy's query parser reads it as literal text, and makes + * every word of it mandatory. + * + * **Escaping.** `matrix-sdk-search` hands the query to the **strict** `QueryParser::parse_query` with + * `body` as the only default field, so an unescaped `:` sends tantivy looking for a field named + * `https` and the whole search fails — pasting a link finds nothing at all. Unbalanced quotes and + * brackets, a leading `-`, and elastic ranges like `>5` fail the same way, and the error arrives as + * an opaque `ClientError` string we cannot tell apart from an I/O failure. + * + * Escaping is per token rather than wrapping the whole query in quotes: whitespace stays the term + * separator, and only a token that actually contained an operator changes shape. Wrapping instead + * would turn `design review notes` into one ordered phrase and quietly break every ordinary search. + * + * **Conjunction.** tantivy's parser is OR-by-default and the FFI takes a bare string, so + * `set_conjunction_by_default()` is unreachable from here — `check the photo` matched every message + * containing `the`, and buried the wanted one under hundreds of unrelated hits ranked by relevance. + * Prefixing each token with `+` makes it a Must clause, which parses to exactly the query + * `set_conjunction_by_default()` would have built. + * + * The `+` goes on **after** escaping, never before: `+` is escaped in leading position, so prefixing + * first would hand the escaper its own operator and produce a literal `\+`. That parses cleanly and + * silently restores OR, so it cannot be caught by anything but an assertion on the exact string. + * + * The costs, stated plainly: deliberate `"phrase"`, `-exclude` and boolean syntax stop working as + * operators; and a query is now only as good as its worst word — one typo, or one word the user + * misremembers, empties the result set where before it degraded to partial matches. + * + * Pinned to tantivy 0.26.1 grammar. PII: the query is never logged. + */ +internal fun String.escapeForTantivy(): String = + split(WHITESPACE_REGEX) + .filter { it.isNotEmpty() } + .joinToString(separator = " ") { token -> + // tantivy's default tokenizer splits on non-alphanumerics, so a token like `:)` or an + // emoji indexes no terms at all. Required, such a token could only ever subtract, and a + // single emoji beside real words would silently empty the results. Optional, it is + // inert — which is what it was before conjunctions too. + if (token.any(Char::isLetterOrDigit)) "+${token.escapeToken()}" else token.escapeToken() + } + +private fun String.escapeToken(): String = buildString(length + ESCAPE_HEADROOM) { + if (this@escapeToken in OPERATOR_WORDS) append('\\') + this@escapeToken.forEachIndexed { index, char -> + // One forward pass: chained replace() calls would re-escape the backslashes they just added. + if (char in ESCAPED_ANYWHERE || index == 0 && char in ESCAPED_WHEN_LEADING) { + append('\\') + } + append(char) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt index 0039f16ed9..4ea4bb64e3 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt @@ -160,5 +160,6 @@ class RustMatrixClientTest { analyticsService = FakeAnalyticsService(), workManagerScheduler = FakeWorkManagerScheduler(submitLambda = {}), contentScanner = FakeContentScanner(), + isMessageSearchAvailable = false, ) } 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 2b9080195f..f5f3ffd10b 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 @@ -11,6 +11,7 @@ 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.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.impl.ClientBuilderProvider import io.element.android.libraries.matrix.impl.FakeClientBuilderProvider import io.element.android.libraries.matrix.impl.createRustMatrixClientFactory @@ -72,6 +73,7 @@ class RustMatrixAuthenticationServiceTest { oAuthRedirectUrlProvider = FakeOAuthRedirectUrlProvider(), ), enterpriseService = enterpriseService, + featureFlagService = FakeFeatureFlagService(), ) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchServiceResult.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchServiceResult.kt new file mode 100644 index 0000000000..4e31ac89b7 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchServiceResult.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.matrix.impl.fixtures.factories + +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_USER_ID +import org.matrix.rustcomponents.sdk.MessageSearchResult +import org.matrix.rustcomponents.sdk.ProfileDetails +import org.matrix.rustcomponents.sdk.SearchServiceResult + +internal fun aRustSearchServiceResult( + eventId: String, + roomId: String = A_ROOM_ID.value, + sender: String = A_USER_ID.value, + body: String = "Hello", + timestamp: ULong = 0uL, +) = SearchServiceResult.Message( + roomId = roomId, + result = MessageSearchResult( + eventId = eventId, + sender = sender, + senderProfile = ProfileDetails.Unavailable, + content = aRustTimelineItemContentMsgLike(body = body), + timestamp = timestamp, + ), +) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSearchService.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSearchService.kt new file mode 100644 index 0000000000..e24d4eedd0 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSearchService.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.matrix.impl.fixtures.fakes + +import org.matrix.rustcomponents.sdk.NoHandle +import org.matrix.rustcomponents.sdk.SearchService +import org.matrix.rustcomponents.sdk.SearchServicePaginationStateListener +import org.matrix.rustcomponents.sdk.SearchServiceResultsListener +import org.matrix.rustcomponents.sdk.TaskHandle +import uniffi.matrix_sdk_ui.SearchServicePaginationState + +class FakeFfiSearchService( + private val initialPaginationState: SearchServicePaginationState = SearchServicePaginationState.Idle(endReached = false), + private val setQueryLambda: (String) -> Unit = {}, + private val paginateLambda: () -> Unit = {}, +) : SearchService(NoHandle) { + var resultsListener: SearchServiceResultsListener? = null + private set + var paginationStateListener: SearchServicePaginationStateListener? = null + private set + var subscribeToResultsCallCount = 0 + private set + + override suspend fun paginate() = paginateLambda() + + override fun paginationState(): SearchServicePaginationState = initialPaginationState + + override suspend fun setQuery(query: String) = setQueryLambda(query) + + override fun subscribeToPaginationStateUpdates(listener: SearchServicePaginationStateListener): TaskHandle { + paginationStateListener = listener + return FakeFfiTaskHandle() + } + + override suspend fun subscribeToResults(listener: SearchServiceResultsListener): TaskHandle { + subscribeToResultsCallCount++ + resultsListener = listener + return FakeFfiTaskHandle() + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/MessageSearchResultsProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/MessageSearchResultsProcessorTest.kt new file mode 100644 index 0000000000..28eabcf3ed --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/MessageSearchResultsProcessorTest.kt @@ -0,0 +1,176 @@ +/* + * 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.search + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.search.MessageSearchResult +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSearchServiceResult +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.matrix.rustcomponents.sdk.SearchServiceResultsUpdate + +class MessageSearchResultsProcessorTest { + private val results = MutableStateFlow>(emptyList()) + + private fun createProcessor() = MessageSearchResultsProcessor( + results = results, + coroutineContext = kotlin.coroutines.EmptyCoroutineContext, + ) + + private fun eventIds() = results.value.map { it.eventId.value } + + @Test + fun `Append adds entries at the end of the list`() = runTest { + val processor = createProcessor() + processor.postUpdates(listOf(SearchServiceResultsUpdate.Append(listOf(aRustSearchServiceResult("\$1"), aRustSearchServiceResult("\$2"))))) + + assertThat(eventIds()).isEqualTo(listOf("\$1", "\$2")) + } + + @Test + fun `PushBack adds an entry at the end of the list`() = runTest { + val processor = createProcessor() + processor.postUpdates(listOf(SearchServiceResultsUpdate.Append(listOf(aRustSearchServiceResult("\$1"))))) + processor.postUpdates(listOf(SearchServiceResultsUpdate.PushBack(aRustSearchServiceResult("\$2")))) + + assertThat(eventIds()).isEqualTo(listOf("\$1", "\$2")) + } + + @Test + fun `PushFront inserts an entry at the start of the list`() = runTest { + val processor = createProcessor() + processor.postUpdates(listOf(SearchServiceResultsUpdate.Append(listOf(aRustSearchServiceResult("\$1"))))) + processor.postUpdates(listOf(SearchServiceResultsUpdate.PushFront(aRustSearchServiceResult("\$0")))) + + assertThat(eventIds()).isEqualTo(listOf("\$0", "\$1")) + } + + @Test + fun `PopBack removes the last entry`() = runTest { + val processor = createProcessor() + processor.postUpdates(listOf(SearchServiceResultsUpdate.Append(listOf(aRustSearchServiceResult("\$1"), aRustSearchServiceResult("\$2"))))) + processor.postUpdates(listOf(SearchServiceResultsUpdate.PopBack)) + + assertThat(eventIds()).isEqualTo(listOf("\$1")) + } + + @Test + fun `PopFront removes the first entry`() = runTest { + val processor = createProcessor() + processor.postUpdates(listOf(SearchServiceResultsUpdate.Append(listOf(aRustSearchServiceResult("\$1"), aRustSearchServiceResult("\$2"))))) + processor.postUpdates(listOf(SearchServiceResultsUpdate.PopFront)) + + assertThat(eventIds()).isEqualTo(listOf("\$2")) + } + + @Test + fun `Insert puts an entry at the given index`() = runTest { + val processor = createProcessor() + processor.postUpdates(listOf(SearchServiceResultsUpdate.Append(listOf(aRustSearchServiceResult("\$1"), aRustSearchServiceResult("\$3"))))) + processor.postUpdates(listOf(SearchServiceResultsUpdate.Insert(1u, aRustSearchServiceResult("\$2")))) + + assertThat(eventIds()).isEqualTo(listOf("\$1", "\$2", "\$3")) + } + + @Test + fun `Set replaces the entry at the given index`() = runTest { + val processor = createProcessor() + processor.postUpdates(listOf(SearchServiceResultsUpdate.Append(listOf(aRustSearchServiceResult("\$1"), aRustSearchServiceResult("\$2"))))) + processor.postUpdates(listOf(SearchServiceResultsUpdate.Set(1u, aRustSearchServiceResult("\$9")))) + + assertThat(eventIds()).isEqualTo(listOf("\$1", "\$9")) + } + + @Test + fun `Remove drops the entry at the given index`() = runTest { + val processor = createProcessor() + processor.postUpdates( + listOf(SearchServiceResultsUpdate.Append(listOf(aRustSearchServiceResult("\$1"), aRustSearchServiceResult("\$2"), aRustSearchServiceResult("\$3")))) + ) + processor.postUpdates(listOf(SearchServiceResultsUpdate.Remove(1u))) + + assertThat(eventIds()).isEqualTo(listOf("\$1", "\$3")) + } + + @Test + fun `Truncate keeps only the first N entries`() = runTest { + val processor = createProcessor() + processor.postUpdates( + listOf(SearchServiceResultsUpdate.Append(listOf(aRustSearchServiceResult("\$1"), aRustSearchServiceResult("\$2"), aRustSearchServiceResult("\$3")))) + ) + processor.postUpdates(listOf(SearchServiceResultsUpdate.Truncate(2u))) + + assertThat(eventIds()).isEqualTo(listOf("\$1", "\$2")) + } + + @Test + fun `Clear empties the list`() = runTest { + val processor = createProcessor() + processor.postUpdates(listOf(SearchServiceResultsUpdate.Append(listOf(aRustSearchServiceResult("\$1"))))) + processor.postUpdates(listOf(SearchServiceResultsUpdate.Clear)) + + assertThat(eventIds()).isEmpty() + } + + @Test + fun `Reset replaces the whole list`() = runTest { + val processor = createProcessor() + processor.postUpdates(listOf(SearchServiceResultsUpdate.Append(listOf(aRustSearchServiceResult("\$1"), aRustSearchServiceResult("\$2"))))) + processor.postUpdates(listOf(SearchServiceResultsUpdate.Reset(listOf(aRustSearchServiceResult("\$7"))))) + + assertThat(eventIds()).isEqualTo(listOf("\$7")) + } + + /** + * Regression test for the index-desync bug present in the element-x-ios bridge, where positional + * updates from the SDK were applied to a list that had already been filtered, so every index + * landed in the wrong slot. Our list must stay index-parallel to the SDK's throughout a batch. + */ + @Test + fun `positional updates in one batch stay index-parallel with the SDK`() = runTest { + val processor = createProcessor() + processor.postUpdates( + listOf( + SearchServiceResultsUpdate.Append( + listOf(aRustSearchServiceResult("\$1"), aRustSearchServiceResult("\$2"), aRustSearchServiceResult("\$3")) + ), + SearchServiceResultsUpdate.Insert(1u, aRustSearchServiceResult("\$b")), + SearchServiceResultsUpdate.Remove(0u), + SearchServiceResultsUpdate.Set(0u, aRustSearchServiceResult("\$z")), + SearchServiceResultsUpdate.PushFront(aRustSearchServiceResult("\$a")), + SearchServiceResultsUpdate.Truncate(3u), + ) + ) + + // Append -> [1, 2, 3] + // Insert(1,b) -> [1, b, 2, 3] + // Remove(0) -> [b, 2, 3] + // Set(0,z) -> [z, 2, 3] + // PushFront(a)-> [a, z, 2, 3] + // Truncate(3) -> [a, z, 2] + assertThat(eventIds()).isEqualTo(listOf("\$a", "\$z", "\$2")) + } + + @Test + fun `a result carries roomId, sender and timestamp through the mapping`() = runTest { + val processor = createProcessor() + processor.postUpdates( + listOf( + SearchServiceResultsUpdate.Append( + listOf(aRustSearchServiceResult(eventId = "\$1", roomId = "!room:server", sender = "@bob:server", timestamp = 1234uL)) + ) + ) + ) + + val result = results.value.single() + assertThat(result.roomId.value).isEqualTo("!room:server") + assertThat(result.senderId.value).isEqualTo("@bob:server") + assertThat(result.timestamp).isEqualTo(1234L) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearchTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearchTest.kt new file mode 100644 index 0000000000..38787f4724 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearchTest.kt @@ -0,0 +1,204 @@ +/* + * 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.search + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.search.MessageSearchPaginationState +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSearchServiceResult +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiSearchService +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_ROOM_ID_2 +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.cancel +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.matrix.rustcomponents.sdk.SearchServiceResultsUpdate +import uniffi.matrix_sdk_ui.SearchServicePaginationState + +class RustMessageSearchTest { + @Test + fun `paginationState is seeded from the SDK and reflects later updates`() = runTest { + val dispatcher = StandardTestDispatcher(testScheduler) + val scope = CoroutineScope(dispatcher) + val service = FakeFfiSearchService(initialPaginationState = SearchServicePaginationState.Idle(endReached = true)) + val search = RustMessageSearch(inner = service, onClose = {}, scope = scope, dispatcher = dispatcher) + + assertThat(search.paginationState.value).isEqualTo(MessageSearchPaginationState.Idle(endReached = true)) + + service.paginationStateListener!!.onUpdate(SearchServicePaginationState.Loading) + assertThat(search.paginationState.value).isEqualTo(MessageSearchPaginationState.Loading) + + scope.cancel() + } + + @Test + fun `setQuery failure surfaces as Result failure without throwing`() = runTest { + val dispatcher = StandardTestDispatcher(testScheduler) + val scope = CoroutineScope(dispatcher) + val service = FakeFfiSearchService(setQueryLambda = { error("boom") }) + val search = RustMessageSearch(inner = service, onClose = {}, scope = scope, dispatcher = dispatcher) + + val result = search.setQuery("hello") + + assertThat(result.isFailure).isTrue() + scope.cancel() + } + + @Test + fun `the query handed to the SDK is escaped and made conjunctive for tantivy`() = runTest { + val dispatcher = StandardTestDispatcher(testScheduler) + val scope = CoroutineScope(dispatcher) + var queryReceived: String? = null + val service = FakeFfiSearchService(setQueryLambda = { queryReceived = it }) + val search = RustMessageSearch(inner = service, onClose = {}, scope = scope, dispatcher = dispatcher) + + // Unescaped, tantivy reads `https` as a field name and fails the entire search. The `+` + // makes the term mandatory: without it tantivy is OR-by-default and a multi-word query + // matches anything containing any one of its words. + search.setQuery("https://github.com/foo") + + assertThat(queryReceived).isEqualTo("+https\\://github.com/foo") + + scope.cancel() + } + + @Test + fun `paginate failure surfaces as Result failure without throwing`() = runTest { + val dispatcher = StandardTestDispatcher(testScheduler) + val scope = CoroutineScope(dispatcher) + val service = FakeFfiSearchService(paginateLambda = { error("boom") }) + val search = RustMessageSearch(inner = service, onClose = {}, scope = scope, dispatcher = dispatcher) + + val result = search.paginate() + + assertThat(result.isFailure).isTrue() + scope.cancel() + } + + @Test + fun `results are not subscribed to until the first setQuery, and only once`() = runTest { + val dispatcher = StandardTestDispatcher(testScheduler) + val scope = CoroutineScope(dispatcher) + val service = FakeFfiSearchService() + val search = RustMessageSearch(inner = service, onClose = {}, scope = scope, dispatcher = dispatcher) + + assertThat(service.subscribeToResultsCallCount).isEqualTo(0) + + search.setQuery("hello") + assertThat(service.subscribeToResultsCallCount).isEqualTo(1) + + search.setQuery("world") + assertThat(service.subscribeToResultsCallCount).isEqualTo(1) + + scope.cancel() + } + + @Test + fun `updates pushed by the SDK reach the results flow`() = runTest { + val dispatcher = StandardTestDispatcher(testScheduler) + val scope = CoroutineScope(dispatcher) + val service = FakeFfiSearchService() + val search = RustMessageSearch(inner = service, onClose = {}, scope = scope, dispatcher = dispatcher) + + search.setQuery("hello") + service.resultsListener!!.onUpdate( + listOf(SearchServiceResultsUpdate.Append(listOf(aRustSearchServiceResult("\$1"), aRustSearchServiceResult("\$2")))) + ) + advanceUntilIdle() + + assertThat(search.results.value.map { it.eventId.value }).isEqualTo(listOf("\$1", "\$2")) + + scope.cancel() + } + + @Test + fun `a room filter hides other rooms without disturbing SDK indexing`() = runTest { + val dispatcher = StandardTestDispatcher(testScheduler) + val scope = CoroutineScope(dispatcher) + val service = FakeFfiSearchService() + val search = RustMessageSearch(inner = service, onClose = {}, scope = scope, dispatcher = dispatcher, roomId = A_ROOM_ID) + + search.setQuery("hello") + // SDK list: [$1@room1, $2@room2, $3@room1, $4@room2] + service.resultsListener!!.onUpdate( + listOf( + SearchServiceResultsUpdate.Append( + listOf( + aRustSearchServiceResult("\$1", roomId = A_ROOM_ID.value), + aRustSearchServiceResult("\$2", roomId = A_ROOM_ID_2.value), + aRustSearchServiceResult("\$3", roomId = A_ROOM_ID.value), + aRustSearchServiceResult("\$4", roomId = A_ROOM_ID_2.value), + ) + ) + ) + ) + advanceUntilIdle() + + assertThat(search.results.value.map { it.eventId.value }).isEqualTo(listOf("\$1", "\$3")) + + // Index 2 in the SDK's list is $3. Had the filter been applied inside the processor, the + // filtered list would be [$1, $3] and index 2 would be out of bounds — the iOS bug. + service.resultsListener!!.onUpdate( + listOf(SearchServiceResultsUpdate.Set(index = 2u, value = aRustSearchServiceResult("\$3edited", roomId = A_ROOM_ID.value))) + ) + advanceUntilIdle() + + assertThat(search.results.value.map { it.eventId.value }).isEqualTo(listOf("\$1", "\$3edited")) + + // Removing index 1 ($2, a room we filter out) must not shift anything the user can see. + service.resultsListener!!.onUpdate(listOf(SearchServiceResultsUpdate.Remove(index = 1u))) + advanceUntilIdle() + + assertThat(search.results.value.map { it.eventId.value }).isEqualTo(listOf("\$1", "\$3edited")) + + scope.cancel() + } + + @Test + fun `no room filter exposes every room`() = runTest { + val dispatcher = StandardTestDispatcher(testScheduler) + val scope = CoroutineScope(dispatcher) + val service = FakeFfiSearchService() + val search = RustMessageSearch(inner = service, onClose = {}, scope = scope, dispatcher = dispatcher, roomId = null) + + search.setQuery("hello") + service.resultsListener!!.onUpdate( + listOf( + SearchServiceResultsUpdate.Append( + listOf( + aRustSearchServiceResult("\$1", roomId = A_ROOM_ID.value), + aRustSearchServiceResult("\$2", roomId = A_ROOM_ID_2.value), + ) + ) + ) + ) + advanceUntilIdle() + + assertThat(search.results.value.map { it.eventId.value }).isEqualTo(listOf("\$1", "\$2")) + + scope.cancel() + } + + @Test + fun `cancelling the scope closes the underlying service`() = runTest { + val dispatcher = StandardTestDispatcher(testScheduler) + val scope = CoroutineScope(dispatcher) + var closed = false + val service = FakeFfiSearchService() + RustMessageSearch(inner = service, onClose = { closed = true }, scope = scope, dispatcher = dispatcher) + + assertThat(closed).isFalse() + + scope.cancel() + advanceUntilIdle() + + assertThat(closed).isTrue() + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/TantivyQueryEscaperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/TantivyQueryEscaperTest.kt new file mode 100644 index 0000000000..dae76ed006 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/TantivyQueryEscaperTest.kt @@ -0,0 +1,169 @@ +/* + * 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.search + +import com.google.common.truth.Truth.assertThat +import org.junit.Test + +/** + * Expectations here were checked against tantivy 0.26.1's own `QueryParser` — the version + * `matrix-sdk-search` compiles against — not inferred from the grammar. Each case notes the query it + * parses to, because "does not throw" is not the same as "searches for what the user typed". + */ +class TantivyQueryEscaperTest { + @Test + fun `an ordinary multi-word query becomes a conjunction`() { + // The headline behaviour. Without the `+`s tantivy is OR-by-default, so searching + // `check the photo` returned every message containing `the` — measured on device: a list of + // unrelated hits ranked by relevance, with the message actually wanted nowhere in it. + // Each `+` is a Must clause, which is what `set_conjunction_by_default()` would produce if + // the FFI let us call it. + assertThat("design review notes".escapeForTantivy()).isEqualTo("+design +review +notes") + } + + @Test + fun `a single word query is a conjunction of one`() { + assertThat("photo".escapeForTantivy()).isEqualTo("+photo") + } + + @Test + fun `the plus is prepended after escaping, never before`() { + // Load-bearing and silent when wrong: `-` is escaped only in leading position, so prefixing + // first would hand the escaper our own `+` to escape and produce `\+\-cats` — a literal + // plus, no Must clause, no parse error, and OR behaviour restored without a single failing + // assertion anywhere. + assertThat("-cats".escapeForTantivy()).isEqualTo("+\\-cats") + } + + @Test + fun `a pasted URL no longer parses as a field lookup`() { + // The bug: unescaped, tantivy resolves `https` as a field name and fails the WHOLE search + // with FieldDoesNotExist. Only the colon needs escaping; the slashes are not leading. + assertThat("https://github.com/foo".escapeForTantivy()).isEqualTo("+https\\://github.com/foo") + } + + @Test + fun `a real indexed field name is escaped too`() { + // `date` IS in the schema, as a DATE field, so this fails differently and more confusingly: + // DateFormatError rather than FieldDoesNotExist. The fix is not only about unknown fields. + assertThat("date:2020".escapeForTantivy()).isEqualTo("+date\\:2020") + } + + @Test + fun `a matrix id is escaped`() { + // The second most likely paste after a URL. `@` and `.` are ordinary characters. + assertThat("@alice:matrix.org".escapeForTantivy()).isEqualTo("+@alice\\:matrix.org") + } + + @Test + fun `a colon separated from its field name by a space is still escaped`() { + // The grammar allows whitespace between a field name and its colon, so `time: 12` would also + // be read as a field access. Per-token escaping defeats the spaced form as well. + assertThat("time: 12:30".escapeForTantivy()).isEqualTo("+time\\: +12\\:30") + } + + @Test + fun `an elastic range operator is escaped`() { + // A genuine second failure class the desktop colon-only fix would have missed: unescaped, + // `>5` fails with UnsupportedQuery("Range query need to target a specific field."). + assertThat(">5".escapeForTantivy()).isEqualTo("+\\>5") + } + + @Test + fun `quotes are escaped, which deliberately drops phrase search`() { + // Documents the cost: a typed phrase search becomes two AND'd terms. Accepted because a + // MISbalanced quote is a hard failure and the UI never advertised phrase syntax. Since the + // change to conjunctions this is much closer to a phrase search than it used to be — the + // words must all be present, only their order and adjacency are lost. + assertThat("\"quoted phrase\"".escapeForTantivy()).isEqualTo("+\\\"quoted +phrase\\\"") + } + + @Test + fun `an unclosed quote no longer fails the search`() { + // Why quotes are escaped at all: an odd number of quotes is a syntax error today, and + // half-typed quotes happen constantly on a mobile keyboard. + assertThat("\"unclosed phrase".escapeForTantivy()).isEqualTo("+\\\"unclosed +phrase") + } + + @Test + fun `parentheses are escaped`() { + // An unbalanced paren is a hard parse failure, and parens are common in ordinary prose. + assertThat("(a b)".escapeForTantivy()).isEqualTo("+\\(a +b\\)") + } + + @Test + fun `a backslash the user typed is doubled`() { + // Guards the escaper against itself: without this the user's backslash would escape the one + // we appended and shift the whole token. This is why escaping is a single forward pass. + assertThat("foo\\bar".escapeForTantivy()).isEqualTo("+foo\\\\bar") + } + + @Test + fun `a plus is left alone when it is not leading`() { + // `+` is only an operator in leading position. Confirms the escaper is not over-broad. + assertThat("C++".escapeForTantivy()).isEqualTo("+C++") + } + + @Test + fun `a date with slashes is left alone`() { + // Slashes are only escaped when leading, where they would open a regex literal. + assertThat("1/2/2024".escapeForTantivy()).isEqualTo("+1/2/2024") + } + + @Test + fun `a bare-word boolean operator is neutralised`() { + // A uniformity choice rather than purely an error fix: the query is literal text, so + // `a AND b` searches for two words instead of silently switching to boolean AND — which is + // now what every query does anyway. + assertThat("hello NOT".escapeForTantivy()).isEqualTo("+hello +\\NOT") + } + + @Test + fun `a token with no letters or digits is never made mandatory`() { + // tantivy's default tokenizer splits on non-alphanumerics, so `:)` and emoji tokenise to + // nothing. As a Must clause a token that indexes no terms can only ever subtract, so an + // emoji typed alongside real words would silently empty the result set. Left as a Should + // clause it is inert, which is what it was before this change too. + assertThat("photo :)".escapeForTantivy()).isEqualTo("+photo \\:\\)") + assertThat("fotoğraf 📷".escapeForTantivy()).isEqualTo("+fotoğraf 📷") + } + + @Test + fun `a punctuation-only query behaves exactly as it did before`() { + // The residual cost, recorded honestly: this no longer errors, but it tokenises to nothing + // and becomes EmptyQuery — zero results, silently. Better than killing the search, not good. + assertThat(":::".escapeForTantivy()).isEqualTo("\\:\\:\\:") + } + + @Test + fun `a lone star matches nothing instead of everything`() { + // A real behaviour delta: `*` alone is AllQuery today and EmptyQuery after this change. + // Neither is a sensible search, but the change should be pinned rather than discovered. + assertThat("*".escapeForTantivy()).isEqualTo("\\*") + } + + @Test + fun `non-ascii words are mandatory like any other`() { + // The account this was built for is Turkish. Kotlin's isLetterOrDigit is Unicode-aware, so + // no accented or non-Latin word is mistaken for punctuation and demoted. + assertThat("fotoğrafa bak".escapeForTantivy()).isEqualTo("+fotoğrafa +bak") + } + + @Test + fun `runs of whitespace collapse and the query is trimmed`() { + // Semantically neutral to tantivy — whitespace is only a separator — but it is an + // observable change to the string we hand over, so it is pinned. + assertThat(" spaced out ".escapeForTantivy()).isEqualTo("+spaced +out") + } + + @Test + fun `an empty query stays empty`() { + assertThat("".escapeForTantivy()).isEqualTo("") + assertThat(" ".escapeForTantivy()).isEqualTo("") + } +} 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 0933239c93..cdf7cc85cf 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 @@ -39,6 +39,7 @@ 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.scanner.ContentScanner +import io.element.android.libraries.matrix.api.search.MessageSearchService import io.element.android.libraries.matrix.api.spaces.SpaceService import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion import io.element.android.libraries.matrix.api.sync.SyncService @@ -55,6 +56,7 @@ import io.element.android.libraries.matrix.test.notificationsettings.FakeNotific import io.element.android.libraries.matrix.test.pushers.FakePushersService import io.element.android.libraries.matrix.test.roomdirectory.FakeRoomDirectoryService import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService +import io.element.android.libraries.matrix.test.search.FakeMessageSearchService import io.element.android.libraries.matrix.test.spaces.FakeSpaceService import io.element.android.libraries.matrix.test.sync.FakeSyncService import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService @@ -91,6 +93,8 @@ class FakeMatrixClient( override val syncService: SyncService = FakeSyncService(), override val encryptionService: EncryptionService = FakeEncryptionService(), override val roomDirectoryService: RoomDirectoryService = FakeRoomDirectoryService(), + override val isMessageSearchAvailable: Boolean = false, + override val messageSearchService: MessageSearchService = FakeMessageSearchService(), override val mediaPreviewService: MediaPreviewService = FakeMediaPreviewService(), override val roomMembershipObserver: RoomMembershipObserver = RoomMembershipObserver(), private val homeserverCapabilitiesProvider: FakeHomeserverCapabilitiesProvider = FakeHomeserverCapabilitiesProvider(), diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/search/FakeMessageSearch.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/search/FakeMessageSearch.kt new file mode 100644 index 0000000000..8cb3bae986 --- /dev/null +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/search/FakeMessageSearch.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.libraries.matrix.test.search + +import io.element.android.libraries.matrix.api.search.MessageSearch +import io.element.android.libraries.matrix.api.search.MessageSearchPaginationState +import io.element.android.libraries.matrix.api.search.MessageSearchResult +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow + +class FakeMessageSearch( + private val setQueryResult: suspend (String) -> Result = { Result.success(Unit) }, + private val paginateResult: suspend () -> Result = { Result.success(Unit) }, + private val controllablePagination: Boolean = false, +) : MessageSearch { + private val mutableResults = MutableStateFlow>(persistentListOf()) + override val results: StateFlow> = mutableResults + + private val mutablePaginationState = MutableStateFlow( + MessageSearchPaginationState.Idle(endReached = false) + ) + override val paginationState: StateFlow = mutablePaginationState + + var lastQuery: String? = null + private set + + var setQueryCallCount = 0 + private set + + var paginateCallCount = 0 + private set + + var completedPaginateCallCount = 0 + private set + + var cancelledPaginateCallCount = 0 + private set + + private var pendingPagination = CompletableDeferred() + + override suspend fun setQuery(query: String): Result { + lastQuery = query + setQueryCallCount++ + return setQueryResult(query) + } + + override suspend fun paginate(): Result { + paginateCallCount++ + if (!controllablePagination) { + return paginateResult() + } + + mutablePaginationState.value = MessageSearchPaginationState.Loading + return try { + val completion = pendingPagination.await() + completedPaginateCallCount++ + mutablePaginationState.value = MessageSearchPaginationState.Idle(endReached = completion.endReached) + completion.result + } catch (exception: CancellationException) { + cancelledPaginateCallCount++ + mutablePaginationState.value = MessageSearchPaginationState.Idle(endReached = false) + throw exception + } finally { + pendingPagination = CompletableDeferred() + } + } + + fun emitResults(results: ImmutableList) { + mutableResults.value = results + } + + fun emitPaginationState(state: MessageSearchPaginationState) { + mutablePaginationState.value = state + } + + fun completePagination( + result: Result = Result.success(Unit), + endReached: Boolean = false, + ) { + check(pendingPagination.complete(PaginationCompletion(result, endReached))) { + "There is no pending pagination to complete." + } + } + + private data class PaginationCompletion( + val result: Result, + val endReached: Boolean, + ) +} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/search/FakeMessageSearchService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/search/FakeMessageSearchService.kt new file mode 100644 index 0000000000..38d418e30e --- /dev/null +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/search/FakeMessageSearchService.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.test.search + +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.search.MessageSearch +import io.element.android.libraries.matrix.api.search.MessageSearchService +import kotlinx.coroutines.CoroutineScope + +class FakeMessageSearchService( + private val messageSearch: MessageSearch = FakeMessageSearch(), +) : MessageSearchService { + /** The room the search was scoped to on the last call — null means all rooms. */ + var lastRoomId: RoomId? = null + private set + + var createMessageSearchCallCount = 0 + private set + + override fun createMessageSearch(scope: CoroutineScope, roomId: RoomId?): MessageSearch { + lastRoomId = roomId + createMessageSearchCallCount++ + return messageSearch + } +} From 52d146a59d5cde9fb0400f0281a1b52921f27b58 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Thu, 30 Jul 2026 11:51:18 +0200 Subject: [PATCH 233/383] CI: split unit tests, screenshots and coverage in `tests.yml` (#7296) * Check if splitting the steps for testing and generating the reports improves performance and keeps the coverage stats * Exclude Konsist tests and include `:app` ones * Remove the extra dependency of `koverVerifyAll` on `:app:koverVerify{variant}` --- .github/workflows/tests.yml | 14 ++++++++++---- .../src/main/kotlin/extension/KoverExtension.kt | 3 +-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 72f1f7cce7..5ee7f5065d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -12,7 +12,7 @@ permissions: {} # Enrich gradle.properties for CI/CD env: GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx7g -XX:MaxMetaspaceSize=512m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options=-Xmx2g -XX:+UseG1GC - CI_GRADLE_ARG_PROPERTIES: --stacktrace --no-daemon -Dsonar.gradle.skipCompile=true --no-configuration-cache + CI_GRADLE_ARG_PROPERTIES: --stacktrace -Dsonar.gradle.skipCompile=true --no-configuration-cache jobs: tests: @@ -72,8 +72,14 @@ jobs: with: cache-read-only: ${{ github.ref != 'refs/heads/develop' }} - - name: ⚙️ Check coverage for debug variant (includes unit & screenshot tests) - run: ./gradlew testDebugUnitTest :tests:uitests:verifyPaparazziDebug :koverXmlReportMerged :koverHtmlReportMerged :koverVerifyAll $CI_GRADLE_ARG_PROPERTIES + - name: ⚙️ Run unit tests + run: ./gradlew :app:testGplayDebugUnitTest testDebugUnitTest -x :tests:konsist:testDebugUnitTest $CI_GRADLE_ARG_PROPERTIES + + - name: ⚙️ Run screenshot tests + run: ./gradlew :tests:uitests:verifyPaparazziDebug $CI_GRADLE_ARG_PROPERTIES + + - name: ⚙️ Generate kover coverage report + run: ./gradlew :koverXmlReportMerged :koverHtmlReportMerged :koverVerifyAll -x testDebugUnitTest $CI_GRADLE_ARG_PROPERTIES - name: 🚫 Upload kover failed coverage reports if: failure() @@ -81,7 +87,7 @@ jobs: with: name: kover-error-report path: | - app/build/reports/kover + build/reports/kover - name: ✅ Upload kover report (disabled) if: always() diff --git a/plugins/src/main/kotlin/extension/KoverExtension.kt b/plugins/src/main/kotlin/extension/KoverExtension.kt index c851a25ab9..610562ce6a 100644 --- a/plugins/src/main/kotlin/extension/KoverExtension.kt +++ b/plugins/src/main/kotlin/extension/KoverExtension.kt @@ -64,8 +64,7 @@ fun Project.setupKover() { tasks.register("koverVerifyAll") { group = "verification" description = "Verifies the code coverage of all subprojects." - val dependencies = listOf(":koverVerifyMerged") + koverVariants.map { ":app:koverVerify${it.replaceFirstChar(Char::titlecase)}" } - dependsOn(dependencies) + dependsOn(":koverVerifyMerged") } // https://kotlin.github.io/kotlinx-kover/ // Run `./gradlew :app:koverHtmlReport` to get report at ./app/build/reports/kover From 1a07fdfed0a3855af4ac1e8741c3645605d27130 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 09:03:28 +0200 Subject: [PATCH 234/383] Update zizmorcore/zizmor-action action to v0.6.1 (#7306) 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 cf74a9e396..e72ae0b4d1 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -336,7 +336,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - - uses: zizmorcore/zizmor-action@6599ee8b7a49aef6a770f63d261d214911a7ce02 # v0.6.0 + - uses: zizmorcore/zizmor-action@6fc4b006235f201fdab3722e17240ab420d580e5 # v0.6.1 upload_reports: name: Project Check Suite From c70bd32f59bd3f6920f00b4dfc0756d0dcbcf955 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 09:05:56 +0200 Subject: [PATCH 235/383] Update android.gradle.plugin to v9.3.1 (#7304) 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 23dc990beb..48bf6f008a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ [versions] # Project -android_gradle_plugin = "9.3.0" +android_gradle_plugin = "9.3.1" # When updating this, please also update the version in the file ./idea/kotlinc.xml kotlin = "2.4.10" kotlinpoet = "2.3.0" From 54a8770f317f011b500dd669c22b3ec5620aee90 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 31 Jul 2026 09:46:40 +0200 Subject: [PATCH 236/383] Bump enterprise module to the latest commit (#7307) --- enterprise | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enterprise b/enterprise index 7bbf7db013..2af143e84f 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit 7bbf7db0135c6a537ce360abb482922e6582d879 +Subproject commit 2af143e84f9fafecf9e4468e6a583b14f16039fd From 50ff04ac88e6621dca9874b97dca05d33e16d431 Mon Sep 17 00:00:00 2001 From: Jenna Vassar Date: Fri, 31 Jul 2026 09:52:22 -0700 Subject: [PATCH 237/383] Bump enterprise module to the latest commit (#7309) --- enterprise | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enterprise b/enterprise index 2af143e84f..9b1ee4cd88 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit 2af143e84f9fafecf9e4468e6a583b14f16039fd +Subproject commit 9b1ee4cd8846eb30a1bc62be718e77eed281dfe6 From 0a577ffbb884543e9cbb09249af3768ee2b856bb Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Mon, 13 Jul 2026 12:19:08 +0100 Subject: [PATCH 238/383] Render push notifications for live location share starts --- .../api/notification/NotificationData.kt | 2 +- ...imelineEventToNotificationContentMapper.kt | 6 ++--- .../DefaultNotifiableEventResolver.kt | 21 ++++++++++++++++-- .../DefaultNotifiableEventResolverTest.kt | 22 +++++++++++++++++++ 4 files changed, 45 insertions(+), 6 deletions(-) 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 8a4891a5bf..96ef7044f6 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 @@ -118,7 +118,7 @@ sealed interface NotificationContent { data class RoomTopic(val topic: String) : StateEvent data object SpaceChild : StateEvent data object SpaceParent : StateEvent - data object BeaconInfo : StateEvent + data class BeaconInfo(val senderId: UserId) : StateEvent } data class Invite( 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 e4914019ea..83b4aa7570 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 @@ -40,11 +40,11 @@ class TimelineEventToNotificationContentMapper { private fun TimelineEventContent.toContent(senderId: UserId): NotificationContent { return when (this) { is TimelineEventContent.MessageLike -> content.toContent(senderId) - is TimelineEventContent.State -> content.toContent() + is TimelineEventContent.State -> content.toContent(senderId) } } -private fun StateEventContent.toContent(): NotificationContent.StateEvent { +private fun StateEventContent.toContent(senderId: UserId): NotificationContent.StateEvent { return when (this) { StateEventContent.PolicyRuleRoom -> NotificationContent.StateEvent.PolicyRuleRoom StateEventContent.PolicyRuleServer -> NotificationContent.StateEvent.PolicyRuleServer @@ -71,7 +71,7 @@ private fun StateEventContent.toContent(): NotificationContent.StateEvent { is StateEventContent.RoomTopic -> NotificationContent.StateEvent.RoomTopic(topic) StateEventContent.SpaceChild -> NotificationContent.StateEvent.SpaceChild StateEventContent.SpaceParent -> NotificationContent.StateEvent.SpaceParent - StateEventContent.BeaconInfo -> NotificationContent.StateEvent.BeaconInfo + StateEventContent.BeaconInfo -> NotificationContent.StateEvent.BeaconInfo(senderId) } } 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 0b2ae5be2c..abbda10a3c 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 @@ -303,6 +303,24 @@ class DefaultNotifiableEventResolver( Timber.tag(loggerTag.value).d("Ignoring notification for beacon") throw NotificationResolverException.EventFilteredOut } + is NotificationContent.StateEvent.BeaconInfo -> { + val notifiableEventMessage = buildNotifiableMessageEvent( + sessionId = userId, + senderId = content.senderId, + roomId = roomId, + eventId = eventId, + noisy = isNoisy, + timestamp = this.timestamp, + senderDisambiguatedDisplayName = getDisambiguatedDisplayName(content.senderId), + body = stringProvider.getString(R.string.notification_live_location_started_body), + imageUriString = null, + roomName = roomDisplayName, + roomIsDm = isDm, + roomAvatarPath = roomAvatarUrl, + senderAvatarPath = senderAvatarUrl, + ) + ResolvedPushEvent.Event(notifiableEventMessage) + } is NotificationContent.StateEvent.RoomMemberContent, NotificationContent.StateEvent.PolicyRuleRoom, NotificationContent.StateEvent.PolicyRuleServer, @@ -322,8 +340,7 @@ class DefaultNotifiableEventResolver( NotificationContent.StateEvent.RoomTombstone, is NotificationContent.StateEvent.RoomTopic, NotificationContent.StateEvent.SpaceChild, - NotificationContent.StateEvent.SpaceParent, - NotificationContent.StateEvent.BeaconInfo -> { + NotificationContent.StateEvent.SpaceParent -> { Timber.tag(loggerTag.value).d("Ignoring notification for state event ${content.javaClass.simpleName}") throw NotificationResolverException.EventFilteredOut } 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 e196ddb0ec..eedc107c67 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 @@ -416,6 +416,27 @@ class DefaultNotifiableEventResolverTest : RobolectricTest() { assertThat(result.getEvent(request)).isEqualTo(Result.success(expectedResult)) } + @Test + fun `resolve live location share start`() = runTest { + val sut = createDefaultNotifiableEventResolver( + notificationResult = Result.success( + mapOf( + AN_EVENT_ID to Result.success(aNotificationData( + content = NotificationContent.StateEvent.BeaconInfo( + senderId = A_USER_ID_2, + ), + )) + ) + ) + ) + val request = aPushRequest(A_SESSION_ID, A_ROOM_ID, AN_EVENT_ID, "firebase") + val result = sut.resolveEvents(A_SESSION_ID, listOf(request)) + val expectedResult = ResolvedPushEvent.Event( + aNotifiableMessageEvent(body = "Started sharing their live location") + ) + assertThat(result.getEvent(request)).isEqualTo(Result.success(expectedResult)) + } + @Test fun `resolve RoomMemberContent invite room`() = runTest { val sut = createDefaultNotifiableEventResolver( @@ -829,6 +850,7 @@ class DefaultNotifiableEventResolverTest : RobolectricTest() { testNoResults(NotificationContent.MessageLike.KeyVerificationDone) testNoResults(NotificationContent.MessageLike.ReactionContent(relatedEventId = AN_EVENT_ID_2.value)) testNoResults(NotificationContent.MessageLike.Sticker) + testNoResults(NotificationContent.MessageLike.Beacon) testNoResults(NotificationContent.StateEvent.PolicyRuleRoom) testNoResults(NotificationContent.StateEvent.PolicyRuleServer) testNoResults(NotificationContent.StateEvent.PolicyRuleUser) From 28b90a91d04dc9f06fa761bb39f78315156750fe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:53:09 +0000 Subject: [PATCH 239/383] Update dependencyAnalysis to v3.18.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 48bf6f008a..ec21aa553d 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.17.0" +dependencyAnalysis = "3.18.0" # DI metro = "1.3.2" From 6f1906300c3911c457352545c70a6b953e6fe74a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 20:49:39 +0000 Subject: [PATCH 240/383] Update dependency com.posthog:posthog-android to v3.56.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 48bf6f008a..71d24b00f1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -229,7 +229,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.51.1" +posthog = "com.posthog:posthog-android:3.56.4" sentry = "io.sentry:sentry-android:8.50.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.37.0" From cdc4ac73fc091d3577e9b6b9a6bd67d9da436e67 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 20:49:57 +0000 Subject: [PATCH 241/383] Update actions/stale action to v11 --- .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 622fecc403..d8f57e3355 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@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10.3.0 + - uses: actions/stale@4391f3da665fdf50b6810c1a66712fb9ba21aa93 # v11.0.0 with: only-labels: "X-Needs-Info" days-before-issue-stale: 30 From 6c6f596b1a834dfd980557698d885b4abbb687da Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2026 09:20:04 +0000 Subject: [PATCH 242/383] Update dependency io.github.zxing-cpp:android to v3.1.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 41fd6a5a00..e41d044ff6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -220,7 +220,7 @@ maplibre_ktx = "org.maplibre.gl:android-sdk-ktx-v7:3.0.2" maplibre_compose = "org.maplibre.compose:maplibre-compose:0.13.1" 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.1.0" +zxing_cpp = "io.github.zxing-cpp:android:3.1.1" google_zxing = "com.google.zxing:core:3.5.4" google_guava = "com.google.guava:guava:33.6.0-android" From b327b435ab9a1769b4656d92fb8556441ddfe088 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Aug 2026 13:55:15 +0000 Subject: [PATCH 243/383] Update dependency org.matrix.rustcomponents:sdk-android to v26.08.05 --- 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 e41d044ff6..c7fa8e1300 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -185,7 +185,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.07.28" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.08.05" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } From 38102747adb3544e29d54e4f9bbfb108e5e5eebc Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 30 Jun 2026 18:46:56 +0200 Subject: [PATCH 244/383] Wire user status through the Rust SDK and refresh profile after change # Conflicts: # libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt --- .../matrix/api/user/DisplayedStatus.kt | 6 ++- .../libraries/matrix/impl/RustMatrixClient.kt | 43 +++++++------------ .../matrix/impl/room/JoinedRustRoom.kt | 1 + .../{mapper => user}/UserProfileMapper.kt | 5 ++- .../UserSearchResultMapper.kt | 3 +- .../libraries/matrix/impl/user/UserStatus.kt | 29 +++++++++++++ .../SessionVerificationRequestDetails.kt | 2 +- .../impl/mapper/UserProfileMapperTest.kt | 1 + .../usersearch/UserSearchResultMapperTest.kt | 1 + 9 files changed, 59 insertions(+), 32 deletions(-) rename libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/{mapper => user}/UserProfileMapper.kt (71%) rename libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/{usersearch => user}/UserSearchResultMapper.kt (86%) create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/user/UserStatus.kt diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt index 581658ff28..64cf68cda7 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt @@ -13,6 +13,10 @@ import kotlinx.parcelize.Parcelize @Immutable sealed interface DisplayedStatus : Parcelable { + + /** Useful for adding extension methods. */ + companion object + /** Status set manually by the user via m.status. */ @Parcelize data class UserSet(val status: UserStatus) : DisplayedStatus @@ -21,6 +25,6 @@ sealed interface DisplayedStatus : Parcelable { @Parcelize data class InCall( /** Unix timestamp in seconds when the call was joined (from m.call.call_joined_ts). */ - val callJoinedTs: Long, + val callJoinedTs: Long?, ) : DisplayedStatus } 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 88b1f05909..d946ffd18b 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 @@ -49,7 +49,6 @@ import io.element.android.libraries.matrix.api.scanner.ContentScanner import io.element.android.libraries.matrix.api.spaces.SpaceService import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion import io.element.android.libraries.matrix.api.sync.SyncState -import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.UserStatus @@ -58,7 +57,8 @@ import io.element.android.libraries.matrix.impl.exception.mapClientException import io.element.android.libraries.matrix.impl.linknewdevice.RustLinkDesktopHandler import io.element.android.libraries.matrix.impl.linknewdevice.RustLinkMobileHandler import io.element.android.libraries.matrix.impl.linknewdevice.RustQrCodeDataParser -import io.element.android.libraries.matrix.impl.mapper.map +import io.element.android.libraries.matrix.impl.user.into +import io.element.android.libraries.matrix.impl.user.map 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 @@ -85,7 +85,7 @@ import io.element.android.libraries.matrix.impl.search.RustMessageSearchService import io.element.android.libraries.matrix.impl.spaces.RustSpaceService import io.element.android.libraries.matrix.impl.sync.RustSyncService import io.element.android.libraries.matrix.impl.sync.map -import io.element.android.libraries.matrix.impl.usersearch.UserSearchResultMapper +import io.element.android.libraries.matrix.impl.user.UserSearchResultMapper import io.element.android.libraries.matrix.impl.util.cancelAndDestroy import io.element.android.libraries.matrix.impl.util.mxCallbackFlow import io.element.android.libraries.matrix.impl.verification.RustSessionVerificationService @@ -271,8 +271,6 @@ class RustMatrixClient( private var clientDelegateTaskHandle: TaskHandle? = innerClient.setDelegate(sessionDelegate) - @Volatile private var localUserStatus: UserStatus? = null - private val _userProfile: MutableStateFlow = MutableStateFlow( MatrixUser( userId = sessionId, @@ -458,13 +456,8 @@ class RustMatrixClient( override suspend fun getUserProfile(): Result = getProfile(sessionId) .onSuccess { matrixUser -> - _userProfile.emit( - matrixUser.copy( - rawStatus = localUserStatus, - displayedStatus = localUserStatus?.let { DisplayedStatus.UserSet(it) }, - ) - ) // Also update our session storage + _userProfile.emit(matrixUser) sessionStore.updateUserProfile( sessionId = sessionId.value, displayName = matrixUser.displayName, @@ -495,25 +488,21 @@ class RustMatrixClient( } override suspend fun setUserStatus(status: UserStatus): Result = withContext(sessionDispatcher) { - localUserStatus = status - _userProfile.emit( - _userProfile.value.copy( - rawStatus = status, - displayedStatus = DisplayedStatus.UserSet(status), - ) - ) - Result.success(Unit) + runCatchingExceptions { + innerClient.setUserStatus(status.into()) + }.onSuccess { + // try to refresh data once it's updated + getUserProfile() + } } override suspend fun clearUserStatus(): Result = withContext(sessionDispatcher) { - localUserStatus = null - _userProfile.emit( - _userProfile.value.copy( - rawStatus = null, - displayedStatus = null, - ) - ) - Result.success(Unit) + runCatchingExceptions { + innerClient.clearUserStatus() + }.onSuccess { + // try to refresh data once it's updated + getUserProfile() + } } override suspend fun joinRoom(roomId: RoomId): Result = withContext(sessionDispatcher) { 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 68fcf6287c..db4cd5f0db 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 @@ -42,6 +42,7 @@ import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings import io.element.android.libraries.matrix.impl.core.RustSendHandle import io.element.android.libraries.matrix.impl.mapper.map +import io.element.android.libraries.matrix.impl.user.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 diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/UserProfileMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/user/UserProfileMapper.kt similarity index 71% rename from libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/UserProfileMapper.kt rename to libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/user/UserProfileMapper.kt index 14c813548a..c9c64d83b6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/UserProfileMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/user/UserProfileMapper.kt @@ -6,9 +6,10 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.matrix.impl.mapper +package io.element.android.libraries.matrix.impl.user import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.api.user.MatrixUser import org.matrix.rustcomponents.sdk.UserProfile @@ -16,4 +17,6 @@ fun UserProfile.map() = MatrixUser( userId = UserId(userId), displayName = displayName, avatarUrl = avatarUrl, + rawStatus = status?.into(), + displayedStatus = DisplayedStatus.from(status, call) ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/user/UserSearchResultMapper.kt similarity index 86% rename from libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapper.kt rename to libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/user/UserSearchResultMapper.kt index 5a6481b4f8..f9b1503c8c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/user/UserSearchResultMapper.kt @@ -6,10 +6,9 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.matrix.impl.usersearch +package io.element.android.libraries.matrix.impl.user import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults -import io.element.android.libraries.matrix.impl.mapper.map import kotlinx.collections.immutable.toImmutableList import org.matrix.rustcomponents.sdk.SearchUsersResults diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/user/UserStatus.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/user/UserStatus.kt new file mode 100644 index 0000000000..1b8a738bf2 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/user/UserStatus.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.matrix.impl.user + +import io.element.android.libraries.matrix.api.user.DisplayedStatus +import io.element.android.libraries.matrix.api.user.UserStatus +import org.matrix.rustcomponents.sdk.UserCall +import org.matrix.rustcomponents.sdk.UserStatus as RustUserStatus + +fun UserStatus.into(): RustUserStatus { + return RustUserStatus(emoji = emoji, text = text) +} + +fun RustUserStatus.into(): UserStatus { + return UserStatus(emoji = emoji, text = text) +} + +fun DisplayedStatus.Companion.from(userStatus: RustUserStatus?, userCall: UserCall?): DisplayedStatus? { + return when { + userStatus != null -> DisplayedStatus.UserSet(userStatus.into()) + userCall != null -> DisplayedStatus.InCall(userCall.callJoinedTs?.toLong()) + else -> null + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/SessionVerificationRequestDetails.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/SessionVerificationRequestDetails.kt index d88f9fd6ce..c3b6d33b82 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/SessionVerificationRequestDetails.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/SessionVerificationRequestDetails.kt @@ -13,7 +13,7 @@ import io.element.android.libraries.matrix.api.core.FlowId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.verification.SessionVerificationRequestDetails import io.element.android.libraries.matrix.api.verification.VerificationRequest -import io.element.android.libraries.matrix.impl.mapper.map +import io.element.android.libraries.matrix.impl.user.map import org.matrix.rustcomponents.sdk.SessionVerificationRequestDetails as RustSessionVerificationRequestDetails fun RustSessionVerificationRequestDetails.map() = SessionVerificationRequestDetails( diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/UserProfileMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/UserProfileMapperTest.kt index 61e5886356..4ace520212 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/UserProfileMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/UserProfileMapperTest.kt @@ -11,6 +11,7 @@ package io.element.android.libraries.matrix.impl.mapper import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.impl.fixtures.factories.aRustUserProfile +import io.element.android.libraries.matrix.impl.user.map import io.element.android.libraries.matrix.test.A_USER_ID import org.junit.Test diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapperTest.kt index 3926b93d12..9134fdb6c7 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapperTest.kt @@ -13,6 +13,7 @@ import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSearchUsersResults import io.element.android.libraries.matrix.impl.fixtures.factories.aRustUserProfile +import io.element.android.libraries.matrix.impl.user.UserSearchResultMapper import io.element.android.libraries.matrix.test.A_USER_ID import kotlinx.collections.immutable.toImmutableList import org.junit.Test From ac6cacb415d9e03e5f1328fcf41101490df498b2 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 23 Jul 2026 17:18:02 +0200 Subject: [PATCH 245/383] Add MatrixClient.isUserStatusSupported --- .../io/element/android/libraries/matrix/api/MatrixClient.kt | 3 +++ .../android/libraries/matrix/impl/RustMatrixClient.kt | 6 ++++++ .../android/libraries/matrix/test/FakeMatrixClient.kt | 3 +++ 3 files changed, 12 insertions(+) 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 0dd8821a4f..4ceacebbd7 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 @@ -99,6 +99,9 @@ interface MatrixClient { /** Clears both m.status and m.call profile fields (maps to DELETE on the profile endpoint per MSC4426). */ suspend fun clearUserStatus(): Result + + /** Whether the homeserver advertises support for user status (MSC4426). */ + suspend fun isUserStatusSupported(): Result suspend fun joinRoom(roomId: RoomId): Result suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List): Result suspend fun knockRoom(roomIdOrAlias: RoomIdOrAlias, message: String, serverNames: List): Result 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 d946ffd18b..a80fa72241 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 @@ -505,6 +505,12 @@ class RustMatrixClient( } } + override suspend fun isUserStatusSupported(): Result = withContext(sessionDispatcher) { + runCatchingExceptions { + innerClient.isUserStatusSupported() + } + } + override suspend fun joinRoom(roomId: RoomId): Result = withContext(sessionDispatcher) { runCatchingExceptions { innerClient.joinRoomById(roomId.value).destroy() 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 cdf7cc85cf..56569cb1ae 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 @@ -144,6 +144,7 @@ class FakeMatrixClient( private set var setUserStatusResult: Result = Result.success(Unit) var clearUserStatusResult: Result = Result.success(Unit) + var isUserStatusSupportedResult: Result = Result.success(true) private val _userProfile: MutableStateFlow = MutableStateFlow(MatrixUser(sessionId, userDisplayName, userAvatarUrl)) override val userProfile: StateFlow = _userProfile @@ -288,6 +289,8 @@ class FakeMatrixClient( return clearUserStatusResult } + override suspend fun isUserStatusSupported(): Result = isUserStatusSupportedResult + override suspend fun joinRoom(roomId: RoomId): Result = joinRoomLambda(roomId) override suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List): Result { From 489ef4666a654b1f75ac32d2e35f44933a3f2a57 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 24 Jul 2026 15:13:53 +0200 Subject: [PATCH 246/383] Map displayed status for room members and timeline events --- .../android/libraries/matrix/api/room/RoomMember.kt | 1 + .../android/libraries/matrix/impl/room/RoomInfoMapper.kt | 7 ++++++- .../libraries/matrix/impl/room/member/RoomMemberMapper.kt | 5 +++-- .../impl/timeline/item/event/EventTimelineItemMapper.kt | 5 +++-- 4 files changed, 13 insertions(+), 5 deletions(-) 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 1874986d70..9155d47a08 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 @@ -104,4 +104,5 @@ fun RoomMember.toMatrixUser() = MatrixUser( userId = userId, displayName = displayName.takeUnless { membership == RoomMembershipState.BAN }, avatarUrl = avatarUrl.takeUnless { membership == RoomMembershipState.BAN }, + displayedStatus = displayedStatus, ) 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 a972b3c130..33d7017ff9 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 @@ -16,12 +16,15 @@ 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.RoomNotificationMode import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevels +import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.api.user.MatrixUser 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.member.RoomMemberMapper import io.element.android.libraries.matrix.impl.room.powerlevels.RoomPowerLevelsValuesMapper import io.element.android.libraries.matrix.impl.room.tombstone.map +import io.element.android.libraries.matrix.impl.user.from +import io.element.android.libraries.matrix.impl.user.into import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableMap import org.matrix.rustcomponents.sdk.Membership @@ -102,7 +105,9 @@ fun RustRoomNotificationMode.map(): RoomNotificationMode = when (this) { fun RoomHero.map(): MatrixUser = MatrixUser( userId = UserId(userId), displayName = displayName, - avatarUrl = avatarUrl + avatarUrl = avatarUrl, + displayedStatus = DisplayedStatus.from(status, call), + rawStatus = status?.into(), ) fun mapPowerLevels(roomPowerLevels: RustRoomPowerLevels): RoomPowerLevels { 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 b2a530f806..bcff7fc153 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 @@ -11,7 +11,9 @@ package io.element.android.libraries.matrix.impl.room.member 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.api.user.DisplayedStatus import io.element.android.libraries.matrix.impl.room.powerlevels.into +import io.element.android.libraries.matrix.impl.user.from import uniffi.matrix_sdk.RoomMemberRole import org.matrix.rustcomponents.sdk.MembershipState as RustMembershipState import org.matrix.rustcomponents.sdk.RoomMember as RustRoomMember @@ -30,8 +32,7 @@ object RoomMemberMapper { role = mapRole(roomMember.suggestedRoleForPowerLevel, powerLevel), membershipChangeReason = roomMember.membershipChangeReason, isServiceMember = roomMember.isServiceMember, - // TODO map this value when available - displayedStatus = null, + displayedStatus = DisplayedStatus.from(roomMember.status, roomMember.call), ) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt index 801d5fd146..3a568761ce 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt @@ -21,7 +21,9 @@ import io.element.android.libraries.matrix.api.timeline.item.event.ProfileDetail 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.user.DisplayedStatus import io.element.android.libraries.matrix.impl.core.RustSendHandle +import io.element.android.libraries.matrix.impl.user.from import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList @@ -75,8 +77,7 @@ fun RustProfileDetails.map(): ProfileDetails { displayName = displayName, displayNameAmbiguous = displayNameAmbiguous, avatarUrl = avatarUrl, - // TODO map this value when available - displayedStatus = null, + displayedStatus = DisplayedStatus.from(status, call), ) } } From 494dc026fa5b596d72c55623cde5b01a9c41cd56 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 24 Jul 2026 17:09:57 +0200 Subject: [PATCH 247/383] Create fun ProfileDetails.toMatrixUser method --- .../components/TimelineItemEventRow.kt | 7 ++----- .../api/timeline/item/event/ProfileDetails.kt | 18 ++++++++++++++++++ 2 files changed, 20 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 fed2ab6577..f52a70064b 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 @@ -125,6 +125,7 @@ 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.matrix.api.timeline.item.event.getDisplayName import io.element.android.libraries.matrix.api.timeline.item.event.mediaSources +import io.element.android.libraries.matrix.api.timeline.item.event.toMatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.media.contentvalidation.collectOverallState import io.element.android.libraries.matrix.ui.media.contentvalidation.rememberEventContentValidationState @@ -207,11 +208,7 @@ fun TimelineItemEventRow( } fun onUserDataClick() { - val sender = MatrixUser( - userId = event.senderId, - displayName = event.senderProfile.getDisplayName(), - avatarUrl = event.senderProfile.getAvatarUrl(), - ) + val sender = event.senderProfile.toMatrixUser(event.senderId) onUserDataClick(sender) } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ProfileDetails.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ProfileDetails.kt index 73b0478d63..1a56e888fa 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ProfileDetails.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/ProfileDetails.kt @@ -11,6 +11,7 @@ package io.element.android.libraries.matrix.api.timeline.item.event import androidx.compose.runtime.Immutable import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.user.DisplayedStatus +import io.element.android.libraries.matrix.api.user.MatrixUser @Immutable sealed interface ProfileDetails { @@ -60,3 +61,20 @@ fun ProfileDetails.getAvatarUrl(): String? { else -> null } } + +fun ProfileDetails.toMatrixUser(userId: UserId): MatrixUser { + return when (this) { + is ProfileDetails.Ready -> MatrixUser( + userId = userId, + displayName = displayName, + avatarUrl = avatarUrl, + displayedStatus = displayedStatus, + ) + else -> MatrixUser( + userId = userId, + displayName = null, + avatarUrl = null, + displayedStatus = null, + ) + } +} From 863cece4fb0824fdb4da58ff35cc9c89ed58b4e4 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 24 Jul 2026 18:20:05 +0200 Subject: [PATCH 248/383] Subscribe to own profile updates and gate on server support --- .../impl/root/PreferencesRootPresenter.kt | 10 ++++- .../libraries/matrix/impl/RustMatrixClient.kt | 42 ++++++++++++++----- .../matrix/impl/RustMatrixClientFactory.kt | 1 + .../impl/fixtures/fakes/FakeFfiClient.kt | 10 +++++ 4 files changed, 50 insertions(+), 13 deletions(-) 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 3daeb5aec1..581c26218b 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 @@ -74,8 +74,14 @@ class PreferencesRootPresenter( val showLinkNewDevice by remember { featureFlagService.isFeatureEnabledFlow(FeatureFlags.QrCodeLogin) }.collectAsState(initial = false) - val isUserStatusEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.UserStatus).collectAsState(initial = false) - val userStatusState = if (isUserStatusEnabled) userStatusPresenter.present() else null + + val isUserStatusSupported by produceState(false) { + featureFlagService.isFeatureEnabledFlow(FeatureFlags.UserStatus) + .collect { isUserStatusEnabled -> + value = isUserStatusEnabled && matrixClient.isUserStatusSupported().getOrDefault(false) + } + } + val userStatusState = if (isUserStatusSupported) userStatusPresenter.present() else null val otherSessions by remember { sessionStore.sessionsFlow().map { list -> 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 a80fa72241..faf1503b58 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 @@ -57,8 +57,6 @@ import io.element.android.libraries.matrix.impl.exception.mapClientException import io.element.android.libraries.matrix.impl.linknewdevice.RustLinkDesktopHandler import io.element.android.libraries.matrix.impl.linknewdevice.RustLinkMobileHandler import io.element.android.libraries.matrix.impl.linknewdevice.RustQrCodeDataParser -import io.element.android.libraries.matrix.impl.user.into -import io.element.android.libraries.matrix.impl.user.map 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 @@ -86,6 +84,8 @@ import io.element.android.libraries.matrix.impl.spaces.RustSpaceService import io.element.android.libraries.matrix.impl.sync.RustSyncService import io.element.android.libraries.matrix.impl.sync.map import io.element.android.libraries.matrix.impl.user.UserSearchResultMapper +import io.element.android.libraries.matrix.impl.user.into +import io.element.android.libraries.matrix.impl.user.map import io.element.android.libraries.matrix.impl.util.cancelAndDestroy import io.element.android.libraries.matrix.impl.util.mxCallbackFlow import io.element.android.libraries.matrix.impl.verification.RustSessionVerificationService @@ -126,9 +126,11 @@ import org.matrix.rustcomponents.sdk.IgnoredUsersListener import org.matrix.rustcomponents.sdk.Membership import org.matrix.rustcomponents.sdk.NotificationProcessSetup import org.matrix.rustcomponents.sdk.PowerLevels +import org.matrix.rustcomponents.sdk.ProfileListener import org.matrix.rustcomponents.sdk.RoomInfoListener import org.matrix.rustcomponents.sdk.SendQueueRoomErrorListener import org.matrix.rustcomponents.sdk.TaskHandle +import org.matrix.rustcomponents.sdk.UserProfile import org.matrix.rustcomponents.sdk.use import timber.log.Timber import java.io.File @@ -281,6 +283,14 @@ class RustMatrixClient( override val userProfile: StateFlow = _userProfile + private var ownProfileTaskHandle: TaskHandle? = null + + private val ownProfileListener = object : ProfileListener { + override fun onUpdate(profile: UserProfile) { + _userProfile.tryEmit(profile.map()) + } + } + override val ignoredUsersFlow = mxCallbackFlow> { // Fetch the initial value manually, the SDK won't return it automatically channel.trySend(innerClient.ignoredUsers().map(::UserId).toImmutableList()) @@ -301,8 +311,21 @@ class RustMatrixClient( sessionCoroutineScope.launch { // Start notification settings notificationSettingsService.start() + // Setup user profile logic + setupUserProfile() + } - // Update the user profile in the session store if needed + // Schedule regular database vacuuming to ensure DB performance remains optimal + scheduleDatabaseVacuum() + } + + private suspend fun setupUserProfile() { + val supported = isUserStatusSupported().getOrDefault(false) + if (supported) { + // No need to seed the data here, it's already stored by the sdk. + ownProfileTaskHandle = innerClient.subscribeToOwnProfile(ownProfileListener) + } else { + // Seed from the session store so cold-start UI has something to render before the network fetch. sessionStore.getSession(sessionId.value)?.let { sessionData -> _userProfile.emit( MatrixUser( @@ -312,12 +335,8 @@ class RustMatrixClient( ) ) } - // Force a refresh of the profile getUserProfile() } - - // Schedule regular database vacuuming to ensure DB performance remains optimal - scheduleDatabaseVacuum() } override fun userIdServerName(): String { @@ -491,8 +510,8 @@ class RustMatrixClient( runCatchingExceptions { innerClient.setUserStatus(status.into()) }.onSuccess { - // try to refresh data once it's updated - getUserProfile() + // The subscription pushes the update on supported servers; only refresh manually as a fallback. + if (ownProfileTaskHandle == null) getUserProfile() } } @@ -500,8 +519,8 @@ class RustMatrixClient( runCatchingExceptions { innerClient.clearUserStatus() }.onSuccess { - // try to refresh data once it's updated - getUserProfile() + // The subscription pushes the update on supported servers; only refresh manually as a fallback. + if (ownProfileTaskHandle == null) getUserProfile() } } @@ -616,6 +635,7 @@ class RustMatrixClient( sessionCoroutineScope.cancel() clientDelegateTaskHandle?.cancelAndDestroy() + ownProfileTaskHandle?.cancelAndDestroy() sessionVerificationService.destroy() sessionDelegate.clearCurrentClient() 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 de2c5c0141..d4b9063931 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 @@ -155,6 +155,7 @@ class RustMatrixClientFactory( val syncService = client.syncService() .withSharePos(true) .withOfflineMode() + .withProfilesExtension() .finish() return RustMatrixClient( 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 efae379415..455afe2b30 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 @@ -26,6 +26,7 @@ import org.matrix.rustcomponents.sdk.NoHandle import org.matrix.rustcomponents.sdk.NotificationClient import org.matrix.rustcomponents.sdk.NotificationProcessSetup import org.matrix.rustcomponents.sdk.NotificationSettings +import org.matrix.rustcomponents.sdk.ProfileListener import org.matrix.rustcomponents.sdk.PusherIdentifiers import org.matrix.rustcomponents.sdk.PusherKind import org.matrix.rustcomponents.sdk.RoomDirectorySearch @@ -55,6 +56,8 @@ class FakeFfiClient( private val getStoreSizesResult: () -> StoreSizes = { lambdaError() }, private val createRoomResult: (CreateRoomParameters) -> String = { lambdaError() }, private val homeserverCapabilities: HomeserverCapabilities = FakeFfiHomeserverCapabilities(), + private val isUserStatusSupportedResult: () -> Boolean = { false }, + private val subscribeToOwnProfileResult: (ProfileListener) -> Unit = {}, private val closeResult: () -> Unit = {}, ) : Client(NoHandle) { override fun userId(): String = userId @@ -92,6 +95,13 @@ class FakeFfiClient( return FakeFfiTaskHandle() } + override suspend fun isUserStatusSupported(): Boolean = isUserStatusSupportedResult() + + override fun subscribeToOwnProfile(listener: ProfileListener): TaskHandle { + subscribeToOwnProfileResult(listener) + return FakeFfiTaskHandle() + } + override suspend fun getProfile(userId: String): UserProfile { return getProfileResult(userId) } From 93ca5374d6e8aa377f0e963f5b7cfabc16a8c601 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 3 Aug 2026 17:50:42 +0200 Subject: [PATCH 249/383] Add status emoji badge to current user avatar in home top bar --- .../home/impl/components/HomeTopBar.kt | 132 +++++++++++++++++- 1 file changed, 127 insertions(+), 5 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 8163d29d92..63d28dca21 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 @@ -8,6 +8,8 @@ package io.element.android.features.home.impl.components +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.RowScope @@ -15,9 +17,11 @@ import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.safeDrawing +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.pager.VerticalPager import androidx.compose.foundation.pager.rememberPagerState @@ -25,8 +29,11 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarScrollBehavior +import androidx.compose.material3.minimumInteractiveComponentSize import androidx.compose.material3.rememberTopAppBarState +import androidx.compose.material3.ripple 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 @@ -37,10 +44,20 @@ 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.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.LocalDensity +import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.heading import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import io.element.android.appconfig.RoomListConfig import io.element.android.compound.theme.ElementTheme @@ -71,10 +88,13 @@ 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.user.DisplayedStatus import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.api.user.UserStatus 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.matrix.ui.model.toEmojiText import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings @@ -151,7 +171,7 @@ fun HomeTopBar( }, // We want a 16dp left padding for the navigationIcon : // 4dp from default TopAppBarHorizontalPadding - // 8dp from AccountIcon default padding (because of IconButton) + // 8dp from AccountIcon default padding (48dp touch target around 32dp avatar) // 4dp extra padding using left insets windowInsets = WindowInsets(left = 4.dp), ) @@ -316,19 +336,36 @@ private fun AccountIcon( modifier: Modifier = Modifier, ) { val testTag = if (isCurrentAccount) Modifier.testTag(TestTags.homeScreenSettings) else Modifier - IconButton( - modifier = modifier.then(testTag), - onClick = onClick, + val interactionSource = remember { MutableInteractionSource() } + Box( + modifier = modifier + .then(testTag) + .minimumInteractiveComponentSize() + .clickable( + interactionSource = interactionSource, + onClick = onClick, + indication = ripple(bounded = false), + ), + contentAlignment = Alignment.Center, ) { - Box { val avatarData by remember(matrixUser) { derivedStateOf { matrixUser.getAvatarData(size = AvatarSize.CurrentUserTopBar) } } + val statusEmoji = matrixUser.displayedStatus?.toEmojiText() + val avatarModifier = if (statusEmoji != null) { + Modifier.eraseStatusEmojiBackground( + parentSize = AvatarSize.CurrentUserTopBar.dp, + layoutDirection = LocalLayoutDirection.current, + ) + } else { + Modifier + } Avatar( avatarData = avatarData, avatarType = AvatarType.User, + modifier = avatarModifier, contentDescription = if (isCurrentAccount) { if (showAvatarIndicator) { stringResource(CommonStrings.a11y_settings_with_required_action) @@ -339,11 +376,69 @@ private fun AccountIcon( null }, ) + if (statusEmoji != null) { + StatusEmojiBadge( + emoji = statusEmoji, + modifier = Modifier.align(Alignment.BottomEnd), + ) + } if (showAvatarIndicator) { RedIndicatorAtom( modifier = Modifier.align(Alignment.TopEnd) ) } + } +} + +private val statusEmojiBadgeSize = 20.dp +private val statusEmojiBadgeRadius = statusEmojiBadgeSize / 2 +private val statusEmojiBadgeOffset = 8.dp + +private fun Modifier.eraseStatusEmojiBackground( + parentSize: Dp, + layoutDirection: LayoutDirection, +): Modifier = this + .graphicsLayer { + compositingStrategy = CompositingStrategy.Offscreen + } + .drawWithContent { + drawContent() + drawCircle( + color = Color.Black, + center = Offset( + x = if (layoutDirection == LayoutDirection.Ltr) { + (parentSize - statusEmojiBadgeRadius + statusEmojiBadgeOffset).toPx() + } else { + (statusEmojiBadgeRadius - statusEmojiBadgeOffset).toPx() + }, + y = size.height - statusEmojiBadgeRadius.toPx(), + ), + radius = statusEmojiBadgeRadius.toPx(), + blendMode = BlendMode.Clear, + ) + } + +@Composable +private fun StatusEmojiBadge( + emoji: String, + modifier: Modifier = Modifier, +) { + val density = LocalDensity.current + // Ensure the emoji size is not affected by the user's font scale settings + val fixedFontScaleDensity = remember(density.density) { + Density(density = density.density, fontScale = 1f) + } + Box( + modifier = modifier + .offset(x = statusEmojiBadgeOffset) + .size(statusEmojiBadgeSize), + contentAlignment = Alignment.Center, + ) { + CompositionLocalProvider(LocalDensity provides fixedFontScaleDensity) { + Text( + text = emoji, + style = ElementTheme.typography.fontBodyMdRegular, + ) } } } @@ -432,6 +527,33 @@ internal fun HomeTopBarWithIndicatorPreview() = ElementPreview { ) } +@OptIn(ExperimentalMaterial3Api::class) +@PreviewsDayNight +@Composable +internal fun HomeTopBarWithStatusPreview() = ElementPreview { + HomeTopBar( + selectedNavigationItem = HomeNavigationBarItem.Chats, + currentUserAndNeighbors = persistentListOf( + aMatrixUser( + id = "@id:domain", + displayName = USER_NAME_ALICE, + displayedStatus = DisplayedStatus.UserSet(UserStatus(emoji = "🌴", text = "Away")), + ) + ), + showAvatarIndicator = false, + areSearchResultsDisplayed = false, + scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()), + onOpenSettings = {}, + onAccountSwitch = {}, + onToggleSearch = {}, + canReportBug = true, + displayFilters = true, + filtersState = aRoomListFiltersState(), + spaceFiltersState = anUnselectedSpaceFiltersState(), + onMenuActionClick = {}, + ) +} + @OptIn(ExperimentalMaterial3Api::class) @PreviewsDayNight @Composable From c35a0a386420af8bae2b09b3275af0f4e73cae96 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 6 Aug 2026 11:09:49 +0200 Subject: [PATCH 250/383] Sync automatic call status with user status flag and server support --- appnav/build.gradle.kts | 1 + .../appnav/loggedin/LoggedInPresenter.kt | 13 +++++ .../appnav/loggedin/LoggedInPresenterTest.kt | 58 +++++++++++++++++++ .../libraries/matrix/api/MatrixClient.kt | 3 + .../libraries/matrix/impl/RustMatrixClient.kt | 4 ++ .../libraries/matrix/test/FakeMatrixClient.kt | 3 + 6 files changed, 82 insertions(+) diff --git a/appnav/build.gradle.kts b/appnav/build.gradle.kts index ce9764360b..7b86b434b9 100644 --- a/appnav/build.gradle.kts +++ b/appnav/build.gradle.kts @@ -60,6 +60,7 @@ dependencies { testCommonDependencies(libs) testImplementation(projects.features.login.test) testImplementation(projects.features.share.test) + testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.oauth.test) testImplementation(projects.libraries.permissions.test) 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 0723ad4606..d46fb2f931 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 @@ -30,6 +30,8 @@ import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.core.log.logger.LoggerTag 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.MatrixClient import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.RecoveryState @@ -65,6 +67,7 @@ class LoggedInPresenter( private val buildMeta: BuildMeta, private val networkMonitor: NetworkMonitor, private val localNetworkPermissionAdvisor: LocalNetworkPermissionAdvisor, + private val featureFlagService: FeatureFlagService, permissionsPresenterFactory: PermissionsPresenter.Factory, ) : Presenter { private val localNetworkPermissionsPresenter: PermissionsPresenter = @@ -120,6 +123,16 @@ class LoggedInPresenter( }.launchIn(this) } + LaunchedEffect(Unit) { + // Keep automatic call status (m.call) in sync with the feature flag and homeserver support. + featureFlagService.isFeatureEnabledFlow(FeatureFlags.UserStatus) + .onEach { isUserStatusEnabled -> + val enabled = isUserStatusEnabled && matrixClient.isUserStatusSupported().getOrDefault(false) + matrixClient.enableAutomaticCallStatus(enabled) + } + .launchIn(this) + } + val networkConnectivity by networkMonitor.connectivity.collectAsState() LaunchedEffect(networkConnectivity) { if (networkConnectivity == NetworkStatus.Connected) { 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 faa19d9e61..cc330c2758 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 @@ -17,6 +17,9 @@ 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.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.SessionId import io.element.android.libraries.matrix.api.encryption.EncryptionService @@ -48,6 +51,7 @@ import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.consumeItemsUntilPredicate +import io.element.android.tests.testutils.lambda.assert import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value @@ -127,6 +131,7 @@ class LoggedInPresenterTest { buildMeta = buildMeta, networkMonitor = networkMonitor, localNetworkPermissionAdvisor = FakeLocalNetworkPermissionAdvisor(), + featureFlagService = FakeFeatureFlagService(), permissionsPresenterFactory = FakePermissionsPresenterFactory(), ).test { encryptionService.emitRecoveryState(RecoveryState.UNKNOWN) @@ -346,6 +351,57 @@ class LoggedInPresenterTest { } } + @Test + fun `present - does not enable automatic call status when server does not support it`() = runTest { + val enableAutomaticCallStatusLambda = lambdaRecorder { } + val matrixClient = FakeMatrixClient( + accountManagementUrlResult = { Result.success(null) }, + enableAutomaticCallStatusLambda = enableAutomaticCallStatusLambda, + ).apply { + isUserStatusSupportedResult = Result.success(false) + } + createLoggedInPresenter( + matrixClient = matrixClient, + featureFlagService = FakeFeatureFlagService( + initialState = mapOf(FeatureFlags.UserStatus.key to true), + ), + ).test { + cancelAndConsumeRemainingEvents() + assert(enableAutomaticCallStatusLambda) + .isCalledOnce() + .with(value(false)) + } + } + + @Test + fun `present - reacts to user status flag being toggled at runtime`() = runTest { + val enableAutomaticCallStatusLambda = lambdaRecorder { } + val matrixClient = FakeMatrixClient( + accountManagementUrlResult = { Result.success(null) }, + enableAutomaticCallStatusLambda = enableAutomaticCallStatusLambda, + ).apply { + isUserStatusSupportedResult = Result.success(true) + } + val featureFlagService = FakeFeatureFlagService( + initialState = mapOf(FeatureFlags.UserStatus.key to false), + ) + createLoggedInPresenter( + matrixClient = matrixClient, + featureFlagService = featureFlagService, + ).test { + awaitItem() + // Turning the flag on at runtime enables it. + featureFlagService.setFeatureEnabled(FeatureFlags.UserStatus, true) + cancelAndConsumeRemainingEvents() + assert(enableAutomaticCallStatusLambda) + .isCalledExactly(2) + .withSequence( + listOf(value(false)), + listOf(value(true)), + ) + } + } + private suspend fun ReceiveTurbine.awaitFirstItem(): T { skipItems(1) return awaitItem() @@ -362,6 +418,7 @@ class LoggedInPresenterTest { ), buildMeta: BuildMeta = aBuildMeta(), networkMonitor: FakeNetworkMonitor = FakeNetworkMonitor(), + featureFlagService: FeatureFlagService = FakeFeatureFlagService(), ): LoggedInPresenter { return LoggedInPresenter( matrixClient = matrixClient, @@ -373,6 +430,7 @@ class LoggedInPresenterTest { buildMeta = buildMeta, networkMonitor = networkMonitor, localNetworkPermissionAdvisor = FakeLocalNetworkPermissionAdvisor(), + featureFlagService = featureFlagService, permissionsPresenterFactory = FakePermissionsPresenterFactory(), ) } 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 4ceacebbd7..9ea7d7fcf1 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 @@ -102,6 +102,9 @@ interface MatrixClient { /** Whether the homeserver advertises support for user status (MSC4426). */ suspend fun isUserStatusSupported(): Result + + /** Enable or disable automatically setting the user's status to "in a call" (m.call) while in a call. */ + fun enableAutomaticCallStatus(enabled: Boolean) suspend fun joinRoom(roomId: RoomId): Result suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List): Result suspend fun knockRoom(roomIdOrAlias: RoomIdOrAlias, message: String, serverNames: List): Result 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 faf1503b58..2330ef4642 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 @@ -530,6 +530,10 @@ class RustMatrixClient( } } + override fun enableAutomaticCallStatus(enabled: Boolean) { + innerClient.enableAutomaticCallStatus(enabled) + } + override suspend fun joinRoom(roomId: RoomId): Result = withContext(sessionDispatcher) { runCatchingExceptions { innerClient.joinRoomById(roomId.value).destroy() 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 56569cb1ae..77fc2db816 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 @@ -130,6 +130,7 @@ class FakeMatrixClient( private val getMapStyleUrlResult: () -> Result = { lambdaError() }, private val getDatabaseSizesLambda: () -> Result = { lambdaError() }, private val resetWellKnownConfigLambda: () -> Result = { lambdaError() }, + private val enableAutomaticCallStatusLambda: (Boolean) -> Unit = { }, override val contentScanner: ContentScanner? = null, ) : MatrixClient { var setDisplayNameCalled: Boolean = false @@ -291,6 +292,8 @@ class FakeMatrixClient( override suspend fun isUserStatusSupported(): Result = isUserStatusSupportedResult + override fun enableAutomaticCallStatus(enabled: Boolean) = enableAutomaticCallStatusLambda(enabled) + override suspend fun joinRoom(roomId: RoomId): Result = joinRoomLambda(roomId) override suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List): Result { From 4dffd7ddef2c74f979cffa4fa2b85a4e0f85c8e2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 17 Jul 2026 17:37:57 +0200 Subject: [PATCH 251/383] Move deviceId, gitBranch and gitSha to the developer screens. --- .../developer/DeveloperSettingsPresenter.kt | 3 ++ .../impl/developer/DeveloperSettingsState.kt | 2 + .../DeveloperSettingsStateProvider.kt | 3 ++ .../impl/developer/DeveloperSettingsView.kt | 22 +++++++++++ .../AppDeveloperSettingsPresenter.kt | 4 ++ .../appsettings/AppDeveloperSettingsState.kt | 2 + .../AppDeveloperSettingsStateProvider.kt | 2 + .../appsettings/AppDeveloperSettingsView.kt | 38 +++++++++++++++++++ .../impl/root/PreferencesRootPresenter.kt | 1 - .../impl/root/PreferencesRootState.kt | 2 - .../impl/root/PreferencesRootStateProvider.kt | 5 --- .../impl/root/PreferencesRootView.kt | 15 +------- .../preferences/impl/root/VersionFormatter.kt | 8 +--- .../DeveloperSettingsPresenterTest.kt | 5 +++ .../AppDeveloperSettingsPresenterTest.kt | 7 ++++ .../impl/root/VersionFormatterTest.kt | 18 +-------- .../matrix/impl/di/SessionMatrixModule.kt | 6 +++ 17 files changed, 98 insertions(+), 45 deletions(-) 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 02d2573ed6..ac1ba06cf6 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 @@ -31,6 +31,7 @@ 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.matrix.api.analytics.GetDatabaseSizesUseCase +import io.element.android.libraries.matrix.api.core.DeviceId import io.element.android.libraries.matrix.api.core.SessionId import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.toImmutableMap @@ -41,6 +42,7 @@ import kotlinx.coroutines.launch class DeveloperSettingsPresenter( private val appDeveloperSettingsPresenter: Presenter, private val sessionId: SessionId, + private val deviceId: DeviceId, private val computeCacheSizeUseCase: ComputeCacheSizeUseCase, private val clearCacheUseCase: ClearCacheUseCase, private val enterpriseService: EnterpriseService, @@ -117,6 +119,7 @@ class DeveloperSettingsPresenter( markAllRoomsAsReadAction = markAllRoomsAsReadAction.value, isEnterpriseBuild = enterpriseService.isEnterpriseBuild, showColorPicker = showColorPicker, + deviceId = deviceId, eventSink = ::handleEvent, ) } 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 fe48e8c446..700c989bfa 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 @@ -11,6 +11,7 @@ package io.element.android.features.preferences.impl.developer 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.matrix.api.core.DeviceId import kotlinx.collections.immutable.ImmutableMap data class DeveloperSettingsState( @@ -21,6 +22,7 @@ data class DeveloperSettingsState( val markAllRoomsAsReadAction: AsyncAction, val isEnterpriseBuild: Boolean, val showColorPicker: Boolean, + val deviceId: DeviceId, val eventSink: (DeveloperSettingsEvents) -> Unit ) { val showLoader = clearCacheAction is AsyncAction.Loading || markAllRoomsAsReadAction is AsyncAction.Loading 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 fd285b1bb9..b14446d11c 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 @@ -13,6 +13,7 @@ import io.element.android.features.preferences.impl.developer.appsettings.AppDev 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.matrix.api.core.DeviceId import kotlinx.collections.immutable.persistentMapOf open class DeveloperSettingsStateProvider : PreviewParameterProvider { @@ -40,6 +41,7 @@ fun aDeveloperSettingsState( markAllRoomsAsReadAction: AsyncAction = AsyncAction.Uninitialized, isEnterpriseBuild: Boolean = false, showColorPicker: Boolean = false, + deviceId: DeviceId = DeviceId("ILAKNDNASDLK"), eventSink: (DeveloperSettingsEvents) -> Unit = {}, ) = DeveloperSettingsState( appDeveloperSettingsState = appDeveloperSettingsState, @@ -49,5 +51,6 @@ fun aDeveloperSettingsState( markAllRoomsAsReadAction = markAllRoomsAsReadAction, isEnterpriseBuild = isEnterpriseBuild, showColorPicker = showColorPicker, + deviceId = deviceId, eventSink = eventSink, ) 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 0e5f4026ef..669bcdc8ff 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 @@ -15,12 +15,14 @@ import androidx.compose.foundation.progressSemantics import androidx.compose.runtime.Composable import androidx.compose.ui.ExperimentalComposeUiApi 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 import io.element.android.compound.theme.ElementTheme import io.element.android.features.preferences.impl.R import io.element.android.features.preferences.impl.developer.appsettings.AppDeveloperSettingsView +import io.element.android.libraries.androidutils.system.copyToClipboard import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.list.ListItemContent @@ -31,6 +33,7 @@ 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.matrix.api.core.DeviceId import io.element.android.libraries.ui.strings.CommonStrings import io.mhssn.colorpicker.ColorPickerDialog import io.mhssn.colorpicker.ColorPickerType @@ -75,6 +78,7 @@ fun DeveloperSettingsView( state = state.appDeveloperSettingsState, onOpenShowkase = onOpenShowkase, ) + SessionCategory(deviceId = state.deviceId) NotificationCategory(onPushHistoryClick) MarkAllRoomsAsReadCategory(state) @@ -168,6 +172,24 @@ fun DeveloperSettingsView( ) } +@Composable +private fun SessionCategory(deviceId: DeviceId) { + PreferenceCategory(title = "Session") { + val toastMessage = stringResource(CommonStrings.common_copied_to_clipboard) + val context = LocalContext.current + ListItem( + headlineContent = { Text("DeviceId") }, + supportingContent = { Text(text = deviceId.value) }, + onClick = { + context.copyToClipboard( + text = deviceId.value, + toastMessage = toastMessage, + ) + } + ) + } +} + @Composable private fun MarkAllRoomsAsReadCategory(state: DeveloperSettingsState) { PreferenceCategory(title = "Room list") { 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 e7ad6e2284..9c1127dd2a 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,6 +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.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.ui.model.FeatureUiModel import io.element.android.libraries.preferences.api.store.AppPreferencesStore @@ -42,6 +43,7 @@ class AppDeveloperSettingsPresenter( private val featureFlagService: FeatureFlagService, private val rageshakePresenter: Presenter, private val appPreferencesStore: AppPreferencesStore, + private val buildMeta: BuildMeta, ) : Presenter { @Composable override fun present(): AppDeveloperSettingsState { @@ -110,6 +112,8 @@ class AppDeveloperSettingsPresenter( ), tracingLogLevel = tracingLogLevel, tracingLogPacks = tracingLogPacks, + gitBranch = buildMeta.gitBranchName, + gitSha = buildMeta.gitRevision, eventSink = ::handleEvent, ) } 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 index 1eb5fd7fd3..071670644c 100644 --- 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 @@ -20,6 +20,8 @@ data class AppDeveloperSettingsState( val customElementCallBaseUrlState: CustomElementCallBaseUrlState, val tracingLogLevel: AsyncData, val tracingLogPacks: ImmutableList, + val gitBranch: String, + val gitSha: String, val eventSink: (AppDeveloperSettingsEvent) -> Unit ) 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 index 494b3b6bbd..e4536f4dba 100644 --- 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 @@ -37,6 +37,8 @@ fun anAppDeveloperSettingsState( customElementCallBaseUrlState = customElementCallBaseUrlState, tracingLogLevel = AsyncData.Success(LogLevelItem.INFO), tracingLogPacks = traceLogPacks.toImmutableList(), + gitBranch = "feature/awesome-feature", + gitSha = "1234567890", eventSink = eventSink, ) 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 9b2a2aa3a9..61aa4e27ee 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 @@ -14,6 +14,7 @@ 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.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.PreviewParameter @@ -22,6 +23,7 @@ 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.androidutils.system.copyToClipboard 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 @@ -33,6 +35,7 @@ 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 kotlinx.collections.immutable.toImmutableList @OptIn(ExperimentalComposeUiApi::class) @@ -98,6 +101,41 @@ fun AppDeveloperSettingsView( onClick = { error("This crash is a test.") } ) } + GitCategory( + gitBranch = state.gitBranch, + gitSha = state.gitSha, + ) + } +} + +@Composable +private fun GitCategory( + gitBranch: String, + gitSha: String, +) { + PreferenceCategory(title = "Git") { + val toastMessage = stringResource(CommonStrings.common_copied_to_clipboard) + val context = LocalContext.current + ListItem( + headlineContent = { Text("Git branch") }, + supportingContent = { Text(text = gitBranch) }, + onClick = { + context.copyToClipboard( + text = gitBranch, + toastMessage = toastMessage, + ) + } + ) + ListItem( + headlineContent = { Text("Git SHA") }, + supportingContent = { Text(text = gitSha) }, + onClick = { + context.copyToClipboard( + text = gitSha, + toastMessage = toastMessage, + ) + } + ) } } 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 3daeb5aec1..9ccd8b9116 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 @@ -142,7 +142,6 @@ class PreferencesRootPresenter( myUser = matrixUser.value, userStatusState = userStatusState, version = remember { versionFormatter.get() }, - deviceId = matrixClient.deviceId, isMultiAccountEnabled = isMultiAccountEnabled, otherSessions = otherSessions, showSecureBackup = !canVerifyUserSession, 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 c415547a80..72d7240f2e 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 @@ -11,7 +11,6 @@ package io.element.android.features.preferences.impl.root import io.element.android.features.logout.api.direct.DirectLogoutState import io.element.android.features.preferences.impl.userstatus.UserStatusState 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 kotlinx.collections.immutable.ImmutableList @@ -19,7 +18,6 @@ data class PreferencesRootState( val myUser: MatrixUser, val userStatusState: UserStatusState?, val version: String, - val deviceId: DeviceId?, val isMultiAccountEnabled: Boolean, val otherSessions: ImmutableList, val showSecureBackup: Boolean, 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 0abed1f66f..86f984f254 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 @@ -15,7 +15,6 @@ import io.element.android.features.preferences.impl.userstatus.UserStatusPickerS import io.element.android.features.preferences.impl.userstatus.UserStatusState import io.element.android.features.preferences.impl.userstatus.aUserStatusState 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 @@ -29,7 +28,6 @@ open class PreferencesRootStateProvider : PreviewParameterProvider = emptyList(), showSecureBackup: Boolean = false, @@ -96,7 +92,6 @@ fun aPreferencesRootState( ) = PreferencesRootState( myUser = myUser, version = version, - deviceId = deviceId, isMultiAccountEnabled = isMultiAccountEnabled, otherSessions = otherSessions.toImmutableList(), showSecureBackup = showSecureBackup, 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 7ec711fdeb..104ee7e551 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 @@ -13,7 +13,6 @@ 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.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -43,7 +42,6 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.emoji.api.picker.EmojiPickerRenderer import io.element.android.libraries.emoji.api.picker.NoOpEmojiPickerRenderer -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.MatrixUserRow import io.element.android.libraries.ui.strings.CommonStrings @@ -129,7 +127,6 @@ fun PreferencesRootView( // Version Footer( version = state.version, - deviceId = state.deviceId, onClick = if (!state.showDeveloperSettings) { { state.eventSink(PreferencesRootEvent.OnVersionInfoClick) } } else { @@ -326,25 +323,15 @@ private fun ColumnScope.GeneralSection( @Composable private fun ColumnScope.Footer( version: String, - deviceId: DeviceId?, onClick: (() -> Unit)?, ) { - val text = remember(version, deviceId) { - buildString { - append(version) - if (deviceId != null) { - append("\n") - append(deviceId) - } - } - } Text( modifier = Modifier .align(Alignment.CenterHorizontally) .clickable(enabled = onClick != null, onClick = onClick ?: {}) .padding(start = 16.dp, end = 16.dp, top = 16.dp, bottom = 24.dp), textAlign = TextAlign.Center, - text = text, + text = version, style = ElementTheme.typography.fontBodySmRegular, color = ElementTheme.colors.textSecondary, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/VersionFormatter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/VersionFormatter.kt index 52517b5ca2..6cd41376d1 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/VersionFormatter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/VersionFormatter.kt @@ -24,16 +24,10 @@ class DefaultVersionFormatter( private val buildMeta: BuildMeta, ) : VersionFormatter { override fun get(): String { - val base = stringProvider.getString( + return stringProvider.getString( CommonStrings.settings_version_number, buildMeta.versionName, buildMeta.versionCode.toString() ) - return if (buildMeta.gitBranchName == "main") { - base - } else { - // In case of a build not from main, we display the branch name and the revision - "$base\n${buildMeta.gitBranchName} (${buildMeta.gitRevision})" - } } } 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 52d1247668..bb688f498d 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 @@ -25,7 +25,9 @@ import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.core.data.megaBytes 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.DeviceId import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.test.A_DEVICE_ID import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.lambda.lambdaRecorder @@ -57,6 +59,7 @@ class DeveloperSettingsPresenterTest { assertThat(state.cacheSize).isEqualTo(AsyncData.Uninitialized) assertThat(state.isEnterpriseBuild).isFalse() assertThat(state.showColorPicker).isFalse() + assertThat(state.deviceId).isEqualTo(A_DEVICE_ID) } awaitItem().also { state -> assertThat(state.cacheSize.isLoading()).isTrue() @@ -169,6 +172,7 @@ class DeveloperSettingsPresenterTest { private fun createDeveloperSettingsPresenter( sessionId: SessionId = A_SESSION_ID, + deviceId: DeviceId = A_DEVICE_ID, cacheSizeUseCase: FakeComputeCacheSizeUseCase = FakeComputeCacheSizeUseCase(), clearCacheUseCase: FakeClearCacheUseCase = FakeClearCacheUseCase(), enterpriseService: EnterpriseService = FakeEnterpriseService(), @@ -179,6 +183,7 @@ class DeveloperSettingsPresenterTest { return DeveloperSettingsPresenter( appDeveloperSettingsPresenter = { anAppDeveloperSettingsState() }, sessionId = sessionId, + deviceId = deviceId, computeCacheSizeUseCase = cacheSizeUseCase, clearCacheUseCase = clearCacheUseCase, enterpriseService = enterpriseService, 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 3d2cc85e54..f4dad80e8b 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 @@ -16,6 +16,7 @@ import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.featureflag.api.Feature 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 @@ -53,6 +54,8 @@ class AppDeveloperSettingsPresenterTest { assertThat(state.rageshakeState.isSupported).isTrue() assertThat(state.rageshakeState.sensitivity).isEqualTo(0.3f) assertThat(state.tracingLogLevel).isEqualTo(AsyncData.Uninitialized) + assertThat(state.gitBranch).isEqualTo("feature/awesome-feature") + assertThat(state.gitSha).isEqualTo("1234567890") } awaitItem().also { state -> assertThat(state.features).isNotEmpty() @@ -145,6 +148,10 @@ class AppDeveloperSettingsPresenterTest { featureFlagService = featureFlagService, rageshakePresenter = { aRageshakePreferencesState() }, appPreferencesStore = preferencesStore, + buildMeta = aBuildMeta( + gitRevision = "1234567890", + gitBranchName = "feature/awesome-feature" + ) ) } } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/VersionFormatterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/VersionFormatterTest.kt index c00dc7689b..0a05c0e3a3 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/VersionFormatterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/VersionFormatterTest.kt @@ -16,7 +16,7 @@ import org.junit.Test class VersionFormatterTest { @Test - fun `version formatter should return simplified version for main branch`() = runTest { + fun `version formatter should return formatted version`() = runTest { val sut = DefaultVersionFormatter( stringProvider = FakeStringProvider(defaultResult = VERSION), buildMeta = aBuildMeta( @@ -28,21 +28,7 @@ class VersionFormatterTest { assertThat(sut.get()).isEqualTo("${VERSION}versionName, 123") } - @Test - fun `version formatter should return simplified version for other branch`() = runTest { - val sut = DefaultVersionFormatter( - stringProvider = FakeStringProvider(defaultResult = VERSION), - buildMeta = aBuildMeta( - versionName = "versionName", - versionCode = 123, - gitBranchName = "branch", - gitRevision = "1234567890", - ) - ) - assertThat(sut.get()).isEqualTo("${VERSION}versionName, 123\nbranch (1234567890)") - } - companion object { - const val VERSION = "version" + const val VERSION = "version: " } } 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 d4f49af416..e88dc382e8 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 @@ -15,6 +15,7 @@ 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.DeviceId 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.media.MatrixMediaLoader @@ -37,6 +38,11 @@ object SessionMatrixModule { return matrixClient.sessionId } + @Provides + fun providesDeviceId(matrixClient: MatrixClient): DeviceId { + return matrixClient.deviceId + } + @Provides fun providesSessionVerificationService(matrixClient: MatrixClient): SessionVerificationService { return matrixClient.sessionVerificationService From 10f24e2b8dc82b0f5fa59ff4dbdb4889fe03565f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 17 Jul 2026 18:14:56 +0200 Subject: [PATCH 252/383] Send gitSha in the bug report content. See https://github.com/element-hq/element-x-android-rageshakes/issues/14270 --- .../features/rageshake/impl/reporter/DefaultBugReporter.kt | 1 + .../features/rageshake/impl/reporter/DefaultBugReporterTest.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) 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 735bb1cea0..96bd7adfce 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 @@ -185,6 +185,7 @@ class DefaultBugReporter( .addFormDataPart("device", Build.MODEL.trim()) .addFormDataPart("locale", Locale.getDefault().toString()) .addFormDataPart("sdk_sha", sdkMetadata.sdkGitSha) + .addFormDataPart("sha", buildMeta.gitRevision) .addFormDataPart("local_time", LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME)) .addFormDataPart("utc_time", LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC).format(DateTimeFormatter.ISO_DATE_TIME)) .addFormDataPart("app_id", buildMeta.applicationId) diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterTest.kt index 4f666d374b..ad29e5ed3f 100755 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterTest.kt @@ -534,6 +534,6 @@ class DefaultBugReporterTest : RobolectricTest() { } companion object { - private const val EXPECTED_NUMBER_OF_PROGRESS_VALUE = 17 + private const val EXPECTED_NUMBER_OF_PROGRESS_VALUE = 18 } } From 9d27ab4caf1f903b134219af60347f0663690059 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 17 Jul 2026 16:27:18 +0000 Subject: [PATCH 253/383] Update screenshots --- ...res.preferences.impl.root_PreferencesRootViewDark_3_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_3_en.png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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 08dc4d97cc..6963a4c2e5 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:a89c8eeebf6cba350daa4940ea8248148286341bf19a4b36f63330ab508bfa20 -size 29985 +oid sha256:88178c848bd5740a19df1ec71e0c80249faaa4476fe8069997ce01f620d7a2f7 +size 28790 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 a95a91b731..84c0963ca5 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:db069c64c97811f2b311bb63c8dbb9f78f534bdb3475d7b433412350445ec894 -size 30937 +oid sha256:eaa549a5f94192d69fa01a3768733ce4d0f9b34d8ce35d91df324ffdeaa87fff +size 29746 From beccb1ddfa98065dd63dd6c3da5fd37eabb90270 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 6 Aug 2026 15:03:13 +0200 Subject: [PATCH 254/383] Fix tests --- .../preferences/impl/developer/DeveloperSettingsViewTest.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 adae2ca816..a16ad77d48 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 @@ -15,6 +15,7 @@ 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.performScrollTo import androidx.compose.ui.test.v2.runAndroidComposeUiTest import io.element.android.features.preferences.impl.R import io.element.android.tests.testutils.EnsureNeverCalled @@ -41,7 +42,7 @@ class DeveloperSettingsViewTest : RobolectricTest() { } } - @Config(qualifiers = "h2000dp") + @Config(qualifiers = "h2400dp") @Test fun `clicking on push history notification invokes the expected callback`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) @@ -80,7 +81,7 @@ class DeveloperSettingsViewTest : RobolectricTest() { eventSink = eventsRecorder ), ) - onNodeWithText("Clear cache").performClick() + onNodeWithText("Clear cache").performScrollTo().performClick() eventsRecorder.assertSingle(DeveloperSettingsEvents.ClearCache) } } From 670ddd35f4f5c883b0b65f0f8d61a98ea9262631 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 6 Aug 2026 15:10:25 +0200 Subject: [PATCH 255/383] Fix compilation warning --- .../libraries/matrix/impl/search/RustMessageSearchTest.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearchTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearchTest.kt index 38787f4724..693ed1bdc2 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearchTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/search/RustMessageSearchTest.kt @@ -5,6 +5,8 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalCoroutinesApi::class) + package io.element.android.libraries.matrix.impl.search import com.google.common.truth.Truth.assertThat @@ -14,6 +16,7 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiSearchServ import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID_2 import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.cancel import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.advanceUntilIdle From a7d2b86fe00fd23e83078dc008c28e5517ed8f3f Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 6 Aug 2026 16:15:44 +0200 Subject: [PATCH 256/383] Show loading and failure feedback when updating user status --- .../impl/root/PreferencesRootView.kt | 144 ++++++++++-------- .../impl/userstatus/UserStatusPresenter.kt | 12 +- .../impl/userstatus/UserStatusState.kt | 2 + .../userstatus/UserStatusStateProvider.kt | 3 + .../userstatus/UserStatusPresenterTest.kt | 39 +++++ .../components/async/AsyncActionIndicator.kt | 109 +++++++++++++ .../async/AsyncActionIndicatorTest.kt | 123 +++++++++++++++ 7 files changed, 369 insertions(+), 63 deletions(-) create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncActionIndicator.kt create mode 100644 libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/component/async/AsyncActionIndicatorTest.kt 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 7ec711fdeb..2e449f5820 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,9 +9,12 @@ package io.element.android.features.preferences.impl.root import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment @@ -26,7 +29,10 @@ import io.element.android.features.preferences.impl.R import io.element.android.features.preferences.impl.user.UserPreferences import io.element.android.features.preferences.impl.userstatus.UserStatusState import io.element.android.features.preferences.impl.userstatus.UserStatusView +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage +import io.element.android.libraries.designsystem.components.async.AsyncActionIndicator +import io.element.android.libraries.designsystem.components.async.AsyncIndicator 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 @@ -73,72 +79,88 @@ fun PreferencesRootView( ) { val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage) - // Include pref from other modules - PreferencePage( - modifier = modifier, - onBackClick = onBackClick, - title = stringResource(id = CommonStrings.common_settings), - snackbarHost = { SnackbarHost(snackbarHostState) } - ) { - UserPreferences( - modifier = Modifier.clickable { - onOpenUserProfile(state.myUser) - }, - matrixUser = state.myUser, - ) - if (state.isMultiAccountEnabled) { - MultiAccountSection( - state = state, - onAddAccountClick = onAddAccountClick, + Box(modifier = modifier) { + // Include pref from other modules + PreferencePage( + onBackClick = onBackClick, + title = stringResource(id = CommonStrings.common_settings), + snackbarHost = { SnackbarHost(snackbarHostState) } + ) { + UserPreferences( + modifier = Modifier.clickable { + onOpenUserProfile(state.myUser) + }, + matrixUser = state.myUser, ) - } - if (state.userStatusState != null) { - UserStatusSection( - userStatusState = state.userStatusState, - emojiPickerRenderer = emojiPickerRenderer, - showTopDivider = !state.isMultiAccountEnabled, - ) - } - // 'Account' section - ManageAccountSection( - state = state, - onManageAccountClick = onManageAccountClick, - onLinkNewDeviceClick = onLinkNewDeviceClick, - onOpenBlockedUsers = onOpenBlockedUsers - ) - // 'Manage my app' section - ManageAppSection( - state = state, - onOpenNotificationSettings = onOpenNotificationSettings, - onOpenLockScreenSettings = onOpenLockScreenSettings, - onSecureBackupClick = onSecureBackupClick, - ) - - // General section - GeneralSection( - state = state, - onOpenAbout = onOpenAbout, - onOpenAnalytics = onOpenAnalytics, - onOpenRageShake = onOpenRageShake, - onOpenAdvancedSettings = onOpenAdvancedSettings, - onOpenDeveloperSettings = onOpenDeveloperSettings, - onOpenLabs = onOpenLabs, - onSignOutClick = onSignOutClick, - onDeactivateClick = onDeactivateClick, - ) - // Version - Footer( - version = state.version, - deviceId = state.deviceId, - onClick = if (!state.showDeveloperSettings) { - { state.eventSink(PreferencesRootEvent.OnVersionInfoClick) } - } else { - null + if (state.isMultiAccountEnabled) { + MultiAccountSection( + state = state, + onAddAccountClick = onAddAccountClick, + ) } - ) + if (state.userStatusState != null) { + UserStatusSection( + userStatusState = state.userStatusState, + emojiPickerRenderer = emojiPickerRenderer, + showTopDivider = !state.isMultiAccountEnabled, + ) + } + // 'Account' section + ManageAccountSection( + state = state, + onManageAccountClick = onManageAccountClick, + onLinkNewDeviceClick = onLinkNewDeviceClick, + onOpenBlockedUsers = onOpenBlockedUsers + ) + // 'Manage my app' section + ManageAppSection( + state = state, + onOpenNotificationSettings = onOpenNotificationSettings, + onOpenLockScreenSettings = onOpenLockScreenSettings, + onSecureBackupClick = onSecureBackupClick, + ) + + // General section + GeneralSection( + state = state, + onOpenAbout = onOpenAbout, + onOpenAnalytics = onOpenAnalytics, + onOpenRageShake = onOpenRageShake, + onOpenAdvancedSettings = onOpenAdvancedSettings, + onOpenDeveloperSettings = onOpenDeveloperSettings, + onOpenLabs = onOpenLabs, + onSignOutClick = onSignOutClick, + onDeactivateClick = onDeactivateClick, + ) + // Version + Footer( + version = state.version, + deviceId = state.deviceId, + onClick = if (!state.showDeveloperSettings) { + { state.eventSink(PreferencesRootEvent.OnVersionInfoClick) } + } else { + null + } + ) + } + state.userStatusState?.let { + UserStatusUpdateIndicator(it.updateStatusAction) + } } } +@Composable +private fun BoxScope.UserStatusUpdateIndicator(updateStatusAction: AsyncAction) { + AsyncActionIndicator( + asyncAction = updateStatusAction, + modifier = Modifier + .align(Alignment.TopCenter) + .statusBarsPadding(), + loading = { AsyncIndicator.Loading(text = stringResource(CommonStrings.common_saving)) }, + failure = { _ -> AsyncIndicator.Failure(text = stringResource(CommonStrings.common_failed)) }, + ) +} + @Composable private fun ColumnScope.UserStatusSection( userStatusState: UserStatusState, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt index 60f02ad05a..2358b3502d 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenter.kt @@ -18,7 +18,9 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import dev.zacsweers.metro.Inject +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.emoji.api.picker.EmojiPickerPresenter import io.element.android.libraries.emoji.api.recentemojis.EmptyGetRecentEmojis import io.element.android.libraries.matrix.api.MatrixClient @@ -38,6 +40,7 @@ class UserStatusPresenter( var isEmojiPickerVisible by remember { mutableStateOf(false) } val customTextFieldState = rememberTextFieldState() val coroutineScope = rememberCoroutineScope() + val updateStatusAction = remember { mutableStateOf>(AsyncAction.Uninitialized) } fun handleEvent(event: UserStatusEvent) { when (event) { @@ -47,11 +50,15 @@ class UserStatusPresenter( UserStatusEvent.CancelCustomInput -> pickerState = UserStatusPickerState.Hidden is UserStatusEvent.SetStatus -> { pickerState = UserStatusPickerState.Hidden - coroutineScope.launch { matrixClient.setUserStatus(event.status) } + coroutineScope.launch { + updateStatusAction.runUpdatingState { matrixClient.setUserStatus(event.status) } + } } UserStatusEvent.ClearStatus -> { pickerState = UserStatusPickerState.Hidden - coroutineScope.launch { matrixClient.clearUserStatus() } + coroutineScope.launch { + updateStatusAction.runUpdatingState { matrixClient.clearUserStatus() } + } } UserStatusEvent.OpenCustomInput -> { val raw = userProfile.rawStatus @@ -93,6 +100,7 @@ class UserStatusPresenter( displayedStatus = userProfile.displayedStatus, rawStatus = userProfile.rawStatus, pickerState = effectivePickerState, + updateStatusAction = updateStatusAction.value, eventSink = ::handleEvent, ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt index fa225ae277..6189ee6dd0 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusState.kt @@ -11,6 +11,7 @@ import androidx.annotation.StringRes import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.runtime.Immutable import io.element.android.features.preferences.impl.R +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.emoji.api.picker.EmojiPickerState import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.api.user.UserStatus @@ -19,6 +20,7 @@ data class UserStatusState( val displayedStatus: DisplayedStatus?, val rawStatus: UserStatus?, val pickerState: UserStatusPickerState, + val updateStatusAction: AsyncAction, val eventSink: (UserStatusEvent) -> Unit, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.kt index 13a1d31743..6b198183a7 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusStateProvider.kt @@ -9,6 +9,7 @@ package io.element.android.features.preferences.impl.userstatus import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.api.user.UserStatus @@ -44,10 +45,12 @@ fun aUserStatusState( displayedStatus: DisplayedStatus? = null, rawStatus: UserStatus? = null, pickerState: UserStatusPickerState = UserStatusPickerState.Hidden, + updateStatusAction: AsyncAction = AsyncAction.Uninitialized, eventSink: (UserStatusEvent) -> Unit = {}, ) = UserStatusState( displayedStatus = displayedStatus, rawStatus = rawStatus, pickerState = pickerState, + updateStatusAction = updateStatusAction, eventSink = eventSink, ) diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt index a09afdeb6f..e9897259ae 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusPresenterTest.kt @@ -8,9 +8,11 @@ package io.element.android.features.preferences.impl.userstatus import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.emoji.test.fakeEmojiPickerPresenterFactory import io.element.android.libraries.matrix.api.user.DisplayedStatus import io.element.android.libraries.matrix.api.user.UserStatus +import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.tests.testutils.test import kotlinx.coroutines.test.runTest @@ -61,6 +63,24 @@ class UserStatusPresenterTest { val newState = awaitItem() assertThat(newState.pickerState).isEqualTo(UserStatusPickerState.Hidden) assertThat(newState.displayedStatus).isEqualTo(DisplayedStatus.UserSet(status)) + assertThat(newState.updateStatusAction).isInstanceOf(AsyncAction.Success::class.java) + assertThat(client.setUserStatusCalled).isTrue() + } + } + + @Test + fun `Set event failure surfaces a Failure action`() = runTest { + val client = FakeMatrixClient().apply { + setUserStatusResult = Result.failure(AN_EXCEPTION) + } + createPresenter(client).test { + val status = UserStatus(emoji = "💬", text = "In a meeting") + awaitItem().eventSink(UserStatusEvent.SetStatus(status)) + val newState = awaitItem() + assertThat(newState.pickerState).isEqualTo(UserStatusPickerState.Hidden) + // On failure the SDK does not emit a new profile, so nothing is displayed. + assertThat(newState.displayedStatus).isNull() + assertThat(newState.updateStatusAction).isInstanceOf(AsyncAction.Failure::class.java) assertThat(client.setUserStatusCalled).isTrue() } } @@ -121,6 +141,25 @@ class UserStatusPresenterTest { val clearedState = awaitItem() assertThat(clearedState.pickerState).isEqualTo(UserStatusPickerState.Hidden) assertThat(clearedState.displayedStatus).isNull() + assertThat(clearedState.updateStatusAction).isInstanceOf(AsyncAction.Success::class.java) + assertThat(client.clearUserStatusCalled).isTrue() + } + } + + @Test + fun `Clear event failure surfaces a Failure action`() = runTest { + val client = FakeMatrixClient().apply { + clearUserStatusResult = Result.failure(AN_EXCEPTION) + } + createPresenter(client).test { + val status = UserStatus(emoji = "☕", text = "Be right back") + awaitItem().eventSink(UserStatusEvent.SetStatus(status)) + awaitItem().eventSink(UserStatusEvent.ClearStatus) + val clearedState = awaitItem() + assertThat(clearedState.pickerState).isEqualTo(UserStatusPickerState.Hidden) + // Clear failed, so the previously set status is still displayed. + assertThat(clearedState.displayedStatus).isEqualTo(DisplayedStatus.UserSet(status)) + assertThat(clearedState.updateStatusAction).isInstanceOf(AsyncAction.Failure::class.java) assertThat(client.clearUserStatusCalled).isTrue() } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncActionIndicator.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncActionIndicator.kt new file mode 100644 index 0000000000..058225939f --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncActionIndicator.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.libraries.designsystem.components.async + +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.setValue +import androidx.compose.ui.Modifier +import io.element.android.libraries.architecture.AsyncAction +import kotlinx.coroutines.delay +import kotlin.time.Duration +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.TimeMark +import kotlin.time.TimeSource + +private val DefaultShowDelay = 300.milliseconds +private val DefaultMinDisplayDuration = 500.milliseconds +private val DefaultFailureDuration = 500.milliseconds + +/** + * An [AsyncIndicatorHost] driven by an [AsyncAction], with anti-flicker timing. + * + * While [asyncAction] is [AsyncAction.Loading], [loading] is displayed, but only if the operation + * runs longer than [showDelay]; once shown it stays visible for at least [minDisplayDuration]. This + * prevents the indicator from flashing for operations that complete almost instantly. + * + * When [asyncAction] is [AsyncAction.Failure], [failure] is displayed immediately (failures are + * never debounced) and auto-dismisses after [failureDuration]. + * + * @param asyncAction the action whose progress drives the indicator. + * @param modifier the modifier to apply to the underlying [AsyncIndicatorHost]. + * @param state the [AsyncIndicatorState] backing the host. + * @param showDelay how long the loading state must persist before the indicator is shown. + * @param minDisplayDuration the minimum duration the loading indicator stays visible once shown. + * @param failureDuration how long the failure indicator stays visible before auto-dismissing. + * @param loading the composable to display while loading. + * @param failure the composable to display on failure. + */ +@Composable +fun AsyncActionIndicator( + asyncAction: AsyncAction<*>, + modifier: Modifier = Modifier, + state: AsyncIndicatorState = rememberAsyncIndicatorState(), + showDelay: Duration = DefaultShowDelay, + minDisplayDuration: Duration = DefaultMinDisplayDuration, + failureDuration: Duration = DefaultFailureDuration, + loading: @Composable () -> Unit, + failure: @Composable (Throwable) -> Unit, +) { + AsyncIndicatorHost(modifier = modifier, state = state) + AsyncActionIndicatorEffect( + asyncAction = asyncAction, + state = state, + showDelay = showDelay, + minDisplayDuration = minDisplayDuration, + failureDuration = failureDuration, + loading = loading, + failure = failure, + ) +} + +@Composable +internal fun AsyncActionIndicatorEffect( + asyncAction: AsyncAction<*>, + state: AsyncIndicatorState, + showDelay: Duration, + minDisplayDuration: Duration, + failureDuration: Duration, + loading: @Composable () -> Unit, + failure: @Composable (Throwable) -> Unit, + timeSource: TimeSource = TimeSource.Monotonic, +) { + // Mark set when the loader actually becomes visible, null while it is hidden. + var loaderShownAt by remember { mutableStateOf(null) } + LaunchedEffect(asyncAction) { + when (asyncAction) { + is AsyncAction.Loading -> { + // If the operation completes before this delay elapses, the effect is cancelled + // and the loader is never shown. + delay(showDelay) + state.enqueue(composable = loading) + loaderShownAt = timeSource.markNow() + } + is AsyncAction.Failure -> { + // Always surface failures immediately, even if the loader was never shown. + state.enqueue(durationMs = failureDuration.inWholeMilliseconds, composable = { failure(asyncAction.error) }) + loaderShownAt = null + } + is AsyncAction.Success -> { + // Hold the loader for its minimum duration before clearing it. + loaderShownAt?.let { shownAt -> + val remaining = minDisplayDuration - shownAt.elapsedNow() + if (remaining > Duration.ZERO) delay(remaining) + } + state.clear() + loaderShownAt = null + } + else -> Unit + } + } +} diff --git a/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/component/async/AsyncActionIndicatorTest.kt b/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/component/async/AsyncActionIndicatorTest.kt new file mode 100644 index 0000000000..426aa71ce7 --- /dev/null +++ b/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/component/async/AsyncActionIndicatorTest.kt @@ -0,0 +1,123 @@ +/* + * 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.component.async + +import androidx.compose.runtime.State +import androidx.compose.runtime.mutableStateOf +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.libraries.architecture.AsyncAction +import io.element.android.libraries.designsystem.components.async.AsyncActionIndicatorEffect +import io.element.android.libraries.designsystem.components.async.AsyncIndicatorState +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.test.advanceTimeBy +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Test +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.TestTimeSource +import kotlin.time.TimeSource + +@OptIn(ExperimentalCoroutinesApi::class) +class AsyncActionIndicatorTest { + private val showDelay = 300.milliseconds + private val minDisplay = 500.milliseconds + + @Test + fun `loader is not shown before the show delay elapses`() = runTest { + val state = AsyncIndicatorState() + val action = mutableStateOf>(AsyncAction.Uninitialized) + indicatorFlow(action, state).test { + action.value = AsyncAction.Loading + advanceTimeBy(100.milliseconds) + runCurrent() + assertThat(state.currentAnimationState.targetState).isFalse() + // Once the show delay has fully elapsed, the loader is shown. + advanceTimeBy(300.milliseconds) + runCurrent() + assertThat(state.currentAnimationState.targetState).isTrue() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `loader is never shown when the operation completes before the show delay`() = runTest { + val state = AsyncIndicatorState() + val action = mutableStateOf>(AsyncAction.Uninitialized) + indicatorFlow(action, state).test { + action.value = AsyncAction.Loading + advanceTimeBy(100.milliseconds) + runCurrent() + action.value = AsyncAction.Success(Unit) + advanceTimeBy(1000.milliseconds) + runCurrent() + assertThat(state.currentAnimationState.targetState).isFalse() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `failure is shown immediately, without waiting for the show delay`() = runTest { + val state = AsyncIndicatorState() + val action = mutableStateOf>(AsyncAction.Uninitialized) + indicatorFlow(action, state).test { + action.value = AsyncAction.Failure(Exception("failed")) + runCurrent() + assertThat(state.currentAnimationState.targetState).isTrue() + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `loader stays visible for the minimum duration once shown`() = runTest { + val state = AsyncIndicatorState() + val action = mutableStateOf>(AsyncAction.Uninitialized) + val timeSource = TestTimeSource() + indicatorFlow(action, state, timeSource).test { + // Show the loader. + action.value = AsyncAction.Loading + advanceTimeBy(400.milliseconds) + runCurrent() + assertThat(state.currentAnimationState.targetState).isTrue() + // 200ms of display has already elapsed when the operation succeeds. + timeSource += 200.milliseconds + action.value = AsyncAction.Success(Unit) + runCurrent() + // Still within the minimum display duration (200ms shown, 300ms remaining) -> stays visible. + advanceTimeBy(200.milliseconds) + runCurrent() + assertThat(state.currentAnimationState.targetState).isTrue() + // Past the minimum display duration -> cleared. + advanceTimeBy(200.milliseconds) + runCurrent() + assertThat(state.currentAnimationState.targetState).isFalse() + cancelAndIgnoreRemainingEvents() + } + } + + private fun indicatorFlow( + action: State>, + state: AsyncIndicatorState, + timeSource: TimeSource = TimeSource.Monotonic, + ): Flow = moleculeFlow(RecompositionMode.Immediate) { + AsyncActionIndicatorEffect( + asyncAction = action.value, + state = state, + showDelay = showDelay, + minDisplayDuration = minDisplay, + failureDuration = minDisplay, + loading = {}, + failure = {}, + timeSource = timeSource, + ) + state.currentAnimationState.targetState + } +} From 7adaeca7c7d03958db826a613e36fd37fc485e77 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 6 Aug 2026 16:17:17 +0200 Subject: [PATCH 257/383] Fix overlap issue. Fixes #7327 --- .../io/element/android/features/home/impl/HomeView.kt | 6 ++++++ 1 file changed, 6 insertions(+) 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 50cfc00a78..f5a2400f2f 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 @@ -14,12 +14,15 @@ import androidx.activity.compose.BackHandler import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.calculateEndPadding import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.plus +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @@ -204,6 +207,9 @@ private fun HomeScaffold( floatingActionButton = { val coroutineScope = rememberCoroutineScope() HomeBottomBar( + // The Scaffold uses top-only insets so the scrollable content can go edge-to-edge behind the + // navigation bar, so the floating toolbar has to apply the bottom inset itself to avoid overlapping it. + modifier = Modifier.windowInsetsPadding(WindowInsets.navigationBars), currentHomeNavigationBarItem = state.currentHomeNavigationBarItem, onItemClick = { item -> // scroll to top if selecting the same item From 9c66cd331f61de6e51bf1393b05ec9cf675a3f4c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 4 May 2026 18:09:06 +0200 Subject: [PATCH 258/383] [Link new device] Handle split steps in the SDK --- .../impl/LinkNewDeviceFlowNode.kt | 15 +++++++++ .../ContinuationMessageSender.kt | 13 ++++++++ .../api/linknewdevice/LinkDesktopHandler.kt | 2 ++ .../api/linknewdevice/LinkMobileHandler.kt | 7 ++++- .../RustContinuationMessageSender.kt | 31 +++++++++++++++++++ .../linknewdevice/RustLinkDesktopHandler.kt | 4 +++ .../linknewdevice/RustLinkMobileHandler.kt | 8 ++++- .../FakeContinuationMessageSender.kt | 25 +++++++++++++++ .../RustLinkDesktopHandlerTest.kt | 18 ++++++----- .../RustLinkMobileHandlerTest.kt | 18 ++++++----- .../android/tests/testutils/ExpectedResult.kt | 28 +++++++++++++++++ 11 files changed, 152 insertions(+), 17 deletions(-) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/linknewdevice/ContinuationMessageSender.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustContinuationMessageSender.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/FakeContinuationMessageSender.kt create mode 100644 tests/testutils/src/main/kotlin/io/element/android/tests/testutils/ExpectedResult.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 d686b22860..b1492f53cc 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 @@ -54,8 +54,10 @@ import io.element.android.libraries.matrix.api.linknewdevice.LinkMobileStep import io.element.android.libraries.matrix.api.logs.LoggerTags import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize import timber.log.Timber @@ -102,6 +104,7 @@ class LinkNewDeviceFlowNode( @Suppress("AssignedValueIsNeverRead") linkDesktopHandlerJob = observeLinkNewDesktopHandler() }, + onResume = ::onResume, onDestroy = { linkMobileHandlerJob?.cancel() linkDesktopHandlerJob?.cancel() @@ -209,6 +212,18 @@ class LinkNewDeviceFlowNode( .launchIn(sessionCoroutineScope) } + private fun onResume() = sessionCoroutineScope.launch { + // Application is resumed, if the step is waiting for auth, send the confirmation + (linkNewMobileHandler.stepFlow.first() as? LinkMobileStep.WaitingForAuth)?.let { + Timber.tag(tag.value).d("Resuming while waiting for auth on mobile, sending confirmation") + it.continuationMessageSender.confirm() + } + (linkNewDesktopHandler.stepFlow.value as? LinkDesktopStep.WaitingForAuth)?.let { + Timber.tag(tag.value).d("Resuming while waiting for auth on desktop, sending confirmation") + it.continuationMessageSender.confirm() + } + } + private fun navigateToError(errorType: ErrorType) { // Map the error to an error screen val error = when (errorType) { diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/linknewdevice/ContinuationMessageSender.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/linknewdevice/ContinuationMessageSender.kt new file mode 100644 index 0000000000..0bbbaf3187 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/linknewdevice/ContinuationMessageSender.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.matrix.api.linknewdevice + +interface ContinuationMessageSender { + suspend fun cancel(): Result + suspend fun confirm(): Result +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/linknewdevice/LinkDesktopHandler.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/linknewdevice/LinkDesktopHandler.kt index d600c1a8bf..343624aa34 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/linknewdevice/LinkDesktopHandler.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/linknewdevice/LinkDesktopHandler.kt @@ -18,8 +18,10 @@ interface LinkDesktopHandler { sealed interface LinkDesktopStep { data object Uninitialized : LinkDesktopStep data object Starting : LinkDesktopStep + data class WaitingForAuth( val verificationUri: String, + val continuationMessageSender: ContinuationMessageSender, ) : LinkDesktopStep data class EstablishingSecureChannel( 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 eb2d49b5b0..f187b8275a 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 @@ -22,7 +22,12 @@ sealed interface 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 WaitingForAuth( + val verificationUri: String, + val continuationMessageSender: ContinuationMessageSender, + ) : LinkMobileStep + data class QrScanned(val checkCodeSender: CheckCodeSender) : LinkMobileStep data class Error(val errorType: ErrorType) : LinkMobileStep data object SyncingSecrets : LinkMobileStep diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustContinuationMessageSender.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustContinuationMessageSender.kt new file mode 100644 index 0000000000..98cf29418c --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustContinuationMessageSender.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.matrix.impl.linknewdevice + +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.matrix.api.linknewdevice.ContinuationMessageSender +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.withContext +import org.matrix.rustcomponents.sdk.ContinuationMessageSender as FfiContinuationMessageSender + +class RustContinuationMessageSender( + private val inner: FfiContinuationMessageSender, + private val sessionDispatcher: CoroutineDispatcher, +) : ContinuationMessageSender { + override suspend fun cancel(): Result = withContext(sessionDispatcher) { + runCatchingExceptions { + inner.cancel() + } + } + + override suspend fun confirm(): Result = withContext(sessionDispatcher) { + runCatchingExceptions { + inner.confirm() + } + } +} 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 83e657eb07..8c9695ae4b 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 @@ -75,6 +75,10 @@ class RustLinkDesktopHandler( GrantQrLoginProgress.SyncingSecrets -> LinkDesktopStep.SyncingSecrets is GrantQrLoginProgress.WaitingForAuth -> LinkDesktopStep.WaitingForAuth( verificationUri = verificationUri, + continuationMessageSender = RustContinuationMessageSender( + inner = continuationSender, + sessionDispatcher = sessionDispatcher, + ) ) is GrantQrLoginProgress.EstablishingSecureChannel -> LinkDesktopStep.EstablishingSecureChannel( checkCode = checkCode, 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 a44a8d5943..33f1ad736d 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 @@ -84,7 +84,13 @@ class RustLinkMobileHandler( ) GrantGeneratedQrLoginProgress.Starting -> LinkMobileStep.Starting GrantGeneratedQrLoginProgress.SyncingSecrets -> LinkMobileStep.SyncingSecrets - is GrantGeneratedQrLoginProgress.WaitingForAuth -> LinkMobileStep.WaitingForAuth(verificationUri) + is GrantGeneratedQrLoginProgress.WaitingForAuth -> LinkMobileStep.WaitingForAuth( + verificationUri = verificationUri, + continuationMessageSender = RustContinuationMessageSender( + inner = continuationSender, + sessionDispatcher = sessionDispatcher, + ) + ) } } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/FakeContinuationMessageSender.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/FakeContinuationMessageSender.kt new file mode 100644 index 0000000000..d1544ec8bb --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/FakeContinuationMessageSender.kt @@ -0,0 +1,25 @@ +/* + * 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.linknewdevice + +import io.element.android.libraries.matrix.api.linknewdevice.ContinuationMessageSender +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.simulateLongTask + +class FakeContinuationMessageSender( + private val cancelResult: () -> Result = { lambdaError() }, + private val confirmResult: () -> Result = { lambdaError() }, +) : ContinuationMessageSender { + override suspend fun cancel(): Result = simulateLongTask { + cancelResult() + } + + override suspend fun confirm(): Result = simulateLongTask { + confirmResult() + } +} 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 c0781972ac..8a0a046946 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 @@ -16,6 +16,8 @@ import io.element.android.libraries.matrix.api.linknewdevice.LinkDesktopStep import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiContinuationMessageSender import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiGrantLoginWithQrCodeHandler import io.element.android.libraries.matrix.test.QR_CODE_DATA +import io.element.android.tests.testutils.ExpectedResult +import io.element.android.tests.testutils.match import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch @@ -50,16 +52,18 @@ class RustLinkDesktopHandlerTest { runCurrent() // progress from the handler is mapped and emitted listOf( - GrantQrLoginProgress.Starting to LinkDesktopStep.Starting, - GrantQrLoginProgress.SyncingSecrets to LinkDesktopStep.SyncingSecrets, + GrantQrLoginProgress.Starting to ExpectedResult(LinkDesktopStep.Starting), + GrantQrLoginProgress.SyncingSecrets to ExpectedResult(LinkDesktopStep.SyncingSecrets), GrantQrLoginProgress.WaitingForAuth("aVerificationUri", FakeFfiContinuationMessageSender()) - to LinkDesktopStep.WaitingForAuth("aVerificationUri"), + to ExpectedResult( + resultClass = LinkDesktopStep.WaitingForAuth::class.java, + ), GrantQrLoginProgress.EstablishingSecureChannel(1.toUByte(), "1") - to LinkDesktopStep.EstablishingSecureChannel(1.toUByte(), "1"), - GrantQrLoginProgress.Done to LinkDesktopStep.Done, - ).forEach { (progress, expectedStep) -> + to ExpectedResult(LinkDesktopStep.EstablishingSecureChannel(1.toUByte(), "1")), + GrantQrLoginProgress.Done to ExpectedResult(LinkDesktopStep.Done), + ).forEach { (progress, expectedResult) -> handler.emitScanProgress(progress) - assertThat(awaitItem()).isEqualTo(expectedStep) + assertThat(awaitItem()).match(expectedResult) } // scan returns, no new event is emitted completable.complete(Unit) 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 8c0306c8ad..f1f568e3ca 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 @@ -18,6 +18,8 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiContinuati 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 io.element.android.tests.testutils.ExpectedResult +import io.element.android.tests.testutils.match import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch @@ -51,18 +53,18 @@ class RustLinkMobileHandlerTest { runCurrent() // progress from the handler is mapped and emitted listOf( - GrantGeneratedQrLoginProgress.Starting to LinkMobileStep.Starting::class.java, - GrantGeneratedQrLoginProgress.SyncingSecrets to LinkMobileStep.SyncingSecrets::class.java, + GrantGeneratedQrLoginProgress.Starting to ExpectedResult(LinkMobileStep.Starting), + GrantGeneratedQrLoginProgress.SyncingSecrets to ExpectedResult(LinkMobileStep.SyncingSecrets), GrantGeneratedQrLoginProgress.WaitingForAuth("aVerificationUri", FakeFfiContinuationMessageSender()) - to LinkMobileStep.WaitingForAuth::class.java, + to ExpectedResult(LinkMobileStep.WaitingForAuth::class.java), GrantGeneratedQrLoginProgress.QrScanned(FakeFfiCheckCodeSender()) - to LinkMobileStep.QrScanned::class.java, + to ExpectedResult(LinkMobileStep.QrScanned::class.java), GrantGeneratedQrLoginProgress.QrReady(FakeFfiQrCodeData(toBytesResult = { QR_CODE_DATA_RECIPROCATE })) - to LinkMobileStep.QrReady::class.java, - GrantGeneratedQrLoginProgress.Done to LinkMobileStep.Done::class.java, - ).forEach { (progress, expectedStepClass) -> + to ExpectedResult(LinkMobileStep.QrReady::class.java), + GrantGeneratedQrLoginProgress.Done to ExpectedResult(LinkMobileStep.Done), + ).forEach { (progress, expectedResult) -> handler.emitGenerateProgress(progress) - assertThat(awaitItem()).isInstanceOf(expectedStepClass) + assertThat(awaitItem()).match(expectedResult) } // generate returns, no new event is emitted completable.complete(Unit) diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/ExpectedResult.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/ExpectedResult.kt new file mode 100644 index 0000000000..b5e383f324 --- /dev/null +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/ExpectedResult.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.tests.testutils + +import com.google.common.truth.Subject + +/** + * A helper class to assert expected results in tests. It can be used to assert either the type of result or its value. + */ +data class ExpectedResult( + val resultClass: Class, + val result: T? = null, +) { + constructor(result: T) : this(result::class.java, result) +} + +fun Subject.match(expectedResult: ExpectedResult) { + if (expectedResult.result != null) { + isEqualTo(expectedResult.result) + } else { + isInstanceOf(expectedResult.resultClass) + } +} From 0e563332ce06a7b9a750c4c5c8917929b9dc6f9a Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 6 Aug 2026 16:16:13 +0200 Subject: [PATCH 259/383] Clean up formatting/detekt --- .../components/async/AsyncActionIndicator.kt | 17 +++++++++++------ .../matrix/api/user/DisplayedStatus.kt | 1 - .../matrix/impl/room/JoinedRustRoom.kt | 2 +- .../android/tests/konsist/KonsistPreviewTest.kt | 1 + 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncActionIndicator.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncActionIndicator.kt index 058225939f..f1a58c243f 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncActionIndicator.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncActionIndicator.kt @@ -12,6 +12,7 @@ import androidx.compose.runtime.LaunchedEffect 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.Modifier import io.element.android.libraries.architecture.AsyncAction @@ -36,24 +37,24 @@ private val DefaultFailureDuration = 500.milliseconds * never debounced) and auto-dismisses after [failureDuration]. * * @param asyncAction the action whose progress drives the indicator. + * @param loading the composable to display while loading. + * @param failure the composable to display on failure. * @param modifier the modifier to apply to the underlying [AsyncIndicatorHost]. * @param state the [AsyncIndicatorState] backing the host. * @param showDelay how long the loading state must persist before the indicator is shown. * @param minDisplayDuration the minimum duration the loading indicator stays visible once shown. * @param failureDuration how long the failure indicator stays visible before auto-dismissing. - * @param loading the composable to display while loading. - * @param failure the composable to display on failure. */ @Composable fun AsyncActionIndicator( asyncAction: AsyncAction<*>, + loading: @Composable () -> Unit, + failure: @Composable (Throwable) -> Unit, modifier: Modifier = Modifier, state: AsyncIndicatorState = rememberAsyncIndicatorState(), showDelay: Duration = DefaultShowDelay, minDisplayDuration: Duration = DefaultMinDisplayDuration, failureDuration: Duration = DefaultFailureDuration, - loading: @Composable () -> Unit, - failure: @Composable (Throwable) -> Unit, ) { AsyncIndicatorHost(modifier = modifier, state = state) AsyncActionIndicatorEffect( @@ -78,6 +79,9 @@ internal fun AsyncActionIndicatorEffect( failure: @Composable (Throwable) -> Unit, timeSource: TimeSource = TimeSource.Monotonic, ) { + // Referenced inside the restarting LaunchedEffect below, so keep them up to date. + val currentLoading by rememberUpdatedState(loading) + val currentFailure by rememberUpdatedState(failure) // Mark set when the loader actually becomes visible, null while it is hidden. var loaderShownAt by remember { mutableStateOf(null) } LaunchedEffect(asyncAction) { @@ -86,12 +90,13 @@ internal fun AsyncActionIndicatorEffect( // If the operation completes before this delay elapses, the effect is cancelled // and the loader is never shown. delay(showDelay) - state.enqueue(composable = loading) + state.enqueue(composable = currentLoading) loaderShownAt = timeSource.markNow() } is AsyncAction.Failure -> { // Always surface failures immediately, even if the loader was never shown. - state.enqueue(durationMs = failureDuration.inWholeMilliseconds, composable = { failure(asyncAction.error) }) + val error = asyncAction.error + state.enqueue(durationMs = failureDuration.inWholeMilliseconds, composable = { currentFailure(error) }) loaderShownAt = null } is AsyncAction.Success -> { diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt index 64cf68cda7..8e4ced7202 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/DisplayedStatus.kt @@ -13,7 +13,6 @@ import kotlinx.parcelize.Parcelize @Immutable sealed interface DisplayedStatus : Parcelable { - /** Useful for adding extension methods. */ companion object 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 db4cd5f0db..d454d7c775 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 @@ -42,7 +42,6 @@ import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings import io.element.android.libraries.matrix.impl.core.RustSendHandle import io.element.android.libraries.matrix.impl.mapper.map -import io.element.android.libraries.matrix.impl.user.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 @@ -54,6 +53,7 @@ import io.element.android.libraries.matrix.impl.room.threads.RustThreadsListServ 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.user.map 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 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 e2a387eede..e066a6b7ec 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 @@ -98,6 +98,7 @@ class KonsistPreviewTest { "HomeTopBarSpaceFiltersSelectedPreview", "HomeTopBarSpacesPreview", "HomeTopBarWithIndicatorPreview", + "HomeTopBarWithStatusPreview", "IconsOtherPreview", "MarkdownTextComposerEditPreview", "MatrixBadgeAtomInfoPreview", From f8ce3e9b709e0b2f45b977d56707f20d97d989bd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Aug 2026 18:31:36 +0200 Subject: [PATCH 260/383] Merge pull request #7329 from element-hq/renovate/constraintlayout Update dependency androidx.constraintlayout:constraintlayout to v2.2.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 c7fa8e1300..0ca25f0636 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ firebaseAppDistribution = "5.3.0" # AndroidX core = "1.18.0" datastore = "1.2.1" -constraintlayout = "2.2.1" +constraintlayout = "2.2.2" constraintlayout_compose = "1.1.1" lifecycle = "2.11.0" activity = "1.13.0" From b1b52da38e6aa048fd24af7bd0d5212076073be0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Aug 2026 18:32:08 +0200 Subject: [PATCH 261/383] Update reactivecircus/android-emulator-runner action to v2.38.0 (#7189) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/maestro-local.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maestro-local.yml b/.github/workflows/maestro-local.yml index cdc6fd3330..198b462349 100644 --- a/.github/workflows/maestro-local.yml +++ b/.github/workflows/maestro-local.yml @@ -98,7 +98,7 @@ jobs: run: curl -fsSL "https://get.maestro.mobile.dev" | bash - name: Run Maestro tests in emulator id: maestro_test - uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a # v2.37.0 + uses: reactivecircus/android-emulator-runner@a421e43855164a8197daf9d8d40fe71c6996bb0d # v2.38.0 continue-on-error: true env: MAESTRO_USERNAME: maestroelement From d2b4a8545342fb66a4f2984721e430620bab4d12 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 17:20:52 +0000 Subject: [PATCH 262/383] Update dependency androidx.compose.material3:material3 to v1.5.0-alpha23 --- 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 0ca25f0636..66e9d464c3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -126,7 +126,7 @@ androidx_preference = "androidx.preference:preference:1.2.1" 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-alpha22' } +androidx_compose_material3 = { module = "androidx.compose.material3:material3", version = '1.5.0-alpha23' } androidx_compose_material3_windowsizeclass = { module = "androidx.compose.material3:material3-window-size-class" } androidx_compose_material3_adaptive = "androidx.compose.material3:material3-adaptive-android:1.0.0-alpha06" androidx_compose_ui = { module = "androidx.compose.ui:ui" } From d1cf1aa09f6515a4b5703ef583f4a93329f0b31d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 9 Jul 2026 16:19:44 +0200 Subject: [PATCH 263/383] Fix deprecation warning on `androidx.compose.material3.ListItem` --- .../preferences/AnalyticsPreferencesView.kt | 2 +- .../impl/configureroom/ConfigureRoomView.kt | 2 +- .../configureroom/SelectParentSpaceOptions.kt | 6 +- .../home/impl/roomlist/RoomListContextMenu.kt | 14 ++--- .../declineandblock/DeclineAndBlockView.kt | 4 +- .../impl/details/DependenciesDetailsView.kt | 2 +- .../impl/list/DependencyLicensesListView.kt | 2 +- .../location/impl/share/ShareLocationView.kt | 6 +- .../impl/settings/LockScreenSettingsView.kt | 4 +- .../impl/actionlist/ActionListView.kt | 4 +- .../preview/AttachmentsPreviewView.kt | 2 +- .../messagecomposer/AttachmentsBottomSheet.kt | 14 ++--- .../bottomsheet/ReadReceiptBottomSheet.kt | 2 +- .../poll/impl/create/CreatePollView.kt | 10 +-- .../preferences/impl/about/AboutView.kt | 4 +- .../impl/advanced/AdvancedSettingsView.kt | 18 +++--- .../impl/developer/DeveloperSettingsView.kt | 14 ++--- .../appsettings/AppDeveloperSettingsView.kt | 4 +- .../notifications/NotificationSettingsView.kt | 18 +++--- .../edit/DefaultNotificationSettingOption.kt | 2 +- .../EditDefaultNotificationSettingView.kt | 2 +- .../impl/root/PreferencesRootView.kt | 30 ++++----- .../preferences/RageshakePreferencesView.kt | 2 +- .../rageshake/impl/bugreport/BugReportView.kt | 2 +- .../reportroom/impl/ReportRoomView.kt | 2 +- .../impl/root/RolesAndPermissionsView.kt | 14 ++--- .../roomdetails/impl/RoomDetailsView.kt | 36 +++++------ .../RoomNotificationSettingsOption.kt | 2 +- ...UserDefinedRoomNotificationSettingsView.kt | 2 +- .../impl/RoomMemberModerationView.kt | 8 +-- .../impl/root/SecureBackupRootView.kt | 10 +-- .../ManageAuthorizedSpacesView.kt | 2 +- .../impl/root/SecurityAndPrivacyView.kt | 18 +++--- .../space/impl/settings/SpaceSettingsView.kt | 8 +-- .../userprofile/shared/UserProfileView.kt | 2 +- .../shared/blockuser/BlockUserSection.kt | 4 +- .../viewfolder/impl/folder/ViewFolderView.kt | 6 +- .../components/list/AvatarListItem.kt | 2 +- .../components/list/CheckboxListItem.kt | 2 +- .../list/MultipleSelectionListItem.kt | 2 +- .../components/list/RadioButtonListItem.kt | 2 +- .../list/SingleSelectionListItem.kt | 2 +- .../components/list/SwitchListItem.kt | 2 +- .../preferences/PreferenceCheckbox.kt | 2 +- .../preferences/PreferenceDropdown.kt | 2 +- .../components/preferences/PreferenceRow.kt | 2 +- .../components/preferences/PreferenceSlide.kt | 2 +- .../preferences/PreferenceSwitch.kt | 2 +- .../preferences/PreferenceTextField.kt | 2 +- .../designsystem/theme/components/ListItem.kt | 63 +++++++++---------- .../theme/components/ListSupportingText.kt | 8 +-- .../ui/components/AvatarActionBottomSheet.kt | 2 +- .../impl/details/MediaDetailsBottomSheet.kt | 12 ++-- .../textcomposer/TextComposerLinkDialog.kt | 2 +- .../impl/TroubleshootNotificationsView.kt | 14 ++--- .../impl/history/PushHistoryView.kt | 2 +- 56 files changed, 205 insertions(+), 206 deletions(-) diff --git a/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesView.kt b/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesView.kt index e91c77079f..1158b57673 100644 --- a/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesView.kt +++ b/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/preferences/AnalyticsPreferencesView.kt @@ -39,7 +39,7 @@ fun AnalyticsPreferencesView( ) Column(modifier) { ListItem( - headlineContent = { + content = { Text(stringResource(id = R.string.screen_analytics_settings_share_data)) }, supportingContent = { diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt index 1ee4bcd2b5..c929060e13 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt @@ -312,7 +312,7 @@ private fun RoomJoinRuleOptions( backgroundTint = Color.Transparent, ) }, - headlineContent = { + content = { val title = when (item) { JoinRuleItem.PublicVisibility.Public -> stringResource(R.string.screen_create_room_room_access_section_public_option_title) is JoinRuleItem.PrivateVisibility.Restricted -> stringResource(R.string.screen_create_room_room_access_section_restricted_option_title) 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 c96fbc4d6b..6389f920d5 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 @@ -58,7 +58,7 @@ internal fun SelectParentSpaceOptions( modifier = modifier ) { ListItem( - headlineContent = { + content = { Text( text = selectedSpace?.displayName ?: stringResource(R.string.screen_create_room_space_selection_no_space_title), @@ -126,7 +126,7 @@ private fun SelectParentSpaceBottomSheet( LazyColumn(modifier = Modifier.fillMaxWidth()) { item { ListItem( - headlineContent = { + content = { Text( text = stringResource(R.string.screen_create_room_space_selection_no_space_option), maxLines = 1 @@ -141,7 +141,7 @@ private fun SelectParentSpaceBottomSheet( for (space in spaces) { item { ListItem( - headlineContent = { + content = { Text( text = space.displayName, maxLines = 1 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 9d6a5173ae..bfa6962e8b 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 @@ -94,7 +94,7 @@ private fun RoomListModalBottomSheetContent( .verticalScroll(rememberScrollState()) ) { ListItem( - headlineContent = { + content = { Text( text = contextMenu.roomName ?: stringResource(id = CommonStrings.common_no_room_name), style = ElementTheme.typography.fontBodyLgMedium, @@ -104,7 +104,7 @@ private fun RoomListModalBottomSheetContent( ) if (contextMenu.hasNewContent) { ListItem( - headlineContent = { + content = { Text( text = stringResource(id = CommonStrings.action_mark_as_read), style = MaterialTheme.typography.bodyLarge, @@ -117,7 +117,7 @@ private fun RoomListModalBottomSheetContent( ) } else { ListItem( - headlineContent = { + content = { Text( text = stringResource(id = R.string.screen_roomlist_mark_as_unread), style = MaterialTheme.typography.bodyLarge, @@ -135,7 +135,7 @@ private fun RoomListModalBottomSheetContent( CommonStrings.common_favourite to CompoundIcons.Favourite() } ListItem( - headlineContent = { + content = { Text( text = stringResource(id = textResId), style = MaterialTheme.typography.bodyLarge, @@ -154,7 +154,7 @@ private fun RoomListModalBottomSheetContent( }, ) ListItem( - headlineContent = { + content = { Text( text = stringResource(id = CommonStrings.common_settings), style = MaterialTheme.typography.bodyLarge, @@ -169,7 +169,7 @@ private fun RoomListModalBottomSheetContent( ) if (canReportRoom) { ListItem( - headlineContent = { + content = { Text(text = stringResource(CommonStrings.action_report_room)) }, modifier = Modifier.clickable { onReportRoomClick() }, @@ -182,7 +182,7 @@ private fun RoomListModalBottomSheetContent( ) } ListItem( - headlineContent = { + content = { Text(text = stringResource(CommonStrings.action_leave_room)) }, modifier = Modifier.clickable { onLeaveRoomClick() }, diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockView.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockView.kt index 1028a4c142..1d14df024a 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockView.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockView.kt @@ -81,7 +81,7 @@ fun DeclineAndBlockView( ) { ListItem( modifier = Modifier.padding(end = 8.dp), - headlineContent = { + content = { Text(text = stringResource(R.string.screen_decline_and_block_block_user_option_title)) }, supportingContent = { @@ -96,7 +96,7 @@ fun DeclineAndBlockView( Spacer(modifier = Modifier.height(24.dp)) ListItem( modifier = Modifier.padding(end = 8.dp), - headlineContent = { + content = { Text(text = stringResource(CommonStrings.action_report_room)) }, supportingContent = { diff --git a/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/details/DependenciesDetailsView.kt b/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/details/DependenciesDetailsView.kt index e1d445ea1f..14b195a0b5 100644 --- a/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/details/DependenciesDetailsView.kt +++ b/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/details/DependenciesDetailsView.kt @@ -62,7 +62,7 @@ fun DependenciesDetailsView( } } ListItem( - headlineContent = { + content = { ClickableLinkText( text = text, interactionSource = remember { MutableInteractionSource() }, diff --git a/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/list/DependencyLicensesListView.kt b/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/list/DependencyLicensesListView.kt index b732588217..943f57ab3b 100644 --- a/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/list/DependencyLicensesListView.kt +++ b/features/licenses/impl/src/main/kotlin/io/element/android/features/licenses/impl/list/DependencyLicensesListView.kt @@ -100,7 +100,7 @@ fun DependencyLicensesListView( } is AsyncData.Success -> items(state.licenses.data) { license -> ListItem( - headlineContent = { Text(license.safeName) }, + content = { Text(license.safeName) }, supportingContent = { Text( buildString { 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 dc857b37a6..8b7106e939 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 @@ -261,7 +261,7 @@ private fun ShareCurrentLocationItem( onClick: () -> Unit, ) { ListItem( - headlineContent = { + content = { Text(stringResource(CommonStrings.screen_share_my_location_action)) }, onClick = onClick, @@ -276,7 +276,7 @@ private fun SharePinLocationItem( onClick: () -> Unit, ) { ListItem( - headlineContent = { + content = { Text(stringResource(CommonStrings.screen_share_this_location_action)) }, onClick = onClick, @@ -291,7 +291,7 @@ private fun ShareLiveLocationItem( onClick: () -> Unit, ) { ListItem( - headlineContent = { + content = { Text(stringResource(CommonStrings.action_share_live_location)) }, onClick = onClick, 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 e78a5ee002..d8655e29a3 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 @@ -38,7 +38,7 @@ fun LockScreenSettingsView( ) { PreferenceCategory(showTopDivider = false) { ListItem( - headlineContent = { + content = { Text(stringResource(id = R.string.screen_app_lock_settings_change_pin)) }, onClick = onChangePinClick, @@ -46,7 +46,7 @@ fun LockScreenSettingsView( PreferenceDivider() if (state.showRemovePinOption) { ListItem( - headlineContent = { + content = { Text(stringResource(id = R.string.screen_app_lock_settings_remove_pin)) }, style = ListItemStyle.Destructive, 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 b09c7e4ce7..669a696111 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 @@ -248,7 +248,7 @@ private fun ActionListViewContent( modifier = Modifier.clickable { onActionClick(action) }, - headlineContent = { + content = { Text(text = stringResource(id = action.titleRes)) }, leadingContent = ListItemContent.Icon(IconSource.Resource(action.icon)), @@ -461,7 +461,7 @@ private fun VerifiedUserSendFailureView( .padding(horizontal = 16.dp, vertical = 8.dp), leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ErrorSolid())), trailingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ChevronRight())), - headlineContent = { + content = { Text( text = sendFailure.headline(), style = ElementTheme.typography.fontBodySmMedium, 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 4a14c11f4b..077d086720 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 @@ -494,7 +494,7 @@ private fun VideoQualitySelectorDialog( val estimationMb = sizeFormatter.format(videoEstimation.sizeInBytes, true) val title = "${preset.title()} ($estimationMb)" ListItem( - headlineContent = { + content = { Text( text = title, style = ElementTheme.typography.fontBodyLgMedium, 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 d5fb0a100b..e7006b5aef 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 @@ -106,22 +106,22 @@ private fun AttachmentSourcePickerMenu( ListItem( 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)) }, + content = { Text(stringResource(R.string.screen_room_attachment_source_camera_photo)) }, ) 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)) }, + content = { Text(stringResource(R.string.screen_room_attachment_source_camera_video)) }, ) 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)) }, + content = { Text(stringResource(R.string.screen_room_attachment_source_gallery)) }, ) 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)) }, + content = { Text(stringResource(R.string.screen_room_attachment_source_files)) }, ) if (state.canShareLocation) { ListItem( @@ -130,7 +130,7 @@ private fun AttachmentSourcePickerMenu( onSendLocationClick() }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.LocationPin())), - headlineContent = { Text(stringResource(R.string.screen_room_attachment_source_location)) }, + content = { Text(stringResource(R.string.screen_room_attachment_source_location)) }, ) } ListItem( @@ -139,13 +139,13 @@ private fun AttachmentSourcePickerMenu( onCreatePollClick() }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Polls())), - headlineContent = { Text(stringResource(R.string.screen_room_attachment_source_poll)) }, + content = { Text(stringResource(R.string.screen_room_attachment_source_poll)) }, ) 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)) }, + content = { Text(stringResource(R.string.screen_room_attachment_text_formatting)) }, ) } } 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 007e809972..407cd29026 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 @@ -86,7 +86,7 @@ private fun ReadReceiptBottomSheetContent( LazyColumn { item { ListItem( - headlineContent = { + content = { Text(text = stringResource(id = CommonStrings.common_seen_by)) } ) diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt index 3abf3718af..6163fe19ad 100644 --- a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollView.kt @@ -107,7 +107,7 @@ fun CreatePollView( item { Column { ListItem( - headlineContent = { + content = { TextField( label = stringResource(id = R.string.screen_create_poll_question_desc), value = state.question, @@ -127,7 +127,7 @@ fun CreatePollView( itemsIndexed(state.answers) { index, answer -> val isLastItem = index == state.answers.size - 1 ListItem( - headlineContent = { + content = { TextField( value = answer.text, onValueChange = { @@ -155,7 +155,7 @@ fun CreatePollView( if (state.canAddAnswer) { item { ListItem( - headlineContent = { Text(text = stringResource(id = R.string.screen_create_poll_add_option_btn)) }, + content = { Text(text = stringResource(id = R.string.screen_create_poll_add_option_btn)) }, leadingContent = ListItemContent.Icon( iconSource = IconSource.Vector(CompoundIcons.Plus()), ), @@ -174,7 +174,7 @@ fun CreatePollView( Column { HorizontalDivider() ListItem( - headlineContent = { Text(text = stringResource(id = R.string.screen_create_poll_anonymous_headline)) }, + content = { Text(text = stringResource(id = R.string.screen_create_poll_anonymous_headline)) }, supportingContent = { Text(text = stringResource(id = R.string.screen_create_poll_anonymous_desc)) }, trailingContent = ListItemContent.Switch( checked = state.pollKind == PollKind.Undisclosed, @@ -189,7 +189,7 @@ fun CreatePollView( ) if (state.canDelete) { ListItem( - headlineContent = { Text(text = stringResource(id = CommonStrings.action_delete_poll)) }, + content = { Text(text = stringResource(id = CommonStrings.action_delete_poll)) }, style = ListItemStyle.Destructive, onClick = { state.eventSink(CreatePollEvent.Delete(confirmed = false)) }, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/AboutView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/AboutView.kt index b71db181e8..3a6671f692 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/AboutView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/AboutView.kt @@ -34,14 +34,14 @@ fun AboutView( ) { state.elementLegals.forEach { elementLegal -> ListItem( - headlineContent = { + content = { Text(stringResource(id = elementLegal.titleRes)) }, onClick = { onElementLegalClick(elementLegal) } ) } ListItem( - headlineContent = { + content = { Text(stringResource(id = CommonStrings.common_open_source_licenses)) }, onClick = onOpenSourceLicensesClick, 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 c108c45d3b..438b20049a 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 @@ -93,7 +93,7 @@ fun AdvancedSettingsView( } ) ListItem( - headlineContent = { + content = { Text(text = stringResource(id = CommonStrings.action_view_source)) }, supportingContent = { @@ -105,7 +105,7 @@ fun AdvancedSettingsView( onClick = { state.eventSink(AdvancedSettingsEvents.SetDeveloperModeEnabled(!state.isDeveloperModeEnabled)) } ) ListItem( - headlineContent = { + content = { Text(text = stringResource(id = R.string.screen_advanced_settings_share_presence)) }, supportingContent = { @@ -122,7 +122,7 @@ fun AdvancedSettingsView( null -> Unit is MediaOptimizationState.AllMedia -> { ListItem( - headlineContent = { + content = { Text(text = stringResource(id = R.string.screen_advanced_settings_media_compression_title)) }, supportingContent = { @@ -146,7 +146,7 @@ fun AdvancedSettingsView( } is MediaOptimizationState.Split -> { ListItem( - headlineContent = { + content = { Text(text = stringResource(id = R.string.screen_advanced_settings_optimise_image_upload_quality_title)) }, supportingContent = { @@ -171,7 +171,7 @@ fun AdvancedSettingsView( var displaySelectorDialog by remember { mutableStateOf(false) } ListItem( - headlineContent = { + content = { Text(text = stringResource(id = R.string.screen_advanced_settings_optimise_video_upload_quality_title)) }, supportingContent = { @@ -247,7 +247,7 @@ private fun VideoQualitySelectorDialog( VideoCompressionPreset.HIGH -> stringResource(CommonStrings.common_video_quality_high_description) } ListItem( - headlineContent = { + content = { Text( text = title, style = ElementTheme.typography.fontBodyLgMedium, @@ -301,7 +301,7 @@ private fun ModerationAndSafety( } ) ListItem( - headlineContent = { Text(text = stringResource(R.string.screen_advanced_settings_show_media_timeline_always_hide)) }, + content = { Text(text = stringResource(R.string.screen_advanced_settings_show_media_timeline_always_hide)) }, leadingContent = ListItemContent.RadioButton( selected = state.mediaPreviewConfigState.timelineMediaPreviewValue == MediaPreviewValue.Off, compact = true @@ -312,7 +312,7 @@ private fun ModerationAndSafety( enabled = !state.mediaPreviewConfigState.setTimelineMediaPreviewAction.isLoading() ) ListItem( - headlineContent = { Text(text = stringResource(R.string.screen_advanced_settings_show_media_timeline_private_rooms)) }, + content = { Text(text = stringResource(R.string.screen_advanced_settings_show_media_timeline_private_rooms)) }, leadingContent = ListItemContent.RadioButton( selected = state.mediaPreviewConfigState.timelineMediaPreviewValue == MediaPreviewValue.Private, compact = true @@ -323,7 +323,7 @@ private fun ModerationAndSafety( enabled = !state.mediaPreviewConfigState.setTimelineMediaPreviewAction.isLoading() ) ListItem( - headlineContent = { Text(text = stringResource(R.string.screen_advanced_settings_show_media_timeline_always_show)) }, + content = { Text(text = stringResource(R.string.screen_advanced_settings_show_media_timeline_always_show)) }, leadingContent = ListItemContent.RadioButton( selected = state.mediaPreviewConfigState.timelineMediaPreviewValue == MediaPreviewValue.On, compact = true 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 669bcdc8ff..8bd3d32190 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 @@ -85,7 +85,7 @@ fun DeveloperSettingsView( if (state.isEnterpriseBuild) { PreferenceCategory(title = "Theme") { ListItem( - headlineContent = { + content = { Text("Change brand color") }, onClick = { @@ -93,7 +93,7 @@ fun DeveloperSettingsView( } ) ListItem( - headlineContent = { + content = { Text("Reset brand color") }, onClick = { @@ -108,7 +108,7 @@ fun DeveloperSettingsView( val cache = state.cacheSize PreferenceCategory(title = "Cache") { ListItem( - headlineContent = { Text("Database sizes") }, + content = { Text("Database sizes") }, supportingContent = { if (state.databaseSizes.isLoading()) { Text("Computing...") @@ -127,7 +127,7 @@ fun DeveloperSettingsView( } ) ListItem( - headlineContent = { + content = { Text("Vacuum stores") }, onClick = { @@ -135,7 +135,7 @@ fun DeveloperSettingsView( } ) ListItem( - headlineContent = { + content = { Text("Clear cache") }, trailingContent = if (state.cacheSize.isLoading() || state.clearCacheAction.isLoading()) { @@ -194,7 +194,7 @@ private fun SessionCategory(deviceId: DeviceId) { private fun MarkAllRoomsAsReadCategory(state: DeveloperSettingsState) { PreferenceCategory(title = "Room list") { ListItem( - headlineContent = { + content = { Text("Mark all rooms as read") }, supportingContent = { @@ -220,7 +220,7 @@ private fun MarkAllRoomsAsReadCategory(state: DeveloperSettingsState) { private fun NotificationCategory(onPushHistoryClick: () -> Unit) { PreferenceCategory(title = stringResource(id = R.string.screen_notification_settings_title)) { ListItem( - headlineContent = { + content = { Text(stringResource(R.string.troubleshoot_notifications_entry_point_push_history_title)) }, onClick = onPushHistoryClick, 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 61aa4e27ee..5e2314bebe 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 @@ -84,7 +84,7 @@ fun AppDeveloperSettingsView( } PreferenceCategory(title = "Showkase") { ListItem( - headlineContent = { + content = { Text("Open Showkase browser") }, onClick = onOpenShowkase @@ -95,7 +95,7 @@ fun AppDeveloperSettingsView( ) PreferenceCategory(title = "Crash") { ListItem( - headlineContent = { + content = { Text("Crash the app 💥") }, onClick = { error("This crash is a test.") } 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 2009970448..9ede5138cf 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 @@ -130,7 +130,7 @@ private fun NotificationSettingsContentView( if (systemSettings.appNotificationsEnabled && !systemSettings.systemNotificationsEnabled) { ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.NotificationsOffSolid())), - headlineContent = { + content = { Text(stringResource(id = R.string.screen_notification_settings_system_notifications_turned_off)) }, supportingContent = { @@ -158,7 +158,7 @@ private fun NotificationSettingsContentView( PreferenceCategory { ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.VoiceCallSolid())), - headlineContent = { + content = { Text(stringResource(id = R.string.full_screen_intent_banner_title)) }, supportingContent = { @@ -172,7 +172,7 @@ private fun NotificationSettingsContentView( } PreferenceCategory(title = stringResource(id = R.string.screen_notification_settings_notification_section_title)) { ListItem( - headlineContent = { + content = { Text(stringResource(id = R.string.screen_notification_settings_group_chats)) }, supportingContent = { @@ -181,7 +181,7 @@ private fun NotificationSettingsContentView( onClick = onGroupChatsClick ) ListItem( - headlineContent = { + content = { Text(stringResource(id = R.string.screen_notification_settings_direct_chats)) }, supportingContent = { @@ -218,7 +218,7 @@ private fun NotificationSettingsContentView( } PreferenceCategory(title = stringResource(id = R.string.troubleshoot_notifications_entry_point_section)) { ListItem( - headlineContent = { + content = { Text(stringResource(id = R.string.troubleshoot_notifications_entry_point_title)) }, onClick = onTroubleshootNotificationsClick @@ -227,7 +227,7 @@ private fun NotificationSettingsContentView( if (state.showAdvancedSettings) { PreferenceCategory(title = stringResource(id = CommonStrings.common_advanced_settings)) { ListItem( - headlineContent = { + content = { Text(text = stringResource(id = R.string.screen_advanced_settings_push_provider_android)) }, trailingContent = when (state.currentPushDistributor) { @@ -296,7 +296,7 @@ private fun SoundsPreferenceCategory(state: NotificationSettingsState) { } } ListItem( - headlineContent = { Text(stringResource(id = R.string.screen_notification_settings_message_sound_label)) }, + content = { Text(stringResource(id = R.string.screen_notification_settings_message_sound_label)) }, supportingContent = { Text(state.messageSound.displayName) }, onClick = { state.eventSink(NotificationSettingsEvents.ShowMessageSoundDialog) }, ) @@ -323,7 +323,7 @@ private fun SoundsPreferenceCategory(state: NotificationSettingsState) { } } ListItem( - headlineContent = { Text(stringResource(id = R.string.screen_notification_settings_call_ringtone_label)) }, + content = { Text(stringResource(id = R.string.screen_notification_settings_call_ringtone_label)) }, supportingContent = { Text(state.callRingtone.displayName) }, onClick = { state.eventSink(NotificationSettingsEvents.ShowCallRingtoneDialog) }, ) @@ -418,7 +418,7 @@ private fun SoundCopyErrorRow( modifier = Modifier .background(ElementTheme.colors.bgSubtleSecondary) .semantics { liveRegion = LiveRegionMode.Polite }, - headlineContent = { + content = { Text( text = stringResource(R.string.screen_notification_settings_sound_set_sound_error_title), style = ElementTheme.typography.fontBodyMdRegular, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt index f7fc251eeb..ac4ac3ad34 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/DefaultNotificationSettingOption.kt @@ -40,7 +40,7 @@ fun DefaultNotificationSettingOption( } ListItem( modifier = modifier, - headlineContent = { Text(title) }, + content = { Text(title) }, supportingContent = subtitle?.let { { Text(it) } }, trailingContent = ListItemContent.RadioButton(selected = isSelected), onClick = { onSelectOption(mode) }, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt index 3b46ae737e..24da141a48 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt @@ -88,7 +88,7 @@ fun EditDefaultNotificationSettingView( null -> "" } ListItem( - headlineContent = { + content = { val roomName = summary.name Text( text = roomName ?: stringResource(id = CommonStrings.common_no_room_name), 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 104ee7e551..5727712bc3 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 @@ -182,7 +182,7 @@ private fun ColumnScope.MultiAccountSection( } ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Plus())), - headlineContent = { + content = { Text(stringResource(CommonStrings.common_add_another_account)) }, onClick = onAddAccountClick, @@ -201,18 +201,18 @@ private fun ColumnScope.ManageAppSection( onSecureBackupClick: () -> Unit, ) { ListItem( - headlineContent = { Text(stringResource(id = R.string.screen_notification_settings_title)) }, + content = { Text(stringResource(id = R.string.screen_notification_settings_title)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Notifications())), onClick = onOpenNotificationSettings, ) ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.common_screen_lock)) }, + content = { Text(stringResource(id = CommonStrings.common_screen_lock)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Lock())), onClick = onOpenLockScreenSettings, ) if (state.showSecureBackup) { ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.common_encryption)) }, + content = { Text(stringResource(id = CommonStrings.common_encryption)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Key())), trailingContent = ListItemContent.Badge.takeIf { state.showSecureBackupBadge }, onClick = onSecureBackupClick, @@ -230,7 +230,7 @@ private fun ColumnScope.ManageAccountSection( ) { state.accountManagementUrl?.let { url -> ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.action_manage_account_and_devices)) }, + content = { 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) }, @@ -238,14 +238,14 @@ private fun ColumnScope.ManageAccountSection( } if (state.showLinkNewDevice) { ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.common_link_new_device)) }, + content = { Text(stringResource(id = CommonStrings.common_link_new_device)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Devices())), onClick = onLinkNewDeviceClick, ) } if (state.showBlockedUsersItem) { ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.common_blocked_users)) }, + content = { Text(stringResource(id = CommonStrings.common_blocked_users)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Block())), onClick = onOpenBlockedUsers, trailingContent = ListItemContent.Text(state.nbOfBlockedUsers.toString()), @@ -269,46 +269,46 @@ private fun ColumnScope.GeneralSection( onDeactivateClick: () -> Unit, ) { ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.common_advanced_settings)) }, + content = { 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)) }, + content = { 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)) }, + content = { Text(stringResource(id = CommonStrings.common_about)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Info())), onClick = onOpenAbout, ) if (state.canReportBug) { ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.common_report_a_problem)) }, + content = { Text(stringResource(id = CommonStrings.common_report_a_problem)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ChatProblem())), onClick = onOpenRageShake ) } if (state.showAnalyticsSettings) { ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.common_analytics)) }, + content = { Text(stringResource(id = CommonStrings.common_analytics)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Chart())), onClick = onOpenAnalytics, ) } HorizontalDivider() ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.action_signout)) }, + content = { Text(stringResource(id = CommonStrings.action_signout)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Close())), style = ListItemStyle.Destructive, onClick = onSignOutClick, ) if (state.canDeactivateAccount) { ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.action_delete_account)) }, + content = { Text(stringResource(id = CommonStrings.action_delete_account)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Delete())), style = ListItemStyle.Destructive, onClick = onDeactivateClick, @@ -340,7 +340,7 @@ private fun ColumnScope.Footer( @Composable private fun DeveloperPreferencesView(onOpenDeveloperSettings: () -> Unit) { ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.common_developer_options)) }, + content = { Text(stringResource(id = CommonStrings.common_developer_options)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Code())), onClick = onOpenDeveloperSettings ) diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesView.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesView.kt index 7ea35308e9..a227d0ffcf 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesView.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesView.kt @@ -56,7 +56,7 @@ fun RageshakePreferencesView( ) } else { ListItem( - headlineContent = { + content = { Text("Rageshaking is not supported by your device") }, ) 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 36b407a669..fede373627 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 @@ -101,7 +101,7 @@ fun BugReportView( Spacer(modifier = Modifier.height(16.dp)) PreferenceDivider() ListItem( - headlineContent = { + content = { Text(stringResource(id = R.string.screen_bug_report_view_logs)) }, enabled = isFormEnabled, diff --git a/features/reportroom/impl/src/main/kotlin/io/element/android/features/reportroom/impl/ReportRoomView.kt b/features/reportroom/impl/src/main/kotlin/io/element/android/features/reportroom/impl/ReportRoomView.kt index 4ab1a51336..a754825dcc 100644 --- a/features/reportroom/impl/src/main/kotlin/io/element/android/features/reportroom/impl/ReportRoomView.kt +++ b/features/reportroom/impl/src/main/kotlin/io/element/android/features/reportroom/impl/ReportRoomView.kt @@ -108,7 +108,7 @@ fun ReportRoomView( ListItem( modifier = Modifier.padding(end = 8.dp), - headlineContent = { + content = { Text(text = stringResource(CommonStrings.action_leave_room)) }, onClick = { 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 07d2711cc6..3cf29c18cf 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 @@ -62,7 +62,7 @@ fun RolesAndPermissionsView( stringResource(R.string.screen_room_roles_and_permissions_admins) } ListItem( - headlineContent = { Text(adminsTitle) }, + content = { Text(adminsTitle) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Admin())), trailingContent = state.adminCount?.let { adminCount -> ListItemContent.Text("$adminCount") @@ -70,7 +70,7 @@ fun RolesAndPermissionsView( onClick = { rolesAndPermissionsNavigator.openAdminList() }, ) ListItem( - headlineContent = { Text(stringResource(R.string.screen_room_roles_and_permissions_moderators)) }, + content = { Text(stringResource(R.string.screen_room_roles_and_permissions_moderators)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ChatProblem())), trailingContent = state.moderatorCount?.let { moderationCount -> ListItemContent.Text("$moderationCount") @@ -79,20 +79,20 @@ fun RolesAndPermissionsView( ) if (state.canSelfDemote) { ListItem( - headlineContent = { Text(stringResource(R.string.screen_room_roles_and_permissions_change_my_role)) }, + content = { Text(stringResource(R.string.screen_room_roles_and_permissions_change_my_role)) }, onClick = { state.eventSink(RolesAndPermissionsEvents.ChangeOwnRole) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Edit())) ) } HorizontalDivider() ListItem( - headlineContent = { Text(stringResource(R.string.screen_room_roles_and_permissions_permissions_header)) }, + content = { Text(stringResource(R.string.screen_room_roles_and_permissions_permissions_header)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Settings())), onClick = { rolesAndPermissionsNavigator.openEditPermissions() }, ) HorizontalDivider() ListItem( - headlineContent = { Text(stringResource(R.string.screen_room_roles_and_permissions_reset)) }, + content = { Text(stringResource(R.string.screen_room_roles_and_permissions_reset)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Delete())), onClick = { state.eventSink(RolesAndPermissionsEvents.ResetPermissions) }, style = ListItemStyle.Destructive, @@ -173,7 +173,7 @@ private fun ChangeOwnRoleBottomSheet( ) for (demoteAction in availableDemoteActions) { ListItem( - headlineContent = { Text(stringResource(demoteAction.titleRes)) }, + content = { Text(stringResource(demoteAction.titleRes)) }, onClick = { sheetState.hide(coroutineScope) { eventSink(RolesAndPermissionsEvents.DemoteSelfTo(demoteAction.role)) @@ -183,7 +183,7 @@ private fun ChangeOwnRoleBottomSheet( ) } ListItem( - headlineContent = { Text(stringResource(CommonStrings.action_cancel)) }, + content = { Text(stringResource(CommonStrings.action_cancel)) }, onClick = ::dismiss, ) } 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 412006feae..96dc3e25ba 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 @@ -202,7 +202,7 @@ fun RoomDetailsView( PreferenceCategory { if (state.hasNewContent) { ListItem( - headlineContent = { + content = { Text( text = stringResource(id = R.string.screen_roomlist_mark_as_read), style = MaterialTheme.typography.bodyLarge, @@ -225,7 +225,7 @@ fun RoomDetailsView( ) } else { ListItem( - headlineContent = { + content = { Text( text = stringResource(id = R.string.screen_roomlist_mark_as_unread), ) @@ -268,7 +268,7 @@ fun RoomDetailsView( } if (state.displayRolesAndPermissionsSettings) { ListItem( - headlineContent = { Text(stringResource(R.string.screen_room_details_roles_and_permissions)) }, + content = { Text(stringResource(R.string.screen_room_details_roles_and_permissions)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Admin())), onClick = openAdminSettings, ) @@ -317,7 +317,7 @@ fun RoomDetailsView( ) { ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Lock())), - headlineContent = { + content = { Text(stringResource(id = R.string.screen_room_details_encryption_enabled_title)) }, supportingContent = { @@ -345,7 +345,7 @@ fun RoomDetailsView( @Composable private fun KnockRequestsItem(knockRequestsCount: Int?, onKnockRequestsClick: () -> Unit) { ListItem( - headlineContent = { Text(stringResource(R.string.screen_room_details_requests_to_join_title)) }, + content = { Text(stringResource(R.string.screen_room_details_requests_to_join_title)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.AskToJoin())), trailingContent = if (knockRequestsCount == null || knockRequestsCount == 0) { null @@ -656,7 +656,7 @@ private fun TopicSection( if (roomTopic is RoomTopicState.CanAddTopic) { ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Plus())), - headlineContent = { + content = { Text(stringResource(id = R.string.screen_room_details_add_topic_title)) }, onClick = { @@ -687,7 +687,7 @@ private fun NotificationItem( stringResource(R.string.screen_room_details_notification_mode_custom) } ListItem( - headlineContent = { Text(text = stringResource(R.string.screen_room_details_notification_title)) }, + content = { Text(text = stringResource(R.string.screen_room_details_notification_title)) }, supportingContent = { Text(text = subtitle) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Notifications())), onClick = openRoomNotificationSettings, @@ -700,7 +700,7 @@ private fun SecurityAndPrivacyItem( modifier: Modifier = Modifier, ) { ListItem( - headlineContent = { Text(stringResource(R.string.screen_room_details_security_and_privacy_title)) }, + content = { Text(stringResource(R.string.screen_room_details_security_and_privacy_title)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Lock())), onClick = onClick, modifier = modifier, @@ -732,7 +732,7 @@ private fun ProfileItem( ) { ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.UserProfile())), - headlineContent = { Text(stringResource(id = R.string.screen_room_details_profile_row_title)) }, + content = { Text(stringResource(id = R.string.screen_room_details_profile_row_title)) }, trailingContent = when (verificationState) { UserProfileVerificationState.VERIFIED -> ListItemContent.Icon( iconSource = IconSource.Vector(CompoundIcons.Verified()), @@ -755,7 +755,7 @@ private fun MembersItem( openRoomMemberList: () -> Unit, ) { ListItem( - headlineContent = { Text(stringResource(CommonStrings.common_people)) }, + content = { Text(stringResource(CommonStrings.common_people)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.User())), trailingContent = if (hasVerificationViolations) { ListItemContent.Icon( @@ -774,7 +774,7 @@ private fun InviteItem( onClick: () -> Unit, ) { ListItem( - headlineContent = { Text(stringResource(R.string.screen_room_details_invite_title)) }, + content = { Text(stringResource(R.string.screen_room_details_invite_title)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.UserAdd())), onClick = onClick, ) @@ -787,7 +787,7 @@ private fun PinnedMessagesItem( ) { val analyticsService = LocalAnalyticsService.current ListItem( - headlineContent = { Text(stringResource(R.string.screen_room_details_pinned_events_row_title)) }, + content = { Text(stringResource(R.string.screen_room_details_pinned_events_row_title)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Pin())), trailingContent = if (pinnedMessagesCount == null) { @@ -809,7 +809,7 @@ private fun PollsItem( openPollHistory: () -> Unit, ) { ListItem( - headlineContent = { Text(stringResource(R.string.screen_polls_history_title)) }, + content = { Text(stringResource(R.string.screen_polls_history_title)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Polls())), onClick = openPollHistory, ) @@ -820,7 +820,7 @@ private fun MediaGalleryItem( onClick: () -> Unit, ) { ListItem( - headlineContent = { Text(stringResource(R.string.screen_room_details_media_gallery_title)) }, + content = { Text(stringResource(R.string.screen_room_details_media_gallery_title)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Image())), onClick = onClick, ) @@ -840,7 +840,7 @@ private fun OtherActionsSection( } if (canReportRoom) { ListItem( - headlineContent = { + content = { Text(stringResource(CommonStrings.action_report_room)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ChatProblem())), @@ -849,7 +849,7 @@ private fun OtherActionsSection( ) } ListItem( - headlineContent = { + content = { Text(stringResource(CommonStrings.action_leave_room)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Leave())), @@ -868,7 +868,7 @@ private fun DebugInfoSection( PreferenceCategory { val toastMessage = stringResource(CommonStrings.common_copied_to_clipboard) ListItem( - headlineContent = { + content = { Text("Internal room ID") }, supportingContent = { @@ -888,7 +888,7 @@ private fun DebugInfoSection( }, ) ListItem( - headlineContent = { + content = { Text("Room version") }, supportingContent = { diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt index 8ff1be538f..cee23e6ba1 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsOption.kt @@ -40,7 +40,7 @@ fun RoomNotificationSettingsOption( ListItem( modifier = modifier, enabled = enabled, - headlineContent = { Text(title) }, + content = { Text(title) }, supportingContent = subtitle?.let { { Text(it) } }, trailingContent = ListItemContent.RadioButton(selected = isSelected), onClick = { onSelectOption(roomNotificationSettingsItem) }, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/UserDefinedRoomNotificationSettingsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/UserDefinedRoomNotificationSettingsView.kt index 3e4e9e773e..1721c9925c 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/UserDefinedRoomNotificationSettingsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/UserDefinedRoomNotificationSettingsView.kt @@ -66,7 +66,7 @@ fun UserDefinedRoomNotificationSettingsView( } ListItem( - headlineContent = { Text(stringResource(R.string.screen_room_notification_settings_edit_remove_setting)) }, + content = { Text(stringResource(R.string.screen_room_notification_settings_edit_remove_setting)) }, style = ListItemStyle.Destructive, onClick = { state.eventSink(RoomNotificationSettingsEvent.DeleteCustomNotification) 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 22f7439b2a..a5e0ac274f 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 @@ -301,7 +301,7 @@ private fun RoomMemberActionsBottomSheet( when (val action = actionState.action) { is ModerationAction.DisplayProfile -> { ListItem( - headlineContent = { Text(stringResource(R.string.screen_bottom_sheet_manage_room_member_member_user_info)) }, + content = { Text(stringResource(R.string.screen_bottom_sheet_manage_room_member_member_user_info)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.UserProfile())), onClick = { coroutineScope.launch { @@ -314,7 +314,7 @@ private fun RoomMemberActionsBottomSheet( } is ModerationAction.KickUser -> { ListItem( - headlineContent = { Text(stringResource(R.string.screen_bottom_sheet_manage_room_member_remove)) }, + content = { Text(stringResource(R.string.screen_bottom_sheet_manage_room_member_remove)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Close())), style = ListItemStyle.Destructive, onClick = { @@ -328,7 +328,7 @@ private fun RoomMemberActionsBottomSheet( } is ModerationAction.BanUser -> { ListItem( - headlineContent = { Text(stringResource(R.string.screen_bottom_sheet_manage_room_member_ban)) }, + content = { Text(stringResource(R.string.screen_bottom_sheet_manage_room_member_ban)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Block())), style = ListItemStyle.Destructive, onClick = { @@ -342,7 +342,7 @@ private fun RoomMemberActionsBottomSheet( } is ModerationAction.UnbanUser -> { ListItem( - headlineContent = { Text(stringResource(R.string.screen_bottom_sheet_manage_room_member_unban)) }, + content = { Text(stringResource(R.string.screen_bottom_sheet_manage_room_member_unban)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Restart())), style = ListItemStyle.Destructive, onClick = { diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootView.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootView.kt index 0aff81aafa..626a162152 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootView.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/root/SecureBackupRootView.kt @@ -55,7 +55,7 @@ fun SecureBackupRootView( snackbarHost = { SnackbarHost(snackbarHostState) }, ) { ListItem( - headlineContent = { + content = { Text( text = stringResource(id = R.string.screen_chat_backup_key_backup_title), ) @@ -76,7 +76,7 @@ fun SecureBackupRootView( // Disable / Enable key storage ListItem( - headlineContent = { + content = { Text( text = stringResource(id = R.string.screen_chat_backup_key_storage_toggle_title), ) @@ -137,7 +137,7 @@ fun SecureBackupRootView( RecoveryState.WAITING_FOR_SYNC -> Unit RecoveryState.DISABLED -> { ListItem( - headlineContent = { + content = { Text( text = stringResource(id = R.string.screen_chat_backup_recovery_action_setup), ) @@ -161,7 +161,7 @@ fun SecureBackupRootView( } RecoveryState.ENABLED -> { ListItem( - headlineContent = { + content = { Text( text = stringResource(id = R.string.screen_chat_backup_recovery_action_change), ) @@ -184,7 +184,7 @@ fun SecureBackupRootView( } RecoveryState.INCOMPLETE -> ListItem( - headlineContent = { + content = { Text( text = stringResource(id = R.string.screen_chat_backup_recovery_action_confirm), ) diff --git a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/manageauthorizedspaces/ManageAuthorizedSpacesView.kt b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/manageauthorizedspaces/ManageAuthorizedSpacesView.kt index 7208ee6115..514c38a3fd 100644 --- a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/manageauthorizedspaces/ManageAuthorizedSpacesView.kt +++ b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/manageauthorizedspaces/ManageAuthorizedSpacesView.kt @@ -140,7 +140,7 @@ private fun CheckableSpaceListItem( enabled: Boolean = true, ) { ListItem( - headlineContent = { + content = { Text(text = headlineText) }, supportingContent = supportingText?.let { diff --git a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyView.kt b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyView.kt index 45fce0ca01..43feb99611 100644 --- a/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyView.kt +++ b/features/securityandprivacy/impl/src/main/kotlin/io/element/android/features/securityandprivacy/impl/root/SecurityAndPrivacyView.kt @@ -235,7 +235,7 @@ private fun RoomAccessSection( modifier = modifier, ) { ListItem( - headlineContent = { Text(text = stringResource(R.string.screen_security_and_privacy_room_access_anyone_option_title)) }, + content = { Text(text = stringResource(R.string.screen_security_and_privacy_room_access_anyone_option_title)) }, supportingContent = { Text(text = stringResource(R.string.screen_security_and_privacy_room_access_anyone_option_description)) }, trailingContent = ListItemContent.RadioButton(selected = edited == SecurityAndPrivacyRoomAccess.Anyone), leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Public())), @@ -243,7 +243,7 @@ private fun RoomAccessSection( ) if (state.showSpaceMemberOption) { ListItem( - headlineContent = { Text(text = stringResource(R.string.screen_security_and_privacy_room_access_space_members_option_title)) }, + content = { Text(text = stringResource(R.string.screen_security_and_privacy_room_access_space_members_option_title)) }, supportingContent = { Text(text = state.spaceMemberDescription()) }, @@ -255,7 +255,7 @@ private fun RoomAccessSection( } if (state.showAskToJoinOption) { ListItem( - headlineContent = { Text(text = stringResource(R.string.screen_security_and_privacy_ask_to_join_option_title)) }, + content = { Text(text = stringResource(R.string.screen_security_and_privacy_ask_to_join_option_title)) }, supportingContent = { Text(text = stringResource(R.string.screen_security_and_privacy_ask_to_join_option_description)) }, trailingContent = ListItemContent.RadioButton(selected = edited == SecurityAndPrivacyRoomAccess.AskToJoin), onClick = { onSelectOption(SecurityAndPrivacyRoomAccess.AskToJoin) }, @@ -265,7 +265,7 @@ private fun RoomAccessSection( } if (state.showAskToJoinWithSpaceMemberOption) { ListItem( - headlineContent = { Text(text = stringResource(R.string.screen_security_and_privacy_ask_to_join_option_title)) }, + content = { Text(text = stringResource(R.string.screen_security_and_privacy_ask_to_join_option_title)) }, supportingContent = { Text(text = state.askToJoinWithSpaceMembersDescription()) }, trailingContent = ListItemContent.RadioButton(selected = edited is SecurityAndPrivacyRoomAccess.AskToJoinWithSpaceMember), onClick = ::onAskToJoinWithSpaceMembersClick, @@ -274,7 +274,7 @@ private fun RoomAccessSection( ) } ListItem( - headlineContent = { Text(text = stringResource(R.string.screen_security_and_privacy_room_access_invite_only_option_title)) }, + content = { Text(text = stringResource(R.string.screen_security_and_privacy_room_access_invite_only_option_title)) }, supportingContent = { Text(text = stringResource(R.string.screen_security_and_privacy_room_access_invite_only_option_description)) }, trailingContent = ListItemContent.RadioButton(selected = edited == SecurityAndPrivacyRoomAccess.InviteOnly), leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Lock())), @@ -330,7 +330,7 @@ private fun RoomAddressSection( modifier = modifier, ) { ListItem( - headlineContent = { + content = { Text(text = roomAddress ?: stringResource(R.string.screen_security_and_privacy_add_room_address_action)) }, trailingContent = if (roomAddress.isNullOrEmpty()) ListItemContent.Icon(IconSource.Vector(CompoundIcons.Plus())) else null, @@ -340,7 +340,7 @@ private fun RoomAddressSection( ) ListItem( - headlineContent = { Text(text = stringResource(R.string.screen_security_and_privacy_room_directory_visibility_toggle_title)) }, + content = { Text(text = stringResource(R.string.screen_security_and_privacy_room_directory_visibility_toggle_title)) }, supportingContent = { Text(text = stringResource(R.string.screen_security_and_privacy_room_directory_visibility_toggle_description, homeserverName)) }, @@ -387,7 +387,7 @@ private fun EncryptionSection( modifier = modifier, ) { ListItem( - headlineContent = { Text(text = stringResource(R.string.screen_security_and_privacy_encryption_toggle_title)) }, + content = { Text(text = stringResource(R.string.screen_security_and_privacy_encryption_toggle_title)) }, supportingContent = { Text(text = stringResource(R.string.screen_security_and_privacy_encryption_section_footer)) }, trailingContent = ListItemContent.Switch( checked = isRoomEncrypted, @@ -459,7 +459,7 @@ private fun HistoryVisibilityItem( SecurityAndPrivacyHistoryVisibility.WorldReadable -> stringResource(R.string.screen_security_and_privacy_room_history_anyone_option_title) } ListItem( - headlineContent = { Text(text = headlineText) }, + content = { Text(text = headlineText) }, trailingContent = ListItemContent.RadioButton(selected = isSelected, enabled = isEnabled), onClick = { onSelectOption(option) }, enabled = isEnabled, diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/settings/SpaceSettingsView.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/settings/SpaceSettingsView.kt index ace3a1f670..6237e443b0 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/settings/SpaceSettingsView.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/settings/SpaceSettingsView.kt @@ -169,7 +169,7 @@ private fun SecurityAndPrivacyItem( modifier: Modifier = Modifier, ) { ListItem( - headlineContent = { Text(stringResource(R.string.screen_space_settings_security_and_privacy)) }, + content = { Text(stringResource(R.string.screen_space_settings_security_and_privacy)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Lock())), onClick = onClick, modifier = modifier, @@ -183,7 +183,7 @@ private fun MembersItem( modifier: Modifier = Modifier, ) { ListItem( - headlineContent = { Text(stringResource(CommonStrings.common_people)) }, + content = { Text(stringResource(CommonStrings.common_people)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.User())), trailingContent = ListItemContent.Text(memberCount.toString()), onClick = onClick, @@ -197,7 +197,7 @@ private fun RolesAndPermissionsItem( modifier: Modifier = Modifier, ) { ListItem( - headlineContent = { Text(stringResource(R.string.screen_space_settings_roles_and_permissions)) }, + content = { Text(stringResource(R.string.screen_space_settings_roles_and_permissions)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Admin())), onClick = onClick, modifier = modifier, @@ -210,7 +210,7 @@ private fun LeaveSpaceItem( modifier: Modifier = Modifier, ) { ListItem( - headlineContent = { + content = { Text(stringResource(CommonStrings.action_leave_space)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Leave())), 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 a09a091834..c5a661dbac 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 @@ -137,7 +137,7 @@ private fun VerifyUserSection( ) { if (state.verificationState == UserProfileVerificationState.UNVERIFIED) { ListItem( - headlineContent = { Text(stringResource(CommonStrings.common_verify_user)) }, + content = { Text(stringResource(CommonStrings.common_verify_user)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Lock())), onClick = onVerifyClick, ) 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 62efbf1f0f..30f8c28607 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 @@ -80,14 +80,14 @@ private fun PreferenceBlockUser( } if (isBlocked.orFalse()) { ListItem( - headlineContent = { Text(stringResource(R.string.screen_dm_details_unblock_user)) }, + content = { Text(stringResource(R.string.screen_dm_details_unblock_user)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Block())), onClick = { if (!isLoading) eventSink(UserProfileEvents.UnblockUser(needsConfirmation = true)) }, trailingContent = if (isLoading) ListItemContent.Custom(loadingCurrentValue) else null, ) } else { ListItem( - headlineContent = { Text(stringResource(R.string.screen_dm_details_block_user)) }, + content = { Text(stringResource(R.string.screen_dm_details_block_user)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Block())), style = ListItemStyle.Destructive, onClick = { if (!isLoading) eventSink(UserProfileEvents.BlockUser(needsConfirmation = true)) }, 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 2a6b4031ef..86cd5302c8 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 @@ -100,7 +100,7 @@ private fun ItemRow( Item.Parent -> { ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(Icons.Outlined.SubdirectoryArrowLeft)), - headlineContent = { + content = { Text( text = "..", modifier = Modifier.padding(16.dp), @@ -113,7 +113,7 @@ private fun ItemRow( is Item.Folder -> { ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(Icons.Outlined.Folder)), - headlineContent = { + content = { Text( text = item.name, modifier = Modifier.padding(16.dp), @@ -126,7 +126,7 @@ private fun ItemRow( is Item.File -> { ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Document())), - headlineContent = { + content = { Text( text = item.name, modifier = Modifier.padding(16.dp), diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/AvatarListItem.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/AvatarListItem.kt index c6a85e9b85..c8f8b02b0f 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/AvatarListItem.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/AvatarListItem.kt @@ -45,7 +45,7 @@ fun AvatarListItem( ) { ListItem( modifier = modifier, - headlineContent = { Text(headline) }, + content = { Text(headline) }, supportingContent = supportingText?.let { @Composable { Text(it) } }, leadingContent = ListItemContent.Custom { _ -> Avatar( diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/CheckboxListItem.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/CheckboxListItem.kt index 4775b91720..701e1b7eaf 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/CheckboxListItem.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/CheckboxListItem.kt @@ -28,7 +28,7 @@ fun CheckboxListItem( ) { ListItem( modifier = modifier, - headlineContent = { Text(headline) }, + content = { Text(headline) }, supportingContent = supportingText?.let { @Composable { Text(it) } }, leadingContent = ListItemContent.Checkbox( checked = checked, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/MultipleSelectionListItem.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/MultipleSelectionListItem.kt index f314f17008..cdd0811aec 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/MultipleSelectionListItem.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/MultipleSelectionListItem.kt @@ -68,7 +68,7 @@ fun MultipleSelectionListItem( ListItem( modifier = modifier, - headlineContent = { Text(text = headline) }, + content = { Text(text = headline) }, supportingContent = decoratedSupportedText, leadingContent = leadingContent, trailingContent = trailingContent, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/RadioButtonListItem.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/RadioButtonListItem.kt index 70fb91e2e6..dc690294eb 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/RadioButtonListItem.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/RadioButtonListItem.kt @@ -28,7 +28,7 @@ fun RadioButtonListItem( ) { ListItem( modifier = modifier, - headlineContent = { Text(headline) }, + content = { Text(headline) }, supportingContent = supportingText?.let { @Composable { Text(it) } }, leadingContent = ListItemContent.RadioButton( selected = selected, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/SingleSelectionListItem.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/SingleSelectionListItem.kt index e07cda5e77..d9ce794938 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/SingleSelectionListItem.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/SingleSelectionListItem.kt @@ -67,7 +67,7 @@ fun SingleSelectionListItem( ListItem( modifier = modifier, - headlineContent = { Text(text = headline) }, + content = { Text(text = headline) }, supportingContent = decoratedSupportedText, leadingContent = leadingContent, trailingContent = trailingContent, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/SwitchListItem.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/SwitchListItem.kt index c5016bc5bc..f99b971b26 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/SwitchListItem.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/list/SwitchListItem.kt @@ -27,7 +27,7 @@ fun SwitchListItem( ) { ListItem( modifier = modifier, - headlineContent = { Text(headline) }, + content = { Text(headline) }, supportingContent = supportingText?.let { @Composable { Text(it) } }, leadingContent = leadingContent, trailingContent = ListItemContent.Switch( diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCheckbox.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCheckbox.kt index 6b4a8e1e0c..ff93bc9fa4 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCheckbox.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCheckbox.kt @@ -45,7 +45,7 @@ fun PreferenceCheckbox( iconResourceId = iconResourceId, showIconAreaIfNoIcon = showIconAreaIfNoIcon, ), - headlineContent = { + content = { Text( style = ElementTheme.typography.fontBodyLgRegular, text = title, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceDropdown.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceDropdown.kt index 5fcbcab475..1072dd41d5 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceDropdown.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceDropdown.kt @@ -66,7 +66,7 @@ fun PreferenceDropdown( iconResourceId = iconResourceId, showIconAreaIfNoIcon = showIconAreaIfNoIcon, ), - headlineContent = { + content = { Text( style = ElementTheme.typography.fontBodyLgRegular, modifier = Modifier.fillMaxWidth(), diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceRow.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceRow.kt index efc36544b9..9762ca6c18 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceRow.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceRow.kt @@ -30,7 +30,7 @@ fun PreferenceRow( ) { ListItem( modifier = modifier, - headlineContent = { + content = { Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSlide.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSlide.kt index 671eb5bf3f..5ff97ef37f 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSlide.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSlide.kt @@ -46,7 +46,7 @@ fun PreferenceSlide( iconResourceId = iconResourceId, showIconAreaIfNoIcon = showIconAreaIfNoIcon, ), - headlineContent = { + content = { Column { Text( style = ElementTheme.typography.fontBodyLgRegular, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt index 4545dbdf3e..bf4b76ba81 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt @@ -44,7 +44,7 @@ fun PreferenceSwitch( iconResourceId = iconResourceId, showIconAreaIfNoIcon = showIconAreaIfNoIcon, ), - headlineContent = { + content = { Text( style = ElementTheme.typography.fontBodyLgRegular, text = title, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceTextField.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceTextField.kt index c67b4c857f..ad65ac4d8c 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceTextField.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceTextField.kt @@ -42,7 +42,7 @@ fun PreferenceTextField( ListItem( modifier = modifier, - headlineContent = { Text(headline) }, + content = { Text(headline) }, supportingContent = valueToDisplay?.let { @Composable { Text(it) } }, trailingContent = trailingContent, style = style, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListItem.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListItem.kt index bbc97301dd..2e1c5146b4 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListItem.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListItem.kt @@ -35,20 +35,19 @@ import io.element.android.libraries.designsystem.preview.PreviewGroup /** * A List Item component to be used in lists and menus with simple layouts, matching the Material 3 guidelines. - * @param headlineContent The main content of the list item, usually a text. * @param modifier The modifier to be applied to the list item. - * @param supportingContent The content to be displayed below the headline content. - * @param leadingContent The content to be displayed before the headline content. - * @param trailingContent The content to be displayed after the headline content. + * @param supportingContent The content to be displayed below the content. + * @param leadingContent The content to be displayed before the content. + * @param trailingContent The content to be displayed after the content. * @param style The style to use for the list item. This may change the color and text styles of the contents. [ListItemStyle.Default] is used by default. - * @param enabled Whether the list item is enabled. When disabled, will change the color of the headline content and the leading content to use disabled tokens. + * @param enabled Whether the list item is enabled. When disabled, will change the color of the content and the leading content to use disabled tokens. * @param alwaysClickable Whether the list item should always be clickable, even when disabled. * @param onClick The callback to be called when the list item is clicked. + * @param content The main content of the list item, usually a text. */ @Suppress("LongParameterList") @Composable fun ListItem( - headlineContent: @Composable () -> Unit, modifier: Modifier = Modifier, supportingContent: @Composable (() -> Unit)? = null, leadingContent: ListItemContent? = null, @@ -57,19 +56,19 @@ fun ListItem( enabled: Boolean = true, alwaysClickable: Boolean = false, onClick: (() -> Unit)? = null, + content: @Composable () -> Unit, ) { val colors = ListItemDefaults.colors( containerColor = Color.Transparent, - headlineColor = style.headlineColor(), + headlineColor = style.contentColor(), leadingIconColor = style.leadingIconColor(), trailingIconColor = style.trailingIconColor(), supportingColor = style.supportingTextColor(), - disabledHeadlineColor = ListItemDefaultColors.headlineDisabled, + disabledHeadlineColor = ListItemDefaultColors.contentDisabled, disabledLeadingIconColor = ListItemDefaultColors.iconDisabled, disabledTrailingIconColor = ListItemDefaultColors.iconDisabled, ) ListItem( - headlineContent = headlineContent, modifier = modifier, supportingContent = supportingContent, leadingContent = leadingContent, @@ -78,25 +77,25 @@ fun ListItem( enabled = enabled, alwaysClickable = alwaysClickable, onClick = onClick, + content = content, ) } /** * A List Item component to be used in lists and menus with simple layouts, matching the Material 3 guidelines. - * @param headlineContent The main content of the list item, usually a text. * @param colors The colors to use for the list item. You can use [ListItemDefaults.colors] to create this. * @param modifier The modifier to be applied to the list item. - * @param supportingContent The content to be displayed below the headline content. - * @param leadingContent The content to be displayed before the headline content. - * @param trailingContent The content to be displayed after the headline content. - * @param enabled Whether the list item is enabled. When disabled, will change the color of the headline content and the leading content to use disabled tokens. + * @param supportingContent The content to be displayed below the content. + * @param leadingContent The content to be displayed before the content. + * @param trailingContent The content to be displayed after the content. + * @param enabled Whether the list item is enabled. When disabled, will change the color of the content and the leading content to use disabled tokens. * @param alwaysClickable Whether the list item should always be clickable, even when disabled. * @param onClick The callback to be called when the list item is clicked. + * @param content The main content of the list item, usually a text. */ @Suppress("LongParameterList") @Composable fun ListItem( - headlineContent: @Composable () -> Unit, colors: ListItemColors, modifier: Modifier = Modifier, supportingContent: @Composable (() -> Unit)? = null, @@ -105,19 +104,20 @@ fun ListItem( enabled: Boolean = true, alwaysClickable: Boolean = false, onClick: (() -> Unit)? = null, + content: @Composable () -> Unit, ) { // We cannot just pass the disabled colors, they must be set manually: https://issuetracker.google.com/issues/280480132 - val headlineColor = if (enabled) colors.contentColor else colors.disabledContentColor + val contentColor = if (enabled) colors.contentColor else colors.disabledContentColor val supportingColor = if (enabled) colors.supportingContentColor else colors.disabledContentColor.copy(alpha = 0.80f) val leadingContentColor = if (enabled) colors.leadingContentColor else colors.disabledLeadingContentColor val trailingContentColor = if (enabled) colors.trailingContentColor else colors.disabledTrailingContentColor - val decoratedHeadlineContent: @Composable () -> Unit = { + val decoratedContent: @Composable () -> Unit = { CompositionLocalProvider( LocalTextStyle provides ElementTheme.typography.fontBodyLgRegular, - LocalContentColor provides headlineColor, + LocalContentColor provides contentColor, ) { - headlineContent() + content() } } val decoratedSupportingContent: (@Composable () -> Unit)? = supportingContent?.let { content -> @@ -151,7 +151,6 @@ fun ListItem( } androidx.compose.material3.ListItem( - headlineContent = decoratedHeadlineContent, modifier = if (onClick != null) { Modifier .clickable(enabled = enabled || alwaysClickable, onClick = onClick) @@ -169,8 +168,8 @@ fun ListItem( leadingContent = decoratedLeadingContent, trailingContent = decoratedTrailingContent, colors = colors, - tonalElevation = 0.dp, - shadowElevation = 0.dp, + elevation = ListItemDefaults.elevation(elevation = 0.dp), + content = decoratedContent, ) } @@ -223,8 +222,8 @@ sealed interface ListItemStyle { data object Destructive : ListItemStyle @Composable - fun headlineColor() = when (this) { - Default, Primary -> ListItemDefaultColors.headline + fun contentColor() = when (this) { + Default, Primary -> ListItemDefaultColors.content Destructive -> ElementTheme.colors.textCriticalPrimary } @@ -251,8 +250,8 @@ sealed interface ListItemStyle { } object ListItemDefaultColors { - val headline: Color @Composable get() = ElementTheme.colors.textPrimary - val headlineDisabled: Color @Composable get() = ElementTheme.colors.textDisabled + val content: Color @Composable get() = ElementTheme.colors.textPrimary + val contentDisabled: Color @Composable get() = ElementTheme.colors.textDisabled val supportingText: Color @Composable get() = ElementTheme.materialColors.onSurfaceVariant val leadingIcon: Color @Composable get() = ElementTheme.colors.iconSecondary val trailingIcon: Color @Composable get() = ElementTheme.colors.iconPrimary @@ -260,11 +259,11 @@ object ListItemDefaultColors { val colors: ListItemColors @Composable get() = ListItemDefaults.colors( - headlineColor = headline, + headlineColor = content, supportingColor = supportingText, leadingIconColor = leadingIcon, trailingIconColor = trailingIcon, - disabledHeadlineColor = headlineDisabled, + disabledHeadlineColor = contentDisabled, disabledLeadingIconColor = iconDisabled, disabledTrailingIconColor = iconDisabled, ) @@ -523,7 +522,7 @@ private object PreviewItems { ) { EnabledDisabledElementThemedPreview { ListItem( - headlineContent = headline(), + content = content(), supportingContent = text(), leadingContent = leadingContent, trailingContent = trailingContent, @@ -543,7 +542,7 @@ private object PreviewItems { ) { EnabledDisabledElementThemedPreview { ListItem( - headlineContent = headline(), + content = content(), supportingContent = textSingleLine(), leadingContent = leadingContent, trailingContent = trailingContent, @@ -563,7 +562,7 @@ private object PreviewItems { ) { EnabledDisabledElementThemedPreview { ListItem( - headlineContent = headline(), + content = content(), leadingContent = leadingContent, trailingContent = trailingContent, enabled = it, @@ -574,7 +573,7 @@ private object PreviewItems { } @Composable - fun headline() = @Composable { + fun content() = @Composable { Text("List item") } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSupportingText.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSupportingText.kt index 4be53ddb39..b4f374cf4a 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSupportingText.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSupportingText.kt @@ -134,7 +134,7 @@ internal fun ListSupportingTextNoPaddingPreview() { internal fun ListSupportingTextDefaultPaddingPreview() { ElementThemedPreview { Column { - ListItem(headlineContent = { Text("A title") }) + ListItem(content = { Text("A title") }) ListSupportingText( text = "Supporting line text lorem ipsum dolor sit amet, consectetur. Read more", contentPadding = ListSupportingTextDefaults.Padding.Default, @@ -149,7 +149,7 @@ internal fun ListSupportingTextSmallPaddingPreview() { ElementThemedPreview { Column { ListItem( - headlineContent = { Text("A title") }, + content = { Text("A title") }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ShareAndroid())) ) ListSupportingText( @@ -165,7 +165,7 @@ internal fun ListSupportingTextSmallPaddingPreview() { internal fun ListSupportingTextLargePaddingPreview() { ElementThemedPreview { Column { - ListItem(headlineContent = { Text("A title") }, leadingContent = ListItemContent.Switch(checked = true)) + ListItem(content = { Text("A title") }, leadingContent = ListItemContent.Switch(checked = true)) ListSupportingText( text = "Supporting line text lorem ipsum dolor sit amet, consectetur. Read more", contentPadding = ListSupportingTextDefaults.Padding.LargeLeadingContent, @@ -179,7 +179,7 @@ internal fun ListSupportingTextLargePaddingPreview() { internal fun ListSupportingTextCustomPaddingPreview() { ElementThemedPreview { Column { - ListItem(headlineContent = { Text("A title") }) + ListItem(content = { Text("A title") }) ListSupportingText( text = "Supporting line text lorem ipsum dolor sit amet, consectetur. Read more", contentPadding = ListSupportingTextDefaults.Padding.Custom(24.dp), 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 5a9e56829c..e3f6478b76 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 @@ -96,7 +96,7 @@ private fun AvatarActionBottomSheetContent( ) { action -> ListItem( modifier = Modifier.clickable { onActionClick(action) }, - headlineContent = { + content = { Text( text = stringResource(action.titleResId), style = ElementTheme.typography.fontBodyLgRegular, 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 c9e11b65bc..35d056dc39 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 @@ -113,14 +113,14 @@ fun MediaDetailsBottomSheet( } ListItem( leadingContent = icon, - headlineContent = { Text(wording) }, + content = { Text(wording) }, onClick = { onOpenWith(state.eventId) } ) ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.VisibilityOn())), - headlineContent = { Text(stringResource(CommonStrings.action_view_in_timeline)) }, + content = { Text(stringResource(CommonStrings.action_view_in_timeline)) }, onClick = { onViewInTimeline(state.eventId) } @@ -128,14 +128,14 @@ fun MediaDetailsBottomSheet( if (state.fromGallery) { ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ShareAndroid())), - headlineContent = { Text(stringResource(CommonStrings.action_share)) }, + content = { Text(stringResource(CommonStrings.action_share)) }, onClick = { onShare(state.eventId) } ) ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Download())), - headlineContent = { Text(stringResource(CommonStrings.action_download)) }, + content = { Text(stringResource(CommonStrings.action_download)) }, onClick = { onDownload(state.eventId) } @@ -143,7 +143,7 @@ fun MediaDetailsBottomSheet( } ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Forward())), - headlineContent = { Text(stringResource(CommonStrings.action_forward)) }, + content = { Text(stringResource(CommonStrings.action_forward)) }, onClick = { onForward(state.eventId) } @@ -152,7 +152,7 @@ fun MediaDetailsBottomSheet( HorizontalDivider() ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Delete())), - headlineContent = { Text(stringResource(CommonStrings.action_delete_file)) }, + content = { Text(stringResource(CommonStrings.action_delete_file)) }, style = ListItemStyle.Destructive, onClick = { onDelete(state.eventId) diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposerLinkDialog.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposerLinkDialog.kt index 3ee191d724..9932dbaea1 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposerLinkDialog.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposerLinkDialog.kt @@ -179,7 +179,7 @@ private fun EditLinkDialog( } item { ListItem( - headlineContent = { + content = { Text( text = stringResource(R.string.rich_text_editor_remove_link), color = ElementTheme.colors.textCriticalPrimary diff --git a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsView.kt b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsView.kt index fa5e7078d2..4e0f89155d 100644 --- a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsView.kt +++ b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsView.kt @@ -68,7 +68,7 @@ private fun ColumnScope.TroubleshootTestView( val status = testState.status if ((status as? Status.Idle)?.visible == false) return ListItem( - headlineContent = { Text(text = testState.name) }, + content = { Text(text = testState.name) }, supportingContent = { Text(text = testState.description) }, trailingContent = when (status) { is Status.Idle -> null @@ -108,7 +108,7 @@ private fun ColumnScope.TroubleshootTestView( ) if (status is Status.Failure && status.hasQuickFix) { ListItem( - headlineContent = { }, + content = { }, trailingContent = ListItemContent.Custom { Button( text = status.quickFixButtonString ?: stringResource(id = R.string.troubleshoot_notifications_screen_quick_fix_action), @@ -137,7 +137,7 @@ private fun ColumnScope.TroubleshootNotificationsContent(state: TroubleshootNoti } when (state.testSuiteState.mainState) { AsyncAction.Uninitialized -> { - ListItem(headlineContent = { + ListItem(content = { Text( text = stringResource(id = R.string.troubleshoot_notifications_screen_notice) ) @@ -146,20 +146,20 @@ private fun ColumnScope.TroubleshootNotificationsContent(state: TroubleshootNoti } AsyncAction.Loading -> Unit is AsyncAction.Failure -> { - ListItem(headlineContent = { + ListItem(content = { Text(text = stringResource(id = R.string.troubleshoot_notifications_screen_failure)) }) RunTestButton(state = state) } is AsyncAction.Confirming -> { - ListItem(headlineContent = { + ListItem(content = { Text( text = stringResource(id = R.string.troubleshoot_notifications_screen_waiting) ) }) } is AsyncAction.Success -> { - ListItem(headlineContent = { + ListItem(content = { Text( text = stringResource(id = R.string.troubleshoot_notifications_screen_success) ) @@ -171,7 +171,7 @@ private fun ColumnScope.TroubleshootNotificationsContent(state: TroubleshootNoti @Composable private fun RunTestButton(state: TroubleshootNotificationsState) { ListItem( - headlineContent = { + content = { Button( text = stringResource( id = if (state.testSuiteState.mainState is AsyncAction.Failure) { diff --git a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/history/PushHistoryView.kt b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/history/PushHistoryView.kt index 7dfb8419dd..21e9c64139 100644 --- a/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/history/PushHistoryView.kt +++ b/libraries/troubleshoot/impl/src/main/kotlin/io/element/android/libraries/troubleshoot/impl/history/PushHistoryView.kt @@ -156,7 +156,7 @@ private fun PushHistoryContent( modifier = modifier.fillMaxWidth() ) { ListItem( - headlineContent = { Text("Total number of received push") }, + content = { Text("Total number of received push") }, trailingContent = ListItemContent.Text(state.pushCounter.toString()), ) LazyColumn( From c8c8971889a802c66c10de500089de87bb6fd469 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 9 Jul 2026 16:30:17 +0200 Subject: [PATCH 264/383] Fix detekt false positive --- .../designsystem/theme/components/ListItem.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListItem.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListItem.kt index 2e1c5146b4..c4aeb4582f 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListItem.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListItem.kt @@ -120,32 +120,32 @@ fun ListItem( content() } } - val decoratedSupportingContent: (@Composable () -> Unit)? = supportingContent?.let { content -> + val decoratedSupportingContent: (@Composable () -> Unit)? = supportingContent?.let { safeContent -> { CompositionLocalProvider( LocalTextStyle provides ElementTheme.typography.fontBodyMdRegular, LocalContentColor provides supportingColor, ) { - content() + safeContent() } } } - val decoratedLeadingContent: (@Composable () -> Unit)? = leadingContent?.let { content -> + val decoratedLeadingContent: (@Composable () -> Unit)? = leadingContent?.let { safeContent -> { CompositionLocalProvider( LocalContentColor provides leadingContentColor, ) { - content.View(isItemEnabled = enabled) + safeContent.View(isItemEnabled = enabled) } } } - val decoratedTrailingContent: (@Composable () -> Unit)? = trailingContent?.let { content -> + val decoratedTrailingContent: (@Composable () -> Unit)? = trailingContent?.let { safeContent -> { CompositionLocalProvider( LocalTextStyle provides ElementTheme.typography.fontBodyMdRegular, LocalContentColor provides trailingContentColor, ) { - content.View(isItemEnabled = enabled) + safeContent.View(isItemEnabled = enabled) } } } From e568f1ec7a5de35ce20c4afc62e8f567172f99f8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 6 Aug 2026 18:37:25 +0200 Subject: [PATCH 265/383] Fix deprecation warning on `androidx.compose.material3.ListItem` --- .../impl/developer/DeveloperSettingsView.kt | 2 +- .../developer/appsettings/AppDeveloperSettingsView.kt | 4 ++-- .../preferences/impl/userstatus/UserStatusView.kt | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) 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 8bd3d32190..2fd2137451 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 @@ -178,7 +178,7 @@ private fun SessionCategory(deviceId: DeviceId) { val toastMessage = stringResource(CommonStrings.common_copied_to_clipboard) val context = LocalContext.current ListItem( - headlineContent = { Text("DeviceId") }, + content = { Text("DeviceId") }, supportingContent = { Text(text = deviceId.value) }, onClick = { context.copyToClipboard( 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 5e2314bebe..a4f41edb4a 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 @@ -117,7 +117,7 @@ private fun GitCategory( val toastMessage = stringResource(CommonStrings.common_copied_to_clipboard) val context = LocalContext.current ListItem( - headlineContent = { Text("Git branch") }, + content = { Text("Git branch") }, supportingContent = { Text(text = gitBranch) }, onClick = { context.copyToClipboard( @@ -127,7 +127,7 @@ private fun GitCategory( } ) ListItem( - headlineContent = { Text("Git SHA") }, + content = { Text("Git SHA") }, supportingContent = { Text(text = gitSha) }, onClick = { context.copyToClipboard( diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt index f145ef76ca..19cc43d3d7 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/userstatus/UserStatusView.kt @@ -130,7 +130,7 @@ private fun EmptyStatusRow( modifier: Modifier = Modifier, ) { ListItem( - headlineContent = { + content = { Text( text = stringResource(R.string.screen_settings_user_status_placeholder), modifier = Modifier.padding(vertical = 16.dp), @@ -153,7 +153,7 @@ private fun CurrentStatusRow( is DisplayedStatus.InCall -> "🎧" to stringResource(CommonStrings.common_on_a_call) } ListItem( - headlineContent = { Text(text = text, modifier = Modifier.padding(vertical = 16.dp)) }, + content = { Text(text = text, modifier = Modifier.padding(vertical = 16.dp)) }, leadingContent = ListItemContent.Custom { EmojiText(emoji) }, trailingContent = ListItemContent.Custom({ IconButton( @@ -209,7 +209,7 @@ private fun UserStatusPickerBottomSheet( val predefinedUserStatus = UserStatus(emoji = predefined.emoji, text = label) val isSelected = currentRawStatus == predefinedUserStatus ListItem( - headlineContent = { Text(text = label) }, + content = { Text(text = label) }, leadingContent = ListItemContent.Custom { EmojiText(predefined.emoji) }, trailingContent = if (isSelected) { ListItemContent.Icon(IconSource.Vector(CompoundIcons.Check()), tintColor = ElementTheme.colors.iconAccentPrimary) @@ -224,7 +224,7 @@ private fun UserStatusPickerBottomSheet( ) } ListItem( - headlineContent = { + content = { Text(text = stringResource(R.string.screen_settings_user_status_custom)) }, leadingContent = ListItemContent.Custom { EmojiText("✏️") }, @@ -261,7 +261,7 @@ private fun CustomStatusInputRow( val focusRequester = remember { FocusRequester() } LaunchedEffect(Unit) { focusRequester.requestFocus() } ListItem( - headlineContent = { + content = { TextField( modifier = Modifier.focusRequester(focusRequester), state = textFieldState, From 87b56861e61a6d74f995951d5101b1734a810cdb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Aug 2026 18:38:21 +0200 Subject: [PATCH 266/383] Update dependency io.sentry:sentry-android to v8.51.0 (#7301) 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 0ca25f0636..965f5b9b58 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -230,7 +230,7 @@ color_picker = "io.mhssn:colorpicker:1.0.0" # Analytics posthog = "com.posthog:posthog-android:3.56.4" -sentry = "io.sentry:sentry-android:8.50.0" +sentry = "io.sentry:sentry-android:8.51.0" # main branch can be tested replacing the version with main-SNAPSHOT matrix_analytics_events = "com.github.matrix-org:matrix-analytics-events:0.37.0" From 73119273c2bef69962aee20b7dd28ddcc8f6e84d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Aug 2026 18:38:49 +0200 Subject: [PATCH 267/383] Update dependency org.maplibre.gl:android-sdk to v13.4.1 (#7305) 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 965f5b9b58..5adcf2984e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -215,7 +215,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.4.0" +maplibre = "org.maplibre.gl:android-sdk:13.4.1" maplibre_ktx = "org.maplibre.gl:android-sdk-ktx-v7:3.0.2" maplibre_compose = "org.maplibre.compose:maplibre-compose:0.13.1" maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:3.0.2" From d3f35cb90cc14333561a39bffbb7a02fc37a76b6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Aug 2026 18:39:06 +0200 Subject: [PATCH 268/383] Update dependency io.element.android:element-call-embedded to v0.23.0 (#7323) 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 5adcf2984e..b88514ba46 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -242,7 +242,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.22.0" +element_call_embedded = "io.element.android:element-call-embedded:0.23.0" # Auto services google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" } From e3ce557576880070a5e3be594d88a8356fc79596 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 09:08:52 +0200 Subject: [PATCH 269/383] Update metro to v1.4.0 (#7334) 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 b88514ba46..ef8f8025a1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -54,7 +54,7 @@ haze = "1.7.2" dependencyAnalysis = "3.18.0" # DI -metro = "1.3.2" +metro = "1.4.0" # Auto service autoservice = "1.1.1" From ed44cd776c9fabfce3b8e8c6cd77f8e37973efbd Mon Sep 17 00:00:00 2001 From: ElementBot <110224175+ElementBot@users.noreply.github.com> Date: Fri, 7 Aug 2026 08:12:21 +0100 Subject: [PATCH 270/383] Update Gradle Wrapper from 9.6.1 to 9.7.0 (#7335) Signed-off-by: gradle-update-robot Co-authored-by: gradle-update-robot --- gradle/wrapper/gradle-wrapper.jar | Bin 48462 -> 47505 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index b1b8ef56b44f16b14dc800fa8103a6d89abb526f..eddabd2eef8d94a5437d6168ff9c87a78ff725b3 100644 GIT binary patch delta 39079 zcmXt(}X*9-$vqRyg+4M6*I6`{n_)4-0DrW&l`u!}gMTBwyP!X>63$b2y9g z;(~-IG8UhkP$Q(emT4KjRY>foHo|f0EUEpn_(Vz^4iOq0SGVisX;M1dg7Q-rFZ>{L z*H_YIa`u7Jxi0t8me*Mq4qFrZ@<|407@6O_r$vwJr8uKLLZ<`XU_`LEO=XYFm;Kmt z{2aYQaP)!Febt$h0Ua z5A|38D|G`E3^B}4U^=r?hQg%OZD^aZZK0Kxs61N_Dhnl4EEQ@j%feP6(W=7lPN}%0 zq5M6TTRjSNPB!6pfxj3%Q8qY9=*HGFd=I%d0uR%F|2{kke8*#C?b_G~(DpB0YHOe% z)L?KJN!JD;t~ks8fSLD-X>owB3>ZM)#PM7O>;})-!di^Fto3Mb@29iC>;E=x^7~CI z5$~rll{RHJ;9r{ZS(9$1W~SpS+@M~_$tA!gRMmY2ZXv6+m2MLyGmnmFQLD3ZLCnKc zNRYmWW3+J`ua^|B>jdPWi{f~6dN8Ur*!*=-)$C*j36G8#LqHY?{FH~Zg_@twckNXJ zV13)tIWq3HLZHzN*rNQUc$8{2x8I|Z*hCjNn1Y5P(SoFgBzU$6ms}m-T-8n%1}(AQ z<7s*O9n!-o2I~w4;g1(km$|pL2qzO0(^BqkQxhIq9amCY3MX04b01t{_Sb0#gAx=4 z;$8D}If|B{IDhnywrX-L>0Df`Igd?Vfb>BgH#5}00ha|G2JwcCU2KjBNb=M8Gj?wPXUZv%_w6aEf}d5z0h>q$S0*x4IU=^tCALWM z2@-C!n9LlF`x)myO;Rm?t96G22LsDV`Ho=%F#1o1LJR54M)HN^uQhF zthADV5f}B{-kqLG{pnUaS?)<}X|UHtDz??_S#dWc=I>$j>tPzJ3uo{pwe`q=p>hD| z=)Q|>AjB>~`#`91>Q5(+8c>xFHkkjAu?mQ;uMEWAvF&8$Lk@?JN+UcPJ{m5yIvAwI z4eL2-O{2==t2L$lQ)$PI)oNs>Uu#kOo;O-*lN{V9$cd(Iciym?)$XCVs^_AbE?Hv2h?6nWB$x8MHP8=rrkpEI_cEk+Zb z;-~4)$5%6>M0_miQPZC@S}(8Pc#N2{kF_fZ*9<3bSYzMsNj7J|HouQOz_Vyml3!LK z5V={|E;6*Ue6-$+*8}aK*PQ*uEbR1WSVSCc@++s4NG5qp$7cojpCm$n!AsVD zd}nscp-$Di82c6>vcd1yEb?2(L@U*_!zfkCsI{eT1U~9*5qiL1-@uTdpWs@rJdo=3 zb}+PMkrGD;kG(brgMdT)-BiHn_^7xR9h`Hjx=wICd-^zIPKqD?vDJ`k{3EtAbNL~- zNTMu@%1L^!q2sego_WWVH4VJj<&avCa}uA_64l%BQO-1 zyXbQE*WFNjbHUK+MeC8}%2X*9;jWnjhr?Dz0q7S^0^;74**y|?5`TIAQ&(Iy-Iv@y zab>5N9%OFLp*&rm3yV71L1DK_BF%gv}tE+ z9|~`NuQHM1op*@E238B}MVFb^;>F*cbKqjjEV)zH$9eBL9{B;+9y38NpGOQ}8FvVS zCMtP+?+IiT3N}@ai_)>={0vayXv$mHe07btvQ*&Uc&;is@-LlD#bTE@wsF& z*LQ&w?DE}3%f3cS-MA@MY)K3W=*u%f_dB+@(0Igf8-*2?V{x%@vGH^O=|0>;t12^x z{T63fpxb1vB?C7L0eKakzxQ(GQkx$0X_@YR3&rJ7>}tKE_(pu^CT;UEl_#5G_#5+b zx08~KTc?$tcRPTA(v!opQ)^4k&{7rN%bpaUMH_oj0^1fYf&iU43YUA-s-Msv>v>rRS!<2Zy~ zp?BCHo0SxJCqa5>%!3hIk~j(|5y$FT>xybQ5{4r$ya3u+QWW%HQteIF>YDfCGCQZt zkS#M)2erRZ2*kfB2Q6*QUtVw2j#&rQu0;NRyLZ&lz_hdUmldNA<2?-*rwB)|ZS@R& zn4XXgIS0^uSnb$#&R4)KbU*20)L?!Nx!Q~LX9As5g@_ETc{k*hy3!z*3V82C3GXZ+ z4-ms(9N7v|Q`mrVmDgh#wZ3Gv?4Fb|(`R}(|v>1~A3`SC8__6m? z$;R9DZ)W5ud3Wd8hMWqCG6=(0u$gI?=LM^ip9>xWe`?fvA_`cxjxdov>N9$RqK2(gM4hvAkPIuhoUoJ zl|zY+5rqv4kBT{?v`t*ajgViFE0^`sGSJFJg~2@0yYZ6j-jv%zKEK~yI%BkAx(T}P z_xXT$+eL9@ii{Y!(bS6MCPMN%t<^XQw8{Uta^ZdYGn*d>zY85W=6XLAEx=C_6DZDk$hOQ zRGy~s3TZGp*x+xTwsi1Ge@Vbb45OxQyF#T`@@#Rj+v%cuQx(FM@CDJY;syV9b_F`6 z=U$DiS6bi3#}@iL>bB?D+tY0w!f0;nJ&yp47qU2E?nCoMI8G~>Gf>Ujg6F0YE)7OV z4YnT({?%4`A%#~G?&^E_^gBMp%AWUbCoF&gl~bP3DW^O?eM?~R>qBa6Lgh}hOr zD(3w4=xch2JKH9(jy$;vR3%rff=O+jXt!_$;GS+g41ma@#0YD?GO@%aK7o)MxpaP9TiFOsq%Su?bIBS9>v z(75MDRhy;S&Dt(x8yjws^+bpk38vj0Hf9;Wl9!ulvxbR=n+%7wM%#9k$qyXYmr4AE`7=1s}wPd4Rdxla*;v zNg1RATIneJ^v>2wWj>d1$VI|*ht2U-e^3qq&b$Mro|>j6>Nr)i2;AuDz*%d0o)ffG zsZ{3T7F%hkafU8=axAgmTuIb2@8$Wk+L9!dYPo&EIT7sNE}xJ`eL$C<4wn0pSV&~7SBHJ z6s&eHEU#76xv6dRW6?mP7X2ptqhIjPEpHxbYJN#mg>l9$CzU|ZWzR*0r=NbSk6VY} z%y5!VzNd7bki6B23Hw(^ae`;qz*itv!#6VLHp0y^=NaWMhg@E3yF?LkYQ`shI{YgE z7hm>CHC)VTXVFe?{L9#S{`_(E?A!7e>V+psxc@0d!k#+XCg4-tIeY_V3GI%~2X4vE zx=Up`;3i6SA>(x6cf7PG-U2Oot@(`{PQy!y!)m~M^Oc^uD@gL|tE|A z53iapviWQqk8`xlO)3!o0%Kt{F=s?;y3o$>gM{7EH~%wZjzh8+mfKtd%qt6a5wsAC z)leAq3UIp$0IU+Rm|f6GnxBz>O9ydj4qPY9n5kq{FTdmsZa=zS${r|jw3UW$7moCx zBPWjc<8A)wrLQV%)an?BQLgTXAui7%LEAdKb9h{Zi|0BtWs*ZBuZ?Wr*j-ognDXch zy}}^wywi!Q}s; zdiCxhn@mcuc2I>^HqNduX?P^8u0#Zt96ESiEs39L;ito>g#MH)PN$DU{xtm^r?C88 zL_&g`PBNwxqa>xy)Pyl9o(A8;3X92P7(ycMMe9`VRwvrFhGhV)?T&&OzD=7vh{gU6B=^?9D#Z4VvP{`N~Oi{bJsmazu9j>i|K{le*^?t z%61DUemA5bVMDMY6RAe)8hI%-2~UbT8z@=fWu8Aig3y-pJ&^FhilrPT?;3J>=HL zcvZ}F@>-f@eNUrz1Ky7oGnQ3TWsw*$ntU+v&Kw6AaU8uK2KXLHs4e?7mhS!f(`=mg zhnQUonNun^R|QCucFbaia=^6U=mjc79z&nfd7sY!WWl|05}xCcf>VyF`m}9X=%G!^PD&K?lW06 zh{gMj8(y71z`wzYIu)~^pD}4rm>9wQduj4_17I5Y3DSLxKspLI!3a(+Qk~D3zhJHO zOW&LUVvm@tVQY}tih`r$)$HHdB;`S$B(`UA(iLfIurW8 zb*6<<5pbrAp@#X%ywOyuJ3$?V5MRKwr7Ai>UV_d^-Hd8W`GnG*+s*{Rv2Z+tNhXcH zGfHBwi>?$1Ml#`B24$tdpR#$Ba}#LO-TU?T70MJ|0Wlv1Wo3b6iG0O7qNd8DQd|9? zQoErNIBryIPE#GjEXy20*G3`RKAjuh!qj9`4zT7sH;m4XkE&X7AJ|_C-*cNfH>a*q zLDw#uy;9&>pzO~}L~ckX&CO9(R<6nqG(`-FlUK6ePcwrDX2vjDTIF zw?0*y{orCIB9qanGPcb`G0cgSn(^(@0X?B;Km+rgG(n007zAbB^BQ)>5cYfMlBfuzv)I zYNj@7dx+4Qo#kP>YwCUUf&k31k36h=boBSOkWYk9*!s!FCcz!`OA%|jye{6EHtrwU zHn9kDG5;=fxyerP8)~`1aF>K|`TFsL0svM_8x=1^l6WQL z*-jF*J$_LOA~OC535b{_sLaH9Hwx{oq!w8pAmGOv`VjWXaqNN{y>aZR8 zw_o0*>p7h&Vb}o8e;>o-IE1#u9cYmK0 zPZ5qL6LATBH4(J{?%u3?Lf9V1ad=@v8%!NlsLU<*#T)b|YO+LDCRDIMOF*he6@PyO zraExgzWljNl|RxyW*^ljvLaB@4t#~?Gh8Ij*4FZORLzGZ8$Xj&mI?}C-778AC&GV% zS+V?eFE z404k5A!C!q0HD)g{O+iLnb*vKXLP_<_f|KkQI;fh<{t5V$`tKIAvP5yP-<~*DP!#9#4h%qd(t&^1g!!gp zEJNG1Pc8ZT;i>~IffYglQ9elcxaDx7l_giWLk)T!ab89|`t)bNx!;R7RAYTk7~)|R z@huDt-Iip=V4Exe+Tds=Uz&$q{Lj^v05nvMwXctduLrxpSNbgzua<1Km~jiE6 z=1b{UgbkH~zLMHZ>Zs{iD)m4CE(A_-pP0uWQS{;nW;2a3ovB;vn6qk=Qr__CHp3x} zr)j+$cWz(oymkTD9j12S&sX$ns_G|`XmRv~Jjyptv_=Hf`d6s`K1}L++IYynLXP=Y z$PNIfe`p;wIK2gPLXYuC32GRlnaL?3Dja+SQZ6kYnjV1qjkPeGeYITPh`TelMz6o=zUTpkg@G6i@;BmOodA0qG9Bgj)1d<9`4>*R~{>&Hnt6E3!poqgFMkco4vrAcen zt<6D`NvCUn9>@Kyrt`+1Wb4Vl;+C@o?N*c$&Bk{TYx~>EWa6zvMxo)AJP6vz8W81X z$By_PGhcDM&RUlyWm+j&{2m-)rOLt~BPdNEBIcj3TZ<)Vh1&jw*NI`M6d0UxcygZ& zKi`%oj*bUKhxkYlQVkBZBJLt7M)D@%5=-V3vkUd2Q?lk7P9S;f1Ruc6Hesq12(LZh zHg$ZjlWQ^I@vFr7hbZmOA;}niz;^rq&Q_im?nD}al2^7lI=xeL3;7>ChkUccCNGM5 zM<*%y&vyGi{f(h^n>V9Ef~I5Mw6f$lpX5L>$gBMohX8Su^oI?2_@8oQ3FH!iY0e0P zrnKfYdyC?SLQWKsbzFnRM1UfDM)^;AMwpuB zHvf7;8|43oe<}8P6#wpxSScNBD1aa>10M`6%ui&wOisu`I-D@6d06W15;gdircH5L zb-NUK1TNLsa*pzG(758yOprD+{2NRl2652daC6spx(WT$-z>s^5dISBzhrWj>U3z+ zoLv5yX?^*877qCQd()Z$7Qe>;gn79!x$ectK0dEzZC({s%#HRM)vPj{Ljqi%r)M%6 zWRZ3~SsI zm>eT@$3Z(DUF9#nm&RbRWW3H=PFjW_q<+-qOY=%wk7-o8C6ESQmEmz2cTu)^>_&V& z)+?U(&S9(H#I7}4T6PbeCP1g(8@Rl=I^@c1FjgiL32$*09bGu72ONunsqN@UYLrr& zDj#XPfZrf2!H8^^$YIwx>AJqPldwg+#2;j?+Si+9itTK1#)j*RIU)CvFYY48YctdJ z(3#R($l~yL;y~O``3L>-tZ%9KYk~C$onfk=0Z?OzgqQ#iMLJNgf)VeGz_bM$ym{ojbhl}Qu*cK{ zg9oa6F(iJ{Y2_c%n&+>TmL2jUB!N8JeoVr(x}K-1$Me^*;Gl9&_+g-BR%wnQCw&nq zn~Z^*n2hLL^oL!x{}&dIGOUfIn92d8#ARBi*&wQvbIFxCpqWw8$JQ7tj~9N1D@v!- zwYHKVi&9ucD0{EWu3fFxZqA>o=njn8F{xvv7bgsNfK@AAhn|zccmtZCTYV;jm7Go* zk9nwgGur+4o_?Cbf^HPE4(CLie6)rOyn#+Jee{IZIaMUJ1ZQ4sfJlU|3K(ApZS7K9 zUI045R?1ESz)kOs2!)*DK%{Z5U2~uc;2D3;VubplwLeoM`v510k#Oz_s)t&^F3S2@ zXuSw4TU_LoLafdDw62$Kz`Rr*m;UHa>a-CUQu}J7ZfhgyV;JK*jb-=vTzQ?$D({JJ zk4mVSwLJ9J`h-6NsRl+@svF1F99$BIFkW(C%|T`Z;8A4ouPIQRIMqbC*7yAOOr;&k z-sMPxj*v#GxM>dS5?J>=hvAWFJjRbFoPOQAZ`cXCR}T2pY&gRg?#C#*dBS-@uNC^_ z;(pP(XwS4{w3!mNC)_>-;)yY%iBt7TKfVk93k%vz)0)tpTo`y}v@M(~1!XKGMCDla zT}KfD>MZS&QnG{bwr`(>_2-7lPcoVUHZ~ykX8w{7u+-B4?9c)P0R5l&q+j5^9#8?W z8-k7wZNGr6A1L|c`0+wA`*i#lyDp%JYyO{4b92;U=Im#{G$#YzpdD@k4^B3kTGQz~H6}z9Dk?S<^++1kaBcKA;RQNUll%5wNS9KA`Nq zayxvOQVQq*lnk}(eG{4$|AV6x%T&0ckP+jGXzOAkF3>_}tL_S+E6xzO4dibkeTk%y z_4aiTEcqgB2vQmN*rmICSPlAu_^)s3GZQl*K!JfF!u@X(`Y)q#!A%KB(=yT_utE(s zM%RT6NpDiMm6~t5PeL)Dl%Z3q3VcjKrPpM|GRU}8&|SR*ZXty>3%$W~t%!gO1Yrut z`1D=6ZeL-#9&LOJ-L|L8kd$WB#?5TlGc#W@{f=`#o^D8jAz5R~5lw^wxJ8~Ro5*dr z+iJr{Br=y&IaAr({j>lnPD>yQK8Za`p7s%|9}5W%jaZY_cT+&EF}=b&Exq5qoT;-T z?(V{6F@!o;!B&cRuu? zj$|@(mbP_K*{n)_G{5x88_5dKD}%xci+iPyL!_WpzWRztXh6qd;b0O5SjuqaLAEk| z3DTTgg~T?M|44OaI5Wu%JPS!y#EL=itHSz*rVf%XdZ=&?4jPj!Rxl1OzE*a2qtj3D zJ5i{^&f1SGlA8jZoW)Vpicg~furSHNq#|s-C80-(P+N|HC^lcO(ZG(J&QRV7!qLuw z8+EQfSWOwSiL67QcNYrvXQDeZO->#6lYs=bxhyk7A#Q+JsacZfkl#Jj0N=6+((iTk z-{}`^WV!(f{k?juj>3fuFNj(;ZH9bs7!24*>LYpVoN@cG8x4+BqL3$3*)8Ltm2^4l zLPvv5v`n|_gL~#u#R%?Ic&$)sUUQ}t*Yms+e*}$O{~6~ex+R#-NL4Nl*%%LNJY5rt zV_Q|n;y^%ie99U1!vVz9k3=XDYSy#jySK!`@vAT1e!U_C4TJ~}f_d^sGA%45;$C}l z_q7I+-jspQD0oJqzQhW>T|hRD7$6XfIIW0Po9 z>)hn5g4D|+?pe-6mFKcxKnE_IeKpF9q_OCeS`XmHVCkz_T*AXpS$hP)G-}Y4Pt!w3 zw0U>J)=Vi!6q35wNKjI9B5tD4H2kc_FsPD>plP zwgH&M)Ka;hl;zDe7Vi5+(NvxSa~c(xFhh}p^~N{f$?%v*k%QwO_4wocR7Dz@ZR{4Q zHpM-2j|!N;nw2NimnIaOB0;b1PWwq5-%cFuc0I_eW%h^%tD2BCrm zw}{3Zolf*At~x;bOGJ-M7WPU z=(srSduG^#NcM**aIddBs3g7OwJ)epa;Uh(AAR;mZ^X-;=?hj10=NNzAbMFQL~WGw zNp^Vn!-t9||0_Oh!fR8s!?n2qDSj8F%Ys?JX>iDJrjQ|J(xwDTwB9$q+?bL1BwYYM zAwr<%_XHx&{HXF`A!Y|=`u_9s#4U*9=s*0)5@z;HSOX^L2pqiy!d(I3j`}4g@q)+| zM_mNYWe~O^YPcTqj^7x_Mg1x$X#mI_*&<>!Skp+_hk$QC@+?o|(N`i@e+|yprc^6x zz?>OTW?~q?%>Ivew!ginpZ{}^;Clbp4m$;e0N`qvLUn91G?R7fEkC7Fd1nSn#>rs| zl|t1}+X80@hwr(5Vg>=FFFYbM;h>>Vxl#?Ty=MLz@6lko@2I*cZqz~EgHRN_F-JqWviPva zZ=sz&n)KL@`>Z8upc6C#%8O~mLs)u_j)K~Pxgnxh>nRnbL%4ecdiF9{lXOI=nqW%7!z1D*z(!dP`UD9j(L(rKhC3pRz71RA}` zwk6F-jd>~1Rc)(|F;<;pV5d({M!su{+9$q zp+`yiF2t6iBn1b+UUlk-Xbe<{prQ@ubdsb^y)Q%+Ew&Q_Uo>srbaqZD&EB%|Sx`sA z?7dCVi4?vYsoGbh_m&RyT*TQ4T*Ui?x8cm|v{Rt-8j0NA79#2OxaRBixPK7Y`2sU# zac0|W3;s~NS$c)#84cHneHosf^QCw0z?yCRhgXz!hM55H$?pT$f~X~o4+WEq2p)_T z+M&KXw5O;XU!=XW@AuKBydXCbL;4=uCz?Uo=Ih2Ko(-eE}d*POg7mtK=G9{ z*og(>SG$p8`d`9(^P)5Yuy+`i|&c7z973&U!IsPrc&7ZAZ#n4axfM|XfZZ-qJY@iKqu9z zgBLvX`OZ76DiM6^{9#rJ{Qbb)d7`)u|MB(*A6|o(bfNkybABf=|7oXq(m-R?yYgHDNR2RfudxCp8M)zP5>eyDF^s>D-BPt;=-Qqki{hDd)QU8s`DBhRx*cx$ZM{aAz zGk5PWg6G~PHT?#~aGU5!Kf*R=i;mbx23fsC(>wSS@LCU4d7Q0~AlNaV<`G@oKBj#+ z27LR^ks}zGULgK+0m@g0cM6G)xK2(si?2SE>Z|J|{ElG0^GR^m$uuca!TI+IGk=bIbEE*&vKV0*_K zYda$OFYDCde&>R+e(Qq!CXjSG|LlkzF~&hUqMXd8V48EavfQ*`T8F6*Js_@lxLQ-?#6Dx^6xIfI zZp`y)%4|6d<#wzr!)ed-@VeQwUpaX^5byFy9y07HaC#_CA!!_Z8HGtxfjGHI^g^Cc z9V}jDlRDrvPjM;2*bR$ek$}8D)-)V6qMw^{@A4XU%#g&jB;4fuDA~YR#4D#9);}Vv zgF+$km6O8S^-ZzgfZ$bMiuFeH=T`o@Shgg$(vZ-R{Kc(W_(>nSld!L&RDi)G#w>gZ z&sCEkY*PD9!j(4vf!5tljyK?ugYqiVs51mY+0)*RTK<+AOtHahG1E;O%PrQG$_ipj z=HbCNn}nac7JED}%lEhz^-F>qZ~t4QbivF0^8ZaZhW|TaNQnTnH#9JGaKDIB+T^0L zAhGJ0%CHB3iTW;48Q8S;Szy|t1U17}9^h5kTWxC@=J1;>ew=2E9pU9>#!Io{_Pv>*blSyb&LX&ZhB@{)+ z(UWBq5 zu@501g%}dzR!7?mnAXA-9JL|Cm}0tdfGDAY)kE$!lgEHpSs}4+>ebL%y6hKTS zE{n}_8Uv8esg3jYS#d=)C0c%;`;NpxmQ!Mtmc(0LG_6;MT}!YY zsz@)Ai)EDPN;ScWp#{MHocG=bOH?ANHZ78@W9N%9YFqT}--JL%yIAObGxVct)tD(xy_y8C>_IZ|%Eby2qcOUWD4tyz?n z8o5J%vg({BY9?hK@O}?S8(1a|>(HB0K1q2t?h?m3-;Wutk!C?gPiJN`Xc88z`z1T! za|KAerH^~3Z4E$N@VNz7-u3b;$ zIfqdU?Sppv&CER{{F8!~;){rfzoXQJ@NX#Sc8oX~Tl!LWG$~Au*Z!lOZM&CVKraQd zbl1?4Jb~=~wQXGjp*5}F@GiTlBs6!_VE{p#29FY3gBW{+d6=d^v6Jz@9!mxaejj_% zy~ofWmFs9+>m!-5Xd;*u92G=CHc8jQYQ4mh>~LIhPJ(*fHU#a7UYy8yf6YURZXJvH zeU7-XorbXoc{@yTPf8d6j_o0GL5S#(ms2UKXujSor;%qa&SsO!$YSEL4kHYZT`T$JJSz4#_y^O3p2YYlSY_3<*ptxSfy-!XWu{b1mP ze20G55DJ3n^34X8h@P_i)NWz3iD_?>_MaZR|M9^mkF6B*^JXt-PML)DHHJ#swiXc1Qt>Yf5R<^tRcl?BT6gP3)HB2b*(g2>kI(+Z z2!)6FFZin4P@u|C~^zFBknBNpgQ8e(}jgYM?0&8v?6RR z9rEm!rGS+mx~jY(i)*avD)~jJCl@3$dSNsM!aQk2A$al1O$40c6m8(rQ)rC1F5Q1i zRaDHA^xpsGo_V`UIrF&(q5||)hh4Cdhg;$+=^m5XgAt>Vh$MPb6?$USQ|h6B_$7&Q z>cEM}Gr`u;vIm^`&)Vy4UTqk0+RRb*&{i!T15i!?1Nb37yq{*2-FLz_ye7RI($Psa z3uRX2UA~pJegCn9siX;;WFD4NC`)&*5)d4gI^K5p&Bt+FGYxY(jQk1Yr!*hxCsGsImJQ7IB-he_FjkmW+mOAKQiJ z?(;05uqyd(p$n#U4|0EUcHc0=P2|YA=0RYr12aEF79WeW&EPS~j6{wI$O0yR zy#4QdVST$4Nc1nb<$>_Op`WKH{BP(JuwfEHm@RMyQigzxaggCAthMGUzR@FV?n`R@ zO5!arCN{P?7SUEQ@&Cy55WW$aSj*KS@#U6^B}>KlRmB#G-?>Ukk;=#`$JnXA0%RoEBhFv_ z2q{xx{PWy!fAM^res6C1nia{x9~^3KgeqsByLs+_5&H7L6E9#NE7Pvza7q;w`0a*k z5EBdU!g$o)xM!E%K5%y=bmqA`#&7jv?5B&iO1Quk0i5Uk>&m4)@Aq#$GwbF?JWQn~ z`*8;drb21&oNIPsgdAzV1Bznc^K^C#Cm@p5kCaVYy*@#Jz|XI^kl*}q2^$&U0zOm_ z5(}w3=3&>L<<~zQ@v;-_xAX)Tp}N8e6%azMmNg2s9L+jIp|ijlZhXBe3Wts$^X@X3 z*xU_-O>S#OXmJ(ZMe3iCbX6}_+emnHd!|mk&YN#m|8$^6K@ErXBK_yZ*rncM0RM(M z)c=P1yEsb9P6=#^aXV~ESQ`r>-hc{Q9;4mM+!xtAUAvTSdHN3gkxo@d2~XFd9pO|f^y$B-Dn*Q0axC!G{P zYS=F!mSIG!JypxvI?#rLuRwGSG#@$LNF%<{A^NM-7L(N* zSIf@L&&}rPAqKMm=?4@3+|N3I2X>IGY64L4hWqu7fUmC6E;wT`#?Egj_<8Evg%T9^Eb-MIyAV1FBwd|-mg8n?noCT zB37fo*@6Dso2yz`{2}Tn5KQe1pZ748ZBI`TTjOO$Ox@<$Dj#UUy4_&Pf=Yr9uwY=#@DtHa6pi?IW{jx#gz; z7U%piw05tkRzQm{zTYu;>+z4ii_e++A%dKWAas+F0S>7T(~wEHESI*>n5m-5!cY#) zlD5Cdi!$h3qpW}|Qo`PK-H*pwy0`mI9kyB5ze=b2mr}|qgl#64xFV|?)6Tm$l$Iczq?6RO6tBx)2^eP_TOZe+O++X%qhjk5X2os1mFil2j0<1u~= zXbknKyp1^Sg0Kd&bD;c(hVT#8RZjYE>KmNvcZ;8^Z_Hi+BqPFQ?pXny8^)@{Mbd3| zUH1@`M_uA?y2fjxkHj;_W!R}F6^Cg;Ih|6&fT7)|d^Lv*lH$*5)<3&s&{ThKr3SW> zhu2pCVl5hmKQ{+y5^Rs*a-<0mk_#l6_w~tj>eI)tbJd9lu}i)C%K!m;nFXn9-&eCt9G6V zUdBZI#_Gd&B5?6B^Y``78N&A;Kh1pGdxSHBYFXSKqFtGSBzZEPg0~*!tv2>TuG)Vk z+rT9&?7?0msAIS1v;P1L1n%p|_Xsym5t%$*9En#BP0|TGvN=WT^*{C%e3C@YsrAm-c3a*d!}NLzc*iWgzT0g%K7n> z@uJT}+CPXS=Q_s*bA0vDgsFl6HHt>8=ST!G=T4&W_N!stX3Fol{$HcwVki<9mz&)% zen5^df3%t2e7)H`g5ZJ&?z1z2 zz$TOBF@&7)ct71^CCDwSuv||-t$|1ZbdjfJMygzg(>TPNN4^nil(aZztG-KL82=g`2I1=-0Kuv3Nf7#fCy|!yNq%A=ib4j z6l_2GzwG3i?@ia(hyxXRpN%se4wJ;gQe=ZiM6 zM|49^!2?_VDVu#)Jk4EYc0%D}EP~>ig(DFp!PsQTWvZoQp%k>-BI)3iJaC!Z9O?w+;N-BNZNCuNT+`C5{qL`V=X-8|jkgVn zn1kQum&nQ2*F*jb-&f$-=xh*jAH(5R=%{k;dMn^8>6k)0aB7A!t9bfu@A&!HmpfOX ztXiBs`%KmbgZnN%x3Q*cdRUEN2aTlpz~YZN{|+Hhi@INDHy_V@Qj0s0T&bJQz;+v5 zLta3xQrg4dux3n@MN0~e7CE<<^QmEP;U6^&a#%#mAIh8CNs4QsT6#7m4nqy-be$J% z7DoX0mIW`BXJ6{HW_0MlP+;*gTNQ(qm2}55A)oyy0<=A36%OyRfX58xVo4(fMav+; z8}{nP39~acZuol*C!gJUcDr4{E+q$rA+oDqFAcQbINuuD=*-D`@}JOLwS6BZ$*zIX z^?*yWs-N_lyWJk~DZvt-lqYtzx29xvCs2SVVv=ET_NC^H3AcshSR>v%uMy}JI{^bm z*piHUCpqinh?>xB{aP~9n~smvIRgP_bEw&EYjQz_8VF_tXl=M!f(C@8F2kM1+L-Lj zv}v);?*tIKaoLb@90K0@f7I?BP2)`6CObaF7zd}naaz=nat0Xm^CveVbt#&zXNCei z-22K*<9=UL#NafW8iBPIrEN~@vx8=SkB46AMldQh1TL>_v*$tb&uK*>Z&JhdmJ}gw z3LDVWLg2;{a8A?M?;_i$HO#r>)3zlOBbsAeR}V@{LiNP{FxEG#nD85)!QT9T0GmK$ zzoq-O&e8~#w)S3CgMnAlwlu>o`(zN^x_2A4Q-9Dx*5hd|-Lk6&aW8fRV4#P4d3?W> zD%wHxdIatxlR5RAO)c|TnvYqK?>_8SOZMv}Yl8@&t`>gWA4Cw>>1-f~CEjc(h(I*IvKeqP7dX5$HWop zVt+)P?PUw-VnN9huvPM5#-S5q4mbY4rsy}ETIx_b zR>KC43u>vd0ak)Eo$91|+6g?YnZ+*b%zx$!LA=((J?i21W*sjsdV_c!Uau>Ul~=67 zXb^AocE8E<)%%OKLuY@phx|D~9g#a6Ya~rkf_STkf14oJGT-rk8cgrccFeQKJM{8* zQq9#m8913KSSRj15w~+%I1RA8uACvTuSgrD?W*;kXSnaMSn?8)LN=1KoV*<&9e)$= z6SQ7itie$ydt9?+nW6Uw@LoJY)g{VK=GK5&7WANGwo8lbW~~9iYK(y=%emfisA8`Y zH&oI}$)p?`gSRd;y|_wlYXcuE!hN!IoX7v06-VcW42dx`}n zFDk~iSf+lBWvQCa*{i>zd1Vq`V5?79%1dv zY|myg%n5EcuyT$JGi#J)91{VQaGu;)i9}UYx<}V7Xs-Eml&492R+aZ#EPq6CD-|!Y zQ?oVoY#VWdp`x9yl>3u{TYswPQl2j1 zasXez7bzVHm1$3RC%%?m-Sj2=zHa(5Rp;JjCCWR3_(N~$k18>vOzvc6ox|uKGvSWt zQO~8e)1!j;6HO=2<4-H)lYe&X%~UzSSF0EHR7K#Q3s%gPrn{I-CA7}`g<#nN;(Jc< zmjS$hzhV$*ZqG2>R#U=xo6EFl{J+81^~B%OCXwN+!#MBLNccNJ$3k~plhQvZrEktT zxj?a+fASyoweP<(&_`VVU^OrF*_jc|{r{l``~v<{u;{^V13#d{@EEn~Z+Wm=3&wxre*(CI ztFsz1GHh#S|6?Yuc+t_c<)P;GLmqZ>ke#jsFeQt4Aerwa3yxFF73@S%e44|i#P5gx zX#i;aN-iBJScPJK`+q1&*)C7_-A5;oS_!bnkUHMBQ1&q7I_^F0up4EWqa3{&0#Yvx z0a+rA%sQ2ZAadNwN0Kw#bea+p@WHZ-^^#APpsY}TTQAp>U_6!0+d)~WJ@ge>rLHIoVZhuxscw$z^?zvLl5H{jV z9HxY%WA|q>{d~a%rG<@;+$!rDV9)BlwZ)hAI_bc0eXVrPX{BD$uQxXcoABltbTV@+ zJ7#zFS?MDQYqwpnhOIdJmXn6C8?Q^xAOv5ozM*`MCq}c0omPgOSAK0@Hak|#UAwT) zIyiVTXa8)A-hY+XKD%!I>UJxY8la2NIbR_g0RuX4~hax?$`6Jc7*csXD{+Oi4 z^6Ea3;xvN;%zk5J-QtZ|C;6~@;ZCM+{b^;ztbh0X^aGjpOiMC=@}$_ z)X3&LGgjI*S;ZZ_pK6Y)BQ`Nk3ENvXR`$rG3OTBE`mz2kPEpQz9B6ml=j5+$X=3zN&^+Bl=P-B<`_JKlNgRx|jpJ44aQGaorg#Y> zmvLR#-<0I+66z;0#>3;tOrY=#xn3mi;P)VErf>s{8iU2tzy|kUvw@AkkI-dc8-Ec~ z)KTrc4c;910fJN5N@eOFE&)@nP9g8)X9*Tl$AV*6g!ge?tIrxwe|SG3gX7(kI1y`& z9XeFPBfF%pgj2gqc*E8bPDgzuyd~-{;qB3y*0%N=!ai!GW*qN&deOK8|O`akhl#VzJ$=?fe_l zbDt~W^G&~VxP;$33#)`baKB&qJf8m`dfG4I`4avtwxtnY{1|G^V8bN77Jr+>3$ay) zJI3+XC48gl?@RbrxTb`EF5%nb_?HWPVI%50gRhjw546Whcrog4Y{6$uYVW`9s_m}b zXomf5CHyFMM_|!Mad1Kwm!#%N>{xEDSr#~bsN33TuCWevFBKzQ`}l`Zx7=KP`tc{R zv~>+pcK2BvUVVDGS(0GbXn$M0EKrgrp4@15pPBlUG8mGj%1M|W+IklILbALh;gYN_ z$qmo+QHZ{Z6ytJZNFo&hLek7>tE+%-gk&uN%G5S4w_KG4$2MAP4cc8;M}^zbg~ti&sAjz#LoTeN!VloE3+t%xQ9R_rI)5tc@T;(n3V#S6 zcVQhB{sf+KVI39zBp!|Rvm~deo6~4fJU11#+zQP_!txeQz#?Rz!d`}gUm1j*SHH_NM3;=>D&K0#aR`; zyqzoGn_e-<>}*oY+3sK$~; znIpIhoK`Q9%xx|io}DH{WXR>+Lupc~b<kk6uwEYx(nyq9-8$IrU*o3qm zcuuwevHrG@Y@Lv82ST!42PUGB+}klByJAs#V&kOr#QMWN8Go1EXK9~YV>i=Q?VTJ(xydheW{T-ge_ba8SuOlQ6@SclQBsc92`})ry(pHiO zWBujZm}olmwyAG2=bV}PddFq>p5euhgydC+OJY5VXorT)F1@NRBynbpvod@Mbs-tm z++c>}Xw=u*#(yBfw?dNg?q`U#ca$V|QJmPWlH|!jYe@S7a5ruL z8t!X~Ew(Rep?^3;!-eG7dFfola=Kxc3!bQe zeJ=QL1>Eg|udRUnE_kW}Mtv^)`f1pI7K726v)HdW{e{?}sM#JiV{QE3%KuuCV=O~v ztV1V;erm#|XJb0f8+7odZ5SHgVo2UGnn( z1yD-|2nv2zGVtLJ006HXlksI_e^5~TTm(wOb{~*fk(i(qc&Nd&l!T{d*qv^d&hBhx zcQM3B;!iRrXf*K$_@j)sMPn2ne3`jl=iGDe%(w5KzXEuKMTU20XU*Ch>xjF35qZ|S z<#w$V%T-|o zouS)Kgx*!5XeiasVgsWLlgIpoJCaAfvv+hX+|`vFi( z2M8YQvxUe3005bjkuDvR4@D1?-=qkWU}!jhTbIL_D7$fi(}V;PoV~>DvZZa5v;zq- ziPz%51MpA?mkA#%|DXN;^7qf@7XVzsP{7A-_mIEICF%{;M$V-!wo+ zL(Bs?!brSaVa)W3^d@#yl=A{zq_Om6R-w;qpK)#IDmPQU4f(&n=$vD)r4TulK|Yyf zO{O#XJ^&$L_}Fwo)2($RVAOv<-^%Br~3hM4pKJV26ZGCp5`}a~f6mYu6Eh>j~ zsqU9+(rpUI0#bS<-L)K;oL@XKID!=V5^Nd3Nk2it{Q#0*P)i30b>Mb6=l}o!6O&PX z9h0bOK7aq7naSMA%>ZFSgaLseM6*s(QCS920|^kB1WJH7fWpnpO)@ewH_igY9j#Ss zTf01KQ|+ru+q5oKDclLBidsv3O09j?+Qr&^v#nk1qOFpi-@P-*Ofm`h{(5{ua_{eV z&iS2v`Q7JEJoW^Db1bEV1J_)$dHIzUT}p6|8h;B__$q?k74;QCE!r23D9NxE^G3Ch z%Ik48qACfMH+z+YH`uEN_asu$M1`+gi6qqeioPCiRO$1E1&tLUb=mUJ*$f+Bp2hD@ zMIyYgSB)o_DlaT=IJe>Kb1SZPfCzGjmWl_}wc&_LsMO*;jXiNC6j2-Z#g)E3HQu<+ zcz^9Q-`bRLOoEM2dYQ6UX^bebp2m$`m#M*|1UtbN<$c0w)jRxS`yI)6IM%bWW*cF~ z*y@^yl1NC931vNMa#LJOG7;vlSu<%=RM(g^5^69N4=4K@$HT02!ii}zN-&+UU}{(i ztnq1l&>Gf>DKX*n2}g|WGI1BmWX!}Y!hf8}pd_3|C}FaGEoj(`6_X_zQg6eRB|>?%f4o^&)@*m89$p!BXkc5JoP@PTL4UJx zlalOZBfgJdWro;)s`G`&%9IPwtS!OWGS0#|1lPoU2}_x!q-J{Ls9qREtT6U+tSG@U z_?VjlZYJTptT!0T?V90f&1&~rEfov3#N%3A!ueUHX2?pokRS<1WDcBIZR&0fGjd)y z7EYc&PB)`2?L-UK%4otm!t}nl+JC3Sv!O!RR45GcrK$0sO2kz*8LrH-x8fohMc6>7 zdk=^b+E_YuKRa-eb!x2^jBmuI613y}gt=o(ZcfFL;i%fOKdAPZm>q=KJ@w4^7bCe?T}98*0(q3=G{qo-SodosLvE>hy2?zk591UY)TIDemcsvPK) zu}!GXE?{CIg13+dPEcazeAdTy><}b&5-e2>4qQ5pLe@@GQrImhCfr>Dd+3(lxVBH}64o{RBP^&~X2$F$_K#T7iHJC$2~pGO z+Lfs4gl4Ywu{w4(T&Bb;9e-daDrxA8YplRzSWP&cs>DKmb`C~J2*|OY1X}@3Ml0$3Hng=4q^p591?(n~zS({l<*NKgL#2;ytM-3%{kmk3(u^&apZl)MUb=cz-V1*5)zcJsFqi_f(4zQ}-*;zKB}y@is^M#n!55|6V1MQfoLQ z?&ecMY9bg9XLRH$LSQ3Pm0@IyEwPs8~UI?6T^{1Uz_ zV-WXG)TiMBp&YGBc#su1Mq#~@=w*>5e1#hZ)3S-x{U)pIEPwud$Tp>qk9!1<3P(9O zfe>#?IK%=N3Q34i&EkP=_G9JPc zgrz47h04_`o6rpAj#O7>U&51wb=6Ziu8F;JJj4X$X83tp##8uuw%!`HYvp_`vXq2x zaPA9>x1<&qQh((ts5P_B>iH&~Ex|GT525~~Qkj1`l1h^4Kc77}kD`QcarWbuwq4zy zG>Q@j{I~I930}Z=xM_(Q%lXYs#^0QH3EvfPFSEZ!mHsZ3Pl_iuW<0!Lsb=D@;QKO; z;|E+Uyj}->#Kq#If;4qAyP2FM;m0BXPF3eWk?|US%6~F?y*n;lbxEBAKj)XIlH|TE z;lwWmH+A?G7luTtE0J;U^6J)tx%xNwt$_X==Upw9C++rAEC44J)g+i>IX?FH_=8Z{ z9|=p|JHCWJaYoCqE3DiUX9?d|eG0tfbMY7aRmPw3CR3}vAW@Ui=chSRww?6w}h_V7QWm%nL7V1K;Gf`M~gLOQaNFD!RFyTa(euFOB%4v@sEAW_2E%)aK#;Pdhrv%%7SrrusaPgil+Ti& z#vMsGme`>7JIN_}^}{rc&-XfL2CIzgG$*I5kbh2^i5CTbE<<(}hD%3MbIsI+5mRm4m#K zq<<6PX4EM3!ov?7w1lgnna-ys&hpjc zHcfWc2&tOcuUJ7%k%*JlnoH|O`?&_u&wn)-{T%TyeCA1}fYCCrgf<95{`|?-kU^q$ z(O(%?3r4Txq)puK(njKmXIdVc5_Ooi- z_b_c2xhT;R?GuOX7LGL{pJum;>2kwmA(B>XE5i%q|NvP$5lCc*LOAtL#-hO03@mWk?=P zswN#Kx3Xc@vt9g}wkO4!if~G5Zdu#3)xTxey3I|^{+3-^J6bmHTEDTa#Yr)4BPmLn zc`1_B{5XS7F_O^b6c;99^_PyP?th>ZyAYFAV|$&n&jjSz#U59q+Fn-h6{a&}N0S^M z&hPogcKE=n=^8=j+PqvK%$+oPBRU|{^}dU{0cd_Yv5?WV7PP^KH{Cc^tW zn>M$%wy*QF_Qbfq3weU6M3SdpQ>z}~?;hdro=E2Ai09&1cep1dV8gKqaDP6JgKpt| zm?dlKN@x)tBF3VB3h4=K8m%1h1FQTa5%PC+oLx64N=m z29Gg%wUAj(5|w7QC{Uj!Lljf=|83Jea%$X~iMwl*NTeey`ZfA09g^uF9cGp2gyH{R zCVP+fgBxkc1<($P080MwjUEbnnUp$GCf1b2$xP3 zwkNT{$(YF;^{h-!6SszPFs^bzZZ_^jR!rqG`6+GuWi~xe#|6o6iS!-ra?rOq*up#- z#8o5Mob(+tdH*jb&H{(5*0dy#j!K_!17ptO#B-KJ-<9cQk$bn^yasOs~@Gc}?P$ zUN#_Cjz4g>5PwX?#Wkk6H2%uLTxB-ipg+mO!4|8< zCR;2P9*2v95iOxQEfP z#c=R{vVS=F?G=8u^53YdNXHBvO@ONY&MYln{8Ty=+Wdv^5>UL6pto!ON;dF8WWCE)rT1G?@xj4uq~fnhup z@PFBc@o>O<2w&B4B#p17ada3@1$;$bw=Iolj^H_h&+fJ#0cXwudfr_mp1((Ul1cj{ z9X}kP``wc3Rl_JVhw&QY3e=wsjvVLpU+DPt0Njiwu_<47ORV}gbo|X%G&u4g@BhQt zZxH*Xt91NpsQ@fz(05JH@*>-AZ zI}B+1AWDWw4y38%sF(2=)aPKi-430m4`7xc#?PbNP4{Mq`-%lru>p0XyGS^byLeX_ zl^WjE#csr#c!TBEscZmcSy@d+P8@Ud`f0wRqNR>!1E*kNRbaXWlWVQ}OLw$)8}>H9FO^`HDm|&(>*K=itao{8BEt?bdQh z2x7PG7KXO(GItLP->xg86=^zeh<{f5io}rtFSDDb7M<3Y(M3A7nI{~BlV9ETA==#O zwgp_b@EY^gd5A7{^TUn-bhz1Hn|yZHExgYDXRv&!?Rw!t=8Iyx53}8NrRmULN24S;`O<%Fw;V#bV!C2v_D{>c`3qy3BFwqUebYq}h zXyXnJ)~q)8VMm&79>9FBVRebE{vly?`iN!98zF|wZ5Z_zE(R#Pl`mziOfic zbQ?||!M%{o^k@7WknoU%;}Tu~-oa7{bqmj_8bO&z?IWD(90g$+On_JN-w~`U0QBc9 z&l=`*l&hB*}nNBfM!nuB(kvquxKhyM^FO$=r+tvu{oivo6AHYXjz3SHf*wkGa;}m}l+A>DH?--+CPuSf9m0>znY{ zPQxPG0#w-Qu-Mj!O4~A=VLKmZ+AcxI=!$#1X-Z1wv1ln7=JT7yoMe9r2$kh%FBVa zG<}cXe;8;xhSK^cYD9o_4Gi&PoqpQJZazQ2UOq&>*6Fut z`u!07rBEa1gjwaTL5$t6PwXin&yK{5U^fo#StGU=pbJ%M0*lG*eYM1i6#poIMw`B(Zb%H1jD?LDu z&;$PgP)i30c8TZtkP-j@_$HHq6C42|lhLFW0ZEfyxfg#mjJ2k7LP z;DMrs%oS3nO63VI_Du-f#Fm|(0TqeY>d*)1Lsb}6J;NEk^Yioj^$h^eFcWaSTt2e1 z+@n5GV`MIMAs15H+Et8gWt+6Nh9dXGgn?psz>w+#=~L+HAoBt_&_cR0t zG;Gl%@F3vvh&?LCrd03yBk4AQ=~Tc368MvVar6<4Z%|7I2xi0iz0Cjs0PFyh@ntiU zxO^pl%Sr<=6o&s;wY845t(T3vQP67JS=3^^;6@MyMNlYo8E4XIZ015TtqZZ>Be^Jo z3m?FT63w&rsnp9+c$&2*auy%jHudwv0n>#T$8C|-xGT+uR*MC{mgdO7d zv>_`sTJ>hV(X=0PU<~=2XrNtjDwSZ^jI{6gntMt(_nODC(9U^i60X$7_kNPzpT#so z@s1CygL4pti()*S4AQIhUCI**>mPdz{2bV{aBcri+ zBoj*}nnsd?CdN}{+>E46Ob$oVP0?X9x+k3-NiPo#MdE2QxO{YX(@12rDJExJFleq@ zKez^KQ|k-+hqCcF2KJh%G)~39`sTIGYt}A*pNp8u)0@nuqUPpU++nY9Z5tqZ5NfF5KCmtR3Z|8ZyCbEmUuF{CkB=_&A1(hJ1>kSVwsDXuB|%* zmuKedk26t!C6leL{z@;^&|D80RLivC|ABCWd>)!lwO*P{)oyaoLNB?G)umn#WWvw5*r%Z7)xhTv4N}@;`U@R!?d-oOKU%tY>{g=bd_wO7fTa=yEoKV zC!nz1yF5g`Hh&Z(=vdOC|Q<5o{hx^Mfsa>&1G62fx$9` z23EW1vQsE1=un$pr-wGv<cC)s(o6>u$xI-c zOk^UlL?DtF13i{xVrIHIuxbA&I_6*?lMD>S5`zJAe_HnWS|W z)4aOVDZtg+saLMv!L<5+X^sZL>sI`6^VXtykB9mw%w$i;4w%|lJH2!@?GjyF!?byI zfy*?QNd`v#R9^dW_HHwOBUnu`Uo+UxDj(crer-8SMsP zy_rY~QDo(L1`T^CCYD-1o%uv$L_$eM0#XH+*dsT^nbwr4R_=+Ugr}mC0~IU}j3r7j zCLb3&@+pmJZ3Q#?<7$Cd^loWuI)81eizEx_C22F7O~o=}E!~KJh6sflW4lf9AxN|e za@G1zM4`d+W;X50XFvvfX`hF(v>zUlNlF9}pKEDmF zwQW?SV$i`tEGf?Fpk&bd5e5?GzRtvGHUr|!2&A;RuF_3ccg=KsfgQ}0odeSToIc>8 zo9O1k<gslb{twI@BZvczx~tp8;6F?s@z4k9qYyxLbTE>E91To$c8ZgH zoIWAaxwUYtmh6t4BEl)IQVa=q(p?_9gYFi8sA48|XNJ9W5AE_$J>AQ+ zq^{%4k?cMp;fs=>ZpZ?0dFe|Mq3h|dg=k>24EXqp72NMfo`7++4WyItY{nG5ccDv0-51R1|Mc%b@}Gr;RrmXH#@RAFq%qYV`eM>cO8?vtgz9P z4;#(-d4#Qim{cH^hIgkVMj?a`%9cPR1=8|<47us+^4kMLspJU4Kqi$p zm7|Nm&Qv@USe3?T{+vKp(h`w1Tnv~6=o<>GUX@;dy(-Zb%|Ib#!-4$7m9caz6By29 zM$@5|d@O91u$YI^B@o>r5zC53n)Kp?XeT)YUBz%ix%d#lJBKW34TzBhvT2AX5{QCH zuv@+~7)YC@R!Sh2NsF}i#$Z&4fk$CFL&?-g1onPGh4^!I1!z#ou)jga#1bC__ASkB z&n7Z|u@MuX(9B1d2@g$5I-dpL(VHC|O(C3_@aBc(R~H>rC%T8}xQ7nW-vA<6HVz~s z5NUceuD=TY8rML}S42T;5DY5J8}#>HdXygX0DL}yu#in0h>bFxT`?IK zZ@qFF{KJlxt74-Tko>0#MC!c#jEA14Zy`*7nTd=fVkZAIXt*hn9Whhd>_GK*=)1E1 zd($o|TVl`;;OeNyx|1n$Q`{WEsfY~E2_}1%{uzNOVeZf5Cr*Vb#T5QSdR~_QE3(IF z>}&#=V+OqdiV;zIkdeLg?-EH~q#pr~%~%si%-NBONVONS;EjaJ9|LixBSShO$yrQ) z=lrh_9f8Eltz^ij)4`2#-{kawLUPS~gh`T*IG$es&TQ*acMP7rXkiyCb znJ)X&b6EL7pzoLTD@kI%7KK(`V;R7Idgyif4brL3{$-@J)OA&s{)~C^E&8ok$A3Yw zl`b^scQECBKn~E^+mZ}_Pk)e)&&V!+8+K)c zTWP1ksPw(%u?cd>%i7Ge?A+eD!OJ$byIHXVAR8j;h)2?JlGAy0b{Fcn z{2>NcS>~z}AJ2lhvX^Hwaf^#<;1t*n*$N^>!~WluTdGeq7n?;>7~XIxAuVUdT&jB`V&<6>ce{B7+0qNIYj}D#mnH-E^VV zpDM%Uyu!oFcqL+OCfU~8(b?IXr|cX{7^?x-yEm?NaXn0A=Z?)y>s{PvNxXe5BVlQN zC9wbzaT7NS#VvUhCP0f(oo4xe{DK`KpA5IO$95MG5~DJCWP?%4!Gq zfup)p7Su2*w&f*>#}a#!d(4(DO>noFi3~-wSPZ@z?lV#vV0xz9PV)P(V>mgu1>g+D z!^*B?a!+=&Ldi7K#vNmSqvoGBXv*oqQcYMHDkk zw^ode`P#jr#{U24Pp1MDvMB#jNZ^`I4UN1!z|pxx4D>Wh2RfOT8@)WlVI)M}Em;vM z+TI+G?s4(;Oy_navjB?v1w@-*U{r4_)%yW}!GOHxSvcFp;C<bUF zV1OrAB9ch%h>cjU6PJ5A#c2=Uz!?Y0f7R`m+K8WhyikuqV%wp; zIe!3K8P%zQWGsh&N&uc|pUh*^U+@P#d?TY`or5B2!0eDZ^WE8)nTd~;VkRi7`TWsoG6f3U^~i=To~HY1K?T#TB>yRobWckwf) zyx7iILzbJ~x5f0nQ!2iS!Sl3g%ER9il=FSaIHey8cO$}odP=Z<6!E49X?q_Z9E06cKW=bfb8DjlMb}l;xUo5{ zW#LkDv;@-0_+I3nE`@TzNT!>` z?_8?Mdd|Kg|B~lbEhyLd26b*BlUYB1A4v>04TVZU?d&ar{IWT){VuiEt=6bk{i@oP z+y`u=D}rSA???7tMwJ`hXfBfU$t7m$kH1x_XN6@KDU8^Nd`3t*l^476$duQuy9S9O_xyfhDw zBnMrp6R~35+O;mVRa~pWQ?ZkGp9m+EJ_@c-)B zaQb=ja;PFWQVjr7O;28_RCY9fV-A+N_n_Pjj%MXCs0E8oebll>A(`E37}!XmT6V_@ z=Xup0!9<@>fPM`n(}u?Y(wNa~M$kh57CaJ5%Rf>`i>V`VtAt#uF>{Z(PbUX8s*{7d z0SL8_^njA4KcQ<7t)!S16qHB?kgj8c0l^e9*X&YR$g(3j2=ktWKoQ-4(;XSzAw)1$ zi$nHgM+VGPex#=K^O>$@(lm!0WFULl@y$hUe48Ubrt8*AvvfO~s?oX$`_W^y54|8c zv4<$o5DxE}pn1n>et7EyEogX<{EZLN;^2d{wCO=Q`>4*1Zb^UEPJReCI?>K=$kFQC z$TLYTTgT}V^wxy8K1t4h@u@c&j?=nu_XMqf^kQ49-Dh8V4=ru*+0PG$968!>m^?v0 zzFg9Gvz^DMeiGc;@DRay4%0cuX>)kj+$|HdwJ}HA`sTh{K6A8l>v8G}bHfB(bp&g# zg~aYUeerb_7TX@8K}C<#3Jk6Yhr1i*4o%Q*5Pq2If|{0P!Q&Kv6JoDNe(d2j9e9+-1$ERL__7C~(Pms%R&(UX_a&%j`M?@B~ zPtfg;wmNLBP9M&=hnkyw&NXvr>fj`OAsjMt^jDB`mET@}b8e2t`*6M?g1y-ZqxfD> z4%-<9MPEKF^o4WuRml8Em+=T0Fj>&o&}(n(bp(5zO}%p;@Y^RT2Zc%qR=+Dt34Ua)Ei($uYV7iW4bh{Rx(*7&GjQ`?wf^u794{bAQ8FdGCoVFGu;1YW>*xBQNg_w!+JE!1Avpsjrkns0`?o}h-tM=!En zymZMu6lh#}e#kEF(cp*1c2Cliw~@nk|IIe&;m25i|JD18lEFK9F6Z3Q`c2Y<$=-oLd;+M-Rs=T9D$k1{i9&qq zb$bC_tlQ1-K54sYmu`1aKYdb%fFa!uQ&P8C`iO4jQ`UV7vN(+PFx{>D_tE`S682pZ zKp=60p4Im7v?zZK^h@%+%<}Tn2EB+cvS=B9Im3)hBqYYTAPi>1g$>ea@E#$)X4K1OH5nc35a zPL8Xg@>-sgV;{oF=aDmLw%_h^*ssg+qLAH>xg~`;kKZ10jMFT?T>=iD9da~=amFNn zugY;<$XUw`2waFJetZq)_}mLM!(Z<$Z?Hw+A;1b z9w=5QC&G^9NaGl93x`~VBdg@do^h&w^}7luzE4igX62BCt0L{E!~S{^~R zL%1#Md+0Il=AKE;&f~o!wY>k9$T~ZRoPOt%)SDljZ~ye?Y4dSD5Dtr4-Va`X_@*4+ zB5MCoxcf<3>UTCx^2hLJ4n1|tBp(_l&sM*)dz=zMG$9~|2jJ}yzw-$?H;4?=@DQT_ z0e7Fn9=ZKv4anq2WU6e8yB{kM4vuU2HqG(=9N$sPcZuALX?!#U^F$PP`CZ`m3z}bS zytlNpxWJfUfzCIzJl-(DUw({#=ECbu^#b1qf8VRy8|lN+@-zGc)eO&gnP1iIulYB+ z{VzVL+mnjbS#TDca_Y89&C~5db(U_|sW!D8ZM)hc>(%9|TesWQF5Ox4i~0Kx$zL2%Zx(kEh_Nr_So!^A3%==!-gkSJjZ~^c8wi zN1RK^efl)!T=e^V7OO5lppf3I6*7H`21@#@C0NNx-O));4@xH0g9aZk_(r?I2a8ur zroote9LUEsXKDFCYx#lva+i*O`jBD_mHP@~R66-=Ik{{&zg~cLakxNVqvY*F#bFVt zJO8j$0Du9Fx26q1I|ko>rvqsUeA^I61u@p(TP^5Zi!{0ey!2tTAG<${Grx$C`xW5F zqrd^rBTv1I6!B9?_axOYiU6*sxqLnfw6##|4)XCZ&F5!m0sop7svh#A23(|Wqs8h) z+&4$wRq{X~gFB=k*wGlA7S zPTwuaW$EL*OzNA8PmwdP(#gNA-tnCU_ z+59fB=I(X)Jz(#L{wlDC3+|!n`Ho$Pr}Oyv*gD6}25{SdMSlBZ5c171nV&<L}pmTJb zXcojk5Q?%^e$ccm$K{7_pwzW} zAgIx#qoT@xUMN$UAYr6d{?TESRwylwO!AMz0svkC0C<9s-H-Sk5Ae_Z7f28)2}e)nU=I3@0_ zf?(S6z6!BPC-PH+6JU&Zy-QseZgt(s%YDXeCszna5P&Im(Jf}t^8}r!Rn3#?ya&{} zoZ3*UF3PDkjhmjeN|>fv)d5zy=eXJ=MTgpd5^}%+Th)#bMS-dfdV?}zU?dneSk zoa%*SbLu^ZDI;>|5h)0W&8e#)fc}1nz;8eZ$JI4hIH9g>f;hBs)&c3N>q0KOM1_#s zhFIr!L4Ya>?Y;nXS%bfeeI1}UpXQ$CkRg{2SvyVDx*dD-CDJ`go#k0#At*sRy8PhZq)5Tx=FVmpj&l&h(4>^ z+vzUdeu=)S+aq*Lw~wQ~l=dllTDRY(=XCoL{Y8o4R$8AVyx>d>q=(=C`rIr5I)dRXOt@IyMle#ah^dDA_=)Sble_TDM`_fAP zhw4YVFRk={s(zvS(n|kz^@i?CEB!asN!^zgeVfNtEq&dhZ^1#8p=IyTRt>>_`rf9R zljIdJU7dAYRNWed2N944X&9utOOOx{L>lStjscO*A&1TZrJF%O>Fy2zLAtw?kOo2E z&WHEv<(t2s-+K2u`}8?`t-d4rjW50WU?(u54`bpP?PY#Z2ibU2GMGhQEEeZkQK3AT0N5hqQvz=1_W zpsJWHPa0w%uFBl7*!Mwda}lo$q=D+9hnAb=n?_vXU=uC2!5bvhd4LrQg;ALd61+NpTpGBLR(Zg`VCM#}zTUarlJ zU#ix0LNU#YEpo#X$PIBp5uXX6JdKI_#WT!YLc_s7%DO038TY;Tr;}fu8|5K5d9&z~ z8aktpl90aK^Xm7Tb2Xz6bUE0nPUDtpA_!+Lt;^ZMuM%FP%Xs@tKPD~qx4(Zj+}Wv)Z{ zh=1}gU=4KmmQxU$(jGo-LgUlH1G^&_#9el}!`NO_C8qCMoTVQ(ZOMNbtTi-jd7#ya z)|r}{%aE^WlfHA+Vf}%us3n)Zu))>~)-5sS5?(WhlXuneSQw|OZXghx)53CcO<95H zVj80BucacAYvojGB^xt`=~z6jm9N$6JorQM-OG;b1H`v<*;P#~O${Y2Pac?tPR;jC zb^DAx#^5P&u!0Pey&EyOm_H6GRoCytX$c_iym%tI4o|_A@KRgC^ZZ~GOXZWZNYi0` z&_IWe!G!^oggqjee%iSVCLiPKY{V#^clC|P7Ja`YOX*)OfKQ7TYHCJ|DE&2jgA^lK z@3gCy@DgU4K<8EjnH`|SuL;25vX}JW26Z`C_u^ALrmNFeTn55IxPnO_{p<*66&T?R zNCPrPSlCLW6Q6-nPtwj?IzxSl2Vb)LYq~o8FVypP2FU zd(k)fJ{_mq2$1)PBF!v5an87@ob1k`#3U>%CJ=;2Q&z`*IY!(UN#vBMun}A}Hk%4w zQi;uZ!eT@WWbv~*;RPGASVnkyv=m(LeJ9o(I;3^-)>4h$L zpd4g(&4ow2UHQ^%+2Ulhd9`(n-u9Fb$-vNnolMC<4st#o)dVA|X-*;f&MTKNh_`U6 zN{+h&!IzQqo{5{p7Q$bgGq7p4&}Ek6G7} z&v8)mFa$kGyS4ecZLmkEsM>9?6+vR0L`tCbpMMykU|sGt{40p6yLDnhS)yP(O?Z|O zB~&qhnh00d27?WgiV74*s%%S8{u-Y9kzYoTQCbOf$8bo~N?aM`+30>-Oe6!Vn>?*9`;v$CBY^ZweNxOVZl# z^1>v8a5~cleHRQ>JP0Vi$Q2w1UD%+X5>_;Nd930YyknbTcxs|bH+168y_uk@J|siJ z-P=vw8q1^@Tbeo(!|@X)1992+Oi08?KI}gX>z|IH;zZ`Nyej$PKuT{JI%oe(-?ciY ze~heTQ(#_U$raRq8t64@sZsgJnZTLTxzuJyXLkJKThH>c&o0?n&}?w+;7j`fyr$Vu zGXb(;tKjxHLT;pXt3WAg z$yl3A+ZK-wi)d;XX*&Ba+Np6*vNXG8PPk6^vZON66qRQNAm*Xiffa7l0#V`whytCQ zBl9b18yD0JdL`-vO;q4waseZpOISEnn)x;-=u_XDhLv%Aii->h`FA810H*jN<+~)%)|lg^d7P`o&=zU1 zFx&MNrrA3S-%Zzx2+<|A{p4KirIi>q)@w&X4jyl4(=qmwO3RzV$@Fnu9uc$55 zm2t~lFV45iTY6eD$~Y1Ga$l$aoJLPIds$Fo+KaB{5XZi%@9mU+yTWKa1Fxn#3*(obw`MWD)OqHCF52Y!NA_!~sI1i=b|JWZ zYEHHItWZmB-_$tpg)w#X`X-i!nm1&aDb~3&_8Ij77}gNMk>}cCCa|JgMH3lM^%8GT zp4ZpN3@c`2s*d5+cB;=e88(hDcHigYdR1RfqXZNU5KJvjPtbn5l}FS%Vl!6rP&Kj! zccf^w?2}n2myoTxy7#z%_#2d0G}NN;+LgB^wx#5FT{K^SwXWZnl11hgc8Ddmyw?K} z@+Dki-{>}Ebe?? zByHV`A#Sd4>%Z1&%(uSh&z>74DLqGFo9|7^2`R?-8B7ZEvaqQ;t-G-d&uHxAW8Ewe zwCTInyQSfp=8~EeM&R?VKFYh%T_ve1m|=KC$86WS zK4mvI{S46=gPL?cm$(Pf#)p`u{R&YSZ67pEyTj)Uk=`MeXbezBLPP^0{t7O3arR@X zy85P6nybHRY+@lzS|>TzCq|q* z&)Bx|Xu$d^AcxV{_`W5}M$=qvE8gHj4m&)nim+8)xp_!K5E5ceGL<&_9+IG}oc$b| zjozx#k%Z|g3fQl;ceqFOGxgzsPsVYYQ-+hh1Ni#qAzmAe6^5abQtHI8&HEh*W3uls zc;aSGkx*{Awd1h!?r0y^!*42D0gVCii2LtO{J|q3C8BR9hMv^wDXaBfkA}v`S!^GU z<0uvNAWwY$t_>cpWqlkS?A)IiWCJ&S`S8Io-Uy@c-I|o;bGJ973~FNET} zg$Y%>C|06P&j(vL7>em|Ec<|mrX||*`?gX0aU;zSH;M5(okgr&ugjvT^fT3FI>u&) znk~WOe5p$?FRu0Pw`n>Fl~=b@%`1z3RH7`^$llFIbsI6nk241y*YPVpJXOF`0zUJ$ zjSgD#!mx`m{+Xl;YZoaOG97&_mO^L)Na!6AaGrs7hu zosP92w#|I@Nd36mzS(u!ej+8Ll9o9OOQtc zW7dkC7C|C0lQ? zPgEccrI&W1hkM%}tD3FwePdOvdbt?+#%FIiYwVkMZ{mD4fd6gngL%}Mh1i8*LT&_F zv_n8~IRLwI*UfK~-)NOE_ZVpM+mC*dxRL!a{Pd212sQqo3I^G!PLcRx)tL4+BbhwM zH0OiFc2OK!r96JXX3h9fTPBNm8$-L2>}tBc>x^$|>fxohW{nHQ-eq}o^+=41F29EL zSkk1o)z|PU3bi6$Yf;$VaGnhGEO+!qKBWrV+I+ZviV7>qx?0EfrC-XSt+-Lab zHq_7;ux!x806y5QcM7@6h>YHuk+f7YSkguMv&V1S6 z)#&A!tAs-NFu=Of!hFLwmk}ukrY=puDx#TC$Rt;)2F^?L93($akDEyW>G--MX=IEm z?G)x1u;*b#XC`RR#So?xY0<~kP!&J0#TH0P0pY8L*l)X`vKmU(E52`(?v!Ur4t@7g z`wJP8e+gpkR^?RtI4gsi%~$(eyJ_r4&d%)BQ)#cJxDb>qr?@Z&%DEqj&ek2>o^19O zQEKEW1cD(#x+|SJmPRYm;N>^(Wz0@OX7)!Op^rj#uTerflvA(*Z($;#Hcelfy;N*(vO9AWN z_}5Me-(6g-vB+AyJ(NJ=wk$Cg@;vQ8I#R=hnS>#U>4LT^>wRPa{WxtJ2eba6$%C>8 z;>Y0WQC@8am)p=BZ@&WL)b-i2QbDf<@^*0~!7d-ZCnHgpI+9PM8WMkc1zC{B1=?{V zl(D}Ua&^JTRE^-~XA{hu!$U|LdDD@8E9|x)keM;^<6AR_J_`~j%yZe%Z|Jk2?PKU#lC_`Fu)(^uAuJPnGr3owVCi7{wC24 z>9N<44i^zqs;ea5IP8SAvP$fS*Msugg#r7dQlfKg{6M#v((|JZ3v9VLjH@z(XE~g^ zwJ4Dlz{13y{0*y-9)qndo{mnAMWJ6dsg__>uInKDkyhEPUQ#}3G=Y)Kk>pdcA$SA0pgJ!H1hgji7ZsIvgXb@ zPSeD*O_9-#c)jR>Va9#k(#3lAWtoS7;?%mX$ zuOp`Y=Z<O=`+>C@oT_zvo566M91Pd&< zHC*8ck6K1%r>5S1Q69r~Nop5ia6STxqcJ&rd62#8;Zu^fh0_lk`>Y7Nx^r72GiyT-DAFg)ug{&nzum}HZ&CTys#EyAUd$G#WbY|`d& zxaYbq;yz6hGCepU5b!GfkWnh#5u+fjocU?7a#aL^B@pL|{F+-2RxM#w|78$#*tumn za9+uH-K6w}T(rBQLFK}+-HDtmVV&{OOitAgJ0F?A;S_}(cI_k6@1m)=G@q&<`vO@hNZEp4_o$nw8EejoEbOC zQHJcK72$Dt0oXaT4LYQf@d=8$z})X}klA(fM!80CTZ;)@R+^3!I_nwDjtKL7 zB0vDcGQkuEF{c?Yq^S$Gw=x!4)x2J2I@oet&iEY-Ph*@W_7(2L{tF#iTAGJS9^#&Y z2fy{wgzA+U0_i3ZO5VcHg=uiJVtN27d?mpDei1lO+zKG{xQq@M^^xgT1`egdudsOT zK{|MFhz6=z&H_|>L!e*|R~bP80EF*Bn1pu_gpd|0R*3`rDnV&G0w0eh-0eo>9=JgQ z2ep89bL9#A@Nxn0a`%;(sP2@=sedc|4ZZ)j(iqJh7*mN1rK;or-UYJ5dwvF26}VRt znc=@6C-6@QH@u1aUG6geQ4?e)xNG81Ff?3|`<|jb%N^XxN_q$We~ho_Jy4774jf}= zxC8&@R{nb?_&DJp^*^b2 zB>;fx9$2jUUyuR#$EgQCHnw}vx(OVTCi`P*1OGqocZdVcss}u$9X1MtsM5qRDE19S7d8-1NO&D|9IeJBb5 zP~Owy^S%RLHPQqBJk)~kRTTFizvMe8qmd5y=eZ2L@Wcr?d>sY9fcGejtJhG-IIIVgdj-AOATz F{Rc_uT_ykk delta 40101 zcmXVX<6|9e({vhJC$??dwr$(iX>?+=EoOC4O){~lJWubI=;sm#*96mq6WXv)r1OF7 z?LNed${_;{9|XkS+(%$g4-l-M_ma(L!@+6-(1-07&h*Qi3A=mF(#qXYqL3YXgF*68 z5D(*nwNtBww!zmXFbgr+KUsT&BNvP3@W=*#Y(&*xuPqHq(0bi-?no$~- zq3Z(;YyGv8Xz0K}s7}l}Z26(?IlSXt{;tJ*_p%bUHX?F-8F1BCHP_QMU@e@>!Mgy8 zkOevp?(>^}gJc7|lq}r}Q(<6*DmaI-pL4^*+fjvjt>`DdiaZSL5zK`Q={GPimv1Qx zKC%3?j}C|upaY77 zclHkB0?sS(8%%&EIXVZc&^!MJpf~a-LK?c!?DUUMt6tu{>94ofn(J{>DpDs)RKjjom>)CyAq7rOP8iCK4>OP)S^ zOY9lbgB?ht6nTpST}@i>OTPLs%>OCtmL8GLdqzuq{p6T9oQP-^&YWkd z2~9BKBAp*<0yzi)F|fSEKAr<3mQ6yNJ5Nx<6%IJT!*tjbEwMl1qA9uOdWh5FpVfYh zkm0N+7Cbsn9-4jAjySYoAYCj^eHR^_-JUj#wC$wL`(P-VzFb=BLud4Q@YASb+?*_m z0Dd`#5EQZ5!ha%`My(3(;ytTyrK1S7q!EV?El%Yx#BK6p#DHYpP!FK~LVxwmdbaz> zV;Hy~sV52A%~Ia#ozAWfhLuSYg8xKTy_d1R*C8>n(R@r+gknp+Dv}X~KFcZJLheK( zefJ^jySoPq-Amfw>Aw|{5;~d`s{8CS79Qpi_dG`OdPoPm=B2mdbQR!Brgse z3~USH|9TagmNMlBfDq`YyrhB=#Dt&fY5pDdg-I*1M+HkV1#T2lRzU`fr3mN6?0U1S zuBOM(i9Z$RmGlc**d`>|<`Csp8dtdu4K8IiI)>Oh6*|VCmps z>K>+evKExs+UTIeX+F>Z-goXN;09s)7R+d445xgnqS7!cz67j7s77o3nAfRuWyU~| zT4D{{<=EkgKt&;9ykj%fd<`?U_a$-+^K{xxAYF7VMV(ATzPd)hRAby^W@chcSJc16 zCyp4vd8{ocWw_gZf(*r_DLfSKMZa@KJ7iENEYLTTI9+?%#y+34P-sdK zYFeU(GfXp-Ifqgea$HgIK#Z8uF-f#{N|_*E-i$dSs6TPT77KY#yzPWyfO6s+g{{9R z>r=-1n2_+^WHbdr+?_zMKuSR@%4qHF`OW-PGp;0G?g>;lfX_82;Rg3z%(m|FdjX!~ zTD`%ox`dL_?@CA4)0O{1zzz2Z%3Z7-f0C<~y9SBv!=YAT!LfaHq1X2*+h$(dz)<2h=1 z-?F5@A#5#{!gGgNn?{^*-lJb|%b(S-Qz`L7q0#fZ8sQACM^7q6LN3pg6|OMiS+oN5 zc}7>5ud;mgBF4+Mp6U<$GBnP#X0W^>UBmcCZZd)HlMA$bGC|P{_T|JPhs^)A9Ym(t zu-?D6YfYIaCrqKnQUjJS)Wmda%IjB~B0wfH&`OY^wm=0Gl2@45uotplZ96bcO!iuM zanCDBe?ue>70EVc*?wNZ2p{m7qlf9yv)9VY)%`y> zrQ=$L$u&WAo3QQdY`4k`G2L{v@5q{}E*n2DOVamXh}l}Py!XiN%5#ap9?m*K-+KB` z`?;u>k!X?`)dK8Ufqk5Hc54ey4Y)>tBSa(&+PMV*O;j?DwlSgt7aEZMvJE{o`n&~6 z!D@ToMISw5cobD57>lTq9EBmmQR8+JW|Mh*(l~)u8h^b9gq|umt+`PO%Q)VVuo2;_ z(W7;_iDWgK>q&OWoLS2dGUxdRmoZx+?qi6vIpM<@vjQJ^4vcmO^OFFe;BnU_?&)px z=il_*sv5VPz2}1@y_RSE4GahTpg&o+xKiFQe${TqXF{dtU?uwm$!xP`XX8A@0x~ao zMTceQ4qs;VTeD?^2SgD1nk*p;BuyAY4i09|>o@1qt{}jh^cU%sZ$mbQMdDQv@*>W# zDQ5H&DsWGvOP{*RSxE}dBZw`(HP_o-QGWevMc89O?f^sl=8H{+XO3lgQnsnohJF*_nEB4m#CEK;8yDN%?GBA~4050~IpG(-k@eww6b)!#T=k>o>EmgsC zOUz3@C={)sUR)uJ;(yvh{Cjum7nVpi&k<tedvZUSS5xQF=TiYyQp$LwI0t{flK_0EO*ktisYfwunNkc8!8pP-%_u(nzPkIT9 zROb6p0&pN+Qj`u0J-?GtQ*5yQlQ`Vyr#9~&_T(P9W#Y#h}dwdS!%+HZ5{0sU(%)RZZU zmOb>^2u+F46m^#>gPS4qiV-_I=`~(32n@B`!wgEnXYR*C>xQceIQ=sG+`tLp>D=Kl zApb_#D1o*)?=a2a(B>qHWD?0R;~}dHECX#MXJswaJAa_Xhg>Znyru4Dxgz~+nQDFd zQE||oT(~5IdkqJrjn94d2l!T3ce63NZHuS1Z!fUIQB#P#^`X*eIIxNyRJmSR(9Jrw zzAr84W!nzZvQp7cgrr%K-u2G$qDt=l4GE8H!cb+%$|0!>qDFy!#WKMs1LAP}Cbo&Z^2N=y1_qq~K`Fi>1D z4oZUUY8Dcn6j9+q2}t6ouP!A<0dAg7IPPscTyiZ^=L!*l!WW@m<&w-wDz9eUOU#sX zQ!WQ-!I%LWy9;QokD7VD}g<$w9Joe&X3B- zt=MwvYd>a_g4Y=0r44+(pAZOyx3Zx) zZ;UZ-lTi^htn3yFLNwXRtBWTC~y)e zxRTWJYPm*fjxo^lXxQ1+P}=$+&%LvT&Z$`l=7ewfymD>vD#l08H4ZwsvYM|K?a4ho z;1(SqsJ)-wNfMPh9yH9l$>p?MBf-O+PQ65X+*Dr{0|P`j0t^?kZi_+`>B%g#@0u8r zB#Ndi;_>ieF#hP2$!grcr3k(#22?}u^|$e+5FYUs9$@lXT-@#084TnNKK`L_$6iCh z$T^$JtQ)B8+$K{p(OW;P8(UA%F$d8*?6hR=5r*SE)Z|Pqo!?czG=|;dWt(1gMCY@i z2f$9=0gDc-dDKJK?%dy!$V@$dF;PEdw9~!rs;CG$>Hm0y<<}Z&F(3f8lzDXPd~GJQ zQAX3PCV2O;O19ZD8~F7NIDh(J^qF5eCN-Dg%z7UiK633o(TOCZLxdk&y2ItBoOV|S z2nLk0CFLmJ$);Z>3egeg=vxFnStl0{{-LS(1q?5_zcLsgB!=H!nY0dRyHDD$4IuNO z&&MF5CXcNB*gf7;mD6?+#E8xnHtzjS7*mn(#AM=agZ#`jXX@;O{7&Y+zPFz}G~f-U zyhKVcJJlz1&Q^CSrh7R>cFz>w8+M+E{!M>?)_B>Ef@Ye=9GlAQkyWDFhx6EG-(7AB1#z5u3_81BJUDy$AC%-l6FJ;-?WCOx%K1Wz5IG zm%=~M#aFXv>>BErNzxk82SolP2AXmM+$?3aux#m!PKj@sx1Wh$UZ2sBeK<}b!g{*P zXc{{45>#~gf4=e14qeW`d6iGVw~t>>izrxSU~VJ;+~= zN70EOHlr4j61-><-I&W5(4EujI8}KCe*2GtMf^tlj9|dP_)x&WROBI2R>`sdZM&2y zHl$Sl(^zAFGX^@-$XFzYshdN*P%Pmq5OCtq6%|lp*>QZm*LFSA{&?B)qnjUxzTgHF zM$Ham2Z0Hv-ZgtbBf*JfKW^uJ&E4eW`Crc&?*YMdKohs7&Nq@rxx0s}@rkXyMf#3C zW%|K;o`OVO!5p9cSjQ;g)IJnv<`L3mz!kJrrR4|mz|xr>ndQei^S5sMPB`(%kuCXd z(ai?dNatsP1OnBF>^Af$4+C0>Gr5TFF0xn}>{omQc?6^-tgg3raGcOhM887Hy!Jek zc0icY4qV4oROhdbr?UU=3`e@Ej09E$CjaEYIY6wSW zvf?9&;!;7ZMEgCh5koj^+xfp{vm>pQm;WcKGX9AwTi}HfKosK(1THU+HmNA0VIZo% zS!z&f5T+3Vf|Q4l2my|J@H=38wOM$@ppv5;vcHHUWk>*s`y<%$97U%n&z+js-*ayQ zPT8!3{=VKJ^iyEr3gze2lnYhy*4-db*UwhH)n%zX6$P5;ZL`P3TVX$hxX>~T7>bU9 zdvo@X03QR}EV_PQGPM~bsh}XvoWNwA+rzR7aSo^tr&ZGb-AT4Y+sA6>I#DMW@(4>T zGe`BKDUol4RgP1LEotuN(GcbgW)0(trmT!vE2G3Ii&>PxOFm^xT4rSL&}eqNKGv3{ zohqe2-ro$)cYlM($QTEW2^JRQk*Y4eW=WHa1Al(y4;IwzqS7oqXtKE@#u*KGz)0Vi z?7^S@JXIWf#KPH?uwSx|Na#Tz4?7{jb4e%^>O6!nZ4NIWL6-uA^j3xz&YX<#iiXS8 zFS3B@&VCaKAIrw@OSug_%vm!1$rFuY>ST4K*bRF>_D(4($e`hRwjtVPAu8Yx6M9s? z07fg7of$;+b;@^JjjWuC&fryO_Jw={`5%s_2r$MaGZM^|4$>9M=h;#&sofuGEhwTBk$mV-4W{sh>t8qmtQjc`~VIMV%7V z)t#c~?8H=WjpJ9nm@7j#I?oI>V@IPZiSj85cY3~ zdMVM%w~vZwS6Dk|SmKY-n;C(*>H4kge6U-*Jh+!2&nMnqM5@f36s6D}k{{4rqH4#b z8fO-TL)|h_zT(mI=rQcgrfkK>+gcq+z&~Xb3|G*WSSLE5MSoPJT}0Ls1Hj+fd@VUv zQ)`^wds@DftZ|uKR(@*pSLTzWuLj}>+L=)2Y7)riF-c4GHyTVh91N-$w$REV8dWwv zntK9IKC^NFNBZ=`(c<&RDXZ661(fGEeQTaEnZntkqX}HfIw-|&Gi_?}&q^Y-z%72m z2u+`P5LPqPa#uvp5*J6nHZ8|Hj<*E%bM64QaeP#9IyW37nd`koS#nWwxYs_R;NMDuo%l+zeLKVaU!E5DFPX2sreet-9+0 zZ`u2=Ze2@$fWm*ycp&)ycN@ikhR*1s7=r4FrR_4oTFsi(TXw-ssI^ojoI>lv<#utI zcmb?KYz$l1+E&;`v7i5W;wvSkQB+@Gz*Il)!aIm*iWGM1Yr*H)AMc-I8O~tW#k02u zFE5f0wW|lCNiJQRtyYiCSyn#r&Km;F0@~i)btFdc`nMwUmiaK93)sL>RTdX;$F8v} zk!6m(Wy0$VtrF7V9vJ;@*~TW{ygmGNE;P~n3-4mowPpj-l3!WF$l-_;Sa&mTT0NEC zBP#wG(B|XK-N78gfGI4*PU;yDt?wEZ(oid2SKg6JTbH!lTnA#9!QOLmp1x^GHOWMS z%Xmb$sr#D4r8jao8XZuEm7<*k7v8^*d5o4Hk(N1~f)&R6Hbcip9q=JP=fh zTdQeQturbIt?e3D_;~Yq6m01ouHkYde13=EWYrL@Zvp-sm<2>=3eq~m;6&R~Z3I2Z z9JWSFGDzBl1}}8cAx;=(!Gavfa`&)tS+Upg zu}stDV!3y!T&=_csN<@uKe%q$<>PBgsvn5Mv>HHk8xmPq8!hET=2WTnFQO^q#?883 z+SJ*C+yb7#TvoJ6V%4nq72$Jb*K@op-Ras-i6m6@aqC=>=#nvdvicZ z{+oEK|M}FB^di8dIVF5n)X}jp3XVkdg8rzfs)&-wro;T^kSZ9|G&;%eG9$rTm)92N zx0^}c065KGqCPQsbWi;dwJcWSMZq9uXbmgtwGM|Vry&i}~ zS3QJ?8}>t|Pd$Zd2IKE%&b%>7rBqF7^aZZrHEK+EyizCYhWqd;n<04z7GIxu^}BmmjB|2;MKDtEJyN z7wQ8t)C1JDymq^10kul>fGrSw=}b z3fq^T?A}(hKiJ)$zrG$Gu)lX@TD~;({cZY?t#`B6hHULE(AW1J|@e}YG>c17& zS22KBzLimN%a#VU02ym`Dz2s92C<&WRG01J4<51(=#WWIu4f+DRwnORgQ~B6F(O+# zT&2?>&QP4fd<^-bZSiEm5WIQNS)(} z`-`SHHJ7)7PJRL|(=9rR3Y9_^kW&TuR!;ZpjvtWcL1)lTACaQRU)GljE<$&&o*;{B z-5^78VJ53YDJ^m6z#bV>nNSeIB>uvDsL`)D)<=G_pvhv&^W{LaVU8fCKG_2n5;@%Z zNR+$e%`pciAaGaGYVf<9U0!53NLIn3;%LR{rDW@fz18hnN1HhhH481P-@G6&QZlc}nZtnFXnfe`CizRxO#* zDf1p?DUhgH{;W!@_gMjqFVZbOW&w^D3==anpO>3~9`Y9IBqKNl&QVJ09!klCOb*?O zAN~8&-#{@iIGo5VUxYS?Ob2e&o%sypTWKGglZFEl^cjx7)WXFL-dE+65B&5yFFgG2 ziQj~1wayv`N2MT&=kQA^g12svO}lMP48Gw^mxV#biKhUzQ~;?eA&D;t|Fxpkd5@zT zI2btC*#8|Mlv&t;ahitO0BM|{QAqA#9m)z0EX!;;xZp%OJ@OY!axHiY85R76MN@AX zEv_zC?;+`0qsPb2Q=iI=p1amsEC<1so@+&*1W;OjZ|7Gvs=y5IMy~Ja59?ju-GtAh zeB)g(o;XR6bpo-n1<|N=I~z43rx2>P)lrY@NX;roE`Ju#wxp_zZrlmZ&_#dVEPRW$ zlq{9E%c$iD;-^8Iq;t2HlBO?XX$OH=4&TxodsqwG#k=)IrxJA6pgOf-r0OanDZ>m+ zil>ndSFYqA1!JHwRcZ9=OED^rc)QIiqol!-#{fyT7O!DzdsR$xk^Om&ZmpX*A!V7X z)5c&jss#_wCx7mtc{a|ilf~VbCO)hOu{Qi};y^5jFP{)Ui)cM2eA)RR8Nu(l#eb~?c~dADTg-zcit}zTi46KPyd!VC zQ!6H#?Cx7t2g5k`5+L~YG{#s`z`di907_Z4QIz=V$G_-UptEYY&gO+M?@Qv zl%oqc>yaYR+m2`rP>);pn)_yKx)_*mhKIa{=r6&*O0fGoH6Jas4xRR~}r>48lvU!!bs@k z*w<{CWOp1FN?eD6S3H@)@Hq2JSf-9|J&{vD#Jiazkf&j4M_$Y1Qx!{2p`@hGp-lTA zOWG00l#fkYa|2ud`ge1eh11lwP8-ej{CvhSC!=NE8eL9Ph@DmvW+$>XO*Gd^$#&ZB zd!r@8KvIKJ)Y&Yo*D;s6U;}leqDBDb0B69VoL?aJLeJzYM=XI94)oV)oIxzMl5a3@ z@cc~?If2y!qt#*2CdCP^j%lJQv$R_cPNTriDKQ@1sk?;{b5(=6&N>5ow#M>~vT8M( z0<%q;GrQ!s!X;B|+eCO0L))D$PMZoD5PeHKP_=9@bJ$Q0&AsQy;YLaFfGsfo+)6B{ zvG{JjDGc{F2Od-=Kh>}Mq+u;>(Ap(XqDU;P&?KF-)7=m}EmmSLrd!8@tUcjR;5^G1 zD#v)g3(Z2$!z`MHX**Afo>r|=gF+~H(7)q|is1KOt30--(+l2_rox`$mhpNQC0lcq z;hn0JYt`(7_Y5|LOcV=itdW^psoz6c+tiawM;r$qt$fC^VQeI3vhzH%2%k@YA{@GU zqK}-&X;NA)Jgkli! z#^l=YU+|S2=#fw{3x&t@i1jAG$2P}5A54Gl6yGf>IaVLwy|r9!C|}qniv@+nt$m`4 zW${*Ug2v7Tc+-Cyg52LHt3YpGyF0-KIRPb!U_(1$sEc8NDxH+`^NtPAr=pW&p9L**y1|=n#_Ek5IvW3XOh`@-YF)F7Mmw#dq1t`#@u%wa#D=H-oB*4 zv{g-f{yd)dykrb8QvRHJa&V!_oPZ)9h*hPj$^x2IgNPV$bd~&4>lzjLyy@~E$f zxEUuU-(FspeFU<8`47|!{JYXl()_>;l3(Ew?`L^v?5?!nB$~3ZyR0+Q6X>$QfRD~o zQ~?UWIe}96C-cykFa(M9_cjl3^~JD<;EHJ`8?o|B9Fo!wGzM82Hmb1nRco$F)N(A( z=(DyDJ9~^cojK)Q^)r8Tn_S*qHtG@s9kM4welTN>XJdRK1tFAG3dmNZ-(F^^d#>~j zxL7qS9yh`u)-5!`80CCd20;pk)MC@_;01Yy?MT=^;BOi^hJ?|A=>JM4bzX7eE&&hS zehC1VF22gZF9h$%;xE`{rW61jRRYN@(wvy`8e##>Eg@QpTWrqzWj1I2h`Y>kpc(AP zOG5D#Tq=CorUpy2F}6R+g|^4inb}2}-_S;8ztr1w)LIzImAaYDbv3Sl<_FET^2Hmk z1u*nQ5rj$KVZ0+NrhUcI5m3oK~{nlh>->SrIB{0xy~0PZ56>s7Tkfefv7w(|3zKBPE*1 z9HR=aJ~YX+_ec4g;JS>3tr~~338Hl5z2n6gh++hph__Wd_)1pq4c#9h)&tS9-Z)eg zF>!EPrNBE)VVVS_!J3YUjv+g?3cRsqS`q(2g=>@-r?~TESs#QR`!f{tezB9xBk+JK zY86RVs8J+w%WH{baOAAwvscY;e*?3c$Oto7iYX+i9RSg**v zNvMFvs3a+jY;Qp1g2W5vC=j=IL;x-YvEH>M_T1wh_J+tT9dWftGj!6q&}POgXf*J9 zu>18mDHd0rb`Ve$2ZzHCc|dc3fDbl9LLLf8Mq-*Z49_TdcY$?TJ@6Ma>ALU(F|9Gj zNN|wxd7FOQN=C{qlZr{=H!Wa}B;unwLT9hQ?2{Otlz~Wdf%Cch9%z4tN_<6Z-a*mu zvY*^AO~8VQ$mfiHlKU*oBC==8Wandb&bH$*N;B{c+Stte2`uAWhQK5;-eL_UaWUJz zPGyo%$x}-0%j1z!Xu})+;Xpk=3!zyonD2}LVSy8EeA>QqVI_Y7cau4^e1~khiazK5 zRQwnimYW|h`W&LUk4xfT_9STcs+Q@a{!@gURkPzX1VoD{1-EKtZUH=Cw z?_Qu#FBpNj{Jtey2SVO<9b!bP)O98PpKTDn)r5@gk7|aeWCpSmB-`Y4olE(P@Id&8 zR+$?A&6G{GA;J+OGHGC5mK7>tE{A2m5#VFy8NT*ML*O}~5~FR68d>pT<_0V7R97Yn zau!T5_QHA~lQ^u#_0PdDk6I46ODn2B=H%pxK^190`nb|FI(hUTQjD|q31!M&EX)l; ziRS0_KSqPP_zPIP8)zDM(mP4$8+NkJCF`1jwy^;YwAuNM2L{HabbY8aS69LsssnCN z$W`Fke_se|v>HHmn3fETrr$V&U+KS??Y4OW%m*S{aM71I>aw@53Wj0VE4+6b@1t5~ zXZTkyoY#Gztgg}5cvJr;wJVm*@znpxw3`3L7ollUQfix6fu5RE-T+OUzdL0tOB~_o zyK1Je;I>&2-SWOPkn=WriC~;6;ad}mY#wX?D=J3JZ+kC;f`*Oe)jmq_e`uHle~;$M z3r6&bC5+xEZK}x`9OrfH9X)?uKTpp64SI(7zSBO#;(0WB{$-z}T9*JNeL<3zQgPf=%Wh#Ms6xVQ}Xz%m^1cS*3HbC>U4N9wuK=D;lhZ6E}lxbf06| zRc=-Kn*(gL%A#8gAR9IFTkbk$@ z6BRD_!tMhp!_YlR=R9FZbUZSHXl4;|h0aL9@77F^8GMRQ+ zwkL-lPH_APc4(Eadgzxi>!gm}Y&DNhoO3MdKxu*qWh1{Y% zf&;UeWi+nrr>@EbeN{14+wkyAY&C`o4>mI_2yVALL!CcYGcA>MvKZpH_RJx&-~}U9 z`(S)pv!{?&e(u97Emo872jmZW^&6`ln}!7#EJ2bSJ(qIoX&sgZeEJFOjfuAz&RdJs+^%jnD!Wae_WBWM$M&o z%^7ZM#Q2u{MObYL+m(J*@DSnc{?4}K_j=mgtch|^!wsp8rSj3OIDzH(;u9u_ zUx&E7ehoKhxHp1lLPgr?#puYjJD&Z4i~mHS^FH*z-SfD-!FbW(0~f_O5x6#b^EI}m zz8+A2XMcHtYcM%y!m;PhYLE%47^*nB=NOIjr`-DzOby^doeIC|g>flA5WG*hhsq^C z(|JHKqbsTr)f`0jJVIi8zf2j#uGkyo9RJkhvS?Mjkkdct`%M{)c^GU(h#qIFjv8}XZDNx zyYce(Il)`v|H!HXrw^P23Jgr^e`J-d@E?dGr*Mn00|%Uz{?XPJg=flWbD_$$P>ZS| z0({yE8HL6`6uhV^uQM0GI{RsJv!z%oG6+_4^B)db}y|4olCd)DXc z#g;c%!kx(e($mw{qc}&Bov0Tcp`;zwm1NbpyrV@a0{-bpDvq~>jGvhsQ((lQ@C-snYE)89fM5rSCX^1QPGD6nur3eI!^>+fLPs3<9SkB^m8qV}!wg>8 z*-kO71ATqhcO~nL%odK9)uY>g_VDjMm^Y+fm2AYi1dtFP2hQOWKV+=5X~XS1WAHUx zy&Q=^^$WL>^5W7A4BGHs6l42@;fq}*}k_5U)_5gUxgIsXWd>VG~Z9STZ{hy)8z zbH^Q^iSc)b$~1*zK0t-eSkK&XNpW#JV_B`LxfLgcOGb}Hk}-Qmv9nxv-dBoO8och9{>B#1{@;603XlC zpyrB-whq=s!n0wPR|oS{1Q?`=7J%anuu zb}O4dkV7gCeQ!Y%x17-04ljCOJ3MC*VdCF>4ju+VO~AfZ>84%ATeX=T^ zX0ob^+~KHkwzb_mUK!E7bCR#Ne8wVD&aBT`XKH*C=)`-5Sa7!LchCf)pCMns#P@cW zCO~Bw?Ubg8i#D7?k=U%DU1Y>oc+z*)FrF1Pjwn?#885XRYCCdO9@$tREH*6&(1`4C zr6E9xq0H{%_|tRTg=dv@>?aSkhp+|Dm#}6UiyWbR@CE(W$JN=Hp=+Dux7Y(QZlOV* zUo}~vs&#({<81Z~rG4{(Pil*)8;&!&t3oe;cT#eVi@%)q?-KNlv=VX(<9stcgAiQM zyjMIUjEA`JmV5PP9=|CNiY039Q-)l;f+IM++@^*{n^Ccr2C^v4*@Hz9CUFSU^bJa~ z1E{k7Os1U6A(TI*FsJC#D8gPKwXnxts|MU?e(PyhI?Yl&+&h_s#F9tIhhl(FcVc<@ z9cR{K_?x`Zqm#VS_z1tSm!dr&7evMpjd;(cnGt3!*(UTxOSb|UrQx2aH)=~41zww)h{DxFAb zAPVZ@UAo8FCF#dQl4kj!3p#h&NERn*k+Q;`??K?9!p_&rb{)Aa;GZQSgmXR)=aZ)T zfX0QKmL!C%4mg#!y7=^>oJ$Ee@Pby(${_D&+u=Z zwvenb9bCgCzo<##C!p?AN#AQuwPnIXU*CWULS=j8G}! z48lRB+X*gjH7^sZh{6Ee)Eu$!Lv*gv#a ze)vYq4|qnYlpTwURSZulHS#t1ixdcl34yvVs`*8qW{DWPQp&$W@QjGwqoxBjS4sR{ zd<;RCoCk1w_%<_Q3mIRbi^-#Olx%cyx`fHJ?bsIwn{Rq&-nM6fnc=7vtxdsEXW@$! zs8&?SX5?L2A;Fq_DwUML6gk3fcDA_*0qt9pyvOn(8JlC@A%flA2M5?xT>2pBUxG z071*Z>(kN%APTjH57Dq^UaAIl*@Q{Z$K!Xlh0e=1AR9A0=|^hvr<9qy`H$Sjjs^rT zBR{x&BovS?+lk~yBUI@;k*0h3YdEb=p>c=63}GCC(jI@6z1O*{CKU1UeR3=zlw0sl z@h5CGJU+XgieBQ(lD0MbD(PV7;A}Fd=B9-nUADs=P{M|`Mwopy%sf2J=&vG-CL0_--YvhqT>1PlZwAurq6!kB?TR6njIGH&rUq#YlEZ0=7#!Y4s;Tf zP)UB_SG#}3_}e3{xLO;E8{Q1OqM24Lc*3*qGq@ow^>}ZlYUwK=*Z%bG|G{i1x!%97 zzfT|6CWI^=uzF_qV$J|>DJi)H{8y#I<*(29e^ny-UzM^IRDg5N0BMXbX#bygUMV~j zAQ4C^eel*Oa}v~T96cMbi2+oMViI{7mJPysZrz*C_aV`$$x?1)LD#~FKkMvjfFi9T zLCmPXC4WVg=eeiqn~N&C7Q4Bfdw<;YJkNCdyiT!$SvQQ|eul!(uhhqJIyu44v0)+p zbezU1+q>drN&ph<(R&BVs|cXh?H3k|AfrrKNoV4lZX?Bob9sxinm=B;Wjs&D3y4Q9 zS)cl(HHbc4eR*AWV!-lu2gr#DY~6*y63ms^7(5oX z?z8X6uRKFtBYkYE60`57{ZEeikccU9D5xCCBX~mvl8g<$5>W;(sJDNu#H6oopo(r@ zTwjpMD`c3>Ogtw~yN`GmP7xyzh-E9!#6!35T!yEr(j%lrzwh7C_3E)N`0ja% z4p_=8w(mRw-u!|di5Z=w)Qm94aF&I<%^SDNDBz#Wj`lLM;=!Zw;){n}_J!@WSjBge z&=MAfbk{wRF##MS+Ksmgs#}UKw4x83+Ncu@bU?gG9$AX;k%R&z`DKD3oe-A~xxm-S zK=sGtP!-qogZ=kf`bKPC!$$j0f}!E-Z6{A~AUp4Si(bBMg;{WO9^tSrA&iR(d9cjQ zBUuk7h;(smyM5Nb?U)Lb1TC0`@9M1xDGON)sV!TH;Y-2mTdZ~~!JnLcNmNNDWz#M5 z6DY8V@oiMDmS4H?c^GSS1M5#|E6W{4Qh)~49rOn^^chU=j5X2ccmLA-#v5KeT}FFF z!D->gG1iVd!{67)v4jfNoX<|>ob>`yX)XZXU(y^rrJ`rE~%-#eqLFs^Onj3VXwMh#zV}cKF5ug?!Ymh>X+ns_6d6 z+JLUGv|%pWR4)`J)kT0zUr6_u!pMibg$B*}?jns zRlKWdr}n3QBF-nN(90P+9-}JYD23{a=8ge-Nef`RxUu2h>ptr}8}L&Y82AOhPgjO( z)aS>U?^jsw;;zV}8z{rA{q$|e13_}?r1ux!T}U>jMaCf3HsE;L9mwo-65er=2A?O? zJn5*6cs63t-5=vhKTbNFW*;gbsq=#`(wK3B3%6S!!5EoDY1S<)F+GL+qBD_bh0LFh zHB)Bfrd6h`kpk#nr8Pr*&Wj1{h+)Q%s2b?>m3{o@9i6RB%L(P zP`8g3IuV-DHp3!h>|}ox=&dSo2rs^XecvOs@P-8qz7rP@cyeM*Y>C4}&^qp#V>8H_ zQ$r?i-N~W68Lg2_iEyBNq##liAzJ-N!!tHdfT+;fYv0Kwek$59lWX8MfRZW(=eJNU zHs%Yu*1PeUX!;qV^rr|Og3-e*SS*J@eEWreWpCs8s8R;;Q#ATpvT+g4xZMQc-`7s@ zb?@hXJSHdwAfkblO=WU;h-fm@lbCr;4S(0YMrM%aPGAbizI|8W`3`!fCOs`A8?n}( z1348Px-zuHE2i*Nm`%+kg6g8{Tp+_-?OqY&NB+iBYl?V82TClH{W2FwSn}`etv16* z!P{IwBiIgvS6&J)E5i4fP8@!|5YN=J)LaAYCIkNT> z2%EptVlNwhhrRlP`G)i#3lVQJhCuzB57Gb4$A~&BFhKp(Q+RB=w~3*@_4{xz>Vep; zJl6qQEQxI6&`=`_ebx6{$YRi{n-{{ezP zeZTQxBYxP7-LKpxH`1sT`WP~tZezqxYh-U5-2|B(GwO(c&gAQ2 z!FL_4_mM^$uovX}^iL?-DOv|q(j_YMReYAtR{N$r5IknqQ z3uvLtb}=o3#}6ila+U$^$40j1oMCueGOn_apLUCjmeU@%fvpc3eO6MPsBVb>YU|tE zRn%7zWb&878uc<&!ctLWuQW`xPwdx6`@w$_*qx^B_$lV%?sjo|Ow08)$b69AAuIP3 zR&;0BPxrdJb=L##%o!G3DDEN?OjST`xAdVjF5;&_7Y~2RHq3UXw}R>V<;Yy!C*|-% zNP?w0iH>9({n)l+aU&~g)+ohv-4uhpIanZVl&ohEMB8;_<3!LggIV3OjUf1VDa(J< zboFcX4qN6?eIR8N1hRZ&5)zs>QSd6J8)g{Pg_35QQdC^ zPiypHrfW;(oWA-I$+9!AFIs!pM-S1jFx5@1mQogWeauG>(#NL0?(s4n0cFyTr!oAG(5_*c#iA4PI19U zWAqY&Kr(X%;kFDnoVB^Y3&#HveOV~J0-FQ}O$%`zkw|!%DKys^SLO6I;q==xDCa11 zvnjtWl$YdZgOBnee_)QBqR}^zJ|?XYHPO!&O5W%u?S;t8D>2D;5eUJXOoaA3M z5sY8VrBO$Ba(3r1SQ&pxraSHsC-?#VgOuQZEH-*GvWG_hjJ-!Kv}-7HxJQ=?fq$hR z`siQi-;i~R9YFA?ZU>W7(zJT%-c5<9_-tamSz1f8)G(%Cr#? zKa&c7j^2=?-Vl4E9jz&z2d4-QT4oyl_jAO3a8T8taL{p09BhB^qHm^oX}i(OW#T6& zEDMGai>+DdCM2hLxqMo4D!njkAR3aM_Qqe}n8p5!E7@1YUamq=3xB)xfcZ?VS8JnY zb~b2ic_FS-+R{s>rs9=rd|b`7r5SJr=^{iXa#Eo=LuoI`$J4e7Ltety_;@j2JMB^6 zUdz__I_S$nDouY{Mvs~4!E4RW%h>1RrF?xg`xaKRe}su7Lfh9)UJg<$$t=?MioPz;-ioq7g3wO2+=^KdSE^~Pr!Ved%R z_~jPeBd<=|ID55IPo<&=Avnt_zR|}kdG*2y#xtcH?vQ`NC0l3Ny96H0WmMg0+g_M} zO%pfQBE0c}S(re}Z6ybCveIXzyxjT=UlVf}YSNpR@ftDlP44qoRZuwTkz_*Lc^w*v zf)DrNVi_;vtClk+s7pDbRiYhxYdhDw*p& z#+x|o<92`EEVb@AncY(CcIW1z@ojLw!Uf#`-U7c!@Sv_4#k-h=?)LL;-s7Xq zd?$+E{;hj^x_Wj5`)tXHs#*1NRQ04V5t7MVs_B2@eU(rMo;v;x1I@A(EEqHf!VVGH z%Lka!!Rakt(3H+t&mhy=2FjJR!^OTv`u}3J34$oNL-|Co)InQ=d(>AWA+yD&g1Jel zqpedRg~FflBf?l%(VY)+km~WmaH~o7ZcMca;yC-j^a<-B)e4qOu>=<$6i_PRSbqGBevOON!M8(EN23Qbo`ZTsYX5F^*-y53jEHRMrUE zXkHAs#|N(v5bE#``}hPui13p2)+1gX%=iR9DUN|xkVjq(h!(hJ{4fmID^`=QiOG!7lS>aEL%W#j z4%2kR&RMre*;Ipfm4*h9fl#s|%@?SV=`q@bNr>rXYKz5oU7)p$#_Q&u3$%&pRYGPvL-Sh{1oW<^ zP)nX}+ka-_m8KWKmiZa{wvuOpYN<@4fJUo`-lQgt+BDic0a-jQ77+f3UI%{)jVryq zAmAFRPy()OiXA*SN?V)HQ)kP0+BQx*V%^Q7bVt*9id=u5dh&GVS=A#~${W5weF~7M z<+gF^iwTE3-PO&JJRR7Tr~X^>G!XXW$q1L{X*gWb)ZB7?ou{t6u40r9ztBBSW~}zU zrcrV(DkfF5j?&O#jT&odu^NAuP@Ni=(sDHh>1}FUMQhdQs=!Y?0T3F|fUBV#9dSjR z_chl}{6I4__pUs>dw=bFdpPXjaQPU$KTjWug)7GC!B|)ur-x!Kqx8{H`b3^S1!FX| z;D1c$K9i>>YoF@R)32QqO?*N9{>E47`NwES%ggk9o?eV?siAK?MHPQ%Xu~+=W8*Xy zTiPEQrSUvnto>@9Ua70d)2n&<#wh*H#YmkN_MD;D3gfAkSf2hcTwc>aU-CkGe{xG@ zN99IuU3qh!{vvj>uk5oF8>8>%>F-X{_9fmGi+v{!cIX?uEA)dMi|Fsul_#H|swLiK zCr+NGMNKP!GCIytWZ8d-CEh&!Q=Qg4Z?P{=KLX`OZ^xO5FNlD({~?0ZX?5jI=cu#x zKlAi@p8h9Km(NDd(E3R64x{vD?L<-f05hgd>h>1{JP!aa)I7?bizRF>5hMq%I*-g? z|I5u6X@wY&L-d*&8)2yx)S_S+1#Y1>Itf_DhXJppJ_XAt@Lhk@uV5JkK1BB^SVn;@ z{0c0iz>m|@3YJmeXX$eamQmo((-##iqrflXwIr~N0$-%BD_BN>zeC?uu#5u#h<>bK z83q0cmnm3Azk7)ED(FAlN3#8J? zIT9rN`gbQVE5UykwqxbB$rTN+>FKN%s|Ag|&7Mg-0{${>;OYsY*90~w$S z7YSI&K7_54whxh-=O)5y^qT1Mlfr{ zSR)_T+#||1L6{2IDBCO?Vq?5~|4VRHiuE)HxNVHr?ho*K8Ib1!d~;}wx5UC8b!dC6 zr_RHpeCruHir_r}e1JRL9p!bH-!Ai>OSC0)iP|N=>dN~OV~C{caGrOB+>q)KPGL_d zz+E`!Wt4xfe(rAGEm%(vezO7?xz}!VOgzS z7Q|-pD35rPi=05w@VHS{M69NHZcS7n^Exe4E^#Yrcr9FF4P4?jc-p<-azEVRQ8>ht zpdNoi_5U_}@`rGqH>rxzDRCFvsh1Y80ooe*2wU*fr^%=4+9@fF$~zxc-idp6EAXR5 zFrvVZ7r|W${A3aAQQ*lU81^Xm(Mh3PraaOc^R&#e)$_Yw}>J`&Ep$5$o2mVP)i30-M3~u@DBh0 z;U1IGBOH_dVn}~cP*ikPC<)t*qDh0q1f{@34W_jwJ~hMc?RM#YWp=lQ82KUo3uA&t z6Muj|%6PYEjN*eYGjq?JbMLu#=G*trUjaP8vcS9J<96eXaUks>g^sad*nMNou%jUM ze3^PtXa|v4xiLud_enM+T?3#apj7=}kL3ID&x@<64HGb*) zneQ`@45WE4r-ZH-5-Bfq86A;IxEAA$`g*-#Iy5rg>JS2@PLwH|c08X1RwCtEu9A*V z)@vo>n3T0U4!a4dy(pko6b-Xj!=%9Mp&Uuem!WIz9~_dMYM2&S*lzA@bz3ibyX~#* zR`ljoKU{T=l9U1s7X`{LrO#Ew{iH_%%eAvkR?k8eT*BoN<}lBN z^I?RJfcanApPo6z6kx!OOAFX3jcyj6jYVi8lgEin0% zADd@C1&u$L;Ou-iKItf-%==xARxrUQVDSrPUVX%DwfYGQC%9I_64N$Lb~sGVRC%($Y2jr7(=jS0taIS3FjS1egIHQ z2M83stMO_F46{wl&uJEVYeQx@ci0m-Vi zv#Z@Vt(ElqyLTp;NhSf`Uyn~n?*0AFIlr?nzx&*YCyo%&1*X%O?%TI-)AH*ox|HB< zH5PxWXs8HwSJYMnwP;^Bq9nsw%p280D%Rs_L{$CDg++ZhWlKomL9#q$aBPvs+7Vm$l?};m+h+4lVuJrY(@%pv;YlrdHri5b> zS(s*Ct@JDP5hd1BzoF}DHJFsh#$<_NpJ}#dyKj8opA<|qR&8aPF}}Jwq9hU$$xLNE zYI0*-OM(bkY}O1K6`m@CMnVmy;^E{#{Y02X2RZ08nM&z&rZcC9m1ri@X*g&#lx2TN z%(P(A5#zfc?xZrA&Y)RLbEkrmXf{(R$ojOPZcHd9M>M7;>$hz3fzVuX$ux)NF*)*g zBwD~^O=?>!urF6bb=g|dB&dK`{EdxtQ&G5)Ey#Pe40DC!ITuK*F1Gp*TW)fYJ z^9FsnUDG|SS?ykiOIItgn3i;h)TA1ZBCEKA zLZy9BmAhMuyR*l;FIVF3?zn#zbq5h3UC3qbC1)p=)Y)kZ^a#MH0vEZsh#t2Wal2wJ z-9c9hKMcsUStxvdzOVTQVo7Ch9^*R@xA|vn?u~1ElrEuk-E6xAl};m+Ho|PNq=OV; z_a^Exe4$;5styVnYtWl*N8Qy*ywXlR2>QCdxCWtDJ*7!(Kz z6=9JQls3xLPkRtuN+hD~*%I3w)AqzR=voC8Mm`vzYfAug9o~BEbOWN)AnQ$minmvb zBHO$N`qKK0oOn^udfDf)ejZMIrp=fj(I5jJ#v@ zGyszCqxYB4ZFD=Bzs64gg%o^EDy$~$^g*mN+vzSCH!+Y%s!^{nv7P=Kp{S43Z*zZiKy0mu4)iOLlv;(5 z_y|r3sfl1boYj%Dm@9mY?iIWa<}$a=K~p@g3?S=%92!;r;1uP@YyL`Xm%MPGOyr=!M7+XI4r4^X7i4;fz9_m6-z2WHAdkzm zpT5Mj>|~)(xk`lzjbQety0ZHc9b#JRnZ|Jq?8b=@la!m~CnHmuhI3_5w_Pi8tjJOl zJ;7uTi?^f}7gFUbs5QF|^?aG0ETs`T!c==wsf<7Vq>_IG{iky07EqMvE69FmLEF{6 zNxfDe;J->=E2XFDIC_bgzFgRIWc|%S&(O01?m75tR2k?}aZ)_FA?x8qD=3IRPcO)H zjK0Za@_Oy`Z6@zY1!?LAyV;y1(TgGgPF3gMmFXq=9%S@-x9?i9v&K$8zzb><+Np$t zUKZTc(2svm7!s+jMAp5_J*`D^^{ez_0sX(oyIQP3+HI#;08T2ZK`_s9IQA#>Q=zh- zF)e-f_!9jB87<4MuyRuz5}xZh1zrld_$B>Hrq}7$pypYbsLJYdMP0R>ehZa`VEjIl(EHD!NOIn%0Qp7UaOJ2i(BBK|@Sddnzt|3a$HVt987gn#EI0-c|x9A>t)JR#GlD4(T4 z4IN21mRPS2I523Tg?@xhOmilRvMLphgiw7MV-8cR)CiB<$}=q!ckY3LE<*i+39x; zdY9(l4d}GFoi`$T7qBVuCS#mSAU?)A--#`bXe%7NnYWa{6SpGRaslt)D@C+F!~u~7 z6D`p`aoBc58CNsL5=$a{E#hkz!U%s0os+6do-~Spz&NrfuR%cD)1yT6v^GBOF!IEF zgH<<*w>z4OB*O?~x6xqL*|}S0Riu?gS*VbvCfs7I>s9(yw-OsLKmmzqX33P(x@;h;#`+!HZvY~-*y3tb>xY5|3}?7DI~3*laACJOzJmj= z=Nkl_eduwDK}dX~%r^;7brn&OPwVLs!Sh~G^tKt!eyhy4@NG<2bTn;hZ*5=eZtaPo zwG6p~sYDXPvY}SDaCoovwj%djIAEY&cg*(MX&tBv+_~+ds<2NxTn~EY*WG@g}^!oyoH2yF|7D;xx&l>i+R&io=s&6s~jBbpMD_!GrF zwHQ^2G4z}sQM?U)!zL`*ca#)TGj_1i{;Y#E&B}M8_AH zp3hGVSv+9$Y9XUCB`S@?Q>4^Qg($89{%@Pck<;T=P2OFtL?ZsMXgc{IACmb?oQ6s= zOi%p3ve>)4dfdQ=okWbOv^Kl%9`8on;`&yZiC7NCRg~gp z{T}Ax=`38BJ+ zb(#+f6UO)Yct^jE{B1MdDd8anYSY@dGbRlZwtKqgnugY zYy2|@DaO+;ge=<&Ke$YRZCLG>GQZ5fDrgTk_ricECcl3{pAbyN#nq{?H1V3lSOpuu z<2PjfE&m?kCB!GCSQ1lofe`aNQ**(8jb~S8jz^g;X@bBRNhJQ6sf6tK&!&G8yuE;RGyVph)-=sXQ+b-^r|GPK zFHK9FRcWdpr0SYsy6`YHGWmwc*)c**fwr17HD_pDtxs(F4ig5E$3|##!15$Xf%WDZ zzjJH#Fm21w_M_{?dUb}bI!Y!SbUFoSC(Wly^3X~$nPl+=nk=JuHA%EWqQ%4#tsDiQ z@!o$#G)gjX#TFiC0|5{_O{F?D!90wI{Z)9D#iu7jG|2@aLEUnox+ceS5dXWKz0RxC z6wA;xX-XPDz7gsV?AXzsp}m$vbiMUSstE+l&V7E1^G1J~ZgJKeq7UR&@4)JvVznc; zayM2!Bvt~>djRPC=pnjqm>wLV{ecF{2t9uk@E)Xx)AacaJ(i(^Ba{v_SiLSwh7KR5 zqf8Apm+dfpooSGtby>ypH<+FR=>{oH-x}nHU6S)Vx+%^Wp_hOwP`^Jk`aITun5I_- z$pthC27JvWb*Aa(Y5Glrb!hYe_J61E*NOd^E7J7GWdg7qpnowy%dM8H^rzR-^bdc5 zvPT*ZWElr_Nw#sYjgQmY_t9JczoP@&hNyIeMgwRcj(ULx$Ob#4cG=Tx9;8`< z7M{m=o9WHcZYU8@B|6ltF6#(e1Fn+JGL|w7R7aX;V3U3hsnhHnq_Ui(1|KJ$abdl@ z!D?M*FSom-G`senIOwvL+bvfKQOkerx~vU$ovyu*uFejS0pqeafWpw|5m@T_0(J%Q zp%co~oMjYIq>ST4f7QpE=$0<4{PA7;~;mq@UU%={4RKFQ-jU959{zg zo#maDn}q`zFIQPUMRQy>{mq=_ASfdZ43Rp*YM_jJGTeLAc)VIXKF(SP&K%~1etx;& zwgJKb$0aquXS`*c8s@!I?9PACS8SkyrQEI|tS)B*EDot5sxIes$4Rmbk;N=F8%kVu zS4mC}`U+ys>MAi7hWS0hL^qG{ErE8SjXMykIc?x!TZZ2^NDIBX)g@T{cHQcC7=};t zUA1Zc&>%IA@I64RMl=U%NBAcA|3@->??JwQ{Rlr0X!BMdIn@OH(-}n(gbEW`7N;Uw_nvT;^Dka<4 zHW`~@d4ArqM33kjp!t6e)eG+4q=iBy>>s6#LLaiI8Ius$PjnUlOR@A0RT&$X@hAoJ z70tH@R`t4bsi-gdvtDkF(|IT~X#VhfF}CW+LQ7FWSCNg@0d5;A>uzYV4~NGgNQxY^ zmrkR5QK&vnGw3CnNw3furU7!AZlW^NZ8XbtJC&PWrP-!8XpVpBZJKMIO)m3%nrB`_ z^Ubxiz~?+yp|iN&T=EwTkfQDE%!hMSq#BOnPfZowh7rr_-LTI6JC5QuwEpv z41d*Io#C&;nbUv#jrAh_0&Uf0`~t#Hcm68Gz_$mf0w^yA+A{nS-hU8iJ5Doek60cg zxz@b2Z3vTgTkUc3kMPTZ9qR${qcs1x4X(d10M8$0bL{Oe)xflf7m_0MSHTGLO=gqKSY}SBMZm*U*2<`Rq)hx@dS&CH-acAf`Z^>+)lUA?15xk zFT_5GZ{dXqUibh$lsH=z5gEwL{Q2fjNZvnQ-vDf3R^YMMI}h&NYZ=~B(sXy+u;n(~ zFpV>%Wv+TgmkDh2`r{2@*^Xg zn*2K>vy6;?oY-7yz3`n6ii?#oC@^^=yVBP(iTtzc8w&F>hS~3H{3wmtZ{noSsMIg~ zcUfpjr8|ayPRUvsF;PGHb-Bok+cGu0rxKO#3(PP5HTVxNUka3#mMC0lyMz+?4re2DoC1t6ITu790-7d7a^I4kZqtx^i{(g2~lq)Em#3 zeggVvsc%vG1W-!{2)_=Od1(Ov0OtV!08mQ<1QY<1*&`H_Pkb(aS_xpA)sdcgI(|u3 z5+{yA6fhAvz=v#;K%AgJAa)XBVmlBgq=G<@<=?T0EEye1%u-6Xu%%G8w53Nl3Jq=D z1GWKzY?_wPZ5wDy@6r=?X-f~vwxun-D8&2C`+v!@BZuAYLZZ=oZ{ECl^XAQb^OUa~ z`^@7+bhi2@raP~HzkbWAe_GTVi|;m5eTyQC;{A)li{k0Qp+qv4OQcgxgXumK{TVZ9 z#}jMe%k2}?mjn>O61ls zT~T*}O`dRDZ@h>4OPL&X^_Tjon&$Y(pcRXlPc!7(sZ8_WD2e{zb%|^)ljzNhe{M;Cr*ll3>N@q=C( zX-_AU@I+{uHK>8fYYq>0-J>47CL}cUnW)_Q}Ew>CoUmYNf4Ma+jHtv+bxq-Xeawl(vg1ZvtO` zGSTay%fus~Z+!)0wBgo4&Dc;E6zj>wGPwCmmKk(~kFFH&s-J9=RBTYLe@=o(1vkD* zR*ErQ^v1p-%f~XZ)sokQD$K%u;}hY+4sq>v(qdXs!Asuw5aHlG8`m~1U(xEJT}UUI zC2Pj>nM7{5r3--#QEgpfmnqjFfhz`ob8Bx&#c|%tDy(UrLuDB-&2CEi=xTz-?p#`e zG4@o987Zi$1FiIfH%&ug#%q}7PafYqWTrL`iB$~B7Q;emRL2*C^0?6{b8km#D4&CJ zW(;d?sH?Qn<(<=sFK!1TWpbd}UfSoQJv3Zgd@_SUz#;1LHiO=b%Yh!mA6MOf8E!{ z!n%%bft)^VT&#qM+UBQs(rqH-UztvtdOU6UM6yrP)a^ccw|MpJ362irI-SDai*wGU zH=6sbImcbEQgnGAz28T7&<6y6kO2MU2K=<2E|Gw9C%VM1Q`q<^b?wK`wiSVpyXhX$ zyG}WF?^(Qieq1-?$hYvG!M)~BPff#OW zPk!)>&`>6giMinrLdUSIWkt3oJF+#~C30D@_MQYB5b^kbARzFBuWiYva*06` z;Lx-~)5B9x$E4hO$VZRRqd?w3Cq4P0p$r10iR&`Id`9W&>q(aQha02T?6$?#tN&QzJzQGdx4z6ZY>TFCDj? z^-y!zpdUhG#D{J`06+a$;=+&US;Vht3kQiHTQf1K31b$2%#t|!AAsfASig=hB8%zt z|4{^llF!pmeDt66Q&|}Z*FCr!xCndwxfQ^Efv8(FcU!){U&6}fe6B1%{R);saxCv; zy6_**j^%=&->>N}2U?lOa)96Z=tcS+61Bz^WvaB)byl|iv>EyL^at^dKjL63 zEoji6;L3Y{fk|*?e~~o%XZovr+#<7(MSXFw$(71ln7aZ*+-^}Fn0MuEzpS6^*p-oX zrI`jDg9DUD8rZ?MwV7+#wxwgWpNZK^a4mKuH)mT0nDo@T$wsT6YQu#b z^6{yB8e(lOy|$;lqoc>xY_VmGC8!U&)~)a`s$bW(ts9zFdAQE9c-wGJ!qU7-W&zgX z25uC8jl(v+69~u6KwsQa^h4Be11)WdT}61s%Wz-oIxOaDKFi0;`D_6w@0V|_sK3iy zq78WtRdpp}t>SaUHE{i_FWj!XylJ8DH+>DDRl%<|_ay;uvANy<%*% z-w-OE*#FP@=~RFc8HHsA30&)`p^=|=@>O$)81?oH9q43SR`he6FGWJ+KFNwm(az>% ze7A>DC!E=y&I9)8#~ST|p&>nO;(;N5)Su3TjgjGfts1G zfaO!WQ%GkXzHd^gKT$mJ0q8X0qd>JNKLqfEth9SXG1MG9f)m$}Uh1=?pT0y#B^rLR{3&B|nIaFs^b?Bcnb^pGzrp0PNe`n6 z3Qqe#Z}7wN_?AYpJ%o~nA7NY|&lVhq)P)`%wcO8sCGzuQf~Ifg&!8J-jhh?HTzo*h z@;d5T(^g{2;6A`d??rQES0zrp_wAK4R2=1oCB^Cmljownh?U*s?O z=ng*0v@%qeG2!{L*3!OzkW_uyuvH<(QX%=-Lds3~0ZNKbaWQZWX6rrt6dbl0fhOl+ zls*1+WhJ+VpPuprGVQ}|xm$i+-0~X})mbUJ9#?Mp_*(*lz76|l^z-G`w4c8#W!_?b z2Dol*E+-H9(6t5XTJIOlq2f_3&3gFzR-7UN9Cb9O5lDXw*G^=Atx)@%u08la{1l?o z#G{^UK9w? z$-gf1)v~z;qu?-xq$8Q~^KZrBe#0m)0u^6Q{QP?hk^Di&2)hDhpxsyaPtyNqXrK?e z4M(}TzrQQ%=f7HiLx1!0XZdro%fG{($d<@e=}g&MrcMtXc0V@tIv=Z|wLA_mcl@}a z7%Je7ccVb{D+el8rIZs_ETuc#h-K(7uC zFsXzpU28Q9D>i4fEj((rwm>$W+=JY-X!SPO(?_7obbRNfV^Fg6nb*fjLq82hOp9mJ^ zCF1mxb#PRt`P2fnNUE#SbW2rxe2GuZS4;KniS>0RQl?*>foO%!I($e88Jq}{{Su3; zs4eNiqZ(m<;dHiH?wv<9Sug1q+Yfhs)q;AS)9TD(ma~3@lK5;IYB}=tww_WIP&S5b zpRHDS)mf@lzu9)C_X0fWlHv5aA0B!8edK9V$Pw^)j)MDlS zAU5kUugROKxI8ua)f#oa%tsO7>rJHWEZ|XXMHHidXJMz36^qZ$YMs1e4-BUJJZb~N z!O9gYJPP$gwIC5-q*Ma>>Y_niq@P{YCb?P_-m0vl>GG-ds$0N-{BEP)y*iIu9DBW3 zT_T)YCcS&x!-m=_CO}T#kk0tkr3BV(YCF?Ob<;jMsHpH`r-q|MaMxOy~Zue#@IIPkzo*F^E*XfLoI@R3?)j%9(v-*Sk;F{wM&kjZZDeH1*ZX z>V;)?sR7_7g>u@PD9ZDz-GY~HQ-FmH6RwRL1GrKdTeV$uVGn*3s}QMQtQYFiLeDjh;jPV|KYZ^&4)N9AG5_H-ZI zdjQ)n2s1luiymO0`Xo(!z&yZuClj z`m<*8hcM5LzP~pV=!`qbH%2X+M(BLB&Wdh&lH4QXFE<>fmC>$ITJ`uEN2@d7tUW-r z4FTu!Xv9^Z)%(d84&uxC+i!I8$oS8~n;IS?T%P?@>--!U(M^uVo;e#D#^|C=hp98l z4WqRAAXpGBocEUVY@5pCc#NWoo}k5l=v*9)b~Vhoe3W)T&HYpt)+?VDK1^4NYCF;H zjdmTSS>eZ>_mMa3SUy5dezIJC-xT@st%2p6zy-ArpE2@}!~P0?>xsr;7-i66yHO>L z6}oYZW*D@RIXI5+vfeN+Y9vRPD9Ke-4Ss*8hV_KJ+5$%yQyc+LqVr?7LP=66on%} z=TWNG>Wq-5VP}Cp({KbfnNPK}3j1A1r)wIKC&Gw>b`}NBD!>P}FCX{fKTnk0t$9J#%d|}_-9oVaAd~SpG>a#$eh;|;OhQ`Ow zbF8U7n(9MhC3_6YxLq0Oqr{2Ua>p0fYXX`Q*Ps zu2;$@+k;-Q!;hSMEpR6N}*!jZFo5Zj64WFWw9L ztyB8t_L1>#z?XW%O^4~lXt(s)PWYQqdbvQaz!jZST=6cNRdmIFzm1Ilx+!YA->djD zGJeCRCZVO%$9?|$L-JAP5Y@O2GpJ2(ajvE(A&?1OL`yZTqgGANp*5Orz!ekP1rxVv zL+_Lm#69oVbb!*D=IK^V& zl6)_EoU1f!(2wwcMVL+_cUkX?mLC$mO7q7N)SX%Y`fVA8EOB#5s8hm=y$EDECq{Lo zn&NLh_*ow&+zL7y-u$}d0j~SOioBv;Y;0&e#Ez~*v=G;pjqPX@*pDNx;h6=V6K!?f zjW9togU*14+4s;P6u$}2M|yqE_h+Y zeTY{>Pz|4_!;8P^5U-6GBQ!UNzIN&3m(jN&Vl)QbK|{nfinK%AQ4%O#C=%hvBGNd- zozaM=D6&d_M0Sr*P0&-6_-2vV-4HaI%H(aHEYJSxEQvluLCgrc!;PQeUZPE6SDm{$ z5iHr%8#VMsxnIv8C{4w1v|D+b*6^O2Vk?~-aR=Q`Qjgs`&w0n)wBa!Ci$>*tSgyxj_$>u~n;iSwqg}|6L3h&_ z--8YE>_}wGq+Z1$njZi8K5<#+f7`HtZbRVTN!%abV!(;qjmfgJ{b7b{f8<3?B z%1~J!cO5Azjvd$V2lbBk6!@+hzDMk4Oxj07*jA!6E9k*~@74Ro#1BufmKcm_7<6W- z;g2?djPl2i&>Y-)Q$5S~Qqfvs;kI5wZ{x z5G%$F_8L4F>4YU9_+F#AJdT?>byVk@*J;RqLm$)mshT{;bLc@GaV{Y5@xvJN(BJIL zHLF}eF{N1?GJKOpLt54;;N(Hw(1}iW&PDdrod)kS_*$pI*Oiu*OoKl8*k{Ky_XPWO z7W+P%-J|257E+3#vR<)|CL}Ku$z|O(zd+_vcTvAa$<;TPy2Yek`-!NC@iugIK zdyJ|XaGvXF4lhTkwE_pbl>$6K^Z02xiGN4)RW}7u%`H%O(#h&MtT$U;NNjMB!x{qZ zw>E~y_)`x>yBng1=;UHJ_;e{8)bK-p_zV{tLF+aYxL|WPfqP82`EY6I2=;}XKyH4} z1`o(18w|8&%iEEqfm(yz`C*av+Pfqixg2W(PW{a@n_p>l);3^;h^vN=MBIY5BZi~Z za}QP3@aH4m5kjR z45S~RS@T>w5KHIs4-+e0HyXfyX%_^YM_}N$(L3k`nD{ojL(})sr!_qYw-Nd*J+JAD z^gB(hgL%vsE?9We$BLe$rFJup^SBZ+!)sQ(pB*k zpDjB@!NW+l{Ga=&F^sa}(_{RTs6c`j011u~9Ohuq^)UY`h_06k{IVQl(0Pde7;!sV z4R@=jQP1@RjQz9#;29X@FRe)bueN#{n*v4vr}!JIS{0}Y_zuv2!k`hTLIv#C8de3pLBB46t8mWG2fctj#$yVnV|{T6xISCH zc?4Z!)ZsmV_kh?>H8jdj0LzvFb)98gRNMRZ2ayKp9y(OIhfeA4 z4(aZ$5fBNH8d^F>M!MtBAt0U7AyQJ3BEo;!Hd_K>-*)Qfh_r2Dhz1QruX5H5{ z7Xx>w%e6Mwr2D=^dDJMT1Wx3+t#(w1C;pg^)Xb`R)th7=%c?p2mSlc?S%HYX8trw6 zU!XbV7YHu+2&vR8x7%JcaEbpTk@!kf=n1^$Q2VXy^bV4C+#_{_UjUY|WbTqW6A zRKF@|z-8`*+;ew{elo(o;xY_<8iSoFQC=g2IXUVhC@jA$8~b?umD^TT?<4ZZ?$M^6 zQHJmlYt}*QB+cNw(m-Dg<}l@lRHsAt!RBLr@dp`jods+$NUtnzopx4MJ?49ip#4<1 z$Ozf=_{O6b+F7rlA_evy5@#K?NN2^rlklZH-;zF_C7Rl->=?!CzYL z7%EchGlOtl3Ztd`jf#6L7%HQRGhUXv&cAGfzz;k236b0FPxVu_*oA9;^`wmd;6ZZ| zRLDyN!}wp;of7Dxf!4jDpS>v#FT=w^1G^g0H~G<`BsXhW+w}|1l{)AR~?XC!dv?nVjxidsn+ow*Y{q-ls zCiWz~_;GjF;)@l1lZzKFm02QL24`(EHbpYPPfoBh+L8|^PAS_|ClLeHCZ(=A)8OP$H-Md|3QIjjQhlGgWpS=)&5jBX3TxRCC zQaW>JSRzM%p-eXr{KH*|dB6-~R++mzi83xzd>Wcp+P{+>4HQH~SAcxgO7B!V`O^1h zIeGzyw72>T?~_-ccR>CmD0trck#-5_`QEq{Ut($jo~?biW=)dBc-gmwnrT8VZ~rd@ z)iSvsxE9t>EAp;%btAoodYC4^(fTzok*}gWMb3l}e8?d|MdNQEVzvhj`MYe_=7^OY z;4z6({W_35Byx2MTV!5i(UtndF#vmm!qJZrzk!HXzApH~gKl_rm`5GbFwSyAt#< zj+|2{V2?iy_&uVnt0BIh=NGFYI8c@RO=$UrL_c9|hZ|wm_w8@wfyZtmR5`e&|M&?x`_V}ZMWxiiw)zz%;Te%`FC)vKWwEj~u*)vjVq+AOw%a&po$ z(x2fuaQtv;7I7p#*EkR5lnF*{mwacwjskwwF8A9^Sn4f~qt(-v^q?)_Ljef)$?uC< z7r;y zm?bsSl>`+z4F9FUmg?+=WR&s2C2jrHxm?%5!=Bh~Nj=C^*-tDh=XS_XyTv!axCh|o{AL(CB^n(qq$~APnIr-BGKN&_o3I5|&-ptWAQh+d z1S_K(5`GX#e_@B*TL6~kBLic!*wh|O8T_<9UN-$~M_IF-Kvr^I(j+@E#!+ygdHt0A zi8R6n*Vi0cn><)62uWwY`u%$+d^Xc3b#ekF8p~^aHhlAfs@KL2FXJ_lPZp=KM8h8; zZbo8XS?GiF%tExHu-71SWooYZ)Wae()MNcF2E18^@}N-&$*N2CZQpn&qTE-Lpw6)= z8%*#k{|S;#TW;%eQpjLX*O4tQ9+jKd4aux_ZijjIkEh7#>Amk5Yi2Abu!`F|7yZ)% zM$P-5pJ6;F5#E2PFfh30J-J5N>Y-S8))rY&B8T{=^gbgtXM1_DFfne=;Wd%eDoN!ZeUd}$-YyBoQ>rK@@ zi2@ENYJMb!ggSwdH)FDVfA&tEP*mi$L~A$(u8}VQn_=dKk(`9r^j?LDL{Jbo@X=gf zXvfgWiPhycua&2)-O$2We!cDmEyPk`D4Xj;P8v~_vpmGJCx>F^8Y(rOwfA&n!AWr+ z3O=x^%K7wJw+Ur@Mn&q)=lLU-wx!t&q}hZU>)667g{Y4T7CI=F6o=*_i?)uhgWn=A zYobZ!23lS5<>MF0n|+z%k1TVvLq90{%vIeP{@v?IRzcy10r;kGj>%+1Qrq;tPQMyO z^@>Qhkln+@I=TRRJU&=9mVj00Vqn}Bmjl@ST2FtZPZTxg5T1ECqmGf=#=!VXqW{gzw>O{eA{?~94u_%T9c^H zQjRvPIX3KCOxt>$vKM7A1X+_5Cf3{2k?B%;w+{?b1#z7$W}8RW?h!&UmzrB3IyQmd zgCFCbLQyy9yTylm=D9GVmFk+%{YfSBtpf~Se{vNJ=9haM#9y$^b47XuuWZXkAJLeD zHGc@04XeDM<&U5t4C5c=0MBKwW!k~VMUTf7&wZ6;gtW|7ubQJ@8kuc#v6z_i&vMzH zU^}jeE4?9o$)87>!c6O{h)mh{>}7*{)~0i^f;x^aCnIFngxJt;je;%ph1LOoA|6lg zn1^@~wN%-J$eQb@JIM&;QPx5-euuOX`UZs($0@}$b7NO7jv;XmBA7k&Vhq2p<&#Do zBO0_f0O~|Q^I2X=z6F*PVxx`{nHS;YQ)n4L0n&PQ`HJTIfd>;sR~h2>1y0=~n(;4x zwELNxbs4gI;>;Bom-=LxtT~2`qW6fGmI#p7J^H^LaURI+0ng@hKO}ba#5AE2RX!v1 z*)d80agd1_98^*0fhA2$hPVXq&`7HL`EOLA0eT59E@Re`TqYRDh6LHkXh~k#UgO-x zjdTYEvTdzlkSzq6vyBLky=IkF=+q5}rrvd*uHs{84Xq#@X&_K++u7kA|E9M{o?36R z{KKn&-Umgw>r>2zo{DD;(`RTVmWJ&9Z-JN;yVvF6YB#Aum|$yIsib&`VM4$l{pTt0 z>8&`C*0mrenmPpBQ`y6r;NDNrPQI*@w?IlH-;#c5m6y*8Nm+CZH@ z`%0)1DDqgc{REib*_v~m0eahl}Y%p0Be z+eud(Ue(2XVlKb*)kU*)eC_ zgp$|<1P5vDtB}hQh~NX27B?-hc%HL5=_@!P_F=uAVt6ipDJO}TSB;^Kqro$`arOo- z3vY~Hr+q>l^ybF4$RPQu0DBBBg8=nu6*Bu=SYLZF(zLbMJw2&c8icpBU8O zG$pi|8I>}_{NP@*uiIk*m*q?^b|H4m(KS~0-9OP$ybM32Yx#0&AG>tk!uvGAj3l6U z6ztmx*WsKK^J8Foi5G?`GmR#>B4DRT+5O2mbu+5cRc*dWwsiRtnIetmuYiOPz`^KW zek(sJM>xJKU_)^WMR@+&J>3^MIv^OPNTK+|;f7|mk*H9JY){?Ikl6#q+R`Nc*^tZ@2YgTr77 z6J-ixad0fEGOmG!lZvHJp{Uh`*_2uHGw$NE@$8IwqSJe|x>;ULjF>#7O~UYj-M4>V;L z6T6-@@G}{ht?L!j>J^(HzE!hY85^`o4%B4N(f+|&7N|1NaP~uh0sK+KP$p|Xs*RVF z0US;7PPpXj%4)hw_S>(gU1KL?$TxR2=i3)_H}Y`pL4*I@Y*&RK@J}##FX3%0LqK>n zf0a3;g)kq-Fonh4JW(x!A3@3Ssh$ASQ=X4S39ZKpu!HjNj};o@Qr;7xBXk9olua^L z)8M2s8;M*di!rq0EPt0vu^bA#w6a$Hgtofv=<&cQ}?&*4KTC&2oRNxYl}37;n%f zU!Rp~Ivi_c)>*H_3sOF9+*g9}MgspllE|1&%birDzo}@8i$|!B^?l%YpwDb``GIY8 zT=>Ch2%}S#uNVadYC$mhsKRQ>`>59e124QBO#|ANFRDHrmVtsv`zD&S!UO>po zq-ErfM&_1|P6cMe1uJS_R*7G;+Ni-c)G8B0zshtaotKX)y>B z(y*LDl9@@^>Kaq#RXBzg9Y`_D_9=o0uQp<#N7jV8>r4oG%C9heyd8)}1rk@Jt;ExD z2`Nx9`m->Xv;|s#I|31g0>jU24*X{#FlgO=sJ<98p#>8nsWZ82MAsydl$RU6-i=h` z+-$^O5Smlu>~*c9GS=&^9Q(#gL~1baP$#`K^YSlf7qS9}c2VoQk$CJ`4wjKA16&NI zazdUubNuc{5)jMlXUAirpdP=la;spBa{SMeGlq_%UISw~{k3wdpgAVVFMP})OBvkj z-RDhckw{=d(5J`FnS09R7YZ;CWW^qKjO(=j=H0R6OoZs0q8g>qkEJB>=RTZ9ziOV5 zW<)>?A3qKII+#5>O-Z_IBKW*v?{E(G)f$miEY;e&cfMMCfvg4__q&xl5rR2|)7C37JcYF&H?L0DFOjJ7@Q?tX&h;^qN zl1DK<0V}uO?qug+5uTEvHDBYELV#B)w(9JncC{q>jbs+TlY##5hxQ@t)8V$2-JENi zV_mWAP7lnr98u-~85R#C@?x21E}0v_!r{bVk`yh_z_L->Do%=nJ`%fjhDlR|!uC*b zW(Tt;)>O+3L92`xanD#MtOLfR;~sS5&6^U#b|<_2}MjYgddNS|;+5E@r$$!?9l=h|yOw!~XI_wC+K=zzt)s(C5?c zOD}mhsV){_Cnnn0{vpHSEG{2A2i^C#ia_|NG^**;>&juC9Zor+8^v8GXVju}zpmWk zBi^>-4dy__v%@?T8WF_xCt0n*tnIQ|;ON0A*~88dN$)hn155*G#IsYSvoR_W)9ngr zVUxuKN2LN9qVddB>-IxTpEq=CJ@k)k#xqFLUKpNYretsY( zxzf5Ftx8P1Ra(=PuDu|}&0DD(my&kG^pt%&XVh~hxr_FldZ#$CmU~Qf!dVs94NP-@ zah=kGSk$|M zY3(bdXw zqZB-wJT9Sa8fRf1xb`W2)Xj*TFBq>vCfc_p5>jF-ETHUjGs#6-pKgZB>|BX6MjLB%AG)xA-4JI2iVP{3gG#*L~oBq zk4=IR^bP`10f8`Flb*KY)Yh0(SL4_CJCD1VALZ<4cKtk}iTbU|>W#2JX#InwvLUI` zFOl4?RYh%FUWuO1Z?wQJ-G|nl@?AodcK`S%Yt0GOUN6$9&(?)l*(q-=$M#ZANE5yy z;SG^idI7kOc$0xr7 z9c5Q1G~m%7C;)))15lRe4x}#U0gC(gwVS{JLAU~t$O8zI3=Zi5?Phw9!AQfzXJ~{kRh)s*nusR{`h(Deh0x}{s$>HpZ*PU z0Pn5l|J%#6=l?{rsAK@%`5~6NKq9P@ZJOQzfcz+WVK3y;@-RuE;{odRh|$4f*{0q*PwfMs{eLT zR|JwNR2YZy=4RdAo}2aUIhSz z=LHSP|Ib|nlF&c}y!SEy0N5XV{IwDUw}B9HTf+;ymty~KV|`Wbpru+gh;ywd@LrP| z0N{BLO-SQ!P!M=8N(Eo{c>uw*|AtT@YIRh=du1a4fb{`*Vs!`R)^P*>EdccJ{IJ{p z4Ix9&>p6k_e<9R0QG}tTETDt2yqI; zzPl3sS#gA4np6+Ky7zZ!*BTgr|6Ue*cxhT@-$9^87U2C17XV;;5Q!%D50sewznk^` q;rzd+t-kOs*xkIC1?ct9kOcrddl1h8`Zvdf9)Se_R8{;LuKo|`10Hn% diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index dbe66e1d66..84c5a9c661 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=9c0f7faeeb306cb14e4279a3e084ca6b596894089a0638e68a07c945a32c9e14 -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip +distributionSha256Sum=84fbba45c7f4c64abc77460e1c00f541e9f960e3c7ed2538f1ede19eacd873ae +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.0-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From 0e1cb2df5e160c8800236cc2e85a40ca6af304e6 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 7 Aug 2026 07:20:49 +0000 Subject: [PATCH 271/383] Update screenshots --- ...tics.api.preferences_AnalyticsPreferencesView_Day_0_en.png | 4 ++-- ...tics.api.preferences_AnalyticsPreferencesView_Day_1_en.png | 4 ++-- ...cs.api.preferences_AnalyticsPreferencesView_Night_0_en.png | 4 ++-- ...cs.api.preferences_AnalyticsPreferencesView_Night_1_en.png | 4 ++-- ...eateroom.impl.configureroom_ConfigureRoomViewDark_0_en.png | 4 ++-- ...eateroom.impl.configureroom_ConfigureRoomViewDark_1_en.png | 4 ++-- ...eateroom.impl.configureroom_ConfigureRoomViewDark_2_en.png | 4 ++-- ...eateroom.impl.configureroom_ConfigureRoomViewDark_3_en.png | 4 ++-- ...eateroom.impl.configureroom_ConfigureRoomViewDark_4_en.png | 4 ++-- ...eateroom.impl.configureroom_ConfigureRoomViewDark_5_en.png | 4 ++-- ...eateroom.impl.configureroom_ConfigureRoomViewDark_6_en.png | 4 ++-- ...eateroom.impl.configureroom_ConfigureRoomViewDark_7_en.png | 4 ++-- ...eateroom.impl.configureroom_ConfigureRoomViewDark_8_en.png | 4 ++-- ...ateroom.impl.configureroom_ConfigureRoomViewLight_0_en.png | 4 ++-- ...ateroom.impl.configureroom_ConfigureRoomViewLight_1_en.png | 4 ++-- ...ateroom.impl.configureroom_ConfigureRoomViewLight_2_en.png | 4 ++-- ...ateroom.impl.configureroom_ConfigureRoomViewLight_3_en.png | 4 ++-- ...ateroom.impl.configureroom_ConfigureRoomViewLight_4_en.png | 4 ++-- ...ateroom.impl.configureroom_ConfigureRoomViewLight_5_en.png | 4 ++-- ...ateroom.impl.configureroom_ConfigureRoomViewLight_6_en.png | 4 ++-- ...ateroom.impl.configureroom_ConfigureRoomViewLight_7_en.png | 4 ++-- ...ateroom.impl.configureroom_ConfigureRoomViewLight_8_en.png | 4 ++-- ...pl.configureroom_SelectParentSpaceBottomSheet_Day_0_en.png | 4 ++-- ....configureroom_SelectParentSpaceBottomSheet_Night_0_en.png | 4 ++-- ...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 ++-- ...vite.impl.declineandblock_DeclineAndBlockView_Day_0_en.png | 4 ++-- ...vite.impl.declineandblock_DeclineAndBlockView_Day_1_en.png | 4 ++-- ...vite.impl.declineandblock_DeclineAndBlockView_Day_2_en.png | 4 ++-- ...vite.impl.declineandblock_DeclineAndBlockView_Day_3_en.png | 4 ++-- ...vite.impl.declineandblock_DeclineAndBlockView_Day_4_en.png | 4 ++-- ...te.impl.declineandblock_DeclineAndBlockView_Night_0_en.png | 4 ++-- ...te.impl.declineandblock_DeclineAndBlockView_Night_1_en.png | 4 ++-- ...te.impl.declineandblock_DeclineAndBlockView_Night_2_en.png | 4 ++-- ...te.impl.declineandblock_DeclineAndBlockView_Night_3_en.png | 4 ++-- ...te.impl.declineandblock_DeclineAndBlockView_Night_4_en.png | 4 ++-- ...licenses.impl.details_DependenciesDetailsView_Day_0_en.png | 4 ++-- ...censes.impl.details_DependenciesDetailsView_Night_0_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_0_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_1_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_2_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_3_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_4_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_5_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_6_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_7_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_8_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_9_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_0_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_1_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_2_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_3_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_4_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_5_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_6_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_7_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_8_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_9_en.png | 4 ++-- ...ckscreen.impl.settings_LockScreenSettingsView_Day_0_en.png | 4 ++-- ...ckscreen.impl.settings_LockScreenSettingsView_Day_1_en.png | 4 ++-- ...ckscreen.impl.settings_LockScreenSettingsView_Day_2_en.png | 4 ++-- ...screen.impl.settings_LockScreenSettingsView_Night_0_en.png | 4 ++-- ...screen.impl.settings_LockScreenSettingsView_Night_1_en.png | 4 ++-- ...screen.impl.settings_LockScreenSettingsView_Night_2_en.png | 4 ++-- .../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 ++-- ...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 ++-- ...s.impl.attachments.preview_AttachmentsPreviewView_9_en.png | 4 ++-- ...ttachments.preview_VideoQualitySelectorDialog_Day_0_en.png | 4 ++-- ...achments.preview_VideoQualitySelectorDialog_Night_0_en.png | 4 ++-- ...s.impl.messagecomposer_AttachmentsBottomSheet_Day_0_en.png | 4 ++-- ...impl.messagecomposer_AttachmentsBottomSheet_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 ++-- .../features.poll.impl.create_CreatePollView_Day_0_en.png | 4 ++-- .../features.poll.impl.create_CreatePollView_Day_1_en.png | 4 ++-- .../features.poll.impl.create_CreatePollView_Day_2_en.png | 4 ++-- .../features.poll.impl.create_CreatePollView_Day_3_en.png | 4 ++-- .../features.poll.impl.create_CreatePollView_Day_4_en.png | 4 ++-- .../features.poll.impl.create_CreatePollView_Day_5_en.png | 4 ++-- .../features.poll.impl.create_CreatePollView_Day_6_en.png | 4 ++-- .../features.poll.impl.create_CreatePollView_Day_7_en.png | 4 ++-- .../features.poll.impl.create_CreatePollView_Night_0_en.png | 4 ++-- .../features.poll.impl.create_CreatePollView_Night_1_en.png | 4 ++-- .../features.poll.impl.create_CreatePollView_Night_2_en.png | 4 ++-- .../features.poll.impl.create_CreatePollView_Night_3_en.png | 4 ++-- .../features.poll.impl.create_CreatePollView_Night_4_en.png | 4 ++-- .../features.poll.impl.create_CreatePollView_Night_5_en.png | 4 ++-- .../features.poll.impl.create_CreatePollView_Night_6_en.png | 4 ++-- .../features.poll.impl.create_CreatePollView_Night_7_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewBlack_0_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewBlack_1_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewBlack_2_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewBlack_3_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewBlack_4_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewBlack_5_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewBlack_6_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewBlack_7_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewBlack_8_en.png | 4 ++-- ...references.impl.advanced_AdvancedSettingsViewDark_0_en.png | 4 ++-- ...references.impl.advanced_AdvancedSettingsViewDark_1_en.png | 4 ++-- ...references.impl.advanced_AdvancedSettingsViewDark_2_en.png | 4 ++-- ...references.impl.advanced_AdvancedSettingsViewDark_3_en.png | 4 ++-- ...references.impl.advanced_AdvancedSettingsViewDark_4_en.png | 4 ++-- ...references.impl.advanced_AdvancedSettingsViewDark_5_en.png | 4 ++-- ...references.impl.advanced_AdvancedSettingsViewDark_6_en.png | 4 ++-- ...references.impl.advanced_AdvancedSettingsViewDark_7_en.png | 4 ++-- ...references.impl.advanced_AdvancedSettingsViewDark_8_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewLight_0_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewLight_1_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewLight_2_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewLight_3_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewLight_4_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewLight_5_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewLight_6_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewLight_7_en.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewLight_8_en.png | 4 ++-- ...nces.impl.advanced_VideoQualitySelectorDialog_Day_0_en.png | 4 ++-- ...es.impl.advanced_VideoQualitySelectorDialog_Night_0_en.png | 4 ++-- ...ferences.impl.analytics_AnalyticsSettingsView_Day_0_en.png | 4 ++-- ...rences.impl.analytics_AnalyticsSettingsView_Night_0_en.png | 4 ++-- ...eveloper.appsettings_AppDeveloperSettingsPage_Day_0_en.png | 4 ++-- ...eloper.appsettings_AppDeveloperSettingsPage_Night_0_en.png | 4 ++-- ...eveloper.appsettings_AppDeveloperSettingsView_Day_0_en.png | 4 ++-- ...eveloper.appsettings_AppDeveloperSettingsView_Day_1_en.png | 4 ++-- ...eloper.appsettings_AppDeveloperSettingsView_Night_0_en.png | 4 ++-- ...eloper.appsettings_AppDeveloperSettingsView_Night_1_en.png | 4 ++-- ...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 ++-- ...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 ++-- .../features.preferences.impl.labs_LabsView_Day_0_en.png | 4 ++-- .../features.preferences.impl.labs_LabsView_Day_1_en.png | 4 ++-- .../features.preferences.impl.labs_LabsView_Night_0_en.png | 4 ++-- .../features.preferences.impl.labs_LabsView_Night_1_en.png | 4 ++-- ...cations.edit_DefaultNotificationSettingOption_Day_0_en.png | 4 ++-- ...tions.edit_DefaultNotificationSettingOption_Night_0_en.png | 4 ++-- ...tions.edit_EditDefaultNotificationSettingView_Day_0_en.png | 4 ++-- ...tions.edit_EditDefaultNotificationSettingView_Day_1_en.png | 4 ++-- ...tions.edit_EditDefaultNotificationSettingView_Day_2_en.png | 4 ++-- ...tions.edit_EditDefaultNotificationSettingView_Day_3_en.png | 4 ++-- ...tions.edit_EditDefaultNotificationSettingView_Day_4_en.png | 4 ++-- ...ons.edit_EditDefaultNotificationSettingView_Night_0_en.png | 4 ++-- ...ons.edit_EditDefaultNotificationSettingView_Night_1_en.png | 4 ++-- ...ons.edit_EditDefaultNotificationSettingView_Night_2_en.png | 4 ++-- ...ons.edit_EditDefaultNotificationSettingView_Night_3_en.png | 4 ++-- ...ons.edit_EditDefaultNotificationSettingView_Night_4_en.png | 4 ++-- ...s.impl.notifications_NotificationSettingsView_Day_0_en.png | 4 ++-- ....impl.notifications_NotificationSettingsView_Day_12_en.png | 4 ++-- ....impl.notifications_NotificationSettingsView_Day_13_en.png | 4 ++-- ....impl.notifications_NotificationSettingsView_Day_14_en.png | 4 ++-- ....impl.notifications_NotificationSettingsView_Day_15_en.png | 4 ++-- ....impl.notifications_NotificationSettingsView_Day_16_en.png | 4 ++-- ....impl.notifications_NotificationSettingsView_Day_17_en.png | 4 ++-- ....impl.notifications_NotificationSettingsView_Day_18_en.png | 4 ++-- ....impl.notifications_NotificationSettingsView_Day_19_en.png | 4 ++-- ...s.impl.notifications_NotificationSettingsView_Day_1_en.png | 4 ++-- ....impl.notifications_NotificationSettingsView_Day_20_en.png | 4 ++-- ...s.impl.notifications_NotificationSettingsView_Day_2_en.png | 4 ++-- ...s.impl.notifications_NotificationSettingsView_Day_3_en.png | 4 ++-- ...s.impl.notifications_NotificationSettingsView_Day_4_en.png | 4 ++-- ...s.impl.notifications_NotificationSettingsView_Day_5_en.png | 4 ++-- ...s.impl.notifications_NotificationSettingsView_Day_6_en.png | 4 ++-- ...s.impl.notifications_NotificationSettingsView_Day_7_en.png | 4 ++-- ...s.impl.notifications_NotificationSettingsView_Day_8_en.png | 4 ++-- ...s.impl.notifications_NotificationSettingsView_Day_9_en.png | 4 ++-- ...impl.notifications_NotificationSettingsView_Night_0_en.png | 4 ++-- ...mpl.notifications_NotificationSettingsView_Night_12_en.png | 4 ++-- ...mpl.notifications_NotificationSettingsView_Night_13_en.png | 4 ++-- ...mpl.notifications_NotificationSettingsView_Night_14_en.png | 4 ++-- ...mpl.notifications_NotificationSettingsView_Night_15_en.png | 4 ++-- ...mpl.notifications_NotificationSettingsView_Night_16_en.png | 4 ++-- ...mpl.notifications_NotificationSettingsView_Night_17_en.png | 4 ++-- ...mpl.notifications_NotificationSettingsView_Night_18_en.png | 4 ++-- ...mpl.notifications_NotificationSettingsView_Night_19_en.png | 4 ++-- ...impl.notifications_NotificationSettingsView_Night_1_en.png | 4 ++-- ...mpl.notifications_NotificationSettingsView_Night_20_en.png | 4 ++-- ...impl.notifications_NotificationSettingsView_Night_2_en.png | 4 ++-- ...impl.notifications_NotificationSettingsView_Night_3_en.png | 4 ++-- ...impl.notifications_NotificationSettingsView_Night_4_en.png | 4 ++-- ...impl.notifications_NotificationSettingsView_Night_5_en.png | 4 ++-- ...impl.notifications_NotificationSettingsView_Night_6_en.png | 4 ++-- ...impl.notifications_NotificationSettingsView_Night_7_en.png | 4 ++-- ...impl.notifications_NotificationSettingsView_Night_8_en.png | 4 ++-- ...impl.notifications_NotificationSettingsView_Night_9_en.png | 4 ++-- ...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 | 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 ++-- ...res.preferences.impl.root_PreferencesRootViewDark_6_en.png | 4 ++-- ...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 | 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 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_6_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_0_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_1_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_2_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_3_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_4_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_5_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_6_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_0_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_1_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_2_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_3_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_4_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_5_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_6_en.png | 4 ++-- ...hake.api.preferences_RageshakePreferencesView_Day_0_en.png | 4 ++-- ...ke.api.preferences_RageshakePreferencesView_Night_0_en.png | 4 ++-- ...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 ++-- .../features.reportroom.impl_ReportRoomView_Day_0_en.png | 4 ++-- .../features.reportroom.impl_ReportRoomView_Day_1_en.png | 4 ++-- .../features.reportroom.impl_ReportRoomView_Day_2_en.png | 4 ++-- .../features.reportroom.impl_ReportRoomView_Day_3_en.png | 4 ++-- .../features.reportroom.impl_ReportRoomView_Day_4_en.png | 2 +- .../features.reportroom.impl_ReportRoomView_Night_0_en.png | 4 ++-- .../features.reportroom.impl_ReportRoomView_Night_1_en.png | 4 ++-- .../features.reportroom.impl_ReportRoomView_Night_2_en.png | 4 ++-- .../features.reportroom.impl_ReportRoomView_Night_3_en.png | 4 ++-- .../features.reportroom.impl_ReportRoomView_Night_4_en.png | 4 ++-- ...permissions.impl.root_RolesAndPermissionsView_Day_0_en.png | 4 ++-- ...permissions.impl.root_RolesAndPermissionsView_Day_1_en.png | 4 ++-- ...permissions.impl.root_RolesAndPermissionsView_Day_2_en.png | 4 ++-- ...permissions.impl.root_RolesAndPermissionsView_Day_3_en.png | 4 ++-- ...permissions.impl.root_RolesAndPermissionsView_Day_4_en.png | 4 ++-- ...permissions.impl.root_RolesAndPermissionsView_Day_5_en.png | 4 ++-- ...permissions.impl.root_RolesAndPermissionsView_Day_6_en.png | 4 ++-- ...permissions.impl.root_RolesAndPermissionsView_Day_7_en.png | 4 ++-- ...permissions.impl.root_RolesAndPermissionsView_Day_8_en.png | 4 ++-- ...rmissions.impl.root_RolesAndPermissionsView_Night_0_en.png | 4 ++-- ...rmissions.impl.root_RolesAndPermissionsView_Night_1_en.png | 4 ++-- ...rmissions.impl.root_RolesAndPermissionsView_Night_2_en.png | 4 ++-- ...rmissions.impl.root_RolesAndPermissionsView_Night_3_en.png | 4 ++-- ...rmissions.impl.root_RolesAndPermissionsView_Night_4_en.png | 4 ++-- ...rmissions.impl.root_RolesAndPermissionsView_Night_5_en.png | 4 ++-- ...rmissions.impl.root_RolesAndPermissionsView_Night_6_en.png | 4 ++-- ...rmissions.impl.root_RolesAndPermissionsView_Night_7_en.png | 4 ++-- ...rmissions.impl.root_RolesAndPermissionsView_Night_8_en.png | 4 ++-- ...cationsettings_RoomNotificationSettingsOption_Day_0_en.png | 4 ++-- ...tionsettings_RoomNotificationSettingsOption_Night_0_en.png | 4 ++-- ...ficationsettings_RoomNotificationSettingsView_Day_0_en.png | 4 ++-- ...ficationsettings_RoomNotificationSettingsView_Day_1_en.png | 4 ++-- ...ficationsettings_RoomNotificationSettingsView_Day_2_en.png | 4 ++-- ...ficationsettings_RoomNotificationSettingsView_Day_3_en.png | 4 ++-- ...ficationsettings_RoomNotificationSettingsView_Day_4_en.png | 4 ++-- ...ficationsettings_RoomNotificationSettingsView_Day_5_en.png | 4 ++-- ...ficationsettings_RoomNotificationSettingsView_Day_6_en.png | 4 ++-- ...cationsettings_RoomNotificationSettingsView_Night_0_en.png | 4 ++-- ...cationsettings_RoomNotificationSettingsView_Night_1_en.png | 4 ++-- ...cationsettings_RoomNotificationSettingsView_Night_2_en.png | 4 ++-- ...cationsettings_RoomNotificationSettingsView_Night_3_en.png | 4 ++-- ...cationsettings_RoomNotificationSettingsView_Night_4_en.png | 4 ++-- ...cationsettings_RoomNotificationSettingsView_Night_5_en.png | 4 ++-- ...cationsettings_RoomNotificationSettingsView_Night_6_en.png | 4 ++-- ...tings_UserDefinedRoomNotificationSettingsView_Day_0_en.png | 4 ++-- ...ngs_UserDefinedRoomNotificationSettingsView_Night_0_en.png | 4 ++-- .../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 ++-- ...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 | 2 +- ...s.securebackup.impl.root_SecureBackupRootView_Day_0_en.png | 4 ++-- ....securebackup.impl.root_SecureBackupRootView_Day_10_en.png | 4 ++-- ....securebackup.impl.root_SecureBackupRootView_Day_11_en.png | 4 ++-- ....securebackup.impl.root_SecureBackupRootView_Day_12_en.png | 4 ++-- ....securebackup.impl.root_SecureBackupRootView_Day_13_en.png | 4 ++-- ....securebackup.impl.root_SecureBackupRootView_Day_14_en.png | 4 ++-- ....securebackup.impl.root_SecureBackupRootView_Day_15_en.png | 4 ++-- ....securebackup.impl.root_SecureBackupRootView_Day_16_en.png | 4 ++-- ....securebackup.impl.root_SecureBackupRootView_Day_17_en.png | 4 ++-- ...s.securebackup.impl.root_SecureBackupRootView_Day_1_en.png | 4 ++-- ...s.securebackup.impl.root_SecureBackupRootView_Day_2_en.png | 4 ++-- ...s.securebackup.impl.root_SecureBackupRootView_Day_3_en.png | 4 ++-- ...s.securebackup.impl.root_SecureBackupRootView_Day_4_en.png | 4 ++-- ...s.securebackup.impl.root_SecureBackupRootView_Day_5_en.png | 4 ++-- ...s.securebackup.impl.root_SecureBackupRootView_Day_6_en.png | 4 ++-- ...s.securebackup.impl.root_SecureBackupRootView_Day_7_en.png | 4 ++-- ...s.securebackup.impl.root_SecureBackupRootView_Day_8_en.png | 4 ++-- ...s.securebackup.impl.root_SecureBackupRootView_Day_9_en.png | 4 ++-- ...securebackup.impl.root_SecureBackupRootView_Night_0_en.png | 4 ++-- ...ecurebackup.impl.root_SecureBackupRootView_Night_10_en.png | 4 ++-- ...ecurebackup.impl.root_SecureBackupRootView_Night_11_en.png | 4 ++-- ...ecurebackup.impl.root_SecureBackupRootView_Night_12_en.png | 4 ++-- ...ecurebackup.impl.root_SecureBackupRootView_Night_13_en.png | 4 ++-- ...ecurebackup.impl.root_SecureBackupRootView_Night_14_en.png | 4 ++-- ...ecurebackup.impl.root_SecureBackupRootView_Night_15_en.png | 4 ++-- ...ecurebackup.impl.root_SecureBackupRootView_Night_16_en.png | 4 ++-- ...ecurebackup.impl.root_SecureBackupRootView_Night_17_en.png | 4 ++-- ...securebackup.impl.root_SecureBackupRootView_Night_1_en.png | 4 ++-- ...securebackup.impl.root_SecureBackupRootView_Night_2_en.png | 4 ++-- ...securebackup.impl.root_SecureBackupRootView_Night_3_en.png | 4 ++-- ...securebackup.impl.root_SecureBackupRootView_Night_4_en.png | 4 ++-- ...securebackup.impl.root_SecureBackupRootView_Night_5_en.png | 4 ++-- ...securebackup.impl.root_SecureBackupRootView_Night_6_en.png | 4 ++-- ...securebackup.impl.root_SecureBackupRootView_Night_7_en.png | 4 ++-- ...securebackup.impl.root_SecureBackupRootView_Night_8_en.png | 4 ++-- ...securebackup.impl.root_SecureBackupRootView_Night_9_en.png | 4 ++-- ...geauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en.png | 4 ++-- ...geauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en.png | 4 ++-- ...geauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en.png | 4 ++-- ...authorizedspaces_ManageAuthorizedSpacesView_Night_0_en.png | 4 ++-- ...authorizedspaces_ManageAuthorizedSpacesView_Night_1_en.png | 4 ++-- ...authorizedspaces_ManageAuthorizedSpacesView_Night_2_en.png | 4 ++-- ...tyandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en.png | 4 ++-- ...tyandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en.png | 4 ++-- ...tyandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en.png | 4 ++-- ...tyandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en.png | 4 ++-- ...tyandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en.png | 4 ++-- ...tyandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en.png | 4 ++-- ...tyandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en.png | 4 ++-- ...tyandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en.png | 4 ++-- ...tyandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en.png | 4 ++-- ...tyandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en.png | 4 ++-- ...andprivacy.impl.root_SecurityAndPrivacyViewLight_10_en.png | 4 ++-- ...andprivacy.impl.root_SecurityAndPrivacyViewLight_11_en.png | 4 ++-- ...andprivacy.impl.root_SecurityAndPrivacyViewLight_12_en.png | 4 ++-- ...andprivacy.impl.root_SecurityAndPrivacyViewLight_13_en.png | 4 ++-- ...andprivacy.impl.root_SecurityAndPrivacyViewLight_14_en.png | 4 ++-- ...andprivacy.impl.root_SecurityAndPrivacyViewLight_15_en.png | 4 ++-- ...andprivacy.impl.root_SecurityAndPrivacyViewLight_16_en.png | 4 ++-- ...andprivacy.impl.root_SecurityAndPrivacyViewLight_17_en.png | 4 ++-- ...andprivacy.impl.root_SecurityAndPrivacyViewLight_18_en.png | 4 ++-- ...andprivacy.impl.root_SecurityAndPrivacyViewLight_19_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en.png | 4 ++-- ...andprivacy.impl.root_SecurityAndPrivacyViewLight_20_en.png | 4 ++-- ...andprivacy.impl.root_SecurityAndPrivacyViewLight_21_en.png | 4 ++-- ...andprivacy.impl.root_SecurityAndPrivacyViewLight_22_en.png | 4 ++-- ...andprivacy.impl.root_SecurityAndPrivacyViewLight_23_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en.png | 4 ++-- ...yandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en.png | 4 ++-- ...eatures.space.impl.addroom_AddRoomToSpaceView_Day_0_en.png | 4 ++-- ...eatures.space.impl.addroom_AddRoomToSpaceView_Day_2_en.png | 4 ++-- ...eatures.space.impl.addroom_AddRoomToSpaceView_Day_4_en.png | 4 ++-- ...tures.space.impl.addroom_AddRoomToSpaceView_Night_0_en.png | 4 ++-- ...tures.space.impl.addroom_AddRoomToSpaceView_Night_2_en.png | 4 ++-- ...tures.space.impl.addroom_AddRoomToSpaceView_Night_4_en.png | 4 ++-- ...eatures.space.impl.settings_SpaceSettingsView_Day_0_en.png | 4 ++-- ...eatures.space.impl.settings_SpaceSettingsView_Day_1_en.png | 4 ++-- ...eatures.space.impl.settings_SpaceSettingsView_Day_2_en.png | 4 ++-- ...eatures.space.impl.settings_SpaceSettingsView_Day_3_en.png | 4 ++-- ...tures.space.impl.settings_SpaceSettingsView_Night_0_en.png | 4 ++-- ...tures.space.impl.settings_SpaceSettingsView_Night_1_en.png | 4 ++-- ...tures.space.impl.settings_SpaceSettingsView_Night_2_en.png | 4 ++-- ...tures.space.impl.settings_SpaceSettingsView_Night_3_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_0_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_1_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_2_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_3_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_4_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_5_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_6_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_7_en.png | 4 ++-- .../features.userprofile.shared_UserProfileView_Day_9_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_0_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_1_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_2_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_3_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_4_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_5_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_6_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_Night_7_en.png | 4 ++-- ...features.userprofile.shared_UserProfileView_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 ++-- ...ents.dialogs_MultipleSelectionDialogContent_Dialogs_en.png | 4 ++-- ...em.components.dialogs_MultipleSelectionDialog_Day_0_en.png | 4 ++-- ....components.dialogs_MultipleSelectionDialog_Night_0_en.png | 4 ++-- ...onents.dialogs_SingleSelectionDialogContent_Dialogs_en.png | 4 ++-- ...stem.components.dialogs_SingleSelectionDialog_Day_0_en.png | 4 ++-- ...em.components.dialogs_SingleSelectionDialog_Night_0_en.png | 4 ++-- ...mponents.preferences_PreferenceCategory_Preferences_en.png | 4 ++-- ...mponents.preferences_PreferenceCheckbox_Preferences_en.png | 4 ++-- ...mponents.preferences_PreferenceDropdown_Preferences_en.png | 4 ++-- ...nsystem.components.preferences_PreferencePage_Day_0_en.png | 4 ++-- ...ystem.components.preferences_PreferencePage_Night_0_en.png | 4 ++-- ....components.preferences_PreferenceSlide_Preferences_en.png | 4 ++-- ...components.preferences_PreferenceSwitch_Preferences_en.png | 4 ++-- ...thIcon_List_item_-_Primary_action_&_Icon_List_items_en.png | 4 ++-- ...othIcons_List_item_(1_line)_-_Both_Icons_List_items_en.png | 4 ++-- ...ox_List_item_(1_line)_-_Leading_Checkbox_List_items_en.png | 4 ++-- ...ngIcon_List_item_(1_line)_-_Leading_Icon_List_items_en.png | 4 ++-- ...List_item_(1_line)_-_Leading_RadioButton_List_items_en.png | 4 ++-- ...itch_List_item_(1_line)_-_Leading_Switch_List_items_en.png | 4 ++-- ...x_List_item_(1_line)_-_Trailing_Checkbox_List_items_en.png | 4 ++-- ...ist_item_(1_line)_-_Trailing_RadioButton_List_items_en.png | 4 ++-- ...tch_List_item_(1_line)_-_Trailing_Switch_List_items_en.png | 4 ++-- ...thIcons_List_item_(3_lines)_-_Both_Icons_List_items_en.png | 4 ++-- ...x_List_item_(3_lines)_-_Leading_Checkbox_List_items_en.png | 4 ++-- ...gIcon_List_item_(3_lines)_-_Leading_Icon_List_items_en.png | 4 ++-- ...ist_item_(3_lines)_-_Leading_RadioButton_List_items_en.png | 4 ++-- ...tch_List_item_(3_lines)_-_Leading_Switch_List_items_en.png | 4 ++-- ...LinesSimple_List_item_(3_lines)_-_Simple_List_items_en.png | 4 ++-- ..._List_item_(3_lines)_-_Trailing_Checkbox_List_items_en.png | 4 ++-- ...Icon_List_item_(3_lines)_-_Trailing_Icon_List_items_en.png | 4 ++-- ...st_item_(3_lines)_-_Trailing_RadioButton_List_items_en.png | 4 ++-- ...ch_List_item_(3_lines)_-_Trailing_Switch_List_items_en.png | 4 ++-- ...List_item_(2_lines)_-_Both_Icons_-_Error_List_items_en.png | 4 ++-- ...thIcons_List_item_(2_lines)_-_Both_Icons_List_items_en.png | 4 ++-- ...tem_(2_lines)_-_Leading_Checkbox_-_Error_List_items_en.png | 4 ++-- ...x_List_item_(2_lines)_-_Leading_Checkbox_List_items_en.png | 4 ++-- ...st_item_(2_lines)_-_Leading_Icon_-_Error_List_items_en.png | 4 ++-- ...gIcon_List_item_(2_lines)_-_Leading_Icon_List_items_en.png | 4 ++-- ..._(2_lines)_-_Leading_RadioButton_-_Error_List_items_en.png | 4 ++-- ...ist_item_(2_lines)_-_Leading_RadioButton_List_items_en.png | 4 ++-- ..._item_(2_lines)_-_Leading_Switch_-_Error_List_items_en.png | 4 ++-- ...tch_List_item_(2_lines)_-_Leading_Switch_List_items_en.png | 4 ++-- ...em_(2_lines)_-_Trailing_Checkbox_-_Error_List_items_en.png | 4 ++-- ..._List_item_(2_lines)_-_Trailing_Checkbox_List_items_en.png | 4 ++-- ...(2_lines)_-_Trailing_RadioButton_-_Error_List_items_en.png | 4 ++-- ...st_item_(2_lines)_-_Trailing_RadioButton_List_items_en.png | 4 ++-- ...item_(2_lines)_-_Trailing_Switch_-_Error_List_items_en.png | 4 ++-- ...ch_List_item_(2_lines)_-_Trailing_Switch_List_items_en.png | 4 ++-- ..._List_supporting_text_-_large_padding_List_sections_en.png | 4 ++-- ..._List_supporting_text_-_small_padding_List_sections_en.png | 4 ++-- .../libraries.featureflag.ui_FeatureListView_Day_0_en.png | 4 ++-- .../libraries.featureflag.ui_FeatureListView_Night_0_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 ++-- ...iaviewer.impl.details_MediaDetailsBottomSheet_Day_4_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_4_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 ++-- ...oubleshoot.impl_TroubleshootNotificationsView_Day_0_en.png | 4 ++-- ...oubleshoot.impl_TroubleshootNotificationsView_Day_1_en.png | 4 ++-- ...oubleshoot.impl_TroubleshootNotificationsView_Day_2_en.png | 4 ++-- ...oubleshoot.impl_TroubleshootNotificationsView_Day_3_en.png | 4 ++-- ...oubleshoot.impl_TroubleshootNotificationsView_Day_4_en.png | 4 ++-- ...oubleshoot.impl_TroubleshootNotificationsView_Day_5_en.png | 4 ++-- ...oubleshoot.impl_TroubleshootNotificationsView_Day_7_en.png | 4 ++-- ...bleshoot.impl_TroubleshootNotificationsView_Night_0_en.png | 4 ++-- ...bleshoot.impl_TroubleshootNotificationsView_Night_1_en.png | 4 ++-- ...bleshoot.impl_TroubleshootNotificationsView_Night_2_en.png | 4 ++-- ...bleshoot.impl_TroubleshootNotificationsView_Night_3_en.png | 4 ++-- ...bleshoot.impl_TroubleshootNotificationsView_Night_4_en.png | 4 ++-- ...bleshoot.impl_TroubleshootNotificationsView_Night_5_en.png | 4 ++-- ...bleshoot.impl_TroubleshootNotificationsView_Night_7_en.png | 4 ++-- 570 files changed, 1138 insertions(+), 1138 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en.png index b1cdddd1f8..6c79d26f2a 100644 --- a/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:449c07469b107a598ffbaaeaa930dc241a1706312b3a6a29fa77763a595259d2 -size 22118 +oid sha256:e8c7f586a1b8910608ba6ba901eef916b8c38e847dc81794b5bfc9add309212a +size 21990 diff --git a/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en.png index 63fb55cdcd..645b6e3e13 100644 --- a/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b525a67f606797b724e42d79584b5c009ba5ef5dfcfbc021d3ae20eedc773080 -size 18349 +oid sha256:45ebd24e0d99af06a52f5ed28612ad503bbc21319b5f5653daf90bfb14788294 +size 18218 diff --git a/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en.png index bce9dad828..c5ce753a6b 100644 --- a/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58bc951d97f1fe3034c78d65e1b338c1f001df85b748d15ad2744b35111a8e2f -size 20878 +oid sha256:55b00fc31fe9e9f44c2cb2c46cb66e31e8e4f91fa987d09420d1d2ce4d57342d +size 20898 diff --git a/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en.png index 4b22aad74e..cbb74018ac 100644 --- a/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b79b9cf687d2de94f45e7131bb9862e23a96780f140f50a0a1bf6fe9c6a2ee4 -size 17283 +oid sha256:0eae3d32d4208a9959a9a7e7ac733d273722003af13ea7c59337f2b8289a4bb2 +size 17319 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en.png index ceb4413a16..7d2eb3802f 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a79354416a9a99eeb652b0a9381e694529b10e930d82bb04ae175223fe4ee4a2 -size 28736 +oid sha256:f6eab283d68f0665e8f2440ca6bbf28be81aa6e05cdbecba8ba3bd25d156c39e +size 28811 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en.png index c762b76dd2..8a1ccf243b 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:145e1ac30630e4f13df29fc92b2e4f305ec014fe85a4c178e6bc0bb76041587d -size 33942 +oid sha256:768236582fdd9dd6b5d47ef07aa8012c868cd20e088bb0fae6cb7ac31f48f825 +size 33916 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en.png index 6aee832eb6..7b8acf97b2 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9adf6cd9c1d5a0afaa94228037646835c4c22d4ab664d44405f387c6546bec3 -size 41019 +oid sha256:f5f0104589a04033362967c35c178679be41495023c4e8d805963fc029c85c97 +size 41077 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en.png index 7f77ca2730..d8e8cbf4ac 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:47121746126e9d867c80a6426d851100ab81db82e9585d3e5219a2b677d26ce3 -size 42009 +oid sha256:ad30892b0048bc25e6ca453e39ff41f62c5778a0822e4a9b217bfbe37e357496 +size 42066 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en.png index 0f5c6846f7..7b4ef034f6 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:02fefe256f1a0f9c5c0ad464eeddd70e8335a11cc6e73bbc5d04ff3a3ff0ea0f -size 43728 +oid sha256:edc28162aefdb6f67d7d0a3ab47b21154feb7f475ad37db308441aeec038bfab +size 43773 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en.png index 6aee832eb6..7b8acf97b2 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9adf6cd9c1d5a0afaa94228037646835c4c22d4ab664d44405f387c6546bec3 -size 41019 +oid sha256:f5f0104589a04033362967c35c178679be41495023c4e8d805963fc029c85c97 +size 41077 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en.png index 6f7fced7b2..6d642b316b 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1b9f48a2166442bb5a3555128af31d79acf82746517b1352021289a852864061 -size 41981 +oid sha256:546428cfa1a64bd9ff21b6ac6df60767767872d831036acaada91058b038ef21 +size 42046 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en.png index 144166d170..e22cdef4ef 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7b55ab3959b1189d0af772f47da0751844e8ea59fa65705baba0d6828fc3c03 -size 36858 +oid sha256:7c2eb3358fbcdefbc1dfdf7faf2c0f63002a54b6b44011723d01a2f857ac6236 +size 36903 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en.png index 577de0f744..7f3b7eb4f9 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f4c3e7f20ce61d54845022afef017edcd1d8df5f15116ad3ba04a6529a5900c7 -size 39765 +oid sha256:6dde01d87247739630285247d0a642eb0e14ce728b49f466b39c50bde81e0cdf +size 39514 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en.png index 63547859f9..cecdbb82ed 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5de69f76240ae56cb28d4819f9e787f280c8a2cc4cc61aab2505f144414c6488 -size 29810 +oid sha256:ceb4402440bb956a8c1f6c7224c8b0e895651de7e6ca4f15e6e0d7e216f397bf +size 29864 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en.png index 85071dc677..bf1b9fedf2 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:631fe0c5bfdecb8782a46005edfd92e1b42fd323a316b2084a48118e0ad49c35 -size 35260 +oid sha256:d72f23869b29a5d9c7993443795785350251eba495df062adb4c0612b42b0a7c +size 35262 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en.png index a1dbe81d8e..2604908cbd 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:55c66afbe31070cb85746b2ff1897517b4839a9d5767caf1050265f3c10d195c -size 42701 +oid sha256:629c2c1d830ef1afcb07d5b633a91b9a776a2112e1731183d44033d6ff4ed00f +size 42798 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en.png index 765f6713e3..81341995b7 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:508a81fa57693cfd414db0b16e81fe9441b0fb06b43b4ef9a4b4b685a7ab1b08 -size 43752 +oid sha256:13c6d5a6a47b77bfa58c88cf2cf468debf8c4f1b40194bfb705e981be770eaf1 +size 43858 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en.png index 463bf3963a..658e6be5b2 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd5d3ee7b7b5c5f08c9461fa79e98dd08ac791f29f3ef3637b9a8ddd54f036bc -size 45561 +oid sha256:444800a03628241725a962f7c40a8807bd756fa8f615e10577d4412899cfa74b +size 45663 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en.png index a1dbe81d8e..2604908cbd 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:55c66afbe31070cb85746b2ff1897517b4839a9d5767caf1050265f3c10d195c -size 42701 +oid sha256:629c2c1d830ef1afcb07d5b633a91b9a776a2112e1731183d44033d6ff4ed00f +size 42798 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en.png index e652f66e33..286faada56 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7fb6d97314e612541c29bde743190a8b6ecafb22abfb9257b4b3351010acbb7 -size 43774 +oid sha256:a8442460c022c1b4d8081fca23a9b6d70b0bac96810619de5fc57c141fcc76ed +size 43884 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en.png index 4854bb4608..f4dd48ad86 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc921fdd55417c80aaf9ed33b9b30b623120c6aec0aa0f19810f4ed91435bba0 -size 38304 +oid sha256:efdc694c1db28b7535f77ea63fb07e622f5861ced3fb1870e56423cc8a5acf71 +size 38403 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en.png index 560ddb5530..f751e292cc 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cee85a4b9f76fef13813cc0a8542d5c0e767e9be529c5c877c30158225767c45 -size 41406 +oid sha256:a14129b063873056a02ea2ca0e106b92e70ef1b140f254a22ba93a1f3201dfa1 +size 41154 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en.png index bb0f9f27c8..31f52bcadf 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74d0d16d8ca722625e8dc729705bcb46ad012d6fc697fedfbe939d5f04cc6aa2 -size 25356 +oid sha256:d6d94a22d60b496f6cf2df617aad08495dc3951fb9ccdf8db700454fe61f3b43 +size 25453 diff --git a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en.png index 3ec5e87c5f..2df57544ae 100644 --- a/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dcfd9bf65ee0ac3c4509eee17c0a1932781978b12f374964e0279b93728d087d -size 24819 +oid sha256:1486b365029b44eb985725adb236afd5eca2a5e72886b0ad2d4d7d3a15d3c9c8 +size 24750 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 1eedab5750..203c950423 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:6f199ef24dbc9d8c89b5b28503a887f489a6970355d591aa05d08968f25ddfce -size 23900 +oid sha256:f4739a2af7edbcee37c1d0d568ab701e4f6d46dcd8d50a326f6aa0403c632271 +size 23912 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 1a5b97b2b5..d107812a40 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:002bb9faa2d3222cf1b5ef4adb44e9a711ff778a6b6c9f7480620a3c3e69bd21 -size 23822 +oid sha256:2699fdbde0b82a22c1955946afce1ef33da7c56653c30beaa2743e4becb9b212 +size 23799 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 49e0ab6f86..9a850795cb 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:47accbc1fbd8a7d238cd540036bacc5233d9feb5499a1a1f0c9d0cb48ec6748c -size 25862 +oid sha256:512620de41fd3ce49cf4275982d5f30de2d6de224cdcabb5767afab8687918de +size 25856 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 28ccf10710..886f4611c9 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:afdd57a26c55f80a987c6d1e1b7c0f19728fcf99613630897e92ba29423f9f87 -size 22212 +oid sha256:d680e9989168e0fe25bb41f97c074fb3adddb166c620a06c1675e303f67299a3 +size 22086 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 9b7d08cec9..f21401bcce 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:1c91577d10dfa10f11c2fed1781559c513b5b376ce7636a6ce3dfab73933b6d2 -size 22095 +oid sha256:fb46a663675e6f439d65199cece8453340d6191ba55068cfcd6a00063ed2d7e3 +size 21993 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 cba5142ec9..43045a8f55 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:20c44f88a9b347569b4f8ced10b29104541637661134c1a82e2746fa00bd1a25 -size 23968 +oid sha256:f1c1c34117cf6c519c1aae87246a44155b175799a036baf258c479a54f916b2d +size 23933 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 91f02401b5..0894037dc4 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:2f19f7f9fd7675dd46fd61764e54ffa02cfacd08173aee0d86512bcdc5f30fb2 -size 54466 +oid sha256:e389bce27c241cc13f60c247fea578fa4cd1ecc7448c9bf3ac3af1179e693216 +size 54701 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 f72667b724..c4630c3e45 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:31217a40625020e07d4f6d6d98d1d5db9d9fabbf0a9f3e4461e72c26e5447925 -size 54272 +oid sha256:5d56802b3e6dd21b20c4e92d47d9b880085f499feac855a46af601a5eb0bfc2f +size 54510 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 f64c1b8a19..ce7b5ea699 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:4e3c83b95b9b5fbcc07e5d84cbc6d3b54d08e1c5964bfc461be1a9c9c33e6e18 -size 52539 +oid sha256:ef1246daff44b29ee4c2b50538a3a948c2593749c70e15e053b8258a377c5756 +size 52745 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 66f1bc4364..0950a6881e 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:9bd841b458babd88d364e4906d199e48491407547430269dfb7b95a5d3055de6 -size 51527 +oid sha256:842d5e0a5cc1102a2e320b43ea5ffda6cf63e94acdbf42adc39edaa1fb355812 +size 51742 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 1264ea44d8..b29ccd3a11 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:5828d3c51711976aaf8906eee401866baa6683e879d5f29da27a2d2110ab1a14 -size 51291 +oid sha256:82b75ce20a535cf1062c4b3ad86d08dc9044cf58d8035a5fdc68c48119157aae +size 51477 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 89af663213..1b1e2edb98 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:4fdf0d6bbb3a760fdfc93e13c4acbe5703d1fe1b99c1e859897a8dcd319eca3b -size 49559 +oid sha256:9bde8e9c5618ffc2b3019ce10db6fca44e4f23f3b987c222b7e838beb0dcb488 +size 49749 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en.png index e5e44ac954..f13a226074 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a223141e779ee6bd301e81dce129482275e5c4b52c4a9c9a32d528b306c1085 -size 32829 +oid sha256:cd743f58369fade101be3ff19ce0664b36b6144aa1983207dd0d3dcb80505f1d +size 32637 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en.png index ed1732dfc9..be2f400625 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f8f8cc3e8ace247b45ecd3fbb642b638e1c8331e1c3d468b633fb20b9ab0ed6e -size 37640 +oid sha256:d444171f25fcdb8e9b54ef8336a675a72360d9441c1efa73abeabc99818a64e5 +size 37404 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en.png index a563739260..d63b6239d3 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b232debfb92c2591ad527b623dce2e8bd016c67f0369521f80b92790a4908d47 -size 33026 +oid sha256:0cad7840ce675bdaf24bc1891f579939213bb948f1a79530498b7cae5b3ba0e3 +size 32775 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en.png index 00294db240..d793169c5f 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e148e67d31bb016e4a93469306c14a27e0c96156f89a223be6c9614bd7a1a5ef -size 29882 +oid sha256:91a4203d7f5c0208f4d4c91cf7f7629e9119e0f0f923d0f30072ee888d2ca808 +size 29880 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en.png index 9fc1544d6e..32346386ca 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:898f8f403f90e59cde88f07ccbf13ee15994996e877224ff853f22a13f6d9293 -size 34310 +oid sha256:c071220ed6ea68843ff7c9b5bcd815be6c9a1be439f2fa896448cc09e09376fa +size 35369 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en.png index 41e8cf0b11..0b176fa798 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9deff4d926422191a2572589768128d9479adc50b741b803c320ae25ce26aecb -size 31481 +oid sha256:ba43cfd279d4a6cfb5fc2e6693aa5586da1c3c276c038b05d62482cca4606840 +size 31221 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en.png index eb42ac27de..159204673e 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:64cdb3d9cf74c557989d16a2e7ea9dc3534616a5470df8b1f511e541fe2b1409 -size 36088 +oid sha256:b57a073a480319df55c1109f775645c75d8bc899dd6c32c67a2c8111383cbab4 +size 35741 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en.png index 1825517041..c7835214c5 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57b0249e9e6669a6ea592058a7c606f7cd127c927bccf33f167c745298d239e7 -size 31596 +oid sha256:cde30852bb9a8622515d19eeac4e05fce41e1b69c0d64c7d7a61b37b592f0197 +size 31284 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en.png index 783a2460c6..3dbe9a5102 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6e7651c0e0ee202a7fe03faf3ea5c91e201b72979b87fc840f91e7d271d19fb -size 28616 +oid sha256:e8925539930009f4a06c1d5ecb6fe0238273440af507987cc3d0cfafde6c994c +size 28514 diff --git a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en.png index 146b0895e5..342c4dcd4f 100644 --- a/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a1829bef4e91622a6a4d0e5c6d566d51bd5dbfa6aa6531fd9dbb744ddd99a5b -size 32137 +oid sha256:5ed6d2b34ad47c2daaaddaaa0f45fa44b710dc185b521c345aad3468bb5794e3 +size 33091 diff --git a/tests/uitests/src/test/snapshots/images/features.licenses.impl.details_DependenciesDetailsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.licenses.impl.details_DependenciesDetailsView_Day_0_en.png index 2ba05b93f3..9845d87c24 100644 --- a/tests/uitests/src/test/snapshots/images/features.licenses.impl.details_DependenciesDetailsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.licenses.impl.details_DependenciesDetailsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:02c0097a56901f6a18065b7c666b2eb69ecfe76105a01f7b12ee2a17a3994374 -size 18533 +oid sha256:1bd83510626d7556e2e484730cd70ca9ee1a7256a3a10a0a6d75201fa3f46440 +size 18608 diff --git a/tests/uitests/src/test/snapshots/images/features.licenses.impl.details_DependenciesDetailsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.licenses.impl.details_DependenciesDetailsView_Night_0_en.png index 2a4fef5599..a2a0dbc4b3 100644 --- a/tests/uitests/src/test/snapshots/images/features.licenses.impl.details_DependenciesDetailsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.licenses.impl.details_DependenciesDetailsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1770ab8b9e7dce57b85b698c072567cfc36c2e2aff249c624c0a25d36343d215 -size 18287 +oid sha256:9471dcfd5548f4617988e14e31c55d0659b21f9cc8263e8a630fd8154c259ed9 +size 18321 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_0_en.png index 898a010ddf..33ef3511ec 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db105243ef507c209c756015cf41a23150259cbe7ab3be6d233590fa9257b0e5 -size 20528 +oid sha256:8f03643af6b4643c0fbfee2d98138aa0350d0fb541de0a8a627570030a8f3812 +size 20466 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_1_en.png index ba69ac150d..b1bdcee7a4 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17ad972930d2b563e278c5eb1296ce12781b85e939d6769131de08fbab9f3f7b -size 38760 +oid sha256:f53a6b803268437c30350857951422dc1723a38922db4441a97bcb926a0e63ff +size 38724 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_2_en.png index a7ce4c15ec..b597367206 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ffd4f5b8fece04b00ad5d866f6fc11e753e800f956c966e703d1dfc66f1ce8e7 -size 37257 +oid sha256:77ce52ef94d449d8eb37a8d84b297800a1663bc38dc27e2ea87e6f7da373195b +size 37222 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png index 3f99f935c9..56bc529007 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccb0deee31506379cfa76f8d39d37639b6b1f03d7eb2e7d5e8c6ceff300b1978 -size 30397 +oid sha256:76c4f1674cda818e0684869050fbad2cb31c02146726d1ee5e57481940218d29 +size 30363 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_4_en.png index 898a010ddf..33ef3511ec 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db105243ef507c209c756015cf41a23150259cbe7ab3be6d233590fa9257b0e5 -size 20528 +oid sha256:8f03643af6b4643c0fbfee2d98138aa0350d0fb541de0a8a627570030a8f3812 +size 20466 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 d70cd4ccd3..be619b419b 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:6ef91ce622a66945ef5475adbe04164635ca155a2a9e1682bc03459e9a6e289b -size 22356 +oid sha256:fc017e7707b83549cda8c06ffe8466596372132ba0b58dd91cfb20c451b6a417 +size 22303 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 db11b33396..201c56516e 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:a1ffc8d536a239ca11de23f3f8e5fb14b429b9beee03c80bbca0321ec853f5e0 -size 26638 +oid sha256:2f5ca554e1ae330865af0d267934d8d1c6dfe42cc3958db3b15b13d376e8721c +size 26667 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 index e8ae396119..3d4aa9edc5 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ddaf978cdf3e70b01fbee75e7e7290fa390e749b48ae192fe7da0dcaa9a1d4dc -size 38417 +oid sha256:fd18d8bb6e61f616451439dff8690afc7473461c87adf11bb9870319d8e06fc4 +size 38447 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 index cce7a48382..fb4db2984e 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a97492422d54a6d6666c1ade693dc9b63bc9ca07c17d6c1f787c081984c09f68 -size 42470 +oid sha256:f8c9a2dd2c3677281b6486af6a0b8a5405dc59bff0390b6ce1bca1cc63d88b0d +size 42546 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 index 41a52e602c..d194937309 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d9f4d7292e5bfb5bdcc699aa3a5d9e065ce66f232a3175294850539b70a2be6b -size 21674 +oid sha256:ebeb2f14074a9bc91dc892bfa056c9c67e83a64c64d645c77d312d64895e3815 +size 21611 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_0_en.png index aa539ed8a1..70de0a28d5 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc1e9df75619bde2571bad0362f147c627ee44a780fbaa9a2c0e5a49e252d14b -size 19881 +oid sha256:dc9a8778869e47b9874c4300cac52045c4be5fac6590acbaa719a065249ed3f5 +size 19856 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png index bf0e1594e1..d9f4faabc7 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:001bcd1755e837c0c05e493f964ee5c71fba81e811bdaf91effba257743bdacb -size 34836 +oid sha256:124381cc86542b2704b619e798f62f58dc7f3b95ab8a1c4eec3fa4b849462f9e +size 34867 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_2_en.png index 11be8ba550..432cbde734 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:38d253d8b3aa1c4599aa6b6f5982b7ef0c87ea7346aba13054a7891197b7c000 -size 33268 +oid sha256:f373df8ce07aa19d467d43306f5a8d6c78915e4e166e08e39bb39cb303b5faec +size 33305 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_3_en.png index 08d4da7504..317a87e2e5 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:931f79cf0cabfe533162ad5b633c7261d06339073f3bd6c7044761aecc27ea42 -size 31143 +oid sha256:ebbeb66a3f67e48668cadb96069f50feba5f4346119ea62c9dfd83ffd621b7b2 +size 31182 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_4_en.png index aa539ed8a1..70de0a28d5 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc1e9df75619bde2571bad0362f147c627ee44a780fbaa9a2c0e5a49e252d14b -size 19881 +oid sha256:dc9a8778869e47b9874c4300cac52045c4be5fac6590acbaa719a065249ed3f5 +size 19856 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 d79bfca142..d261494eb8 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:69bcf19161f70c27256c1bf0e5b99c993c86dd3e77a42d0e87061730a5c0c752 -size 21649 +oid sha256:8a3d7220c216b6fee2384ba2cb263903a8cfa45f3f97302c722188a4a827c575 +size 21630 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 06ec0c10e9..56ef074549 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:4031ae26bb8465a61021c15b6166a2186f8f99d7a4dbad7bb28aaf83493cbe69 -size 25907 +oid sha256:24b8f832cbaa9aaad66187255adcefbb2d7c4407b911c2675a261b6f480aa277 +size 25858 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 index 7ce1496b52..e66ccc603d 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:580ee0fe2b1dd97496850efd8d8f852046473f5acf3cb42dcf862ac3f6de2f59 -size 40266 +oid sha256:1e31aa9639a3805e3644fadbb01ab3503aedee068655920555a4817ae38b6376 +size 40312 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 index 1f8c2d110d..f2f4d7c766 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f139526f69881e08b17d15013d78fb3eeca76eea5b18d378953c37fbd9d76921 -size 44064 +oid sha256:77e1a15b548d944e57b7d71229c28692e32ad9340d04ec0c43c52dafe16e3ae1 +size 44172 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 index 213a75dce9..dcf2ab131b 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5198742a388a2bd04985fe6b9f035de3878125607fe3b554209b0eb5c4590db3 -size 19935 +oid sha256:cab8ea5b016f20de07dd0134836c42f9fd51562837fe4da2be8a8d38ca1f95f8 +size 19914 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en.png index 3206f5061d..2bdc65953a 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c5d291053aab6e5781e4b252d11a36e596d4dd22a08a2b82e381bcf395f86e42 -size 16622 +oid sha256:4615061f43638296af16cf7e515b4a99652fa864e8660774572191bf5ba14745 +size 16573 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en.png index 295525d526..9f6fb3ec3e 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:916649bc7621d7580c579b3520195eab03f32c174f3cfa5f32f95a19b234c316 -size 18941 +oid sha256:7c6ac7dd26d008a0aff402f8c19a099aa632c94db957ed64db39209e5b9aeaae +size 18865 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en.png index 851adf4f5f..15becdb71b 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fcb4dea012f06580b17e6406e862ff40e42486c30d00213f8161333dc2e57a32 -size 28565 +oid sha256:b3e38957ec880adb0826805b16ce17ca02c4d4b4144beecf5fefe38e2474844b +size 28597 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en.png index 34c22546a3..8dd432427a 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cee47e791377ebd2eebda92de0127e5c04b64d84113f459abd731fe49b672804 -size 16000 +oid sha256:987d10d47bb3b3ccfd089cbec88ea893c394753cfab98cd20fa5960cede5610f +size 16025 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en.png index 52081c426c..d2a6609e57 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f06158293bb8ce12435eb7b78c5d8aef3f92e6c847ab389de82e931dd6d3bfba -size 18254 +oid sha256:ad2296982cfe78d9dda44ebfa67069db317ff09db1aade04c6ff1115ff0c2372 +size 18118 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en.png index b5e2a2576c..6ca5b70c41 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:27879114748c757e4e666151b953747c1cc0369e7d5ac1eb3f81e459e4928b70 -size 27168 +oid sha256:1e86e29e9af95e444c8e78f4ff5289eca8c00817ee723b32c0a01e295b3e467e +size 27117 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 e35ea91583..f33238c0bc 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:891555a0886151040ebc4b9e3e4d25c3b2dbcd5af000a10236e292dd2f43c09c -size 75570 +oid sha256:a7ba4c8ec5ec0774719d367b806ee354b6c5c5efbfc9f81601adcb36df8e2da5 +size 75666 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 81e769c771..16c7a686c3 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:7ef0f01ee15b681536a4f6f29cf6a7d1c5907f9e072cf3aa9bba122848a7507a -size 74085 +oid sha256:5ff27a760ef37c3693fe6550b827acca665d7fb2a97bf2e17188e05aeb6285a4 +size 74223 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 35e15394e5..bd536b0151 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:3d6dfb5695cfd24ae8207d66d5fee7695c1b12e1e9310a2ce92f07447f567225 -size 57192 +oid sha256:4aea7bd9cadb8f8257937a8862723924403a3370392671b2c75b141b5a95f92b +size 57352 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 2fc9e99769..bf557992f2 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:2b551591af19b7ff970159df80ac752961d63fbd468217cf935ec39e6dc4f5bb -size 54146 +oid sha256:4322e97f3fed1a2c755a2792a7db605c09e7a6f86d0dc92592d321ae89815449 +size 54252 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 ba112abfdc..a72861461d 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:cd5b298306dc0d435067bb5f9b4e49a8f9d467e108d8715250540b80aea17c08 -size 51156 +oid sha256:e97bfb8bf9e75c1be132e168723ce0379c227761eb6011c94a9d365f05dc0f65 +size 51348 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 35cb8afc49..11a8b04d28 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:546b6f6a18dd79a8baac9907bc8c3a19727b6bbf28db3f379873a56f7c960d8a -size 73549 +oid sha256:45e7c6b9ab1dd2fba672bd14de62ae3693bc4b3c80720b1ef93093f94eb9ebaa +size 73773 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 e2a186c3aa..2edfe77bd7 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:19b2715dfeeee653d97a98f7b12741ae289fd7864e4ccb1fe17e9c02dc3fc826 -size 71941 +oid sha256:e2aa6d286790eff5de61060bfe7520bb026ba17701e4d5261c859b355bac7395 +size 72185 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 332b169553..2be87ea69e 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:ccaa46d8df1a2ab720a50a081cdfe159e9bb28a37c66ffd48340ac45f241a3af -size 54033 +oid sha256:b02a689cae30bac692094061faf2b79bbd8b291807c15f5e6c49bde4cb9084a0 +size 54205 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 617ed1b8d2..559cba60a0 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:8e72138fef757a0b4877b8caf199163dc091fb2539a7aab9dadc9e1cd9e762d0 -size 51684 +oid sha256:a8072a440ef18aad57d5e7fb9f07e0c98f44740a7183f2ae8b521d772a9fa1bd +size 52001 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 145d76ae43..fb2e6bc4ac 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:9fc8e670655f4981a9a01d8ea60391eb5362c130717cf1c88044d8833e6ad06c -size 48249 +oid sha256:ffe0581ceacf19a704a2a1f3af01fd65518f35f4cc3bee730e281dc0f41d9cc5 +size 48453 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 068a5d0023..1a1c8228d7 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:1c792aaf65bc7b87d3a2e7cf034ab7a16e11cef50d1c8d7bc55e319dba8f656f -size 29584 +oid sha256:aaca5e5ea01adce1d1e78ab73e3703e29b7a82a9e309cd1d8a80a8539cc67163 +size 29602 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 3a1db412e2..0ff68a9d59 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:174878f27d737484cf3121ea7f6019f90098f02007c85c27f4b4cb58c1f9a38e -size 49028 +oid sha256:044400f56b5fefddf626b5ee496f7c5fbccf5a56f9ab47263f207a44266fff53 +size 48926 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 03f9cd39b9..c8cead9a23 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:83d2c2bde2cee9c9bd385f94131d5f3d13a24b3e8705b4ae8f47ebc0fc551550 -size 50465 +oid sha256:5843d766400222c5b30bec007192ec3ca1bb6bb421cb3f2b0492c1701b5a9852 +size 50384 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 18971cfdb7..5e35219478 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:bc6ddbbfa3864a4456e564ba76ac303fc2f4f1362fc710f064f6c72e4b99da2f -size 43755 +oid sha256:2743840a5dad5a37db350283fc40b4a082e942e4ee6c8152009a3afeed980cb0 +size 43739 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 3756f9ed3e..e4a190a4a6 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:29b6dc68656a924ba73148f570eaf72b20e9f887b1ae42bfd3c5dc378f2b3791 -size 46613 +oid sha256:dbd46893f0ed5a3c5807178c0282731de6695e5c87723201d99bd3feb208718e +size 46634 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 e3b257c5b7..b9fb489a76 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:35262a34abfe83de81ba1000168773fc867ec14a73daa01ff1c40396fbefbb36 -size 45255 +oid sha256:c147b3396799a5a4dbd71522454380494c86a49c8acee1be560af0ba494fdfbe +size 45283 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 8b0d0ae6cb..edfae4ce1d 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:2cc504e426c4e96b635736c43f0495d226c9fd8dcdb822f38fe3439bc1478326 -size 42260 +oid sha256:069fd3884dea316670d1f22a8b6eb30420ae2bdd09f9d33f424e050fc0d52bc5 +size 42293 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 002d56ab44..72cc38ddd2 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:5c365cbee07a0c25ddb41085eb02dddea84560a5bc0bdccf439e80f46f889005 -size 45557 +oid sha256:4472c465d39756f0c6ea58e4c97a39fffead7322d579def901598932118a01ec +size 45582 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 ca3cb0a3e8..d10f654956 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:61f557888cff9958c99d1e973e4819dab7d23f0eb261d47a69e14ca9e6beb0e2 -size 43498 +oid sha256:7cd5d4be951dadc03b1b1b6e2b15f288c990a4059935e354aab3091c91789c12 +size 43521 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 80eaada8e2..3efc886759 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:c478071682838cd4cc7de83ade5de09a522eac5b1bc0261adfd6b4c4caa6899e -size 45379 +oid sha256:68a86112f1f7f7adc3895ec09e8348ffc6d3fbaa10aab5d6e6e6bd1365b004d3 +size 45340 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 2b3e376564..a3c19e4ad9 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:d2ec2f9105e3aae1f33e98d2bca2743e14d5f9239ba7e78f4f91004fcded11e3 -size 34412 +oid sha256:b1e67ede55ba894773a6cf56a8e759747d79e15629918eafcbed25ffe6d6cc35 +size 34398 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 402a0cfd20..e80741a6c8 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:96ad3fabe9a1753ce36f118c4eaf7cbff8293c5c05b25280f1601d6c006bd055 -size 29010 +oid sha256:4f9b6ee6c09a8753981689538174c865dc01a1a884c8a324657b53023327ecd1 +size 29075 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 043546e64a..a16f485a23 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:0ade5a0171e07299ee3434ce36ccdbe66a4bc5da81409774cfc35d3b99459b20 -size 48268 +oid sha256:fda686dc8d75058000196c2a8d3737ad700762dfcaf4174aeabd430f7b97f5b5 +size 48165 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 a04f0c4bb1..d29ecb1732 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:d5507781d7fbd2cd083f6a9c75118572f269b764da21c91ad82760139ee61460 -size 49765 +oid sha256:d2ad5169a7bc3a1ce9a1482b785587860bc0c0305edc383385b9503010e95ae1 +size 49666 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 dec09e3069..7815919796 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:6b5a66bbb9741274a14afc0e9c117079b4d184623620523fd11af73f592ac465 -size 43214 +oid sha256:be191160f2e61430865dbaa7e94467e9fd90c77c860f89c8fea7d5f2a07b4182 +size 43260 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 948d5d1f87..6290b6aaf6 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:a0177ab6b9034de7eb35bc5774bef46f8ecf89b63695aa92e20407e605c1b0f5 -size 45968 +oid sha256:77947501c39a4a366deb2636d673846ea1f2601c4e16ef6a4ceef73e78bafc86 +size 46037 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 a4c1b92d16..412682e4e2 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:ddde9132a3640c4e41927cc53506d0628effd958ab2f38cc93a965469311c3dd -size 44783 +oid sha256:618dedf4ad81c11f17043d96ac95bdd2445ff6d5803f6bd8268ca62be1672b70 +size 44854 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 df9e68d874..039a376442 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:a228c7efae3558529141ce22a0392944c2475902b217ce11c2217afa136163ac -size 41453 +oid sha256:2f20655dc5e33874f4600386f53bd4aa282d96247abfcc3f4700dc296170f6ac +size 41521 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 f5481bbf61..17e6be53d2 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:e67888597de49ad6c67fcc4bb0e31393bc0c61dcbfecd8efe01ea51b2a067aac -size 45073 +oid sha256:264784675f8343f021e232fb4b5d38d58cd5798cdd0148cf2d2b152a0fc90a88 +size 45139 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 7b830f1377..832b4fa20d 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:3b9d919df0d86bd8e3b177bda45084b40b89803a4310e3782e50ce19ce00fa24 -size 42624 +oid sha256:24d22e617e969936f7bec26264a1a5d3413d6a1f3a9eedff2cbc10c3c4fd30ef +size 42680 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 7fd5f1293b..6a36064e62 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:76203bf3973c8a5234676309fdfff32cb312e2f57e8e63a99061291e9fdd5219 -size 44887 +oid sha256:f67a0f388fd32fb835087e65247238fcef473ac86f583ced3934ec84c7918ca0 +size 44926 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 41ab0f2483..3a77f315aa 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:3b653b0dadf9e69b138bbb0d51e4e2176e0ae6db953056daa0af1559bc747fac -size 33495 +oid sha256:5630290ef710919bd98f98c5122e21c2f62615680d967aee5b5770d47d3074d6 +size 33555 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 84cc698a63..be44dec713 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:6c0ef41360eb82092680b5b262bf1ef8449636387124c5aef940a727b3bc6aee -size 85137 +oid sha256:255631b62a27bc1cc4524da4984fc444c77b10343d3a89899671962fad3a4487 +size 84738 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en.png index 0d75fa1607..9bcae59ced 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea3552c26293d18148ff986df8b492193976e79c84bf5e121041b18e42d81327 -size 56085 +oid sha256:48cdf39c2d520bed76877a316a56509024d8a5a0f03791a68a27003f25f30cf4 +size 55554 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en.png index 8aeb6b5b39..057576a742 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e913c012011504cbce8e67cb0f1d0cc91430275e7b94f4f2dc1ef332c2c714f4 -size 53884 +oid sha256:b917d4400405c7617cb55a9b45d009ccdbe23eb1685ddb693facf8722e138518 +size 53570 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentsBottomSheet_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentsBottomSheet_Day_0_en.png index a0304d60fb..ef4bacc4c1 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentsBottomSheet_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentsBottomSheet_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ecda20f80c78991c5835e3e32fb18db8e08ba0ff8d8308c8a3c06ab46687006f -size 27083 +oid sha256:07c4f0c0a8bd6f9336ba543f464f3e2ac74ac8b6358a111a0afce774f7e82514 +size 27089 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentsBottomSheet_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentsBottomSheet_Night_0_en.png index 51af377a1f..ef6e9a6ab0 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentsBottomSheet_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.messagecomposer_AttachmentsBottomSheet_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ac6266d2081724960015f80dd7a489a6746bd4bd705755b92d91500e1f7bb2f -size 25443 +oid sha256:297822719354940351d5086b15b4ac9b0351db5dae69fd71d29c7bbe873cc31b +size 25558 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 875fb85bda..6c2a7e8460 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:f966bd2eade0180013c2c019963ad9f89c04f16cadcc04954bf3a4427c854635 -size 40002 +oid sha256:984536295516b542ec6aecf7d07baa3c6dfebbc66403b6d4258a6217616cec93 +size 39991 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 5b842a7e61..1ff5ace3e3 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:529c7a98771dbdef837f3aea963871aca1ec086de9d9f8b86c5f6758d21468a8 -size 38724 +oid sha256:8d875f83a3a1977e2a2cf151dcf9d731108a8590eb3643eb057727421eb1e955 +size 38812 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_0_en.png index 77f3d11e97..671ccdaf1d 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:72d279876d8b58aadf1e8aca76f272b5a785f93fe3e36bea98d7aabb9334bca4 -size 31867 +oid sha256:d71e5d6bdf78f145e573181ba8fe5faccf8fc8121d1b0318affc786222166bdd +size 31928 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_1_en.png index f9c2514881..8d7a518c24 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d49dec2d63677550189700908d870d8b3ade414dfd19ce553fbdb2847e604351 -size 36199 +oid sha256:e4d08ca16ac4ebe85c49387264490c076aa95ed0aa15f467acd0f6d07fa6fc01 +size 36340 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_2_en.png index 54934bcf31..19847bbdc6 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f77908c9549e885df89311d21f67cb851739cb62b88151855b3ce544d91341ac -size 37990 +oid sha256:30ff43a32b34192d49dbe9763fe7649c8fa5723c7f2b9ae6ed1531209d986378 +size 39885 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_3_en.png index 20409b5c94..c9a0b43e73 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ab5170975b38b931f1ae28e842e1005535027a2d5ccaa3eea98ed92e7557322 -size 43922 +oid sha256:9a5efead7d85b19215a64ccdc9c1f6ddf66558a27358eb197aeae1aebbac71a2 +size 44019 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_4_en.png index 67ad86e31b..0a38e03a15 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae2450611431109228d8e132bfc84fc854badc5889fab552c931d80d3e8c3038 -size 26522 +oid sha256:a447e022d725043ba4a44dd88e49b6b9c20ca03882badb664b371ca310982164 +size 26018 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_5_en.png index 9d83a40154..948557114d 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:031a0e01b9f50db515ec679624f8061e3f9675958b03eec694d9610e2746210d -size 115797 +oid sha256:b41e96ed731afce2b7a8924994d6ff38e5ff62ee1c4ec1f5ed0e535bae6e9284 +size 115996 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_6_en.png index f98c4227fe..ea57b81992 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:855a852546c6a2f33c079b585016ec71dd375b5b74782d0572388e47ef6f3d8a -size 32507 +oid sha256:3c2b6cae066cb50c3916a08009041d7b2a3335baa8e26e8a29d6bda75818000c +size 32650 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_7_en.png index 135ab09593..b025ff46e1 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c3d58d95320f94c75586d575f94344fa118298eaf157d9c2b795f823ea582457 -size 33830 +oid sha256:f3c20f5f523433f9d750736f006780d943beb47622190bd91980391f2a0ec55d +size 35996 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_0_en.png index 2e466a7c4b..5833854bb3 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d0de0ff521be78f2117831acf64bf0036c130b4caead8017419425a9b627dd3 -size 30911 +oid sha256:cf48171815e7af7568af42d81c861cd6d66f413f16f76afbb5f472828ecf826b +size 31053 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_1_en.png index bf5a258bad..1052f840ff 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1091ef4ff6a828ce7b493c9f824012cfa23bf7729d6db8b2298cbe65aa561b84 -size 35016 +oid sha256:8f38b81f5df1f85f449bc22bd52d19f8dfda7413fd50a880dcf87af6b668a00b +size 35195 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_2_en.png index 8f9b15e40a..0dd50a54c3 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d86c455cfa28e948b91f2fab42333efb8ee631de9a96dab3f8d18a6b2952f59 -size 35876 +oid sha256:e7f6f50bb7b1621f01f21cfde24961080127715be540435a594c356712f10501 +size 37658 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_3_en.png index 23ccf42ae5..d07a35f70b 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2414a68d170ad6f2267a9d3a760571059c7623c00947c02a05c6904b3536af3 -size 42601 +oid sha256:9f3557e5598202ef6d965405a4711bd93f4b7fbee5585b5cd3d4ba8f4307b1a4 +size 42713 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_4_en.png index 50ac05a062..11dc7f1aa0 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de4afbbc0a45396043659314f2a8eeb4694c64b21f7ff344f0753b94a5e7ddea -size 25915 +oid sha256:8972d37b3dc0a1f024e1853ba0ed6667bd58eba022a810ba7de837478710d3f8 +size 25333 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_5_en.png index e542eaae07..30a11d78ce 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9360422defd28223480d6c42f75450b0b092907f65461b8056d04c73aa7480fc -size 112589 +oid sha256:8c75de675ce72010a888c459c173f82b5d782d8cb18a4648abdc88864222cbef +size 112649 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_6_en.png index dd4ec6624d..69a97d0dbb 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d2ba5293880bc3c40d7a3b346424cc5f514cf970213e626e1c6edd4e23575ab -size 31464 +oid sha256:0fbf59e6846ba24941ae9278abf6fa80af208ca5eaea2bd2b65b3c9954f11992 +size 31662 diff --git a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_7_en.png index c13f5e0f2b..93a9905735 100644 --- a/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.poll.impl.create_CreatePollView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5290184e660f4d1e4f22a11e27a32ca1fb67f2c3dcea1a530ad70c767d716f43 -size 31560 +oid sha256:9954304cc948652c3c63378ac77aeaba623398b72eab6bb90d23b15850fe278c +size 33522 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 e0f36af121..23ba289315 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:b7243c65196024fb3d5ff2d0e281adb21cbed44405d0ca3ac30c7c91ca7414d2 -size 59750 +oid sha256:1d74f05d69143cde114ee981ea2c49b6ebfcab5994c2451fb3ef936b477786a3 +size 60801 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 836b0f5742..325a77149f 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:027d59e8fc57b0e599dd1386368189ce193ddb6d77d95116af4574f96ce11988 -size 59615 +oid sha256:a7538e11f392e425d056c000022a32ee4a88b1ec33be0e0ba68cab3a84a69c39 +size 60649 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 5f406a44aa..436907f546 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:64fdf9939053f75434e17dd74aadd60ee21b2254bb0fe2dc70090bb2e6678938 -size 59600 +oid sha256:635ce47036453925a6303816797c6dc3d5d613e6dd3bcf10c1ba2428813195a6 +size 60634 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 3ac454c6de..2c761ac5df 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:9f3a90f5ae1cfb76187e86d298392ae0bc126fa2e8e691b3625fe61cfe90070b -size 59612 +oid sha256:780efd313de655f8211c324c521c88bf009082ae517cbf83cd6d3650dc2f1759 +size 60630 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 473582bbe5..e2859b19f1 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:f8e8c7f85c81245686e69c5886c8cb88760a159806387a3b69c8d746186b2a2d -size 59498 +oid sha256:d0b1b2c6612ccfe175cc658ae81157e177549977c3c075d419bdc46c21e6064c +size 60542 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 11588b5e7c..9d17505333 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:29723fc3ce6d24ae89dad4c3b5705d062db29bbdc16b6c0e4bff9193b683915b -size 59746 +oid sha256:c8cf10c47f698c6dfba261d49c315abe2e79650bb9f652b8d6b726bfe0196d25 +size 60800 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 fa9697e195..660d893e14 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:c81d7887430494d111ffa6ba109dcc81b96d6b9ee788d73e008448acda2d9517 -size 59293 +oid sha256:16afd1f8b974fa81d03b0ca352b75d7a8b25c6df66273dd4862c56fd8b4a539c +size 60313 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 8133c30321..a52819a016 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:cbeae364251d54a8089821e9286a8a10bf97cdfcb3382664b912032a38091c1f -size 58804 +oid sha256:0bf6211cd7511a26a9c07f8a137c0f794fbb0ad647014aa34728bf2e2b157f0f +size 59837 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 07d47f573f..aab0590d07 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:a2dfd70af3fa004f7edfc46f32bc42925d64829875d6dc852245d2d5fab3f88f -size 62867 +oid sha256:b913ccace51348544dc7cba2ff7913d72a085cbbe9f4d36af80f6d18e0a79a92 +size 62940 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 473f98a32f..851e05c237 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:a80835ea11094a66e09528413ef411853ad8218f06051cbd77d5b32de32e8e10 -size 56895 +oid sha256:d4579db3ec0ed0574eddd69f3b1ac4e6476e293c4e7480f1486dec2ed40df51f +size 57777 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 58f2639ace..56ee8e3a6a 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:cf87b258d11b13e98e77b145da51afa40d56248682ea2ef23fca320e190feafd -size 56746 +oid sha256:394b0cd46ec85848f8698adb1ac655098ad8dddd363065b65246b86d5732003e +size 57665 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 62134288dd..0f00adcb5f 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:2f5cb1d3f9effd4099e1a27efef8e3bd40e911e6e935355944090f5ad62bdfc1 -size 56745 +oid sha256:8db8320be4c77860ce16ea4b6581ccd12e6f212e5442809f2763555fdd8f311a +size 57657 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 c83202730e..abbecb8244 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:7f862f27162968dae996e23baeec3291645b125ef25f853d9b9a363d24aca738 -size 56756 +oid sha256:4c45307433a68ab63ee9d4f4f471ab47053f57f01afb4ae1e470864c1b506401 +size 57644 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 77452af18b..41d001d1d9 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:98a269501ae382129654d04852123377be4e6c0ee1b665c989dcef3a1d44a44b -size 56623 +oid sha256:013c2991242bd82401b085036bf09641d5b8b628a125856d90de8c2c574efb02 +size 57525 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 c0806414b6..d5ae542c1e 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:e2342cf3ccf4c59f1bd17d4276c5fd7f29b41cc1a17105272cc1913287e435fa -size 56902 +oid sha256:333b0d9b7f45e5951a3ccf13c97b065fbab112e10fcd1b995c0943ed74e5331a +size 57781 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 c79abdd7c6..0cec5b249c 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:3b14f3c517b570a0724f6ec14ecf3c0ba8881fcdaf643d6ce9070f0871e03fc7 -size 56464 +oid sha256:48e4aa772d1c791e4b2974a545fd9e92bb6a317228c5f1e589b34bf190bda30c +size 57394 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 dd8afdfe37..8f06be615b 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:46aca63876af82eb27f9b7f050716429ae323ed626793968f620dc2464009db6 -size 56146 +oid sha256:fbbd85619bf152f00d60770186e26346d12559077cb5f45f2dea41ed02199876 +size 57017 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 e851a8517a..f31a68d2dc 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:0e73e9eab3864c65badd7660306cfe96e0b45d4963c7cc1e961d330da074b24b -size 59700 +oid sha256:37f61e0097c9e7035d1bd90742110ca1a3e76462b97ba7a1773191bfe4b7ee20 +size 59681 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 edb79ba518..5e929bd32f 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:30a586c9cefe4f7d9b342b792d65314657e3ca7f56a785d7779d855fcbe8a428 -size 59233 +oid sha256:158cd1d7554871d70548dec2e79cad874abe111bd967d03d507ee450988230cc +size 60220 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 c747c2e1a4..d33b24c987 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:3c15192a3094d3b86613c37b8a40391cb6ade53937c172a27d63d2dd644bfba0 -size 59134 +oid sha256:c65c540551e253bdfee59cc6f07d408f835f22f7b053f256d33f42b12323c372 +size 60097 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 440b244d12..3f8976c0da 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:dc6cbdf0c90d70ff85ed3f5133eb1f938602c583639139b9055d43f4b52d6c86 -size 59142 +oid sha256:845fcc8fa7fa20a6d77868d4bf2216b5e9714a6daeabf328dd15347a4db4f217 +size 60108 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 868f9d3682..eb887daa79 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:b9a5f7b9ecffd994a28a21fabb07f089f4bcda19db05ee23250e8b88966752f4 -size 59103 +oid sha256:0c5013e9d0ed2a044f108ffafb8729b0f167a8aaa9cf59426e961b76837357db +size 60080 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 0de67666fd..3578d846f1 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:2ef7a874894de12c6d6e39fbac20064fc35bc3b56ad17c42e2bf06412f2f90e1 -size 59062 +oid sha256:9919bc3968a379acd74c3fdcca21eb98c55087863a15bd8d3f9724997a63da32 +size 60018 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 38057861c0..e780e0bdde 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:e216b29be5c59b8b32173a478e90f9e9b965b4eb7703882d2b8b4499eef4d1b1 -size 59231 +oid sha256:6a3360ae07479ba0080854789da043ec5e71f34dbf3ddeeaf772dbae4cf37fcc +size 60215 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 0c76f03f80..8db8b5a5f4 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:d9130cd7bdf755cbb244cb77cdbb741d4fd97edd18a4d2b342a4d37b9155dcb1 -size 58859 +oid sha256:b77866f774bd2e68234739fad4826fa2a9d1f56378c51fcb14dca7e25a17c409 +size 59866 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 9e39d93bf2..aafd282654 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:d96caac765e3945e6a57c0aa136ee31c581406f90f397afbae2b79d0449873ed -size 58548 +oid sha256:d82dcdcfa60cca28a540a0ad60a19cf3e78f396100db32a7f804512a6f5ffcb8 +size 59511 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 a4f99faf45..163d5733e3 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:d3d41fd6c09dde0db3e37d2a28442b2f7eddfe46bdc0d119773e37a55c46d0d5 -size 62224 +oid sha256:e2cc817cc4983c3851c3063706e40b682a4a630525a5f42fe6cc6fd8d4c74bde +size 62293 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en.png index 9c4bb9c6a8..8a3deba85e 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef458f82d89cd8f82aa4a2e1e00a055a1657b93254218c777b1d7d54f0760b75 -size 49194 +oid sha256:004a9020036620444baccec4da133ace1842251cd42c00ddd184d7cadc65c695 +size 49086 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en.png index 3059612924..38041cbd9c 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:efeef999ff57dd7f5dda390e886c15cf88d8d2a509f5db739553a377548dfa5f -size 47014 +oid sha256:f64dad8aa8d115a5962044f52164c254b5adc73568375ef5cb2e30e00f622dd0 +size 47042 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en.png index e24a0a4e98..5b7314b783 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a33905ae2f0a1b7292a412ad67cec8e85dbc6f8cba52504a0f6b215b50469c5b -size 24412 +oid sha256:200cbb1255804398e0c9861151efa426d0ff6aa78eafb5eefc7dcae309f1b611 +size 24348 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en.png index 8a459e6a1a..765cd276ad 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b393a8ead69368886383c71bccf03b67d86c6406a92a17589e97bc8a97c781b -size 23825 +oid sha256:d765e1ce49d658c5656db89023e3419aa603ff77ab8e7fda8b7ff9eff69ad86e +size 23862 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 index 9e5e42f653..2be985840a 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a955265e37fe0a06065f70b0b9648c8cb85b5e6721336deb7735721dc3c0db80 -size 56623 +oid sha256:404eda8a26f6529bf242b61e032464f83c28ac59d70a661a58706073ab20f205 +size 56334 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 index 3155968037..567820dae3 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ddb64ac02738159cd0897e7fdf62d8138ce1590afeb05ed7492a41fb361b7dbe -size 54681 +oid sha256:2b10df9bc9a6ca83ff2c319d0fb079a72f31e7c100ec3064ee3c55112167b4bc +size 54777 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 index a33ca80765..de0fa6e0e2 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7de600ae1a687929c01ff52255571daa496fbd1c7df8a94e56ebf00f0ef8392 -size 53595 +oid sha256:04c59063b1e836e74dba617c481b02a8c7b65fd31056b8f564207fe6aaae7d0d +size 53725 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 index a45f19a0cb..071738a0b3 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d9c0458f9bf81c02fb10d8d9faf88f3c0813813fc5bad7d3ceedc7cdfe3028e3 -size 52103 +oid sha256:d79170fbf028315b32f7e53b838f796bccadfcb58a259d33acf33f5f0ab0c05d +size 52312 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 index 81a02b4ea8..d49ee5fc5f 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ba238914f025ca392c7f90d6800f57adef47d48bab03bbf4d711cc2f6036c32 -size 52222 +oid sha256:24ef78fded0540a8f1f011e7d9560e20eb60e14300d98249cd7bc593aa89f33c +size 52237 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 index 0b7f81266a..fb78a2052a 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea5d9314cb0466aa16c7d7d28056ccf13a60a493a88104be2686384e66722b4a -size 50727 +oid sha256:2510779bd901b0108ae43650ef3d04d6465d16e65cd580a0426fca4f25b4bb85 +size 50885 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 48914fa409..e35130df8e 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:59b02b82b889878dc908a859bf32c1486fd926034b89a258028835aebe9ca873 -size 53872 +oid sha256:0d195d113274b9bad1a8c9b5cea3e6a58959ae095eefa053580c4e6f5f63d4c6 +size 54210 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 dbafdad6eb..bd067f4024 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:a6c6e4d5ff9f34adbf6dc303e107336d675c874ebfc99a903c44b37693c521ac -size 45444 +oid sha256:7799d21ba75505afdee0a66670187504db8a88654080988495dc6539f8226674 +size 45049 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 48914fa409..e35130df8e 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:59b02b82b889878dc908a859bf32c1486fd926034b89a258028835aebe9ca873 -size 53872 +oid sha256:0d195d113274b9bad1a8c9b5cea3e6a58959ae095eefa053580c4e6f5f63d4c6 +size 54210 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 ef953a39d2..8c81df12d9 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:51947f9062518b5ab89b9bdc20889b5560146b182a4549f3a2b6f7a5d9ca2ee5 -size 52298 +oid sha256:bcbf831c6e9f91f8d13f7b52144139cc0edc59d0211f88872ccff5329c8530bb +size 52303 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 2ad5c53567..ef928d9114 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:762fbce69b40b9b8c1209415a88fe95f0480ef87e1dd2c1748bd7ac3b4cc1d76 -size 43835 +oid sha256:f29226ca1b03c83919ef0efa82b43883d3efe95efdee8616d29542ce9a892e66 +size 43527 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 ef953a39d2..8c81df12d9 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:51947f9062518b5ab89b9bdc20889b5560146b182a4549f3a2b6f7a5d9ca2ee5 -size 52298 +oid sha256:bcbf831c6e9f91f8d13f7b52144139cc0edc59d0211f88872ccff5329c8530bb +size 52303 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_0_en.png index b3cf869f20..90b6fe2b0e 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6e01807f33eb3d754c10197b20f02f8322fe7bc144276a4ea8952ba5baee7d4e -size 42952 +oid sha256:c7e2fa5b5a1de2753eefe71b3a19add3ef5d96679256e48ee1a7a13e01c025e1 +size 42941 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_1_en.png index 3fa84f4c8c..bb5ee61d4b 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7bfdd77de93896a106f1a471ce520509241b53f85688600469b19a55baa7c88b -size 37166 +oid sha256:e812a3ba15595e57158bd1c1bb0983b0dc5ff3f1a9f81b0e86c551b2cb2a5c17 +size 37212 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_0_en.png index 1036232a2e..a09f157c85 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:20cb76deb9b51ed92c2a7e4d6f7d43e5414e91a3fb6d084ba1ca50250478bde5 -size 41724 +oid sha256:0e4a3bd1b987f437886ea74b0c7decb25836b44af5e58a7a70a4eeb9f46638e6 +size 41684 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_1_en.png index 6b104086f1..d19e2c0e1e 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.labs_LabsView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7af4d6a4118d34317fa4d0052749f9f02fd2c02898142eafbcd90110b4b52d4 -size 35365 +oid sha256:7b28f8b1050272e3d3bd112a2c6c22799e70e29688f97fef99aebae260a08a77 +size 35509 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en.png index 3c017856d5..31b414f07a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc9a6e9b1a289cbb56c9cfdf98c978a143255f5309631ab689a180af919c239b -size 32570 +oid sha256:24c511b7b1ee590bb117bff9fede56c2468462267f50a93bec0b4f1b795c81ad +size 32144 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en.png index 931348ff0b..8d266d069e 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa031cddbc8816d55baa0b6945c23a16079edd3e2c5da5cd96523322461257d1 -size 31466 +oid sha256:657f5d5d887fe1aad3bb1e0dda911e861a4cb160c570678ee89b870591e3bb8c +size 31054 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en.png index 26b9256252..3c35726947 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1712b1dfc855f85cc6dc1ae50ce989f75734e5166e033a75d00de0af48387d4b -size 40271 +oid sha256:4a3c3d421a0adb5f1b5d9a26e80a18ea97a19c7dfb4b0cb586b45ea647f4f448 +size 40300 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en.png index 3553072509..860bf42b76 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:39e5c9887e310603142b98518eb708a3afb966e75b2c081aeb54dfcfdf15747d -size 40120 +oid sha256:8f243a0dfacc2583e1812ed1eb310568da7b149258322fbc971cd0aff3104ca1 +size 40153 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en.png index c41a7592db..0f6a2b7ef6 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c2cf996aa6d928e03305a1c0794853f52d21b36ac428dc3ba74901a4bed4b13c -size 34082 +oid sha256:5acb5ef7baf4b9616d7d83990473c07679605d626cbb2c3a165903804843b54f +size 34254 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en.png index 339471e5e5..115e2d80fc 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e907ace209ad950d47b40d9e237cab07d6611c4b96aafc916c7c406ad995aeaa -size 36785 +oid sha256:c71cd007555bd0f503dc7e5723e4dbe40a5afc588f87e65e355798549182801e +size 34812 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en.png index 4d7496d290..05a24284e8 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c566c8fa13f5364f4e806b99bf0b7851ea04353607784f0184aed12b802245c2 -size 53719 +oid sha256:bf2664f828dd7b34784a0881bc7d7a75b4700628503fa20f224c18764645cb15 +size 53513 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en.png index 67cef98faa..4493e2bb7e 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2af900ed5fe55894f175d4c7df02af8ff20ea2e519cc86f8b6ba4cae26809e32 -size 39924 +oid sha256:3a2c654c7792514576de6547ca25f8f9b711952cc24b2ba2bb6c2af4149396dd +size 39847 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en.png index b4e0884041..a8a51dc6a4 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c81117519620428e5dcfecef86a777d7b42baa6af05a58136d8f4af57f0973f3 -size 39804 +oid sha256:167c78e2208f307947d806a1b9cc591b3d5c238acf8b1ab7e1805ad889944960 +size 39729 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en.png index 8b39c3a773..11e0288e10 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:581cda2a65344128a0837150fe8be145de6a2eb921c153ba36186fa0a2adf67c -size 33532 +oid sha256:fc1eeac19091108033918f03117169e6e10b8b07def17d597b7ccd81ab5368ec +size 33642 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en.png index 2736e1dc69..c595b64971 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:10b1e2ea092fb9c48217ab6f61569fc1d243e24b0f153f20ed0685470db46fa8 -size 34692 +oid sha256:8be2c4e279ebb1c0b528e5abaa87d97a85e9f1d0cc689db0672e63ba5ed6f8c1 +size 32775 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en.png index e32928dd40..74e3b02b7b 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:118d4c3ada1bb42ecb9e5ff4d0d92317d99d0e00bb730c0f8bc85085e60001d7 -size 52759 +oid sha256:ca6ae4eb2bd2d59d08e470e14f17c3cd18516fddd24f2e3bf448c49d40c28b00 +size 52553 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 275a6bf885..a1b3e577a2 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:c57b776992a9e756f97a264ab7fec15439403c596d4b97daa268e0f4fb6416e9 -size 51323 +oid sha256:e23e4be9343caa6fb668c7ee83fe44ba98401606c70f797f6fe8de197eceb717 +size 51191 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_12_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_12_en.png index 97ac976470..b371142844 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f57b21a60a713da80f1dd3b56e688ad27828cbea0050310404b3b7abbeafcaef -size 58055 +oid sha256:f009853addec1d9f0297963a4743fcfcf3a100048685a8320bf92951693610e5 +size 59451 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_13_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_13_en.png index 1bdb96a6ce..f8f1dec96a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Day_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3fb8607ad18d2654282478d02a20f416f87b880049c3835016cbcfcd9fc374f -size 15161 +oid sha256:4e4c7d418d1176c8f6821e9021705c5ebd85399529c2e3bddc1b9084510da6d7 +size 15280 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 index 615716fbc3..d8a37a1b59 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:680a2bcd62cfa4ed20676867a90459f698b139ff717873e4e7448f2e741b6b66 -size 42733 +oid sha256:46c6dec8bc599fe1e40f9ab9ee9a143b3529c7652fee6eac7ad88da6472eea87 +size 45382 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 index 66885bf2f2..78a7817576 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6474f0d9c28fb325a44be95de932923d16d6f87863598e9ab83b709baa5f3af -size 41295 +oid sha256:e038c864bc264a148a6aa82e1c318c46a2f3eb97f43bfca2ec7adc4e12f8551d +size 43943 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 index d3807c3f60..a721949951 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c2ec04a123614eddc0d6e51d1feb87680297c5c3f01e81a9f0be3685b768471 -size 42589 +oid sha256:4397906ad8b87ad71d9a4903f791ab6b27a3fbcb440af6d925a2290fdc7e49f8 +size 47198 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 index d680c645a6..209e84f315 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d51086d86f6ad1dc8ab93941274df67e612f03ca945e9f3e844c55aaae1b3316 -size 42463 +oid sha256:3ef8ac012eb0de8dd249eaa79dc69dd4af6d97072e7ac6c9307dffbb893454ea +size 45110 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 index 4408ec767f..453338e568 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb8f82d825a0e97703793b37c8c9525271aebd9cf33d3a6de1422e8515f7f97b -size 44930 +oid sha256:3f98a73792b1ec91ccbcacc4cf9a1c6de00ce03862f69ebc2cb77d17dbdbe1d7 +size 46627 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 index 5b4ddf6763..b995a6276b 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14b9e7f22078be909317cdb8b2823919a9d0f6a179f2964fc855252b4237ab09 -size 39607 +oid sha256:639484bfe7759754da026fea395f3afbf22b403c2abd408204253399fa40a1fe +size 41177 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 d680c645a6..209e84f315 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:d51086d86f6ad1dc8ab93941274df67e612f03ca945e9f3e844c55aaae1b3316 -size 42463 +oid sha256:3ef8ac012eb0de8dd249eaa79dc69dd4af6d97072e7ac6c9307dffbb893454ea +size 45110 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 index 0f7dbeb57c..42574ef3f6 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c048e3b635b98cbd4ce8f04278f568888413d4a7e2414662f57ea6ef662c2a22 -size 41665 +oid sha256:ed13f05fe4352db182a58f1d2cc5c8af415236cf5ba4e6667879847187aa590c +size 44386 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 bcc418b5c0..386a4d2071 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:6e837aa7be784a94b00a930dd8e902c83f3330fe1c5c3a6274b8e6ef3a6ab3c7 -size 39431 +oid sha256:a0260fe74d0464f6981c0fa1242728d1c8f214861c582ac50b188ed37f535510 +size 41637 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 71d8627267..f738183dd7 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:f53a28516bfb1898bdde08ea2c8a408b0e4533e0df293ca526460366eac2ed30 -size 39271 +oid sha256:8cac68cdfc5b2a6c67300deba8b52bd15b19cf71daccef0e0f2c8b60a44f2bd4 +size 42607 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 71d8627267..f738183dd7 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:f53a28516bfb1898bdde08ea2c8a408b0e4533e0df293ca526460366eac2ed30 -size 39271 +oid sha256:8cac68cdfc5b2a6c67300deba8b52bd15b19cf71daccef0e0f2c8b60a44f2bd4 +size 42607 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 d680c645a6..209e84f315 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:d51086d86f6ad1dc8ab93941274df67e612f03ca945e9f3e844c55aaae1b3316 -size 42463 +oid sha256:3ef8ac012eb0de8dd249eaa79dc69dd4af6d97072e7ac6c9307dffbb893454ea +size 45110 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 ff8c8bfeeb..01a4e9021b 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:964005811374c5747c378220205979cb646df301755176d270bd3f8f6a3e5b91 -size 39341 +oid sha256:45cb8f2ee0c044bea37e03498e1ccebb8b3410d98b70a8b66d9b0cc96cb76fe7 +size 41956 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 0f9cd69b16..3e9f191009 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:d0a6d0e6c1e54a1842178576a2f63b29277a116c3d63e1e83c58ee2a2061c43b -size 43680 +oid sha256:39cf206419a6496ace2f47cd581c7cf986dc9f75406c43c2d1bf90c681db2474 +size 45876 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 d680c645a6..209e84f315 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:d51086d86f6ad1dc8ab93941274df67e612f03ca945e9f3e844c55aaae1b3316 -size 42463 +oid sha256:3ef8ac012eb0de8dd249eaa79dc69dd4af6d97072e7ac6c9307dffbb893454ea +size 45110 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 d680c645a6..209e84f315 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:d51086d86f6ad1dc8ab93941274df67e612f03ca945e9f3e844c55aaae1b3316 -size 42463 +oid sha256:3ef8ac012eb0de8dd249eaa79dc69dd4af6d97072e7ac6c9307dffbb893454ea +size 45110 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 d7f4fe3394..f0e4049f27 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:0cfbbb76875b4e18100d9a8793aae106da7396f2087054ea7312b379815c53c7 -size 49874 +oid sha256:3ce468fdf47100eaefa88460fe723d759ca2b84a396a27168c4c4d8b0dc2c423 +size 49776 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_12_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_12_en.png index 3913f4525c..ea40884b8a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:25ebb66460a8f9aac4ea2da291986b42f3651afe5d282ec6688c386e9ec1b83f -size 56242 +oid sha256:3c0c054620d2c52d997502723584cf53dcadc0b7ef228945fcfeacabafd83f6d +size 57478 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_13_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_13_en.png index a77632924b..ed61f3c490 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.notifications_NotificationSettingsView_Night_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f644ae1d229a0114613e0dc9e9a26a3560916b40cac2faf65cc80fb2fe3e13a6 -size 14632 +oid sha256:e64ded1a76fbc2722da8ae5ef3802aa7fbe3364c13089982be0f8982376ad05e +size 14766 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 index 3161a1b000..01cf356ced 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a8ff42ee34d5b3e7d9da11c7c7dcad793b3a2a0200fb141d5c65ce273807fff -size 41237 +oid sha256:702b994b902946d49ee8ee66c93c5e81711bebc53a54c94af31c3d4554089eca +size 43666 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 index 9240bb941b..806f44b821 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d9add786691cd3c839db57e32eaa79acf7c917764edf9f583010073d650c1326 -size 39877 +oid sha256:c5ffdee75b3a258c597ab62661c676ae90676fea913b4feddd912b860e49a3b3 +size 42294 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 index e5165092e3..a46400bafd 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c4415998c4229610437f89f7d931f213e670aca74efd2047d6fd2334777ad9c -size 41049 +oid sha256:6442852768dd251052e42c15517f9770b8f4848a5c2e2c4a241a32e6518769b0 +size 45221 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 index 5c444905af..c7371790a9 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a59478f08ca086e1f60a9a5b925e9745d4e344b6b585116f55bcc503f3305a3 -size 41040 +oid sha256:641d27aa03caee6023678d3985cb32819c6148e171706ade8fde351a52d21737 +size 43461 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 index 88e2cb485b..be7830792e 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ead1fb3338330fb5f6f3178b2f71ed4d1fa45790938db9045b3cc8ebad85cd88 -size 42167 +oid sha256:82a42b7700901f74aa0118c596829125d21c37876b2a81720a31fc2357b5b024 +size 43998 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 index a5dd69f5fb..d8f5fe773b 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e0dc3c944415c2739e330e7cc0c284c1ccd1b4b4801c7b300aba0af0a144c3b -size 37068 +oid sha256:8f2bc8d60cc2f9bb905bc7cccc8e8c94c1473c50c64cbe9d5a80b63905645743 +size 38769 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 5c444905af..c7371790a9 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:7a59478f08ca086e1f60a9a5b925e9745d4e344b6b585116f55bcc503f3305a3 -size 41040 +oid sha256:641d27aa03caee6023678d3985cb32819c6148e171706ade8fde351a52d21737 +size 43461 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 index 6fe937e597..45a8bebecf 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1bcaf45ed5dec3e86d4b17e5a53fbadd455df81a4b30924a6309e472ddaf2636 -size 39206 +oid sha256:96c3d45f50259bcd2a6f368576d4c740c9201ccbeb9213da5f76c934074afdb4 +size 41822 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 4eac5775bd..655fed9a4a 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:59731c89e55eb564fa2d3e572c99a16d3ad88ee1a5e16d4e4d83e1008ea299ba -size 37999 +oid sha256:b032761ba73beef9a67190acf0d6f467997c7e31392e8fc54fc77b9d4fa4b0c0 +size 40097 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 e87402fc99..6e5287e579 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:fa9d8b31efc5b2c369d501bd002f66edccb84e812fa10d5b3284ab13357f7404 -size 36831 +oid sha256:8815346ccae3b712ed47f1770bde1a3dfc10abe1c8f42adb04fb0836a68720ff +size 40099 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 e87402fc99..6e5287e579 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:fa9d8b31efc5b2c369d501bd002f66edccb84e812fa10d5b3284ab13357f7404 -size 36831 +oid sha256:8815346ccae3b712ed47f1770bde1a3dfc10abe1c8f42adb04fb0836a68720ff +size 40099 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 5c444905af..c7371790a9 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:7a59478f08ca086e1f60a9a5b925e9745d4e344b6b585116f55bcc503f3305a3 -size 41040 +oid sha256:641d27aa03caee6023678d3985cb32819c6148e171706ade8fde351a52d21737 +size 43461 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 fc16482e71..8aadf3f98f 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:3efe00ff653c1c6efdc85ef3ab244d8078f6f36cf6cde2620c4b4f5776b019f9 -size 36861 +oid sha256:acbcf41d56b4f3a73908246abe0de6fd16c2f8971babe462c7495743c9cc0a73 +size 39450 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 fd9b76fd36..7fe7019dfd 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:67539cba9fe0e53fd902a878c76b0927cc0afad2a9541781e2ed4a81eba652a7 -size 41089 +oid sha256:5c9f4c003b2e7ffa3d527970e4e6c25be461a6b23582006d7bc3e5695ac35c00 +size 43273 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 5c444905af..c7371790a9 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:7a59478f08ca086e1f60a9a5b925e9745d4e344b6b585116f55bcc503f3305a3 -size 41040 +oid sha256:641d27aa03caee6023678d3985cb32819c6148e171706ade8fde351a52d21737 +size 43461 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 5c444905af..c7371790a9 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:7a59478f08ca086e1f60a9a5b925e9745d4e344b6b585116f55bcc503f3305a3 -size 41040 +oid sha256:641d27aa03caee6023678d3985cb32819c6148e171706ade8fde351a52d21737 +size 43461 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 4e4f3b0fd3..f0f0bbf1b7 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:4b3d5527423e0bb16a65fc9981db06b7e5eaef2736e68833dd91aae5825b9126 -size 40439 +oid sha256:2a778bf05dd64f37df2dd45437a4dc1e74199b4b9eca2d3e9078b5b956a16e20 +size 39556 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 312a9bad45..6647fae806 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:941f79f738e902fcca7e3ec2f71acc4c230532bdb2c9136a2e7420ac88106ba4 -size 27372 +oid sha256:942e5c3db0b84fe8f3125e08dafda1c0b96cdeb332afcbf217f06742f5b29a58 +size 27374 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 32610f27d2..6e3ff8d5ba 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:dc80aa470630ec356274dec6abd0f05149506f4bb1c1b495a4ad8ee4efc8ac69 -size 38510 +oid sha256:4bf9154a844fe846d918f56bcacd30456973ee89f180650956c73b8837039341 +size 38530 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 6963a4c2e5..b03f86cd17 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:88178c848bd5740a19df1ec71e0c80249faaa4476fe8069997ce01f620d7a2f7 -size 28790 +oid sha256:8d55a3fe4b9310220ca46db6e893017ed6f41864b48ebed8717074ec277b4765 +size 28817 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 9c32e85b15..c17a10428d 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:b5743d92c92425093ddeff2af31d8c3a803a029711aed1712c7cbc50890b0d77 -size 29992 +oid sha256:d410ca5322fb3c7ee10d5a489bab118fcc7cba17cf825c8d38ef3c6fde26eb6e +size 30004 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 f6b76e38e7..d14f6264d7 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:7c75ad887209b88e700c6ad53090ed4c2d7e5a3f49836608999e9a3124a63fc0 -size 32869 +oid sha256:4f00e1c36baf1a14ce1a4d67cff18a7a8ea3732c60df5eb0e7ebeb53934387bd +size 32880 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_6_en.png index 273cf6c781..c3a9a89399 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:837ebeb30aebfb154e98b1b4603156cf0ac877b58efae17d534aaf269ce8ba10 -size 20037 +oid sha256:3cc2c582bc6fc6a73a8eb8e873a57d85d88f984b283f889628139021cdc6b163 +size 20042 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 a1906506ce..557538595c 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:50da5b2b2851c4b13daadc44e81beaf19294985fb4c6e37caf2105f0bddc6bb6 -size 41628 +oid sha256:a558ea1da4ab2adaaaffad9b47ce1d21bf27bbe82074927f823dddc05d6d80ed +size 40741 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 8b41f74ad9..e30896324c 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:17fc2a4024aec430ca302e915f951c231d6f8c66de9030bc8acf64954cbd8d8b -size 28424 +oid sha256:b91ad54980525e9977498e22e1428f3ca172ea1e88e7c508feb84d8521e9080c +size 28423 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 09a752bb66..8869bfb466 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:b766642d069f44c06f7a2bf74dba24070fc3260cb77cc9658d163d971b9573d4 -size 39408 +oid sha256:7a6deb7ae2808f1cc361921d204ca4857cd085294c9df915acfbbf300fd198a7 +size 39425 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 84c0963ca5..ab15791ad6 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:eaa549a5f94192d69fa01a3768733ce4d0f9b34d8ce35d91df324ffdeaa87fff -size 29746 +oid sha256:db61ad2899d3b56b7e1cbd43006b1ff03865b58e15d446a9886ffda5e35d954f +size 29774 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 ffa813f1ac..2ca32d37ad 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:66f3f2d1f043603f36187c2ea1e86f40628b23f0aed69f90e2452dbbae558133 -size 30888 +oid sha256:2a52b1bfdb0cec0e8568d23a804f90ca04fd5f5d3da6e1e513b1ec5c652ca0a1 +size 30894 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 13957a0450..e5864fb5d5 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:f12abebdcc42404c0a5719c490f5da4d3d5a1986d469884773bf9ed8071dd27b -size 34154 +oid sha256:1e7f2cd3f6ac709ff1d37c5f212bb254a4bcbd07a71c750f0ef35cac7529d5d9 +size 34134 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_6_en.png index d77f3adbf9..2312bbcd77 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:07ad7e092d6b8e41064bcbce131ef53d70a552dd6f9292dd286dd7c10948cf9a -size 20459 +oid sha256:5ebc219ac4bf4a804c9c8f26028374bb35264266b616db054218dcba0772197a +size 20471 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_0_en.png index d98e3fd475..a613668ed6 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c14e7ad5b7c320873dab0b97a6261b2b62a7405d133e9c53fe2184e9757becac -size 9203 +oid sha256:0981d742141f7b4f0153b897638a7bdd6b20359c051d7c2176a92ebe1f1eab76 +size 9221 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png index 0607484ce0..bc00108ade 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35f0fb99a74477ebfa53a019ded68043035de9ba0f86a6a71b032137a125d107 -size 7168 +oid sha256:57d41ba2f1a644081c6bddcc7e1c27c9cbadb23bff3343e0e0d9deeb6a94bb23 +size 7123 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png index 9f77167b6e..44dc0d0f19 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6432133a87271013cab796baa7d48ab8e96f65f049b92a9074ec03f540e11545 -size 7269 +oid sha256:f9681df4f4000ebca0642e8a4065d23f88981707ba146adc8cbf2757175cfed6 +size 7315 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png index 470324716e..61a7c2dad7 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ebc88a04da18e07b5f94cc52f75ad033fa01917de6c32ac77a1b400fd27c62cd -size 28944 +oid sha256:cf6189630f111d84674843b3970193eefd31d96d9300f36308038313de78b83c +size 28859 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png index 56c7646b1b..f02e51135b 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3cff5ee1c0cc217b20c68bb4f4d2335ab03e9dd8d16045550358e748002c538b -size 27460 +oid sha256:cb7104ccbfcccc9f3afa027db521e8e2f11a015356d47e61e5ecfd173cd80004 +size 27295 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png index 7ef9b7ae0a..82f344f714 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d19e7a09114e76294a0626e5d617cf55fe7c13a0188a7d5b364f57c0d9daedc1 -size 12123 +oid sha256:8d96eefa01a5de803b0cc9d9109c20df86eaff01b73ff24a91945b43d53d5d01 +size 11960 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png index 0ca6f66438..fdd8fcd5a5 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5896eb5df6f5398bdb94e74280d0d5c04b6a5a53c2378b7377c60fa58eef544b -size 12013 +oid sha256:22678a2a8505e1d9d5bfcb44459b6fac69c11a4bf72fae09c48ffa2e54f5a110 +size 12128 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_0_en.png index 00a43265e2..bcf819a97c 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:343ddb8692135fb051766c340a4ac6143a5dc57917f0cc16fe11678f2b9bae6e -size 8774 +oid sha256:90cb31d24d16bc8e13c7e83f26330c9505eee02b91a5bf3ac7bf140fedfcc37d +size 8749 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png index b6c2706180..875d51031a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4b5eb36080cc5750c4cd36ae66ba618c033e794fdf0a4fb5afbae5e1fa10824 -size 6789 +oid sha256:771ec7723dd0b7546e7e73ac4f3f6217ab5d57366ff0309774fc483b02240320 +size 6720 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png index 0b65cb998b..c96f456ac6 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf614dc03afdb990baae40b020bd3f3d6396226b45fc4eee18f2d55100df5bff -size 6918 +oid sha256:3f65c054cc6876f86b6ae6689560581f2c29edcdc86fca992c30054b1f442afa +size 7000 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png index 2aca39dc8d..1496ccac57 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fff529404e3219d00ded2f701066c48506b96512b08b1750665d3c2c0a75ed97 -size 27700 +oid sha256:5c367199db97f227a82bd32292176ade0dcec1633d0383b591204b63ddaf1f48 +size 27660 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png index 5ff2f9b93d..d04157ba03 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1017de34abdb57805946efdd6d486ab76adecdc458d17eb9b1128be0dbe8ff00 -size 26227 +oid sha256:27efc2d19efbb978778dfbb7d87138fbbe7cb17525d03a565e4ec2523ae0a252 +size 26166 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index fb72cafe03..f6e27475da 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4ef1b643a16b5a94c75f8bb845c36d3cbc7f7ed96a0cac32fdb9f0b09d26b4d1 -size 11747 +oid sha256:9ee89826c8aa2ac0371ed31959243f62bf9968806a7b27117cd7b4d849423a33 +size 11667 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png index 8e1b9c99d2..b1bb69efb8 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66f6d0d6b03ee4c999cd4edc9c6ae567d31b8b537ca6f9cc8fbe436d06ce80ab -size 11643 +oid sha256:e27cb9e501ccbac54926f0252b4098867643a2d2683c5b267f86ad99edf6f5d7 +size 11817 diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en.png index a5c4e992dc..6a56529d87 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:015c7855f265ea896320f5bd3319e05a1fd09708644ed4980150e8cf4c6eec1e -size 18365 +oid sha256:9bb43ca503732f8929fe0bf1635aa67398a8655c7f62ea38ffe68b8655d0ed05 +size 18328 diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en.png index 2f9d7380a3..1c97cf62a8 100644 --- a/tests/uitests/src/test/snapshots/images/features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:79cf0d6e42b99ee91917aafb3d28ccb81e45042954370b239703fc3084eb5897 -size 17074 +oid sha256:2681516c21f3e51824152a6bb6b8f4d09db147546c938e99cb899841f1fe83fc +size 17083 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 d600a67219..e6d8d37d58 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:112ad29fea211c36dcb15a0674f1684869318858260799ee52913514f4e3b1be -size 52976 +oid sha256:2ee06b3d6ff72cd658c21eaf10ea1a4a459ef7ab6113cee3960e3c723ad0500b +size 52998 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 29fc43b66c..a25517c78a 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:0bcdd2cc0e47a7303cbcdcf34e069c556287ad30454bc36b068360d9820b88c0 -size 112924 +oid sha256:4b8487d6341b81be8ad31eb83d2392d9e1fc8b0c81c92060c96f31f99969f5b3 +size 116063 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 cf7c538197..cd92d6fe7e 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:6b4572b681595f3893188f9f78e7966d52508d4119451fd7ac86f7bb4f5cef0e -size 50635 +oid sha256:0b177c4faaaa0429d4e8bb65dce19b40e0ede728535ad4ef7a4efec453b1c6be +size 50502 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 d600a67219..e6d8d37d58 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:112ad29fea211c36dcb15a0674f1684869318858260799ee52913514f4e3b1be -size 52976 +oid sha256:2ee06b3d6ff72cd658c21eaf10ea1a4a459ef7ab6113cee3960e3c723ad0500b +size 52998 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 f581ee930b..20d1cfd900 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:e935f2b1f46b5330ea034b6824628f8dab7417f9d185fd720297ac8a5c1ce838 -size 41507 +oid sha256:c7c8f25d1e220ee187bd700f3b0c24ac755dc254366be20b65fde360ae931f21 +size 41356 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 a1b520209d..e2f8fc3e17 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:a6388912c7e4797b63799f2c938a02dc1680de65cbb28ab57fc1961248ccb61d -size 51398 +oid sha256:4b89802553136073e00a7c8690d0c49d8f29b09382dd5cc64c398149f310c3a0 +size 51344 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 cf2783581a..189d3bf8e1 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:ea54b01d2e6b607db3dacfba356ed3e3e3bf4c00ff91b3b65c748c478e776e66 -size 110685 +oid sha256:f458f949f23d4192319f838bb6fc18ec6dc38c1c81c717b1da08529ab082f697 +size 113760 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 b141191872..df8715912a 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:c20206fd5603cf207dc8d504f43b350ecefae39710dced25f0fcca1f34f05c68 -size 48912 +oid sha256:61a36c3c6c09a64d2a398bbda7e86dec8d5c891fa62f15fe489283e4b1222da8 +size 48884 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 a1b520209d..e2f8fc3e17 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:a6388912c7e4797b63799f2c938a02dc1680de65cbb28ab57fc1961248ccb61d -size 51398 +oid sha256:4b89802553136073e00a7c8690d0c49d8f29b09382dd5cc64c398149f310c3a0 +size 51344 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 69d1edb4be..266d768ca5 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:1857e44c3a2e5a0ae49bb4bde22a86eec2e420b71e7f0aeb497b85c92c5d1ab2 -size 39675 +oid sha256:291cea4b33973b675647b150525c8e7e17765d728a444ffb3cc175ec3342693e +size 39521 diff --git a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_0_en.png index db89a07778..1b62c5dac4 100644 --- a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3e9ba4d2b0afd07b48ccae4c9f3c37c9fba1cddb330308d27b14771dabf1e2df -size 30024 +oid sha256:751c7e0ce4cd5f20a6259f305d1d4c4de6fca84870e2a7086b4d66d4f58c27f7 +size 30074 diff --git a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_1_en.png index e13d712ca1..329d9af3d5 100644 --- a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f088be4f5c6cce913ca1a12c161ab65334569ecc22405bba4c3a8764a39b6306 -size 29553 +oid sha256:2b7011041364d6046229a28e10a0895bc153eaaf78838d33e33cb83471a45bc7 +size 29715 diff --git a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_2_en.png index 0c54ad27a5..b394d26672 100644 --- a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d049533611fa17c1b3fc2348127c5b0b6257875e3ebccc2e6df6f3a2c4a1b58c -size 29706 +oid sha256:cf83676d72f74137b6203d88b02fba39e7da90ef116811084d793a48f1e7646b +size 29805 diff --git a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_3_en.png index 642733996e..76e4bc64bf 100644 --- a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef61d994eb7ff50e4e6b59c56b22ffe36342ba0ed53e6e8aa5f27f11dfe24269 -size 27112 +oid sha256:053ef557a5c2c9b1a4f18bed9fa0579f15240960672356a9d6bd524177683fcf +size 27122 diff --git a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_4_en.png index 769971670e..050949b9aa 100644 --- a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:03839b91c2c72049520effd097cb1e531b721ccb77740000802e71d27cdcc43e +oid sha256:b412044c11461abbaafba558cbc8e66f1c6702ad0d02eab0c01fd3ff4f64efb4 size 32764 diff --git a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_0_en.png index 76c1d6964a..4c4205b4c9 100644 --- a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:151338daed6b0987cec720910b552b5821a5a106a6c9e694e33d24e733b85263 -size 29300 +oid sha256:dd99953e28aba7f0644c14ca9ea55461b8d134af9f454859b9771ef145af0dbc +size 29307 diff --git a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_1_en.png index a9efcae346..70d20f038d 100644 --- a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:edecc24faf75d472b94703fe5febb08cc01ee92a6960fd1b2cb050aa9377f451 -size 28838 +oid sha256:024e7a1c12fc99f5595ba26da3cacb95700ba6a9b65f4356115657c3dca7ea80 +size 28866 diff --git a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_2_en.png index 504befb698..b0877ea947 100644 --- a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:436bdad5ca7e52553c7d29a97834d5eb7e5f8e4087dd8b3b2ab5b2cd23e31bb9 -size 28848 +oid sha256:f146ba2a4f0edc4b1b977a3eb8a389eca445aa206243c6d0d9cfd1d859685151 +size 28873 diff --git a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_3_en.png index 4942eee6b3..d0988397b6 100644 --- a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:84abd935a121596053a70ada6ca0b4a62dd467e0407f7f6e61f3cfee374abf3f -size 25917 +oid sha256:2cc316a7902518202d5d215955f0c9463100d30634a2b7fb255988947a41af35 +size 25979 diff --git a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_4_en.png index ed6e11f546..830b054018 100644 --- a/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.reportroom.impl_ReportRoomView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e7dacfcc9de18fdfee387a3ef9fa77fbb252917c974778be5adc80fe6c03502 -size 30671 +oid sha256:b2fe99fc52a7f75962df7515ab2440206496349553eb0a890c6d9bdaf118a7bc +size 30640 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en.png index 21a5549d2b..930f6f93fb 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fff83d7065e2e9f60cc9eea91b3ba4eea1adde637d1cf51c6df01517c96879fd -size 28348 +oid sha256:7a1405e76c5a209a5fc4e6a510aef34df35f0feefb5a52dec7c7f884b0526bdb +size 28353 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en.png index e3e3f4daad..b86c175ca6 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bcbe510bde44898e1967ba2b8311622afd3cc599794b300a57b4b3b8632000ab -size 30188 +oid sha256:d655f0da7f5c2d7526f4b7d79bb18243a278722df3baf0500c71aab35ead3986 +size 30245 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en.png index 0edb2f7b9b..2d7c2ef3be 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5b3ab3cab91ff916f2bf6db476efeb9f809a35a602f90d0cf50f283a6dc0451f -size 58189 +oid sha256:1c77cdf26831cfcee230c25c1c2c1236bd1306bbfddb8e796f04188590a78dc6 +size 58296 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en.png index 6ed5992b27..8d0beacb00 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f122ac9e7601af3b03825ded5eee90a942d4cb3415b479b0c603a7664c12acbe -size 27894 +oid sha256:394c790fd526ab95ee76bb061a7d7dd8c60f35c008bac5f979112a0ccbbb61f2 +size 28084 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en.png index 28089c3a19..73838da8a1 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c48f20baf7ccead203a15ded178a46729d83f492414c907e67956f869c14452f -size 26772 +oid sha256:07b56e0c758eaddab75599a80e0799d5fb35d0194bd5a2114e87183327db4091 +size 26785 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en.png index 6be69c6fdc..9429e7d7ba 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:07ea854f28bfe2328d160739572ad8f2240823823780ba132be39786421ef45f -size 36742 +oid sha256:a50df0a82ccc9cdc80c9a2bba0c19118d0a90d14fb8022574d6fa0c24913ab50 +size 36751 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en.png index 6ed5992b27..8d0beacb00 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f122ac9e7601af3b03825ded5eee90a942d4cb3415b479b0c603a7664c12acbe -size 27894 +oid sha256:394c790fd526ab95ee76bb061a7d7dd8c60f35c008bac5f979112a0ccbbb61f2 +size 28084 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en.png index 707c03e70e..8ba18e2468 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de6537fb8cab6f228c2b837c1833e63bde99cff5fa7d5660e99e0bd6c62d34ad -size 27105 +oid sha256:133fce7270dd0faf6f4ace7e5b042402defce0169e7c6fd6c4eb7dd986681713 +size 27120 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en.png index 05e024ff89..101a2ff478 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5481e49a79c7f5bd2698ee44df7fc78aa2a7cb8567c9ab6f2c28f93f36ee60b7 -size 26620 +oid sha256:911a229d577ccdbe861ec7d74dbf58835a8d7b4a471c6550326fa5bd060bdecc +size 26636 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en.png index 750272f011..684d79fe73 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c2da90677e466c2856fe59aa0053598c163fe33bcb673672f58d4d9a502126de -size 27556 +oid sha256:bca34f7d0bea1403894ea3997db129f8fb6321b2a0be099827121210075ca124 +size 27498 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en.png index 8de25ea721..68a079b789 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e56bcdadd28809627bb3f5f0557b37be511a6369ccd0a9861e77cc2337a0a5dc -size 29237 +oid sha256:dfa892df2794c1a42f01e50d0dbf212b464d1b27959199a4b57da2054aad067a +size 29153 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en.png index 6420909c90..6108e2dc1e 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e1a4458211c4158f95837f3d3388a770e8e092ba43d6653b616a57f5030702e8 -size 55537 +oid sha256:620b76e7de46c7aeafa529eb4a793f96b75697570465431d015e4f7d479b0aab +size 55602 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en.png index 78090c5620..d0b459ef9e 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1c5548cc4e398f15a7ed1118b78520e793e358a67f1d218d003b03f1be13aff6 -size 26751 +oid sha256:1037fc83c15315b619cb90af540b5a8ae009d2eb6957daa01162c7a64df2c991 +size 26869 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en.png index 48a711299c..5a200e1bc3 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c23783e4367a8e732e3f3d528842670a4e110b26a9866fabd8598f382790c1cf -size 25211 +oid sha256:efba79db6336493bd133f59ffbec101eca8d1a4972c56d8435b595dd1efd51f3 +size 25163 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en.png index be1dba1967..48ac8b9e9c 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3dc931893c2233a6a83fe68bf8712ac0793916298978fbdd41c481cfa63eaa98 -size 34495 +oid sha256:e2c34f18a2490abe8cb6949d48d8f5699b7d254ded7dbcb6155c0ac9d4a25411 +size 34422 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en.png index 78090c5620..d0b459ef9e 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1c5548cc4e398f15a7ed1118b78520e793e358a67f1d218d003b03f1be13aff6 -size 26751 +oid sha256:1037fc83c15315b619cb90af540b5a8ae009d2eb6957daa01162c7a64df2c991 +size 26869 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en.png index 893fa03361..26a7ffbd53 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1fd326fc0c8e70625b792ee1d058c370401820ba082aebea938ebf092d200a14 -size 25584 +oid sha256:9ee1c573eb7ca55e70f583e28709ffae78bf584fb731f8afdde7b73c04f18483 +size 25535 diff --git a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en.png index b64cee9c22..5b48011bf0 100644 --- a/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c2518b9917b3eaf7381a1dd12d6f3b3aba65ab678fedb369889e8f76d609782e -size 25750 +oid sha256:2b2890e06a07ee90b06dba3adde8d59753d0c53a90277c1f1f6c726f1c2bfd20 +size 25747 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en.png index e78051b2eb..9b6f6976b1 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a61fbd3a88240c2e846ddcb235a9c656ad974eb148f96b66cc2811965260da22 -size 28715 +oid sha256:cafffeebf11df13dd9bfca09a4ea57245cdf1440bd5499d7095197824884293f +size 28632 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en.png index a9059f984f..54be022f26 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:597830f7117feeb6cfe3a9db25bffe060efe5f505a5d39e40b210a5ce4ff0347 -size 28085 +oid sha256:734a534e4a15dcd5f5fbc5bd3ade8c1062b05fc876ddff7e4e0c71fb1dc824a8 +size 27975 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en.png index acf2d10b4a..3579ee64d3 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:419fa8d8d1e5290bdd2506824663c995cef09f52c9b4a9a52926b6cf94809b37 -size 31620 +oid sha256:2b88578c9265674c4fe3973591aacae7ea83202d6753b98fb416903947077a3f +size 31602 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en.png index 81b844f361..9a0737c008 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ca893611301a03342d21d6fb3b173d69d579fd063fb346a07ebd54b91613366 -size 34613 +oid sha256:b62e9ddbd1203a3463d91728f87506176fca85840c25db9169fed063f7eba9c3 +size 34772 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en.png index 23935dc73d..d1c21e8f99 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91f38a465b40119727d4a0995ee26170d35d128bf485dbff1d6aa263e5f17513 -size 30303 +oid sha256:e401b1f2d7cccff403e6eec79f60d5b9a7c04b465bc9779b4b23b04dd1afc9b5 +size 30213 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en.png index 7c63030292..ac416513d8 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:836ab57eebcd04857028dea821380b0d8b46964ef2775bbeed0e4ed1a6ee05fe -size 31547 +oid sha256:effcf70d68aa8ba7ee40896d8ca39951595afd7ad227c8ff384cf71a91d703b8 +size 31661 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en.png index 23935dc73d..d1c21e8f99 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91f38a465b40119727d4a0995ee26170d35d128bf485dbff1d6aa263e5f17513 -size 30303 +oid sha256:e401b1f2d7cccff403e6eec79f60d5b9a7c04b465bc9779b4b23b04dd1afc9b5 +size 30213 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en.png index 7c63030292..ac416513d8 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:836ab57eebcd04857028dea821380b0d8b46964ef2775bbeed0e4ed1a6ee05fe -size 31547 +oid sha256:effcf70d68aa8ba7ee40896d8ca39951595afd7ad227c8ff384cf71a91d703b8 +size 31661 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en.png index acf2d10b4a..3579ee64d3 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:419fa8d8d1e5290bdd2506824663c995cef09f52c9b4a9a52926b6cf94809b37 -size 31620 +oid sha256:2b88578c9265674c4fe3973591aacae7ea83202d6753b98fb416903947077a3f +size 31602 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en.png index 64e9b67cd2..42ec11a9df 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1639b16313e7c2e552fe741dc5af84c946bb9bef39fdbf98f3a5b473fa8de1f -size 30651 +oid sha256:76b7d21acfa225b567e406d0caa329050d6cacd807d3eed5db869b8052567e7b +size 30547 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en.png index 653179d981..f0eb526ef6 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29c5fd69085f619352bd1f674150e1af3b3b512a06f3f29810e0dd2d13c1787e -size 33537 +oid sha256:37c043231ce5736157d7a2396252dba0240068d602dcff03881a59db92febb54 +size 33545 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en.png index c44f3259d5..6587487aba 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d935d8a9e4254d5f7220576f2c3a3272d2668829ab9f0cb0b7f6739a0b52658e -size 29037 +oid sha256:12022efb64da10a3343488b5475cb8c7c5d121c217eaad1d141206dac1aba91f +size 28976 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en.png index b2f184d679..25bf6acd7a 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58d71e51474d4247b855e2155a287ba7785e25f2ef962bf11c0ad4967bff3f35 -size 29562 +oid sha256:927e3169b0ecf27385f8ba268d633fa2385793180f828e45f8fe388b616f5e2a +size 29615 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en.png index c44f3259d5..6587487aba 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d935d8a9e4254d5f7220576f2c3a3272d2668829ab9f0cb0b7f6739a0b52658e -size 29037 +oid sha256:12022efb64da10a3343488b5475cb8c7c5d121c217eaad1d141206dac1aba91f +size 28976 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en.png index b2f184d679..25bf6acd7a 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58d71e51474d4247b855e2155a287ba7785e25f2ef962bf11c0ad4967bff3f35 -size 29562 +oid sha256:927e3169b0ecf27385f8ba268d633fa2385793180f828e45f8fe388b616f5e2a +size 29615 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en.png index 64e9b67cd2..42ec11a9df 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1639b16313e7c2e552fe741dc5af84c946bb9bef39fdbf98f3a5b473fa8de1f -size 30651 +oid sha256:76b7d21acfa225b567e406d0caa329050d6cacd807d3eed5db869b8052567e7b +size 30547 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en.png index 9aeebb2177..2ce3f41d5c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d87aed1fad3eab0c41d8fc284c0224df596b3dcbf9e2c82a5eaff8f10448c17f -size 21839 +oid sha256:6fa470f9ef32dae886e25183403882ead91f3138b3fcfcda91deea35e0832eb0 +size 21685 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en.png index a6ffc4590d..a8e56aaecd 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b41d47c1a1e7359c4b991a1ba7a0585dccbeb1400b2b424f7240134c63c8492 -size 21148 +oid sha256:7b122142624ed5f5f0cb655eacf8bb0367f363298e9bbc88a4ebfccb4d70770e +size 21089 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 e9863d1b93..cda44203a8 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:8a6fbd84c3f2a9e40a2e8e81a00ffb82d48e8714035a2da737953e15bac7ea93 -size 67635 +oid sha256:104368b8327a971e2135d74461a7a471cedd4a88d09caa34bde132058f67a33a +size 67491 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 29980e7099..c9dc271f46 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:fbb8a435e9753f441c832db6622ed94b404dce4237996add3aeb72e518cc14fb -size 40522 +oid sha256:d0e5b3a9c3d43c2007e0145afad49cdf97f163706f04b16a852ba107ac808533 +size 40173 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 b45888cc98..ac587ae11b 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:c4c5e6f2905960f6042ecb61d57a7a2a2b882c73fb49d043bd2d9d71e075c3e8 -size 38657 +oid sha256:98b54ec3c153035407f5769bb461fa00c13bba8ce8345f8253e3b8c0d9d062f9 +size 38338 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 18caac8b41..a8dc78884d 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:f45a01ce91d5e56c19d47a01fd3845a92d32f364925d2490ccaca889e288077e -size 38221 +oid sha256:6d2c8756af09a88c8b68749e6f45a30d3408ff6f222e1c78888ea4f8a75e2e11 +size 38050 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 231dfeaa33..24a1b6b746 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:9d87f7b70a1043231c213cc2e11c8d6aec03b49b24a7fce2261a865d16fd3146 -size 39008 +oid sha256:878bc7688a46fe3e1dc82522b496d205b571b3e73334d6f277983836cde55fcb +size 38687 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 78ddf668e3..0097772a76 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:4684ba74e78e6ed36ce3fa168ce50c3bd828d70e9bf54c9c3f8d8ddccf7e5d81 -size 38948 +oid sha256:31c9782ec0ec1d00aec8c4e3c1ca5faf14a331b37de9df9e5396d07b21c6b76a +size 38633 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 c7db94c48b..29ba5986be 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:e6a301bdb68740effd68841d5f4afab2ad211ff02fdf99828f9780bb43975709 -size 40361 +oid sha256:9aec6fb2da24577e148b2b25d58151c29dd662b9e42252c5ec39aa45e889f8d2 +size 40044 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 8d2ee2032e..20b8a5e619 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:7cdd7dce0071f305c82c4a084a8d6112fde6ee79c0e347109edba61baddebeb6 -size 40714 +oid sha256:4ab43948e7b58860945365c7a7d8bbf61f1edf7d6463296d57b94591b3c829a4 +size 40389 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 58f6776089..a66b4356bf 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:548a7a2b247dca3a454951d168eb30a8fdce2d1c0c5de77ee7e623e3a2355b3d -size 39235 +oid sha256:2c103a46031fae57a0a5ae0ba10631821146a3645ada35574f0eda8f70225e59 +size 38924 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 e1dccc7bc3..17c187d067 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:1131ffbf59970257df26ba42bf2a5612398a7b62393c41753e84af0fe1a61af2 -size 38648 +oid sha256:d0420ff1e4b928c67f7a4f9df441e7a3650e9e58baa81b8d212fc30c004595c2 +size 38328 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 68b81c731a..8cef9eae9a 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:6922b04770ab6805693ef7fe9f0c5ddd93afdceb2725b3b1b795c6ab8c10d136 -size 37520 +oid sha256:abf5bcaeb1e744ef9b65850b26b6788a241e356dccdf662b39c980300c42b0c4 +size 37433 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 f1f356e0a1..b3431e07be 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:ffccceb346d0c768fa98e233701058fa5b73f480f6390b26dbbf2ab7240511ad -size 37525 +oid sha256:e113c9991419e4d47e961192e8a60d216a89df73221a39aecca26f6aa54b252c +size 37432 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 211d398cdb..f5c01cc6c7 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:3abf55145dd71a1f511ebb07b7481f4538eeb2730bf3a23d83e4dbd2fbd5100d -size 34829 +oid sha256:210fbfea81564674e150061d1f42d7b0884c8a287e39628d68a2e0e5732e4608 +size 34503 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 bc377f0cf3..48f398d3f3 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:c5137c3539f68dd9d501d8745645847304ca40a58517baa4d4fc21fc99702520 -size 39382 +oid sha256:a3bf201d346413a3008a727b1268c954403a6faad0a6bfee352146a12246599d +size 39071 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 8a5000cdf7..08858f8634 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:c6a26f7ac512ab192f0b022bf59ade1c0275b34943e4c06016d873ee6dc1b49e -size 39107 +oid sha256:da6643aab9f173b7f0bc5df854193af6301dea202accabc501b7ec55489468ec +size 38789 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 1ef2d75e9f..688916d10a 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:3b8cfb69cf931f52a5110b08b262cfe943e82cc95d10afb5c3126acdd6908055 -size 39002 +oid sha256:5fb4005e03fbf477dd1a3c01b557c1a16353d26e6bf900d5aeed92a8b9982c6d +size 38685 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 28bf4f49dc..5d5a97fede 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:9e086cdd74b0f4620ab8e1fd026792e91365f6d71b246d7f34688f55f29e9d91 -size 32270 +oid sha256:fec18f9b702a3093808914135b75a515ab241c9e1c1a1d96e8f3beb56e0be4e5 +size 31942 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 1bcec82516..2c9b951ba3 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:af53108a51bba6dd19f89d416a513a014dc93709bb92e84f1a97a3936e9a656b -size 30989 +oid sha256:5ab4165ec7f3a329691f7a20a6bc822ee11ac2ee209f582f013573ce25634f4a +size 30748 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 c02a47d24c..b4001ab811 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:250ec00454674d1a240eb1189586bb313f61950d8bf736d6812208c0c49c223c -size 37459 +oid sha256:5e7fbb7cd48300741b3bd390fd90208ca1d94a2123c011b1003d9e9197187cf9 +size 37319 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 2dd2e61820..b1680151d4 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:446b9f6e5b9fd3ead36ef3983eec7445fb647b28719ac37ea42911a34ba639d8 -size 37236 +oid sha256:51c762a3e1350e5dc2ac85157331809d564a710caf72df79e879738912a518e6 +size 37149 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 f3b24f79b7..b170d8a573 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:de8a33b55900579b94ba7201a924a35e0d64a7c231591743386f3653f334f3be -size 31516 +oid sha256:80b5f6c01aa73f55b73a179448a225a199ad49973daf4220278f23efd2c5168b +size 31458 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 35b64abb88..b26335b2af 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:8c15274bfe393b43066b7885e300b8fbeba83993d4ada34c260cb41fb6425476 -size 39555 +oid sha256:398d83dc49923e014e81d565b9e4f3d2c2dd985c18e53856885c46c79df64e04 +size 39242 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 5af1e44f46..8451d1d645 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:69cb1432c2fdcf5b9f29774baa8cd5d628a76feee10fda86e3aeb284078a108f -size 39005 +oid sha256:e14f6fd5ec0f7abcab209743554ebbf66e125dc6b03001c22b06e1b8bd304129 +size 38710 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 5d0b8251fa..c3a9c557ff 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:cf9e568b617a863fc2c4ad221f6453a739a385867e30cb2f813c55964fd27646 -size 39153 +oid sha256:08ac66c12bd42f5a1c5941d88f9f2a9dbfa98611b604a9100c143584a00658b2 +size 38824 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 ffea1c96ec..c26999a9e5 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:bdc91adbd0eafe0ca75381cf1362e4421c12b9871efc558f8203fba43b119e84 -size 41670 +oid sha256:4656145e26d387b5c300c6520ff448f7eb113c5e51bffea66d70122c7348fadc +size 41418 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 b17010db4a..639290708a 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:4078a0609c3b9c45307bbe5d2a1dcf8aedbcd58e3fefa24c0d1ae4156702ad49 -size 39733 +oid sha256:4da21ae4058d74a463725dc9bd4727f763fc75350691537c99cf24ab65ad2744 +size 39469 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 04927b495b..e000fffbe5 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:7ef80e3950422cb5ea2cbbf4822d3a34229286719cb0d43159f6d252eaed5cf7 -size 39515 +oid sha256:13562a00e6dbca6edd08b4627188f674d31208c6d034d662e639676c5d03a55a +size 39493 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 af9e54e79a..6fe35cd494 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:e17a12f4586b3b6f57a99a0dd6a26e5b6029bcac995ee6f70c9047f913708242 -size 40060 +oid sha256:8d4065fdb9814fd0cc088413d5d505021b4141f93dda271edc23be50c7b4fe68 +size 39797 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 048c1037ba..cddc0ee1b9 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:fd6ec055f0139812c8b0ab9017526760706d5ee7ba29aedc9e292e8286994687 -size 40004 +oid sha256:6b29fb74626b9720eb5ef4c8bbdc66c08bf670180ea4110a82de33038b8fd8b4 +size 39738 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 00c3a5cf5b..8e89fb18b6 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:3a443622d261092af01abe5717ba1e52b06ab5e46c5428d21523b57c6dd76738 -size 41511 +oid sha256:ea3c7900ce1590aecd57799d3e333db42f9d6b817995b8d2d358e785c1e671af +size 41249 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 964d90da1f..12eb9af146 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:20fd55f968c30945318e80f2c003c67c02d7495b661475087fc0b0e724210f84 -size 41940 +oid sha256:7e97d75c02a333e0ba2b66abb364bdbf70db08ed92614d10c7f0c9ad38b20600 +size 41668 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 e099e70827..097574a7f9 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:25ec51f2100062e64501a88595a4f4ca7a8ab2e70aaf18ce65df49fd444b81ad -size 40303 +oid sha256:d1ad34e9827d42c925371fe4d689d38ca5a7714963cfdcbeb4445e5f3707441a +size 40046 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 21cfb86dab..1253d3ed6b 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:27a90a335b3ea802a72e6157493b2aa3f8e131a9de39e88a3cad6843f1f4c038 -size 39833 +oid sha256:3719fd40b9a47f2a600e504446652cb5aefcaedcadc75eee4038d5be741c2b8a +size 39569 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 ca593f67c9..9500bc2a82 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:72bbf2ec4beb1b9cb526d47013773b26267ac2e019c218cf81231f86cca6b13b -size 39164 +oid sha256:623eb89cb3130d4b171a1c13756b2901b592f76bac669ab1ecfc22a5ef037e83 +size 38897 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 781c3c3aa6..5f0ac8dc44 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:e93f90d704f810f2cd0ddc82170e429c53d09039a39c45d2177e431f1c3e683c -size 39102 +oid sha256:1a4e95467a96acf94a89411e4150f4d274a64dd936b44c2e9bd64b32d3adb77b +size 38834 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 76bbb7afe4..438fd30055 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:8ee504b49e9b7595feeff6a2cb7e96a581ae39cf096732fff9b8eedaf2779ccd -size 35959 +oid sha256:b27c755535ff88f7052c206d4a1e4d59a721fa769f0b21811a7d5e522d43bcfe +size 35847 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 bfcb5051ef..e6b60f74e8 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:8cfc4b97ed57ae7bf2f54ab574cd82b3190fcc2bc6873447a5d1fbe63e374b73 -size 40418 +oid sha256:003b935e1147ed7f9d69bd8e5f88aae90b11cf3c6058bd43c80a2647d868bff3 +size 40153 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 ffb83196e8..bde34a8b45 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:8a1aa73c2c4316ce86d8d657d563d146080bfb81e120328b512cef714e57d340 -size 40176 +oid sha256:563e48fa6b4521492974e2e7d16451521e9eca3c9586fcb148abbe8a358bb5cc +size 39915 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 c1d344c706..79d3a74283 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:616d6eeae9be6af14620508ad4ac835e6651537b8656b556624b062c89e84ae8 -size 40064 +oid sha256:1feb6b1a4aba58534355af7f93415fb16d7bfdcf1d64ab4b251f4eab232e85ab +size 39804 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 bfc5a1bdd1..f22e044e67 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:1804ad3cea84565e84944959c9d57faa546e8f2ddefe59998c9dae352951d72d -size 33392 +oid sha256:38b5a318b8fc33f4d9abb44f78e3d34e95fd7dd687fd4c5ac3b1b84a3ef2c391 +size 33189 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 347ca6f537..04e319681c 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:89a7d8046a9206a5bb0d5969eaf406fc1a4922d47871782b3e153fb7859ec36f -size 31928 +oid sha256:8917c0b2791679fb07b4ae34df225c9e6ec7cc9d1e2b548b406705176a27f370 +size 31873 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 97cfa26a7d..ee01bbdd1c 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:e3b592944d49fa32a35042fada1a6fe7ccc64fac066c14214a351ac922dcb860 -size 38524 +oid sha256:df2bb8ee19cba8f6e13862c4265174ba389e114281543dc876fcfa7fdbca513b +size 38680 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 0cbdcde004..929ee183f7 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:5500501d34b1cf5db3b68b0c620e915fe882536d5cede2bc920de05ca43100b6 -size 38825 +oid sha256:9dfa6b12b844c741cc6859c540f2036e9ea11b6875ce89e93ed466d61bb985cd +size 38556 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 25545ffdcc..d0383de612 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:f7f6d55c95501d8c8259a4318f7897f11f5e0effd53f37b441a7adfd409935d3 -size 32822 +oid sha256:596d9499210d731ecaf3a99af047c1a40eab4da7f82c61b8ee31772e4fdf88a7 +size 32853 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 a32798b98b..1f946de38f 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:ff81f7a43722314cedd1d4fc271d994002502141fab672d5d1d142403eaf4732 -size 40714 +oid sha256:27f6afe2f5ae91fa063ab723faf245c78f14529317db13730cb14a4fdb28218c +size 40454 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 37ec51d503..05ce43121f 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:b8776b535fa481298d2b3e29621174048b42590a9a4f8a2aaf644dc020bd08eb -size 40131 +oid sha256:c07b28bbf8c689a1e21a17304bda708e801823daaf70a33392999fde2490c6a1 +size 39884 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 951615ddbd..f081f3f170 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:f2ce271672bcae59e254facedf7fdfe7f71ae21f9f3a147fe9657d2943281bcb -size 40165 +oid sha256:ee7d773cf7cd5f717f776c5582661290478121ea812e28025209614130aed578 +size 39895 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 60997dceec..a2dd2d7d0e 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:bc0c611e5c552906b26adda91bd3601f34fc190860a1b1368b0e1c9b0835c9eb -size 20056 +oid sha256:87f838ca9caf6f047d7273ad18ccb4eb97ad593e3c3ea9ce337eacc00040c359 +size 19961 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 f646e0ee30..5c03fac730 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:03e68ff235e90c659a3a15d26f3ede94aa169fd7142eabc19b5511047577df93 -size 22912 +oid sha256:2d145ee0ea1d6b4b17d45f2075d0f90c8fb0560c598601bd763f3c1f7b5df743 +size 22908 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 51dd1fea52..b23d5cc0ed 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:baa29dce32895f21a4799a47a62e7152c99d56fc22a3882ac7da7f005a3532f2 -size 25259 +oid sha256:e91236d2597589d5a29a1cf801bafe62d47060bfd77c1241ceadd031375652ba +size 25179 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 72bc2e1d8b..bdcdbe3e82 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:e02e039a0586a8f36c00d4e237885a55713040036b4481f0626beb2b3b8ea161 -size 25365 +oid sha256:b0c1bc8124c3b5271059aa05cee7da58efc91ae6fee9168bb843a16b08ebfe6e +size 25254 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 834857696d..1275815ede 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:38d2e1c53d09debe38dbd49a058f3612c4a6cc4d3a604f53f86d0db29f0efecb -size 19047 +oid sha256:f8899f724a37c3f852186528c2cf1a93d99ecc13b6a398b2f6f3a619255448d3 +size 19058 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 778f0c8209..2b8e82d340 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:4680eb47d53ea43ba48e4164ad819278fd8844e24f77badee742aa4e8ddca452 -size 21859 +oid sha256:21db73c6219186d201b2bde4f36aa9935842ea051fee3a38414776dc11a4a4dc +size 21891 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 1bcdbbd146..e23546fa4f 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:d07c9ab2a4bea18c3604675225d23b0d4dfa41d16676eba821adcbcc619bdabf -size 24246 +oid sha256:f7ec286959c79eb80e22f4cc68c7aa10c15e0cd003dcdfe64af1877a1d805968 +size 24268 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 9a97f2911f..ef970ab4dc 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:e596a8cda9c1054b5f780798fd455a004acb1b848bc21069e415dc700a106b10 +oid sha256:4a47b9cf51e2da26d8e8085e7c539ff4ea8d396aebfabd5f168e2622b2c3b2dc size 24337 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_0_en.png index 7575635c8d..3ca31399af 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:198e6320c42714d651e1c0a770efaa620dca94dff435683a34f06c2e1e946a4b -size 30480 +oid sha256:1175477d4879bd032110b82d123346bf49e1593a782afdd872aa45d4555c2d9c +size 30473 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_10_en.png index 7575635c8d..3ca31399af 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:198e6320c42714d651e1c0a770efaa620dca94dff435683a34f06c2e1e946a4b -size 30480 +oid sha256:1175477d4879bd032110b82d123346bf49e1593a782afdd872aa45d4555c2d9c +size 30473 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_11_en.png index 2daf914755..e3e025bc59 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0cec64b7a5f5762717821cbb10fccfff4f06695a88d9404a08fcc5b51fc96e3c -size 31382 +oid sha256:83a4c517395facd11355794baf36564070a862fb81ddba98553d86e1148348a7 +size 31336 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_12_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_12_en.png index 2daf914755..e3e025bc59 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0cec64b7a5f5762717821cbb10fccfff4f06695a88d9404a08fcc5b51fc96e3c -size 31382 +oid sha256:83a4c517395facd11355794baf36564070a862fb81ddba98553d86e1148348a7 +size 31336 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_13_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_13_en.png index d9747b1991..7c3d70782f 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b46afa99f390d90461f74ca3c25acc3a5a9a47167fc828e2d7bb732073c4502 -size 59824 +oid sha256:3eddc70823d0c9349a00f56c2baf0d2fb36c397202663b0709233c52d04468bc +size 59804 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_14_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_14_en.png index a004a503a1..e2406a4d70 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d776daac96caf933c8043f4525a7a3e10bd7df82375fb841e876f3855a58d82e -size 60289 +oid sha256:04ea61e66ca5f3565ac3a048bfbd6f9c9491a754d9d910c7e010b374c5c21476 +size 60018 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_15_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_15_en.png index 4e20779219..f8c7003292 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:907f6e63ea0975f47ebe9bcf6211d54910d30bc03bb81a966d0af11f3b8cc410 -size 40967 +oid sha256:e2eb4c69725f73786acd9d9e36c79c75f3ca4f9581b9fb67cd2a6ef6fbc23f25 +size 40811 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_16_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_16_en.png index 1a9570f98a..9bfc3e0838 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c01448cd985faecdee7a30b2a9195d80a333e874e47ac1d96f91f01163c5b911 -size 57420 +oid sha256:3eea1ff559477eafbce65907022c4881cb1a39f2e3f6da450593ad851f038159 +size 57430 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_17_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_17_en.png index a011ffe8af..3d2ad0ba86 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b36d73ccf855d00bcb85772da0a295efc4982bfba45867373adaae9cc1da086 -size 38816 +oid sha256:b54b4e1fd75ad55a77ae3db7b0f73148ec6c93b2cfa3d5173ab23ad3624e2abb +size 39956 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_1_en.png index 2daf914755..e3e025bc59 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0cec64b7a5f5762717821cbb10fccfff4f06695a88d9404a08fcc5b51fc96e3c -size 31382 +oid sha256:83a4c517395facd11355794baf36564070a862fb81ddba98553d86e1148348a7 +size 31336 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_2_en.png index 4a2acf121c..92c12ecee5 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a92bbc343d11f32019369bae97c582f1ff0e6d867c9bb85b8b2f82421cc0656c -size 31738 +oid sha256:11347cc627fcad16419322836451281f1ed74ff61a7a4feb25d717d3b75fd05e +size 31698 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_3_en.png index 80b46c897f..c8454bf60e 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b30fb3c864ef609f3e6fa861bb77773f25587ccdf77ae2dcfa71808f39474ec -size 30571 +oid sha256:ad5ae48cdcce852bea8a80f4d7f2f985b6f15db49ddfaba07055741c98af6579 +size 30575 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_4_en.png index 7575635c8d..3ca31399af 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:198e6320c42714d651e1c0a770efaa620dca94dff435683a34f06c2e1e946a4b -size 30480 +oid sha256:1175477d4879bd032110b82d123346bf49e1593a782afdd872aa45d4555c2d9c +size 30473 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_5_en.png index 2daf914755..e3e025bc59 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0cec64b7a5f5762717821cbb10fccfff4f06695a88d9404a08fcc5b51fc96e3c -size 31382 +oid sha256:83a4c517395facd11355794baf36564070a862fb81ddba98553d86e1148348a7 +size 31336 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_6_en.png index d846e3547f..af58d6e586 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e1c127d917fbc8a655fe1f957b879472bb940c7258c33e406d5e257732fb9d1 -size 32093 +oid sha256:b5184d4f5c699e80a07a5270bbc9c10b07c936ad654b6bbcba728c0e3d265473 +size 32031 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_7_en.png index 2daf914755..e3e025bc59 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0cec64b7a5f5762717821cbb10fccfff4f06695a88d9404a08fcc5b51fc96e3c -size 31382 +oid sha256:83a4c517395facd11355794baf36564070a862fb81ddba98553d86e1148348a7 +size 31336 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_8_en.png index 2daf914755..e3e025bc59 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0cec64b7a5f5762717821cbb10fccfff4f06695a88d9404a08fcc5b51fc96e3c -size 31382 +oid sha256:83a4c517395facd11355794baf36564070a862fb81ddba98553d86e1148348a7 +size 31336 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_9_en.png index 2daf914755..e3e025bc59 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0cec64b7a5f5762717821cbb10fccfff4f06695a88d9404a08fcc5b51fc96e3c -size 31382 +oid sha256:83a4c517395facd11355794baf36564070a862fb81ddba98553d86e1148348a7 +size 31336 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_0_en.png index 888bcc72ac..ef06f3a736 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:507a24f95e364976360e03baa3a8c7fb9aa47ae013e1c299b984a757a83c6211 -size 29627 +oid sha256:ffa0c05495e46dd7162f46e3039e6e2814ee7b596abfc993b22f1e695fd2be59 +size 29802 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_10_en.png index 888bcc72ac..ef06f3a736 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:507a24f95e364976360e03baa3a8c7fb9aa47ae013e1c299b984a757a83c6211 -size 29627 +oid sha256:ffa0c05495e46dd7162f46e3039e6e2814ee7b596abfc993b22f1e695fd2be59 +size 29802 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_11_en.png index aa48b9f158..68f933cc2a 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbeeb89350b85c5ca23f9e4d8bb980bcb5620217150b6434d2b4c4d1df4e74e9 -size 30498 +oid sha256:e7cffc393e87d7740682641a729a8082b6fdd97c274ee580654e2afeb3597a42 +size 30434 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_12_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_12_en.png index aa48b9f158..68f933cc2a 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbeeb89350b85c5ca23f9e4d8bb980bcb5620217150b6434d2b4c4d1df4e74e9 -size 30498 +oid sha256:e7cffc393e87d7740682641a729a8082b6fdd97c274ee580654e2afeb3597a42 +size 30434 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_13_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_13_en.png index 7a6b531589..249eb3d6b2 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eac4a38a303f4d590bcd98d5f82402234009d4929d42290661b9a388972dedf9 -size 57879 +oid sha256:4f4df0625b26b89431c1f6a316a4bb4dc1dd15b699bcd8517bd787d7bb884b0c +size 57969 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_14_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_14_en.png index 503ddfa0b5..44e3c6c6dd 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5b87f75ef0fb631db93894aa13b4a157b70d73a3143f8a6efaba6e5fa2993856 -size 58587 +oid sha256:60bdc03eb85f9c17d9d329261786ebab4c65eb18dd1a1eef01d66ead65d81045 +size 58425 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_15_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_15_en.png index 4e00fd1711..f8927e3a29 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ffd6e9fbe283e921d5db9a6df46801300e0d1ff3879694203520491e4f7e33f0 -size 39907 +oid sha256:6e8d19f9d6f4951dba75120b6b84bd5910c5c75681e554edcc51172768623993 +size 39652 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_16_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_16_en.png index 3f6dfb400e..a846e09ee8 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1ae027d2fd14b2fcf5ce1121c0986f4e54f1156d660d16e667b8d176a1ef2e81 -size 56365 +oid sha256:7081e97504108b32bc49d72765a55c9e7cc048221281b38d1b80562e4a93b7fb +size 56305 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_17_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_17_en.png index ced01412cc..42e6aa4444 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ddd31f317fc31f901a25a55b95dffcdee36a054e69230a45fe8be7179b77fee5 -size 36405 +oid sha256:a472f0bb6c412bc3d7eff2a75493ce9bdf6a3bdf947358e5e1867e4d5d80772d +size 37663 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_1_en.png index aa48b9f158..68f933cc2a 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbeeb89350b85c5ca23f9e4d8bb980bcb5620217150b6434d2b4c4d1df4e74e9 -size 30498 +oid sha256:e7cffc393e87d7740682641a729a8082b6fdd97c274ee580654e2afeb3597a42 +size 30434 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_2_en.png index 779bfb91ff..85a64c03be 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e15b5a6bc261e7a5f579ef87d1a6fef7896f74edebe4bf01ddbbdaf4439be34b -size 31010 +oid sha256:b1b791febf7e9a07b2bd28177fb5405f645af517782bede4d075eae846beb4eb +size 30987 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_3_en.png index fbe7eae12f..36c94e3426 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:622f8a378608576d7491597c6ef50e9cbef3e9fedf3051339c4891357e70e9f5 -size 29739 +oid sha256:8fdd5b8ac66ae699592b7de33f057ae4623b5a1a2c3999a8e8a7d63fbac7128e +size 29874 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_4_en.png index 888bcc72ac..ef06f3a736 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:507a24f95e364976360e03baa3a8c7fb9aa47ae013e1c299b984a757a83c6211 -size 29627 +oid sha256:ffa0c05495e46dd7162f46e3039e6e2814ee7b596abfc993b22f1e695fd2be59 +size 29802 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_5_en.png index aa48b9f158..68f933cc2a 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbeeb89350b85c5ca23f9e4d8bb980bcb5620217150b6434d2b4c4d1df4e74e9 -size 30498 +oid sha256:e7cffc393e87d7740682641a729a8082b6fdd97c274ee580654e2afeb3597a42 +size 30434 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_6_en.png index a792c8206b..b44f602bcd 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d921b380e05063273f52c4d7fc613f464a43ad1dd28c8aeda6ec101f653f2fd5 -size 30224 +oid sha256:5096f4c8d78f2408c958f8894c1db75b028c9dd10243785d08ac156498383e2a +size 30250 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_7_en.png index aa48b9f158..68f933cc2a 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbeeb89350b85c5ca23f9e4d8bb980bcb5620217150b6434d2b4c4d1df4e74e9 -size 30498 +oid sha256:e7cffc393e87d7740682641a729a8082b6fdd97c274ee580654e2afeb3597a42 +size 30434 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_8_en.png index aa48b9f158..68f933cc2a 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbeeb89350b85c5ca23f9e4d8bb980bcb5620217150b6434d2b4c4d1df4e74e9 -size 30498 +oid sha256:e7cffc393e87d7740682641a729a8082b6fdd97c274ee580654e2afeb3597a42 +size 30434 diff --git a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_9_en.png index aa48b9f158..68f933cc2a 100644 --- a/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securebackup.impl.root_SecureBackupRootView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbeeb89350b85c5ca23f9e4d8bb980bcb5620217150b6434d2b4c4d1df4e74e9 -size 30498 +oid sha256:e7cffc393e87d7740682641a729a8082b6fdd97c274ee580654e2afeb3597a42 +size 30434 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en.png index eb8ccb31f9..b4b2825be1 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35b2b13201f62d5b413a7bd62dc9d7d47a36e1ae4cd68f90a95505c56f86a672 -size 49736 +oid sha256:e19cfcd28e8937b0b3536a2c7037c85ae0abc1c4bf71831a66cfbc1446f96324 +size 49460 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en.png index eb8ccb31f9..06d1c8013b 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35b2b13201f62d5b413a7bd62dc9d7d47a36e1ae4cd68f90a95505c56f86a672 -size 49736 +oid sha256:14e55642b2e48c0e110b3574531f70198da4eda59fe628f466cffd1ae8433a18 +size 49479 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en.png index 376a554a2f..9881a278a8 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d1f5807dc27a391435d48dc107e1830d40520ef7ea7585f0bbc2f3580fa4a23b -size 50362 +oid sha256:ddc2921acc17df274b389637ed597334ec70e320c6abebcf8a1a2127f9f959eb +size 49959 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en.png index 7c8f6b9795..50ad9ddc59 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b639d24cfa2c78304ac2d976d55344a83414cab584b48afdb83a20fab30516d6 -size 48430 +oid sha256:f2dd5ca149a11467d74b77c0f5dcde69196fd9e0ee0753a12edfcb41e37f07b0 +size 48076 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en.png index 7c8f6b9795..4e6036d026 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b639d24cfa2c78304ac2d976d55344a83414cab584b48afdb83a20fab30516d6 -size 48430 +oid sha256:6c9dcc25981af2b2fc471260161a1dab970605dcf3de24a8198146c7fa1ec693 +size 48085 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en.png index 51c7fc72bb..0fec265a70 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:38251453ecf826ff41dd3267f20c807e9d2412fd1fbaae07abfa917d04435980 -size 48956 +oid sha256:f75f11c8ede2d6cfbd111e952787eaf9763dfac32b45b6f220a08676d435a247 +size 48507 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en.png index 32856638ab..c5396ba814 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5beafca9d7a67740fef1f02d9ed300ea3c8dac06263269e721289b04ae175a2 -size 38727 +oid sha256:f89d101821ddf9b7f39869821ea93cbba9ff0da550c5cd862e7e959add7c007e +size 38692 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en.png index 912e229bb1..bffc2006c9 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0864de8d1cbc19554f0199374daa5a540b102b4a42cc2e60370a5bb74fbcebb2 -size 19840 +oid sha256:72b986a9c460d2da27624fc46665e81445306345ca9e3c55a4a3d9e9674839e9 +size 19802 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en.png index d24f13c289..d80eb005d4 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f59de7148c1d7796dab19c666892a73545b54723a36a284f874447abfbcb228e -size 39540 +oid sha256:c4c25c819690c34368c8f913ba70b2425269c2398de0af3ea73baa4d22b4e8cb +size 39523 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en.png index 91a48946ba..16a92ef23a 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63252e12d82b4033ff771063cccbcff2d5e0eb960656b40f7c1559b29d4b1e0d -size 39242 +oid sha256:ee60ec157962d9393a683bd3935c582ef422d4e3c3c15d4cf56f954f10420c23 +size 39235 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en.png index ad57dad1d6..065e57f157 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e380a9c7a4d70f86842bdf86c2a87703538ee9674d985727757d493cc0b3ea05 -size 39522 +oid sha256:727167769e999840490f8e44b2e374c62136cf679ab61f3718994069114c5cf9 +size 39505 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en.png index 27e7c1f8e0..0201133c69 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:514a5f490ea2e497145e55139ae03c187055c5b33fdad8b8a73aabdae95550ab -size 24879 +oid sha256:f91dc565672c381bd14043a11e8c8ec8c78da0a138ecaf16feb63ab33ee52d64 +size 24714 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en.png index c8f0d2b5d3..ed112a8c3c 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:830921552127e9c76357f294ebe9e12883ba7bfb7a98169369eaedd9bf3e2cc3 -size 51434 +oid sha256:a234d800bbdd5af2756459d81bbae629f71d7f992bdce63c9716ca7094992376 +size 50626 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en.png index c8f0d2b5d3..ed112a8c3c 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:830921552127e9c76357f294ebe9e12883ba7bfb7a98169369eaedd9bf3e2cc3 -size 51434 +oid sha256:a234d800bbdd5af2756459d81bbae629f71d7f992bdce63c9716ca7094992376 +size 50626 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en.png index 4104cae0f1..4ee3d35678 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4a288bb8b0da35579252cb58197df35c1e70a5c5b159ba0265ab527d7431d4fe -size 40177 +oid sha256:04aea446fcdfeefd54ff057d67eebb486fe208356db5264c0b6fca500799cb04 +size 40160 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en.png index ad57dad1d6..065e57f157 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e380a9c7a4d70f86842bdf86c2a87703538ee9674d985727757d493cc0b3ea05 -size 39522 +oid sha256:727167769e999840490f8e44b2e374c62136cf679ab61f3718994069114c5cf9 +size 39505 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en.png index 42c6dab2c3..ba3de9d448 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe3b86c487db6c880d26f384be6a4cec2babc1d7b3af5613323db4a3bb3bd9aa -size 39877 +oid sha256:e1c17074d23a1d97062bca30fab5a40cc70b6b59cac63e3aa0e39402ac1ec851 +size 39862 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en.png index fed921f1d5..6ac6af81a6 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bdde10d6fec6cdc6da430eb4f8a63da36c96021180ff1f50ef7a528fbaa8f89a -size 55481 +oid sha256:072998a03dd04c535439850f80313dbf4726422209c841cf684772912bb4c39b +size 55455 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en.png index f444a98a30..eb791ef631 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d6d77dce89d86bda6e4be7b93c7a0f5e5dbe84a482de8c562ceecddaa8107e9 -size 33498 +oid sha256:c2d715e94108a26be495dcccb59c3a23bb9e7ea58d352d78380d8fb530976655 +size 33697 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en.png index 7fdd30512f..cf25250fb4 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e61e006cc266b148bd0c09468e79d9077b96edb5fc2aba02f0c102bcb7f052b5 -size 32108 +oid sha256:77347e91ddec13ab69083a2c4905107bd4240cc49c36f5d2168dec1faa1c9fc1 +size 32181 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en.png index a29aab89e0..f7eb3efae9 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:162df243c49c7a03d44b9d4acad882bab0156924e5ac65e021c0d9877ad574d9 -size 34342 +oid sha256:938aec48d565322ab5d33c206acfe6496ec16daf31fdd90600ee919a35bcdcf4 +size 34415 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en.png index 252fe104ab..2f765435bc 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7df363d57b1ffd6cb31de77207478272657cfaa7c6599354d8533f32c3df71d5 -size 40749 +oid sha256:a21fbd162ef813ccde42e6be164432ebec9de097e8eba68cfd99efdc713ed1f4 +size 41002 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en.png index ed4c3eb1f0..a04d326424 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6866a3fa342a07d8b3caded1bca6069d170aba75da7b18f9dcfb79a53d0d593c -size 55204 +oid sha256:47881831487dcf33c9fa43d97c418cd0ff9a417e684a38c555bda3887692912e +size 55201 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en.png index 5eb1040a08..564dbf4a00 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f713f353e524afa10b8eb3133b0d8eaea7a1e77f6f34b31fa67f5b05bd4a3e88 -size 55704 +oid sha256:4e89f6b7533b11df6ceae1959bf0192a6cf73373a25cb17d12c7400e3c62d061 +size 55705 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en.png index 0129c9f065..b76f86ec63 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56bdd0ec5104c363983408ced699ba87d9297e723f7b7e6884c2f27d0487e443 -size 44088 +oid sha256:e2cc12036b90857acfc70b6932e74e823018c25052db0b7dfdd541ed74f8f8cc +size 43891 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en.png index 0623be997c..da1e8361b6 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ead04dcf21ce07f7ec750f498048a6100487137cb781932da104b52e0ab3994 -size 58447 +oid sha256:3031fa39be2f1ed6f20065397d7483a09679f4f84ebb1367d339611ed3efaff4 +size 58557 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en.png index 0623be997c..da1e8361b6 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ead04dcf21ce07f7ec750f498048a6100487137cb781932da104b52e0ab3994 -size 58447 +oid sha256:3031fa39be2f1ed6f20065397d7483a09679f4f84ebb1367d339611ed3efaff4 +size 58557 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en.png index fd4f7cbf6e..52f30eb67a 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e20e43dcf14088eeadae32f7d428de71d334f10dfe3ce43b5e8e42bebac152d -size 56118 +oid sha256:064957a92b109305704f8d812dd8065cfffaa11df6fdbf5c9acc2a507f1bd2f3 +size 56094 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en.png index 5af2e09dde..cc6c805d0a 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:319ba9f6e74f0ca21654cde88cdb44662cf11181ae30e9455ccac048e0c52e1e -size 55459 +oid sha256:f88447684350ceabd3d497430449dc3cd8925c588547b80dcfbc19a92a8796fd +size 55435 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en.png index 6778e4a00a..120ba3ad7c 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed5abf37daa0f363b029c07a9209ccea97555b2c31e01f1f9ec0588fbf6ffb69 -size 55822 +oid sha256:830f80abc95090f1062616c6c0f39c27a90fce554222117512929292eec7d284 +size 55811 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en.png index 84c7526b4a..48fc37e537 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88058a16e383e580f20f0c010c14d63e4712e007c4016be0f6fc029309482568 -size 40242 +oid sha256:e22e322cd647eb60e0da1010527ce044a79806859698994af703e9ce75e586db +size 40283 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en.png index 3b2952e617..6416a4ab7e 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aeb28f7ee18c588132b611dccb17ed100d91dd0b588c48cbe290107018857025 -size 20440 +oid sha256:77cea40c4d040cebb98608bb60a8e3aebf35d327ec57c97ef451afdb44b17e77 +size 20473 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en.png index 6ddd3086fe..e4126fabd8 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd3ac37151e303598570455bc10206a58410100bd3db1437581181d1ca0c39fe -size 40666 +oid sha256:d3f4e2cff9e9a7d0f8a4ecd84ca7e2c007adb14189aa0dcf2c3da76a21330f4e +size 40703 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en.png index 324e6dbd51..4c6c01772f 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b15f07242602bb5e8c19ff3d821230122e1b331fbc0178ee4b3c2bcd6d270ce8 -size 40380 +oid sha256:f71e37f3f5d0b4bbd8c0234363dba9fd275bea3c9bc1b7afc1bbf585a14e0f4a +size 40410 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en.png index 70c12f8dc8..3db5449204 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26162b442c3e569bb9ba359c5f3ac6f5563ac175fe78088ec31d89bd6a3ddf0e -size 40662 +oid sha256:cdff4ce956589c96df7bf0e6f00b7a2f3f94c15b40bc1a812961515bef30070e +size 40706 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en.png index 66e270de9c..4f4aac791e 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a5a729790a34e95f9b3744cf88d4d5e3a7289c14669301e3a60841a972650eba -size 25273 +oid sha256:0a2eb12c4e797abe3ab5f3db37079a841182268aed4c5e42d7516b7ff92c4b61 +size 25133 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en.png index ed1c17167d..44ed276e90 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f10cdc5541d9199788e7e75f76b46dd861970811ceaa6603fe827b3950c91eb -size 52892 +oid sha256:97313311051f2decb6c535b38fbca76a6ce9af8943eaf2aed898cff2e2e90082 +size 51966 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en.png index ed1c17167d..44ed276e90 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f10cdc5541d9199788e7e75f76b46dd861970811ceaa6603fe827b3950c91eb -size 52892 +oid sha256:97313311051f2decb6c535b38fbca76a6ce9af8943eaf2aed898cff2e2e90082 +size 51966 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en.png index 0368dcdd06..a286d3d73d 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c9e224c5fc2ea084f97818ba32574606782c92345ca5819c3d3235c1b1723980 -size 41383 +oid sha256:b4306c5615ffc1fc13618e9b1344dee4bb2968b808e283ab76a528f2cceb2aab +size 41417 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en.png index 70c12f8dc8..3db5449204 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26162b442c3e569bb9ba359c5f3ac6f5563ac175fe78088ec31d89bd6a3ddf0e -size 40662 +oid sha256:cdff4ce956589c96df7bf0e6f00b7a2f3f94c15b40bc1a812961515bef30070e +size 40706 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en.png index 3bbe4b7683..07ea5601cd 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90b4895d4ccedf4adf6fc470698b194b315f51ccd547ef5b5c0ac4b945d3f757 -size 41125 +oid sha256:eaeaea007e904953f8a284dd04a9db581b69a24cf5a81e1777be9a20401fdcc0 +size 41141 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en.png index 32bd89a615..d357f1ecf9 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ee7585b0c8ca85ea4dde61a2685a012a57b704675227835af2df95a389ed831 -size 57322 +oid sha256:a28782b448b87b412ccd7c12dd12ffb76db04adf867c1334fe0637a2c73b5094 +size 57366 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en.png index 88a5481a2e..f20ff17ef8 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43d831a51115745c8b90c0966811a7a725ecdac4e75425bd9dab14e85d98ed54 -size 35043 +oid sha256:19d63cd8758188b15c418865204092ae9a5e99af6fb61c09c89ef87bf87f6c06 +size 35232 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en.png index 36d63d5bee..ea91803e4d 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66ce52ce8cf7cea8fd6322167fb99790dd28c6a93a9db4923373a6ade9be530f -size 34292 +oid sha256:dcd2b01ce2bc6c36d16117420fb0f3a70eb1527cc26da3db7260dcee4c0ac643 +size 34341 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en.png index 38c5771f72..29127b5f84 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a9ae1fe64156b3e12ef94a96f7c35f007f170f37c34ac823b562bcf77a63ee14 -size 36461 +oid sha256:fdd3a6ca1feb3caaabbae00b6b61553e5a332f97a62ae836a16404247812a7c5 +size 36506 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en.png index cb969b5be1..232066b56c 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3a106eb66716b317b7f66faaea09ec19272c18245fb3b82acfcdb07e308dbbf1 -size 42952 +oid sha256:d6df276867d4dffd59ae9a88bd518d13db3e44e9f5433c58847bc86da18d759e +size 43201 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en.png index a33315a22a..5c81790881 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c08f7eeb22d7f6652a2bfe681913515f4c79855c8f0ade5649743f4ce440137b -size 57028 +oid sha256:b054389ee0d5296760cb025b236d9a4ab5c0e96165e288d3cdac3f13430183ec +size 57086 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en.png index 705e77f421..d50f5e46fa 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7bf5fdeba61909591340e2fb84732002cc3526077e2e2c47d867293cb53add31 -size 57719 +oid sha256:c21118d9c455e6d9a967dd8d70e0a8cd7e9da6d3f7fdf5ce66d1044b0ac33cdb +size 57746 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en.png index 2898a2f123..775296b390 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63c14cd8fe07bafcbd0374e8b4981b978509b6022d60ca38a37c3500e547accb -size 45769 +oid sha256:a43e6c037debb33ee2d7eecb7e1732e63fa556a7a0e729d6b2f916813bd642f9 +size 45609 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en.png index 3e93b799b8..15e47d1450 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56d0dc43ba0e17d35ada6c37a73442a5f586a6cc411075f45ca42b72a7c30681 -size 60329 +oid sha256:803b04a9295b8500f95976eef56b2ce27de6444a9e9f2063e0e7838ba9ec0f26 +size 60522 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en.png index 3e93b799b8..15e47d1450 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56d0dc43ba0e17d35ada6c37a73442a5f586a6cc411075f45ca42b72a7c30681 -size 60329 +oid sha256:803b04a9295b8500f95976eef56b2ce27de6444a9e9f2063e0e7838ba9ec0f26 +size 60522 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en.png index cee811de8a..fb3fe908ff 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d7cb0d4d4e44e53336748c6c7527180bcd852e4ca1b5c347e46e2ca64cb3bd6f -size 58002 +oid sha256:2b3e332c18a339c20f77f592639dea6fbdfd7b3e7fdaf8901b83aceb7660b497 +size 58054 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en.png index 156fdc9aa9..f7219701b9 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:37438de5c8d4b190f0e234907e35bd318201dec6e0bf6f96086ccf7dd5cfb406 -size 57316 +oid sha256:189defb47c6402f380d06da8c0ce162f0b90f78026bae8b1bbac886c3d65f0ae +size 57366 diff --git a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en.png b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en.png index feb995598b..c61835b8eb 100644 --- a/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:889f976c8fb5a245e7855a69e3fe1c8619d68695d8bcccc59b38af49efd1ad38 -size 57750 +oid sha256:1cca6b3e7a2856bb4d49805e137e1a15d73c5d4b630716038f9f3fed63e1df21 +size 57769 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Day_0_en.png index 9d9b261e38..da0949de84 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0cf081ce4abb6cc0d5e80ac8387a91e29139f79762f107eb274d70246950c552 -size 37667 +oid sha256:e09f17baa9b6eba866855cb8f75ccde5c7d9db550f3cf0b8a15e29a1cb2a35d7 +size 37587 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Day_2_en.png index d1aacd1904..6272999415 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2eb30c10e1c6e8c1ff3ac3adbf6e5a95ff933f5fe7420b65aed34643b07a059b -size 21227 +oid sha256:2375940852e1b63e0caaca5e74a82e9468d29277da42c97a7e367f002382de2c +size 21212 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Day_4_en.png index 3c34238b9a..2f42c69aec 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4e89a186de091f4e23630ad5fc71c0e01296876d8c3a2a5fc6fa6ac00220e468 -size 42083 +oid sha256:cafb5b13d10812171a262ec27676b8fcaf984202e809e3f1a83a4a97c541e717 +size 42153 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Night_0_en.png index 519167682a..7aef200cad 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4be298e13b622228c0890d8597b304507fd7c8057fb776cb8f1857a5b9e6d731 -size 37588 +oid sha256:83bfa85a90ef732047fbe5330202a2d5a139499b893aa176f7b53f125cafdadc +size 37552 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Night_2_en.png index 433ab118c2..941975e910 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ece2a836b5ceb25847d40396239d029e7a4ecde52c294d8e2beb073ee154776 -size 21599 +oid sha256:f2a36e62ebb97b895f05c516351f609203cb5f1767d93486dcdd486aa1eb4d61 +size 21547 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Night_4_en.png index 43a70b4471..cc5caef9a6 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.addroom_AddRoomToSpaceView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd2b7f829f6232c62980386225e82dd946e132dd50f8e571b74a7f305965d26f -size 42395 +oid sha256:a7a3e0e5dfa82460a00a2ebf768e9ed08caa89868252aa40dca401889e527c23 +size 42480 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_0_en.png index 95af0557b4..4fa687ff88 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:65e6adcb15b51201224b3566ec85b9a935a45bc5b9a4b9a5d2d1db125425fe59 -size 22063 +oid sha256:e8e2feebc67d2056d982bfbfc0130916603fbf4297015703053f439892d1df01 +size 22097 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_1_en.png index e50ea76ce9..7002bdcddc 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f1b901895aa8cce2f8c183ed872c5b50575faf9c1cfb58e0225a22a08b0443ed -size 18385 +oid sha256:6328cb4da78e63430304b7bda55a3720970464592541dde3877bb658da812048 +size 18438 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_2_en.png index 83d98a46a0..cbd0be7eda 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a87ef69a7143c6b637bf87fc82d7d04ea64d5024c6f44411d2fa60fb04d9d882 -size 26065 +oid sha256:761637accfb56d5b97db590bb2a8a0cd70d4dde53fdbd1ad355541f6cf8e9827 +size 26022 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_3_en.png index 842ee7204f..6b4e7c1615 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e6bb50005ca745dae15c2e4d7a5f28368effce2917c9e35ebeaf21b69e5c4c1 -size 26584 +oid sha256:0cecd46b3eb2ca4083eb44c73049a8b020415dd028130407653eb792dbde0316 +size 26586 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_0_en.png index aa6160d8af..d9e0d5d644 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:087adc479cf8e9b87f4f269b94fb8b3661b0a6902a0b9d921622bfafa53e0610 -size 21516 +oid sha256:ddbb118c51dd205f4cec37f0fef07afce941457bd6e953d2ab9890e4f7ecbd7e +size 21504 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_1_en.png index 8ea57ca08e..334dbe1080 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:afabb2f9b78af8ade56f79a4bf02039c6e4b3ccef8c60e89439de091da089ca7 -size 17840 +oid sha256:88867849fbc0420f0772e4a3907ab5f21da41125e24de9c4951db248cebcfb2c +size 17827 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_2_en.png index c538831670..6619b3df83 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0abf4b9725268a7762ff1b426cc97f96d8e71012d35102c968f518f05007241d -size 25210 +oid sha256:75c5a38547242a6048e679059d2eda72af502be758d5daa29d53ac33a7c424f1 +size 25208 diff --git a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_3_en.png index 5df4e31394..87364a0a84 100644 --- a/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.space.impl.settings_SpaceSettingsView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c5a119b8c5bd09a62382343043333dd478ab82fdb6f04ce420641edaf6fff7b -size 25649 +oid sha256:846062c957ac24c9ade2dc1a3014cca735918f695bee1601c3937a7323b3cd52 +size 25673 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_0_en.png index fc6d33f7f0..76f78e88c8 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:413a3f42ad23bbab9a920128950b40f9eac5ef9248fd5ca164b838b7d10d9cdc -size 24062 +oid sha256:d05e20da85581d94fff021469cd5e42b0cef9d77c038d1d50f7abb15f793b7fb +size 24100 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_1_en.png index c5b576ef74..9671c0ee0e 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5893b1d1b8851d26d3bdb12f6b68954d03c9234d4ebf0ced6aff13b155595f83 -size 21828 +oid sha256:d1377f09436d2724a7924fac070ff7c7b1489c561025bc02627bb42c3cc10438 +size 21822 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 f255914d84..3abb30ae8e 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:ba293e027a30171d36aba06bbead8b616c706822fefea912b1f4beb9a3985da0 -size 24290 +oid sha256:6e091802351a5ed213f2dc60187a439a5afef998136fa508db42931764ac58af +size 24284 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_3_en.png index 43b8414534..6e0d93663b 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a233930f23a1ffd82b9c48a3106218de88df49ef785b252ba1844a126c7eddd9 -size 36159 +oid sha256:98da2250342ee964260c48a52acb366ea930cb65e967fb89ee94261562da2367 +size 36226 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_4_en.png index 51a45218fc..518fcb41ce 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2583c6fca6d7528b7bb8ea2eb3d82e012b970ef7b024c5bbeefc1c4973794e32 -size 28715 +oid sha256:01452418d8e609ba37ff44756835f26aed949d4b781c67efe6fd3983d93591bf +size 28819 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 2d7523e28c..a3f5ae86e4 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:94b86f639e03998bd47b423f0c90dbb9767165cd2905a700b5ed29ecfa63d525 -size 22496 +oid sha256:9280e315c64dbb8e100f20bcbb2b8d68f90612a94df8b71878059321352f6156 +size 22447 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_6_en.png index 1b3752626a..3d03af0f9f 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9848fa1e1af5dd63be1f6df0375627efab136fbada1c6afb7aa058db697f245b -size 22284 +oid sha256:a05a107e16f30cf8fcb59fec83beed44b890560b6e5b7e1aeb1aafaa203ffd3d +size 22389 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_7_en.png index 356db152ec..6d71c066dc 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db9f567fdf457f2ce5072c0c848ad48942f92f5af96c7d0f144d4e12fd651e6e -size 26688 +oid sha256:d21e2e85db54d0074376e72a3ef1b91caec01c8e8c2d6d0b1f87034687440fe0 +size 26723 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_9_en.png index bd9cb74dc5..7ecc9dfbec 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e87058ca16fa51807d79a8112aa3c105957c9785ae057686a92403133a556c2c -size 32353 +oid sha256:fdeaf4edcfe9b8ddac1276c51cc668d1da9198359b8874c3928d899e9c0a7c07 +size 32336 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_0_en.png index 3b4a36e777..c7e9da3fbe 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:33356c2a7ba816a0a6920e50eb8bf20212a062d11d6ba117923c9ea973d171d8 -size 23455 +oid sha256:980c3503b30e3c421c664e90ed3d53a7f091fb9ae1c815bc678753c6c7c35957 +size 23488 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_1_en.png index ce6861e02c..edaffd4455 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c4d8861aae54ab13cc8fdba1d506b8bb682fc41bf05584db55ca8fce688ef240 -size 21435 +oid sha256:1770b536c1f3ca83f226bc29efa7e909aaa6b05ea8cc8901821c73392b51a2d7 +size 21482 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 097e96258f..bd4be11d2f 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:e42a2617242df3e2dcad13ca623ef2a2f60fd133a2da287a49255808cf31ff4e -size 23640 +oid sha256:d2b9f4f964f15396c3652fb709965069c097754332a5a4d7e4f3c61b71ba542a +size 23573 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_3_en.png index 34304b7884..8864b5e730 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3acb94720610f1a0ea9a1861a091109b1fb9555b09faf432fb1bd702f5c81320 -size 33946 +oid sha256:ff1f5ee1042b3012884fa67f993bd3d829befe5b97b0ef3392bce69f7c791dd6 +size 33994 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_4_en.png index cc712188d9..1ef711b008 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:490fcf83d06592f39d88906b445aa826f6f4c0d0735e7fd8187b1eada5474d79 -size 26981 +oid sha256:a51d1ef5ae6de13bec4829fe7643e5cd21c98551814edfa1d0a71eb8c104cf86 +size 27034 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 2056976aac..ab8718e0a6 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:89b989f3c910c24270a09e2804e9e5bf1901d0247d00f7abc6045f394acb7dfa -size 22030 +oid sha256:728c88405eced49102354f3b72643eb9c2b55ff9aebd50853523cb0f79407f11 +size 22041 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_6_en.png index 981ac8e6a6..3d24b36c71 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:25496e6505e3905108d74bbd0d299576a24d1a40e78107b0780f50a5ed1617ab -size 21065 +oid sha256:ad3f942e972558c4ecefa887bfd97d5785c2c256feb2fef4fa6f32e0c68d6040 +size 21161 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_7_en.png index 43a79d0897..f8d55e6be8 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e29852c6193c1fdac9b81629844d32399d8e8451e1ec7ff1f5185904a2eb2361 -size 25947 +oid sha256:cbfd9a1ad8a72ab42eeaef6ea4a0f8a7a579b158bab29b05808170dfe5a0c728 +size 25986 diff --git a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_9_en.png index 3b411f6e37..cfdd735be0 100644 --- a/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.userprofile.shared_UserProfileView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:92b56ea3b119795c4d4f9b4a8f430a5ddac400f87651419e35d1668c90833e13 -size 31285 +oid sha256:4d637d0ce849388c5b67770ab2d493c877f8f690bb735e5fa00815152f7da3a7 +size 31346 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 9b53e56d9f..8ed8df62d0 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:a7983d27647e60d385703d5bb91763ab787ee69e0a0ef04acd13ca86d5d5b1ec -size 9560 +oid sha256:501b8ac2a46e21bab7699dabcd256752e4a409f84fcdfd6ca8fcb4aa7188e4ef +size 9711 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 ced849e58a..fe85caeddf 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:c32280e645ff1459b179423f67077dfc75093f5e6c40fff659769d164f391aeb -size 9408 +oid sha256:eabc2b4dafa69c29ad216997303e48194afd958cddd9ec94f21ec7109304ad6a +size 9555 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_MultipleSelectionDialogContent_Dialogs_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_MultipleSelectionDialogContent_Dialogs_en.png index 071581d869..372cbeef54 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_MultipleSelectionDialogContent_Dialogs_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_MultipleSelectionDialogContent_Dialogs_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e68131a1dbc3aea5bc096fb240f035dd7fa1907dfd1ada5f6f3f3a6bd3ba606 -size 37349 +oid sha256:1e6681255561c96b0ff17ab926dbb0c5666bac399044929898e029a16a429a66 +size 38322 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_MultipleSelectionDialog_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_MultipleSelectionDialog_Day_0_en.png index 58df54c186..e741d18262 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_MultipleSelectionDialog_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_MultipleSelectionDialog_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4acaf30457978c09cdcd8582a6eda7ab82cc21eeb3fd7ffcd016033969efa32 -size 27587 +oid sha256:672240fb9bb51c4d6f67b6aea7755e7cb98af405601c3fda5456ea0dd4dc0ae0 +size 27615 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_MultipleSelectionDialog_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_MultipleSelectionDialog_Night_0_en.png index 147ebba78b..4e36600fab 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_MultipleSelectionDialog_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_MultipleSelectionDialog_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a68b58db6c683e010806067aa531af1e6343bda0ee53a36c7767127c409df306 -size 26195 +oid sha256:72f1f9515f26927124f2cd90d3442819c5edaad8b2a84878286fa3d01ca01d4e +size 26142 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_SingleSelectionDialogContent_Dialogs_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_SingleSelectionDialogContent_Dialogs_en.png index 4987933ce3..767cb5157e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_SingleSelectionDialogContent_Dialogs_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_SingleSelectionDialogContent_Dialogs_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec0a9180716520fdc61c9e0192d9bf85bbccdb94a107c4020c2ed8c6c70e56be -size 18566 +oid sha256:cd253110c5030bac938211823bee88b46c13e4c8d4c384afd56e3fb395e020b7 +size 18668 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_SingleSelectionDialog_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_SingleSelectionDialog_Day_0_en.png index cdd08c032d..840f8a1c17 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_SingleSelectionDialog_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_SingleSelectionDialog_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:098b138a40327f84a7476a9148c96475e629a7ee150f2e1615cad780f242bdad -size 18921 +oid sha256:423056bab129f1376b61e0ff09e8c6e76e325d6c13ad4dc808538b6911d1b6d2 +size 18986 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_SingleSelectionDialog_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_SingleSelectionDialog_Night_0_en.png index 9c826999db..beeb10153e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_SingleSelectionDialog_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.dialogs_SingleSelectionDialog_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b43faf9b2fcd8f9bbecc372921b2734bf440e9745a8b90962ea9de052abae538 -size 17591 +oid sha256:8bf92f9aaf2d9b4d96c23293c36b1dd5fb46be41ea5d0605c90b67697e1f50a5 +size 17560 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en.png index 29fe0beee1..f08195c813 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f56ec8ce787f1c5aa7f107daf76b1c114b4336b9e863b09392966a1568077a3 -size 24714 +oid sha256:ca93aa09997467d8abb13ebe011128c17e0a8b6518a62350382cfbd71f196ce8 +size 24805 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en.png index 32c07e7294..650452cf36 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:daa67933b6b932cd1efb72dae107877d8742b167969074aaafea04c4f826c892 -size 65167 +oid sha256:7af8326bf7f375409c40180a8dfb835a9ceefa5ea058766251e1205d2e9b9bfd +size 68704 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceDropdown_Preferences_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceDropdown_Preferences_en.png index d061849688..6c1e30afe2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceDropdown_Preferences_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceDropdown_Preferences_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66c00d723a56ef0e6a904e07d5b6d8ea537018b0098633339506afbb1697944a -size 41149 +oid sha256:5d50217b9058d394d32a5e8ef07fdd0bfff058d315c0e69ee9109bcc47c23579 +size 40931 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Day_0_en.png index 64086bcf0d..c2a724427a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2765082210b5e2d66badac2176460337972df0c5c82c8512a700fe941cdeeb7d -size 22232 +oid sha256:38631edddc9eabfb83967abc240f0bb8957dd593d1d193e35c44931ccfbb499e +size 22074 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Night_0_en.png index 4b3ca0b6ec..6d0921261a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferencePage_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9020479ebc44a6a41f4542bd6bc78240ed701dde274a320f2dabb5e3a62d8fe8 -size 21548 +oid sha256:e2631c3ffe70f5d2ee719415c9629b86b660e93abbc113b0062916ac8523665a +size 21308 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceSlide_Preferences_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceSlide_Preferences_en.png index f519c20296..8de4d025b2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceSlide_Preferences_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceSlide_Preferences_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b1d79f0f51dcdc17953355313fc16751c6615eb4cee88ae847e3e0733014ddda -size 23626 +oid sha256:23c0c6aa38bebef3a9c89d6db2e73ee37eb5643ac6fcd70a3c1087819de12445 +size 23660 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en.png index 31d1d66f92..456518d3f7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0b5366e81ed7d1238ec881cfd715e895fb2a6589b7b840ead83ba82dd5eb274 -size 35637 +oid sha256:a073d17826ab42c019f90c86631ec19fd4adefdd874ea62f89509daa48e8d3db +size 35828 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemPrimaryActionWithIcon_List_item_-_Primary_action_&_Icon_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemPrimaryActionWithIcon_List_item_-_Primary_action_&_Icon_List_items_en.png index 86cd39272d..7304cd8c35 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemPrimaryActionWithIcon_List_item_-_Primary_action_&_Icon_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemPrimaryActionWithIcon_List_item_-_Primary_action_&_Icon_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2107e822d312b25a19c1b062d7497bbad49cd0f2cacd65a3d08ef868609c438 -size 13331 +oid sha256:2e8c8d42a8a0f72c298abb282ee218a0dcd50bdc61419e32e66693e2d401ea62 +size 13369 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineBothIcons_List_item_(1_line)_-_Both_Icons_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineBothIcons_List_item_(1_line)_-_Both_Icons_List_items_en.png index 1a16aae1fe..9600224209 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineBothIcons_List_item_(1_line)_-_Both_Icons_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineBothIcons_List_item_(1_line)_-_Both_Icons_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ed896e700fecc71d4b3d11697acbe8d971a49c0ae97e160544e7d392adaf298 -size 16731 +oid sha256:69d76d91f33c11facddf3be290020c9dcb12a48f7062a4c2731b48bdd97b7305 +size 16732 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingCheckbox_List_item_(1_line)_-_Leading_Checkbox_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingCheckbox_List_item_(1_line)_-_Leading_Checkbox_List_items_en.png index 48d3dd62ed..2a4aef9a23 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingCheckbox_List_item_(1_line)_-_Leading_Checkbox_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingCheckbox_List_item_(1_line)_-_Leading_Checkbox_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bdb9a27772fe8de617de84b37a8d4d729d9f45987aacd8859eba012ebbba3e1b -size 10566 +oid sha256:eab65c8c1c62098b3abddfa7c5510de4b82f0957f959463f4c3b36b40835707a +size 10527 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingIcon_List_item_(1_line)_-_Leading_Icon_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingIcon_List_item_(1_line)_-_Leading_Icon_List_items_en.png index a6d755dc6d..af9353b354 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingIcon_List_item_(1_line)_-_Leading_Icon_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingIcon_List_item_(1_line)_-_Leading_Icon_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d55eaa95e367f77897ab2dd1d5a31c572ff3d3e5b0066f9a545917386a3083e -size 13542 +oid sha256:92d8641e31136a7faa27314514b55837b9627214cf13524ca64d8d01458ccd3e +size 13547 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingRadioButton_List_item_(1_line)_-_Leading_RadioButton_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingRadioButton_List_item_(1_line)_-_Leading_RadioButton_List_items_en.png index e47d23ddba..400c0acd62 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingRadioButton_List_item_(1_line)_-_Leading_RadioButton_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingRadioButton_List_item_(1_line)_-_Leading_RadioButton_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3175fb068e7a1049efec3cb710052c1da33917b1ec86162b1c959439d72d0ef2 -size 13214 +oid sha256:9f8390d624ad20902ad183a794f28b76f3ac7ad299ac66a5f74e7d12c8e2adc0 +size 13164 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingSwitch_List_item_(1_line)_-_Leading_Switch_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingSwitch_List_item_(1_line)_-_Leading_Switch_List_items_en.png index c2060478c3..4b24210ffa 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingSwitch_List_item_(1_line)_-_Leading_Switch_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineLeadingSwitch_List_item_(1_line)_-_Leading_Switch_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b237a6a4a6cd367457a06ea102cda7239e5a7747068d9bce9cd7982fb14ffe50 -size 17440 +oid sha256:4f34772ee85bc9b55ab8c1ce4d833208882a4b9696f49000fb346dc85a968c99 +size 17296 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineTrailingCheckBox_List_item_(1_line)_-_Trailing_Checkbox_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineTrailingCheckBox_List_item_(1_line)_-_Trailing_Checkbox_List_items_en.png index 971ad0d595..579f68c0b5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineTrailingCheckBox_List_item_(1_line)_-_Trailing_Checkbox_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineTrailingCheckBox_List_item_(1_line)_-_Trailing_Checkbox_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba6c487bc98a2ace5e275b51944c6ccb32c832b0279ce018f636559bdddbc1de -size 10470 +oid sha256:b3b91e45fee56f0aef50a481918536399b5a15ec84e8a68390fa95b8f2daaf27 +size 10508 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineTrailingRadioButton_List_item_(1_line)_-_Trailing_RadioButton_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineTrailingRadioButton_List_item_(1_line)_-_Trailing_RadioButton_List_items_en.png index 04205e28bf..579c69e716 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineTrailingRadioButton_List_item_(1_line)_-_Trailing_RadioButton_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineTrailingRadioButton_List_item_(1_line)_-_Trailing_RadioButton_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3e28c242fec3e32c0a01e1830ba34b68afcc9886a234876407b1ace2d4688f4c -size 13097 +oid sha256:00990e6afbb823ae7ece6d89abab7739664e260c3b9fd2882eec685ab1e577b2 +size 13069 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineTrailingSwitch_List_item_(1_line)_-_Trailing_Switch_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineTrailingSwitch_List_item_(1_line)_-_Trailing_Switch_List_items_en.png index 4658d00c61..3e8540e03f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineTrailingSwitch_List_item_(1_line)_-_Trailing_Switch_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemSingleLineTrailingSwitch_List_item_(1_line)_-_Trailing_Switch_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7e558b303bd338b13ffc2b728161c7a6d756a362b6ee9c78cb5180aef878ace1 -size 17194 +oid sha256:6281271effbcc831bcf3e47fe547bddfef2b8a394c457f621bb8643b74cc9b29 +size 17059 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesBothIcons_List_item_(3_lines)_-_Both_Icons_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesBothIcons_List_item_(3_lines)_-_Both_Icons_List_items_en.png index 7e8a091f5b..0dbd6895ea 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesBothIcons_List_item_(3_lines)_-_Both_Icons_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesBothIcons_List_item_(3_lines)_-_Both_Icons_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d986b1dcb8553060f66e78f5882ac2de519a59ed07d7ba600a2e25be7091dc8 -size 46805 +oid sha256:1113bafef8a52c986f84dd388abfea93d93eb4630536b6e36b1d8626b16131cb +size 46718 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingCheckbox_List_item_(3_lines)_-_Leading_Checkbox_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingCheckbox_List_item_(3_lines)_-_Leading_Checkbox_List_items_en.png index f48e6c8b84..6c256593f4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingCheckbox_List_item_(3_lines)_-_Leading_Checkbox_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingCheckbox_List_item_(3_lines)_-_Leading_Checkbox_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a5a194e333f5941850ec59f1b632521acdc9e0d0786a74c1093b8cf08ce32cc9 -size 40887 +oid sha256:33193e1c2197250e9be9c58faf66c774feca32297d09ef3872b0e6611ebf2d04 +size 40965 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingIcon_List_item_(3_lines)_-_Leading_Icon_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingIcon_List_item_(3_lines)_-_Leading_Icon_List_items_en.png index 877ee1dd0b..1403bc1fd7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingIcon_List_item_(3_lines)_-_Leading_Icon_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingIcon_List_item_(3_lines)_-_Leading_Icon_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86911fd851d25569259cc76db52c34f3ec4ebf9df6898bee13016f8f3d5638cd -size 43840 +oid sha256:daa4ad5e65a0da81debb12f638c8ba3c65571c4fb8413594a8f0239d1f13fcc2 +size 43769 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingRadioButton_List_item_(3_lines)_-_Leading_RadioButton_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingRadioButton_List_item_(3_lines)_-_Leading_RadioButton_List_items_en.png index f57544073f..c872436568 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingRadioButton_List_item_(3_lines)_-_Leading_RadioButton_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingRadioButton_List_item_(3_lines)_-_Leading_RadioButton_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:84699e66aab169a83725db1069f8cf52e3f96720ed2252d3574a8d6895c5bf9e -size 43143 +oid sha256:dc7bf60912a15c1663d02efa5211589990f50c76de061152b74eab4f9cf6add9 +size 43499 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingSwitch_List_item_(3_lines)_-_Leading_Switch_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingSwitch_List_item_(3_lines)_-_Leading_Switch_List_items_en.png index 3929435593..603751f57b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingSwitch_List_item_(3_lines)_-_Leading_Switch_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesLeadingSwitch_List_item_(3_lines)_-_Leading_Switch_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe023e608e9ab7bdc4cf9821f508473f7f46bf22d3bdcc4a8bfe24db067ac61d -size 46904 +oid sha256:c166c1bd12e387fb5820ca86534a83c5442af1893b93524df916db9fac2a6cde +size 47085 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesSimple_List_item_(3_lines)_-_Simple_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesSimple_List_item_(3_lines)_-_Simple_List_items_en.png index 7e15b2cf68..0f896c5e10 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesSimple_List_item_(3_lines)_-_Simple_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesSimple_List_item_(3_lines)_-_Simple_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:523f92ecce569d895a4a5da0c473d8e3e7d485594a2e3f2aa9a4dd4d35f281c0 -size 39710 +oid sha256:c71110d154b49ade0a4f01f2e8e3954959c19e76a99bf7777a934045e0cf074b +size 39725 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingCheckBox_List_item_(3_lines)_-_Trailing_Checkbox_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingCheckBox_List_item_(3_lines)_-_Trailing_Checkbox_List_items_en.png index 4c6065e04f..cb3eac70d6 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingCheckBox_List_item_(3_lines)_-_Trailing_Checkbox_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingCheckBox_List_item_(3_lines)_-_Trailing_Checkbox_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:80ffd692a9e9fdccb81c485e9d4aeb17fd79be445bb5abd114367a6718946bd2 -size 40705 +oid sha256:f6bffb6ab53a386f31957f40958873af7ff699e52939aa43444ebc425df5aa67 +size 40952 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingIcon_List_item_(3_lines)_-_Trailing_Icon_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingIcon_List_item_(3_lines)_-_Trailing_Icon_List_items_en.png index 07daf303e2..2661373140 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingIcon_List_item_(3_lines)_-_Trailing_Icon_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingIcon_List_item_(3_lines)_-_Trailing_Icon_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b46f814d5f790381507af54c1e1d25ed5fed870243e9e1af27ca88f936470748 -size 43205 +oid sha256:d2daa67163a8b84cdb5afea72b217cd0db4dd57b32849aa99a26ccdb959b46c3 +size 43501 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingRadioButton_List_item_(3_lines)_-_Trailing_RadioButton_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingRadioButton_List_item_(3_lines)_-_Trailing_RadioButton_List_items_en.png index c8999d5ef4..32603f10db 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingRadioButton_List_item_(3_lines)_-_Trailing_RadioButton_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingRadioButton_List_item_(3_lines)_-_Trailing_RadioButton_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3195751d8dc8ea8740fd9b6059461120e7580737893f38b02fe56e5295017caa -size 43016 +oid sha256:a8f33707d9bdc37214928bba4903497e5a21dd4a68d4eb41bfecd6e58c425279 +size 43485 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingSwitch_List_item_(3_lines)_-_Trailing_Switch_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingSwitch_List_item_(3_lines)_-_Trailing_Switch_List_items_en.png index 225838a112..c0e557bf31 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingSwitch_List_item_(3_lines)_-_Trailing_Switch_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemThreeLinesTrailingSwitch_List_item_(3_lines)_-_Trailing_Switch_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:519c96175e4568585d76656e7993b5c548909d056a9f7a3df50ce4f35938cfd9 -size 46545 +oid sha256:e50872161403076d757b44ae88d2c2cb4eac985fcb2eb148ba3a8fe8ffccfc95 +size 46970 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesBothIconsError_List_item_(2_lines)_-_Both_Icons_-_Error_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesBothIconsError_List_item_(2_lines)_-_Both_Icons_-_Error_List_items_en.png index 4a8a371047..fb33e1867c 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesBothIconsError_List_item_(2_lines)_-_Both_Icons_-_Error_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesBothIconsError_List_item_(2_lines)_-_Both_Icons_-_Error_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe703dadb9d9b908ce8950b5357634d6cb2798816c114d26004098578bed93c5 -size 33699 +oid sha256:832c81d4f2539b38da4d00abd43008cb5df9e35a66d5d700a3522517fce7834c +size 33714 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesBothIcons_List_item_(2_lines)_-_Both_Icons_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesBothIcons_List_item_(2_lines)_-_Both_Icons_List_items_en.png index 94f5e32a84..0f3debc5b4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesBothIcons_List_item_(2_lines)_-_Both_Icons_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesBothIcons_List_item_(2_lines)_-_Both_Icons_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1742b69b9d2f41337b2e5a99c8797a239a673169a5a4d0ef953a4c94d4839647 -size 33947 +oid sha256:43b8825378da7852de8574a1edb6ed293f4dc3c5d099acf9a76c19205384c345 +size 33949 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingCheckboxError_List_item_(2_lines)_-_Leading_Checkbox_-_Error_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingCheckboxError_List_item_(2_lines)_-_Leading_Checkbox_-_Error_List_items_en.png index 285440c5ac..7944fde674 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingCheckboxError_List_item_(2_lines)_-_Leading_Checkbox_-_Error_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingCheckboxError_List_item_(2_lines)_-_Leading_Checkbox_-_Error_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:310e2b99b30ab4805c514ebbc5007d4a0c729990e2109004b9e7849b4e3aa572 -size 29294 +oid sha256:c50173a2e61cb9600935277ee410896d57f47e67b10717e053198a6c811e4ebd +size 30736 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingCheckbox_List_item_(2_lines)_-_Leading_Checkbox_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingCheckbox_List_item_(2_lines)_-_Leading_Checkbox_List_items_en.png index a1d5ec721b..736ef9c857 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingCheckbox_List_item_(2_lines)_-_Leading_Checkbox_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingCheckbox_List_item_(2_lines)_-_Leading_Checkbox_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:475b563ced43038869519c975f6516df7febb5647ee0f07a8f69515f63a4e12a -size 29450 +oid sha256:accc3af351d352f49e9353352b788c17b19cd21da8e251e2fb9c30e02c0e97e8 +size 30872 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingIconError_List_item_(2_lines)_-_Leading_Icon_-_Error_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingIconError_List_item_(2_lines)_-_Leading_Icon_-_Error_List_items_en.png index c676c49626..46ce34304f 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingIconError_List_item_(2_lines)_-_Leading_Icon_-_Error_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingIconError_List_item_(2_lines)_-_Leading_Icon_-_Error_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:949224b62e358713c8199aae8b22686c391f21ddeb32510ab0881b3df477ead2 -size 33300 +oid sha256:348f1581c5ee5b3461e6ed47eba0162431935f25ac7fb2ae016de8b0a849e8f3 +size 33299 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingIcon_List_item_(2_lines)_-_Leading_Icon_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingIcon_List_item_(2_lines)_-_Leading_Icon_List_items_en.png index ae4011fbb5..0ba07ae455 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingIcon_List_item_(2_lines)_-_Leading_Icon_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingIcon_List_item_(2_lines)_-_Leading_Icon_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e53d366114c0839f98aff9a8e7197d90c8cfbe7ce3076329d24a82d8eebc43e -size 33469 +oid sha256:67361da0c04c23fcd8282ad1d07a92db3419e2febed28a98f070ccb222932023 +size 33402 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingRadioButtonError_List_item_(2_lines)_-_Leading_RadioButton_-_Error_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingRadioButtonError_List_item_(2_lines)_-_Leading_RadioButton_-_Error_List_items_en.png index fa63150bba..07989d0ffd 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingRadioButtonError_List_item_(2_lines)_-_Leading_RadioButton_-_Error_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingRadioButtonError_List_item_(2_lines)_-_Leading_RadioButton_-_Error_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:179cf3b7c99383ce5368780e98ff47b335a47a47a6028d8edb03e35539690345 -size 31888 +oid sha256:cc177402db7806358a79b8254e7901028c824ecc050784f01322ef28e618c5a8 +size 33329 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingRadioButton_List_item_(2_lines)_-_Leading_RadioButton_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingRadioButton_List_item_(2_lines)_-_Leading_RadioButton_List_items_en.png index cb874c0140..65a2cd9ecd 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingRadioButton_List_item_(2_lines)_-_Leading_RadioButton_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingRadioButton_List_item_(2_lines)_-_Leading_RadioButton_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0955be0010892edd6e1f53080f1f23acf69595b468cfaafae0ef82d5c3b78cf -size 31939 +oid sha256:bd16b89ff61b0c9391ef50797ec35dbf9dc019c7d9aeabd7134cb564eede3f8b +size 33296 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingSwitchError_List_item_(2_lines)_-_Leading_Switch_-_Error_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingSwitchError_List_item_(2_lines)_-_Leading_Switch_-_Error_List_items_en.png index 36d895a7e4..8e3fb14b19 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingSwitchError_List_item_(2_lines)_-_Leading_Switch_-_Error_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingSwitchError_List_item_(2_lines)_-_Leading_Switch_-_Error_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c49ed6e9c07d7d32e5a0f80e1c5452653304120fc3159f387df6ae310d77cab1 -size 35592 +oid sha256:7d7f4c91c5d24d78a3922f79f8d6a08d4529dab0c3c5aa290aa84c81406e7e38 +size 35669 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingSwitch_List_item_(2_lines)_-_Leading_Switch_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingSwitch_List_item_(2_lines)_-_Leading_Switch_List_items_en.png index 9573748422..59e3d3e381 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingSwitch_List_item_(2_lines)_-_Leading_Switch_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesLeadingSwitch_List_item_(2_lines)_-_Leading_Switch_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a005b8170c0a0db3faa3b20ea5efefd1ca22e492ca9a895253add5df9fcce96 -size 35340 +oid sha256:5aca7ecb664085578f92b0651ece1a7d425f28ef2491d2da355d8989822f71ab +size 35493 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingCheckBoxError_List_item_(2_lines)_-_Trailing_Checkbox_-_Error_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingCheckBoxError_List_item_(2_lines)_-_Trailing_Checkbox_-_Error_List_items_en.png index 56581eab18..0af3327793 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingCheckBoxError_List_item_(2_lines)_-_Trailing_Checkbox_-_Error_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingCheckBoxError_List_item_(2_lines)_-_Trailing_Checkbox_-_Error_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:587703a28e4cfdf44bd22732f143bc7769858c6311c761fec541f319c36359a5 -size 29284 +oid sha256:21287343cefaa8c5a8476e3377de4dd0b2a6c7fe7c8d2003204fcee5f0f4d1da +size 30696 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingCheckBox_List_item_(2_lines)_-_Trailing_Checkbox_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingCheckBox_List_item_(2_lines)_-_Trailing_Checkbox_List_items_en.png index e5f49cddf1..5db106b200 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingCheckBox_List_item_(2_lines)_-_Trailing_Checkbox_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingCheckBox_List_item_(2_lines)_-_Trailing_Checkbox_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:27cff500d92a1ecee970784ddcc48d923e447259487b0f38b3cfe1b55c4f2abc -size 29275 +oid sha256:baa248f7e6d97c8a5c32bb5a63c73488e92cb7f207f7f7a8358db93f676fd2b6 +size 30644 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingRadioButtonError_List_item_(2_lines)_-_Trailing_RadioButton_-_Error_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingRadioButtonError_List_item_(2_lines)_-_Trailing_RadioButton_-_Error_List_items_en.png index 0a439a45f1..3ad64127dd 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingRadioButtonError_List_item_(2_lines)_-_Trailing_RadioButton_-_Error_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingRadioButtonError_List_item_(2_lines)_-_Trailing_RadioButton_-_Error_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7335f19b6c00c337357d436d4a6487da66a09a699880b62448d7b495dce67d91 -size 31891 +oid sha256:ad1d2df948eaa6991d431a7f47d96842b8dca5af0ea32ad068987ab5a7d170fb +size 33236 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingRadioButton_List_item_(2_lines)_-_Trailing_RadioButton_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingRadioButton_List_item_(2_lines)_-_Trailing_RadioButton_List_items_en.png index faac55c52c..93aa303fdc 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingRadioButton_List_item_(2_lines)_-_Trailing_RadioButton_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingRadioButton_List_item_(2_lines)_-_Trailing_RadioButton_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd8f4feac4ee86560ef137ea27659dd23e8d7761fd25fd8ec0dfc524a9b6cf4d -size 31736 +oid sha256:1143780e219e7c9d505bba2778bedf44c5876b291b397e4b5c04315c7cbd8420 +size 33036 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingSwitchError_List_item_(2_lines)_-_Trailing_Switch_-_Error_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingSwitchError_List_item_(2_lines)_-_Trailing_Switch_-_Error_List_items_en.png index d468264e69..a9a8e372a0 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingSwitchError_List_item_(2_lines)_-_Trailing_Switch_-_Error_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingSwitchError_List_item_(2_lines)_-_Trailing_Switch_-_Error_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9525e9b5b57bfe0f3b8d198596742c09a40717c9d48c6f3e5aeb336d3935b8eb -size 35315 +oid sha256:1962ca64598660738313489d148291c23707c8ef9b2380eeea103a50d158bd05 +size 35579 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingSwitch_List_item_(2_lines)_-_Trailing_Switch_List_items_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingSwitch_List_item_(2_lines)_-_Trailing_Switch_List_items_en.png index eb53d5021d..49307d7502 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingSwitch_List_item_(2_lines)_-_Trailing_Switch_List_items_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListItemTwoLinesTrailingSwitch_List_item_(2_lines)_-_Trailing_Switch_List_items_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2168e76fd0ec791e4574bc3033f50ce240cc478c32322b4c29d54bc208370729 -size 34983 +oid sha256:806016d99e43feb0f189ad6686e66e2bbff878a3272a4752f4e64fb696f87a58 +size 35263 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListSupportingTextLargePadding_List_supporting_text_-_large_padding_List_sections_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListSupportingTextLargePadding_List_supporting_text_-_large_padding_List_sections_en.png index d8e3863b41..d0e5b8957b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListSupportingTextLargePadding_List_supporting_text_-_large_padding_List_sections_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListSupportingTextLargePadding_List_supporting_text_-_large_padding_List_sections_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f41ff26dbee0284f543aa5d37844bfb9348b2c5be2728ba08f3041c0538ca637 -size 26074 +oid sha256:94a47747149162a3a3b029274388cf6e7194900bb70a44efa7c0917dd932e9d6 +size 26014 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List_supporting_text_-_small_padding_List_sections_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List_supporting_text_-_small_padding_List_sections_en.png index cc5bc6da9d..318ed5911e 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List_supporting_text_-_small_padding_List_sections_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List_supporting_text_-_small_padding_List_sections_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d9df652b074ed8aa29c4aefeb73cd0324509e5a835eec8d22a7044237acf024c -size 24955 +oid sha256:048e7130bba929b9bb9d272e80835f88d2a5e6c07b378f7854bc607cddfba8c1 +size 25009 diff --git a/tests/uitests/src/test/snapshots/images/libraries.featureflag.ui_FeatureListView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.featureflag.ui_FeatureListView_Day_0_en.png index 6f28f99373..5e2a90acd4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.featureflag.ui_FeatureListView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.featureflag.ui_FeatureListView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f458d172b2c970f57eade721a6176e68f3f8dc75ca7b0dd120e489a93ab5ed3 -size 17756 +oid sha256:d33f9436a29a17b45d79d07a61618ce04ce93eb41176e76fce8432483feb69f2 +size 17793 diff --git a/tests/uitests/src/test/snapshots/images/libraries.featureflag.ui_FeatureListView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.featureflag.ui_FeatureListView_Night_0_en.png index ef3a3e502d..c0b5dc79a0 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.featureflag.ui_FeatureListView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.featureflag.ui_FeatureListView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a6c2d0b236e6d1bb6e31a7f6468a0dd232acfb955b3a495a899413aaebad4963 -size 16853 +oid sha256:3aba828982a3de86462bdc417d5c1e491681986d0a5d79ff5d87297b623c9764 +size 16921 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 50b712b4d2..640aa3e259 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:88d49b19b4ad6ec1a04e6adf0c0a7bfac5a20759b851a021cf3d41685e174508 -size 13530 +oid sha256:519b6260f7cedac5cf7a30a8f15bc35910f3b297b0381f5352330ace006ccca2 +size 13557 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 6422edb4c3..d67d1fd9bc 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:02dbdd5d3c6c8b3dda43b71cbec72448d89d5950ea70c270d4ce88270b3c8c03 -size 12305 +oid sha256:c6184636ebed12ee93d3fe2ad53ec00bda5588d5a6baeb1cfd57bf634777f12b +size 12299 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 968c84c321..155afe65c3 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:f6bc140ee95f9971e95b1eebdc08cd524310cb9f19b5f392832a9cac42de87ab -size 40369 +oid sha256:ae27391650004d4a072211f5bc30aea1dbb05ecf89bbeb9bdcbc2e11640ca470 +size 40365 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 91ede41b24..508d3f9668 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:989b79de2661de014aa33933cf46e3beaa83853f1c4a5869a64aa9569c8f4903 -size 38334 +oid sha256:bd2ea0586f7878797a56f85c66270dac87b14b22e61880aed33471a9f8a0d23f +size 38328 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 efa60ac998..b60fb8b3ff 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:9a11fe51900ac2f82dd134f03cdd070e0d1eea7ef1f857098a719b737c5740c1 -size 44700 +oid sha256:4a7fbdec9b1aeda6ab1d6038eaa46b39dde69a631d85d79cd7537c5745c320b1 +size 44760 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 index 3842333bbe..c6294e1525 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b6cf67bf5ed218c3506304ff0062a91e23c95f189dac2bad32540a64e6556b2 -size 40821 +oid sha256:9cfc8cef1b56a9a442194a14616a520b9b1796f92b8f473ef429141135d3fbba +size 40843 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 3d848e6a90..7962e6ddd6 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:3d19ed9cd344be378c3ac33cc3efe8708e7803fde0234c524d83bf1a27fc2b71 -size 39320 +oid sha256:314ec995682444953e0183a830bc0d56d66dc4121c2b25027c1f13b7a0790f03 +size 39322 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 843c4ca98c..ec264a01a5 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:99a42e82444e021a1fc6b1fbbc92b525fa47b9134ba6cc1f96a625f9ed71bab1 -size 36958 +oid sha256:77069a6b3130927d6f9492d170d956d10c1e2394eecc01070a8f4ac2c0c99f24 +size 36970 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 fd2043826c..99bac276d5 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:0d68ba74c14b13e484ea241ca84c57790504774f305b4201da86074a2ddade7f -size 43594 +oid sha256:e5bb7b5108819627ebd2c49e38838bbcef5c13671bb1f27b253a574c3cbdd9d2 +size 43660 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 index 9ade235007..27ebeadc66 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:67331c3aefde56724a506736863330168c3cc847beae6fd1220fae26c569f8c2 -size 39789 +oid sha256:dbace206ad9b243d1a298e28384a375461a848e24d89614a1f6e24aae99a3be5 +size 39729 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 968c84c321..155afe65c3 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:f6bc140ee95f9971e95b1eebdc08cd524310cb9f19b5f392832a9cac42de87ab -size 40369 +oid sha256:ae27391650004d4a072211f5bc30aea1dbb05ecf89bbeb9bdcbc2e11640ca470 +size 40365 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 3d848e6a90..7962e6ddd6 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:3d19ed9cd344be378c3ac33cc3efe8708e7803fde0234c524d83bf1a27fc2b71 -size 39320 +oid sha256:314ec995682444953e0183a830bc0d56d66dc4121c2b25027c1f13b7a0790f03 +size 39322 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 3d848e6a90..7962e6ddd6 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:3d19ed9cd344be378c3ac33cc3efe8708e7803fde0234c524d83bf1a27fc2b71 -size 39320 +oid sha256:314ec995682444953e0183a830bc0d56d66dc4121c2b25027c1f13b7a0790f03 +size 39322 diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en.png index 5217f8a7aa..5150e7bcce 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26299451ca8645d878fe2944ed10829847387ef36a9d285edc1909d0f911b85e -size 29951 +oid sha256:48f1432bab5cdb84b9dd3810f6ff84468fbc95c401cd07081f124021be8e8867 +size 29944 diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en.png index d9cb653d66..5e2fff9fd8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c5a32aa30c91622e2b105813233684d2d9049d0780abd5e4860ef9255c4f6499 -size 19351 +oid sha256:ba26b31dd921f71497fafbcbe8b85fd872d4f3059acad1b870347010f8fe7429 +size 19342 diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en.png index 46a237b230..095e483609 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:332c6db171facb9a9d0bd75f3171acf41f2bc2be4ffbf81de36c1db39727ae3a -size 24715 +oid sha256:47a8e4421730347371fde688689d6dc053d14a51a40a1b47d5f169d2ed23e654 +size 24685 diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en.png index da72e6415a..30d0ade815 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed54c3b733e4e7c5a8693e78dfb2919f61334b57373202f60b4ca31f7467f4e0 -size 29893 +oid sha256:48b2f97efca072dc2454308785997da48aea94b57d29a530c94cef36b7fb6992 +size 29964 diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en.png index 28f19433fe..869ef27e81 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e0485c0c571a858d185bbfc755719ce342375ce760817329ff8ee0bbce4e480 -size 24033 +oid sha256:0a55e4c56699e1cb36de4f2455c61853442c853fe814aec9a2e6e4fd63ba6c22 +size 23987 diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en.png index cb9051bf6e..c4d05374e8 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3c0db5ecd43e29ff15d822e19a2157e3bb9c0140529a3059ad8791d2c9cb7fbf -size 35793 +oid sha256:0c97d537c38a97b9b33e4b3058863ea2637cf458651f8563fff8a0d87cc3de0f +size 35937 diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en.png index 9d876a6388..2db3cca6cf 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9afb3706fa4674f6c167c9774a065eaed1a28cc9fa8dd14b7b3160ca9f552124 -size 23853 +oid sha256:9684a28c8370d874fbef370e7111750f4a6ee6be2db21aa90abbd8ac1c0f7fed +size 23894 diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en.png index eb2b2a7a53..478a2ec4a6 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df1e95b668e2f543fe4ae8ad2e90d0ed32bb81f078e0adc9b86c13aa9e09f06a -size 29125 +oid sha256:9514a1b5d8735f152833d90cf5b6f465257da30b1b8f30a8ec3051272acde1e7 +size 29121 diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en.png index e8c148a34b..3024407fe4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:031f652c50f9316d992eea1fd4c81d3528a8e11dce1721ef67f84cd4ba2f8a7e -size 18948 +oid sha256:53a5d1ba3d9ddd7ca01fa3892ba7359a5d76a9c664a050e597fdc9ddba42b51b +size 18950 diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en.png index d8795934a7..58b9a95475 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d057847a4e9e222451c9ee67e96e8b649494dd4817f0702508cc0d363950a49 -size 24084 +oid sha256:c0c6845c72b83dea15b1156c58fb5836d35290bf193591736343415bdfe502a1 +size 24117 diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en.png index 2258bf69f9..c569a6131b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:74f39e9e49136645cb54afa375f4007dac9969c79c7a6009dd3694492e8fe483 -size 29118 +oid sha256:9e34ed2bf3dccdfc1965a4ee9194e7ea6a9898c47047ad0d85461aac26665e79 +size 29069 diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en.png index d5123adeac..fe591e8011 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:64d7fda6250d39123b0085301d0de4d511b0308275d333c4f0c938d4f93e7b15 -size 23488 +oid sha256:0daedf93e28cc3bfe72866cdf0c3d0460bccf2af8e89a4fb626033c6f71cf093 +size 23515 diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en.png index 84ae4a8750..35733439ab 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e59c4ef7910585320833ba84afe5d80408f7e5279068ab00c4b0ac205a7003a -size 34595 +oid sha256:25562f10c67c45c919e0cdb8b97e13ff3bf187ce593f91c941e70e3a6299bbb8 +size 34835 diff --git a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en.png index 319b352851..ccb1327722 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ac6fc4e02e62ad0e1504724576d2a37d80a6f11929251ee15442aed22c30c17 -size 23354 +oid sha256:2ec7895c6e610e52927c24de153fc90fdbf39daba393d9fdecbc276d8c715856 +size 23315 From b5e9f42058eef266b17e93d7718069eb85be13b7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 7 Aug 2026 09:52:54 +0200 Subject: [PATCH 272/383] Fix compilation issue --- enterprise | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enterprise b/enterprise index 9b1ee4cd88..029db99513 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit 9b1ee4cd8846eb30a1bc62be718e77eed281dfe6 +Subproject commit 029db99513d569b715ad3bb24145b3c2ac9c14cc From 8a164228bdbca0dfe3a3558074340f4c880fd4eb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 10:02:28 +0200 Subject: [PATCH 273/383] Update dependency com.google.firebase:firebase-bom to v34.17.0 (#7333) 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 ef8f8025a1..f934d1918c 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.16.0" +google_firebase_bom = "com.google.firebase:firebase-bom:34.17.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 e1daec6728a88c8b48ab5ace5f223e1f77e44448 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 08:06:16 +0000 Subject: [PATCH 274/383] Update dependency androidx.constraintlayout:constraintlayout-compose to v1.1.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 f934d1918c..818d7767c4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ firebaseAppDistribution = "5.3.0" core = "1.18.0" datastore = "1.2.1" constraintlayout = "2.2.2" -constraintlayout_compose = "1.1.1" +constraintlayout_compose = "1.1.2" lifecycle = "2.11.0" activity = "1.13.0" media3 = "1.10.1" From b7c0374c7c7a820ef245870034848b8c73e49daf Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 7 Aug 2026 09:53:47 +0000 Subject: [PATCH 275/383] Update screenshots --- ....home.impl.components_HomeTopBarWithIndicator_Day_0_en.png | 4 ++-- ...ome.impl.components_HomeTopBarWithIndicator_Night_0_en.png | 4 ++-- ...res.home.impl.components_HomeTopBarWithStatus_Day_0_en.png | 3 +++ ...s.home.impl.components_HomeTopBarWithStatus_Night_0_en.png | 3 +++ .../snapshots/images/features.home.impl_HomeViewA11y_en.png | 4 ++-- ...krequests.impl.banner_KnockRequestsBannerView_Day_5_en.png | 4 ++-- ...equests.impl.banner_KnockRequestsBannerView_Night_5_en.png | 4 ++-- ...knockrequests.impl.list_KnockRequestsListView_Day_3_en.png | 4 ++-- ...ockrequests.impl.list_KnockRequestsListView_Night_3_en.png | 4 ++-- ...knewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en.png | 4 ++-- ...ewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_0_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_1_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_2_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_3_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_4_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_5_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_6_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_7_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_8_en.png | 4 ++-- ...eatures.location.impl.share_ShareLocationView_Day_9_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_0_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_1_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_2_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_3_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_4_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_5_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_6_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_7_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_8_en.png | 4 ++-- ...tures.location.impl.share_ShareLocationView_Night_9_en.png | 4 ++-- ....lockscreen.impl.components_PinEntryTextField_Day_0_en.png | 4 ++-- ...ockscreen.impl.components_PinEntryTextField_Night_0_en.png | 4 ++-- ...nts.preview.imageeditor_AttachmentImageEditorView_2_en.png | 4 ++-- ...nts.preview.imageeditor_AttachmentImageEditorView_5_en.png | 4 ++-- ...rypto.identity_MessagesViewWithIdentityChange_Day_0_en.png | 4 ++-- ...rypto.identity_MessagesViewWithIdentityChange_Day_1_en.png | 4 ++-- ...rypto.identity_MessagesViewWithIdentityChange_Day_2_en.png | 4 ++-- ...pto.identity_MessagesViewWithIdentityChange_Night_0_en.png | 4 ++-- ...pto.identity_MessagesViewWithIdentityChange_Night_1_en.png | 4 ++-- ...pto.identity_MessagesViewWithIdentityChange_Night_2_en.png | 4 ++-- ...re.resolve_ResolveVerifiedUserSendFailureView_Day_1_en.png | 4 ++-- ...re.resolve_ResolveVerifiedUserSendFailureView_Day_2_en.png | 4 ++-- ....resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png | 4 ++-- ....resolve_ResolveVerifiedUserSendFailureView_Night_2_en.png | 4 ++-- ...meline.components.event_ATimelineItemEventRow_Day_0_en.png | 4 ++-- ...line.components.event_ATimelineItemEventRow_Night_0_en.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 ++-- .../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_1_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_1_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 ++-- ...references.impl.blockedusers_BlockedUsersView_Day_4_en.png | 4 ++-- ...references.impl.blockedusers_BlockedUsersView_Day_5_en.png | 4 ++-- ...ferences.impl.blockedusers_BlockedUsersView_Night_4_en.png | 4 ++-- ...ferences.impl.blockedusers_BlockedUsersView_Night_5_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_5_en.png | 4 ++-- ...es.preferences.impl.userstatus_UserStatusView_Day_6_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_5_en.png | 4 ++-- ....preferences.impl.userstatus_UserStatusView_Night_6_en.png | 4 ++-- ...embermoderation.impl_RoomMemberModerationView_Day_5_en.png | 4 ++-- ...embermoderation.impl_RoomMemberModerationView_Day_7_en.png | 4 ++-- ...bermoderation.impl_RoomMemberModerationView_Night_5_en.png | 4 ++-- ...bermoderation.impl_RoomMemberModerationView_Night_7_en.png | 4 ++-- ...eme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png | 4 ++-- ...e.components_HorizontalFloatingToolbarNoFab_Night_0_en.png | 4 ++-- ...em.theme.components_HorizontalFloatingToolbar_Day_0_en.png | 4 ++-- ....theme.components_HorizontalFloatingToolbar_Night_0_en.png | 4 ++-- 121 files changed, 244 insertions(+), 238 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithStatus_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithStatus_Night_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithIndicator_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithIndicator_Day_0_en.png index 5eb704b885..2a515ca368 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithIndicator_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithIndicator_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c917c554a717315d953b441fa3cbc9242426f0f92ccc4618f6752b6f15b90a83 -size 22462 +oid sha256:dd697e25338f15e3dfeb82370f1726cc337fa74a5e65240cad22c404ec949976 +size 22485 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithIndicator_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithIndicator_Night_0_en.png index 031e8841e6..7dd2daea6e 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithIndicator_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithIndicator_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:34f87a3995ba43f02150837517922c678d7def6573c7d3f4c26940c450a388c7 -size 20722 +oid sha256:0567d8419972054d7dce9a080b856324a1bc97529ff2d15776aba6c023eb90e2 +size 20730 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithStatus_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithStatus_Day_0_en.png new file mode 100644 index 0000000000..4fa1c78188 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithStatus_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd896bfc1111dcb04d94584c19a395e69612dd9ceda8beea6432c14aa4f18023 +size 23126 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithStatus_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithStatus_Night_0_en.png new file mode 100644 index 0000000000..9111455bec --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_HomeTopBarWithStatus_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:262622cd1124902ab45ccd645d33193dd8d0e4a99ba7e4d2cff786393b350118 +size 21299 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeViewA11y_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeViewA11y_en.png index 344bd350d6..aca66273b4 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl_HomeViewA11y_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl_HomeViewA11y_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b5dde8ed5c776f4701f24dd7d411dd78f48adab261efad71e961c845e24d12f3 -size 144367 +oid sha256:9cf305c0e52881fb40fee2ba7bdcdc3dfa5c899577b3e252af19e37ee2efacf7 +size 143213 diff --git a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en.png index ae365f5143..5fe8e62f96 100644 --- a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:645349979f0789dd674b9efcaee305a35955725c5c4d24599984aefc3a61b18f -size 32005 +oid sha256:b2e211a700dfcefab1927926ecd2ab1eee2ceaed6980657e1bad1e70bbc69dd5 +size 29522 diff --git a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en.png index f0bfd0f2b4..33110584a9 100644 --- a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e82c6e4ff563e7ae870431528d9413ac915e16ca0151aa3c86ff5081bfc72478 -size 27563 +oid sha256:dbdf9740221b82aaaf332c95e7299594f0b4fdd258b2e9c733133bdd4a01f692 +size 28378 diff --git a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_3_en.png index 93d24c8613..d002a79378 100644 --- a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3cd12ed914f8c161ef845feaaec416eec9ef1ae6d23d71fb444c93d1388738ea -size 41736 +oid sha256:ab30267a07b1ceb43c1a7f854e758c68123812d99054f6e94db4cccf3214a2b4 +size 41479 diff --git a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Night_3_en.png index 438d96608d..42ecbe8a68 100644 --- a/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.knockrequests.impl.list_KnockRequestsListView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae0b92a52a7f2c0533af7d7f0fbddc6497778e7c5dcedc3344a2ba60a6a948f8 -size 40439 +oid sha256:471abc7c54d0f90ad5a923bd21abbf0960bbb9cbbdb22313a779083baf61ab3f +size 40671 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en.png index 48598e410f..23bb00edfe 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c79c83bde346bec65f67c34805407e46b351b2c91772c13e0a6c23ae09bf7e8 -size 30345 +oid sha256:7270b97b04cd403a5d5e34b55b3303be08497fcb5d750d024565ffa17d20802c +size 31808 diff --git a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en.png index d22d7f98cf..9945685453 100644 --- a/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff17ff66d5c92ab19ce8064e2e14326e9f2921c1b7313a3974547b2932cb7fb1 -size 32295 +oid sha256:29ee97865bc634eb1f30d6866a0a2badc91b5453ded11d7f4905c46db9c0c324 +size 29775 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_0_en.png index 33ef3511ec..374acc4a7a 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f03643af6b4643c0fbfee2d98138aa0350d0fb541de0a8a627570030a8f3812 -size 20466 +oid sha256:f879dd8636314113c9962bedae376f34057fd7af62a3725ef9aca7913ef08abc +size 20453 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_1_en.png index b1bdcee7a4..60bf32612b 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f53a6b803268437c30350857951422dc1723a38922db4441a97bcb926a0e63ff -size 38724 +oid sha256:e44d67574a6d3df53f9c9a6d588461dda932cc77142c07605e2a53a0f7c33819 +size 36440 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_2_en.png index b597367206..a91262bdf2 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:77ce52ef94d449d8eb37a8d84b297800a1663bc38dc27e2ea87e6f7da373195b -size 37222 +oid sha256:a1482966c7528de972c7a9af647eb249329777b4f60f05ffd1794a1cdc8115dd +size 34889 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png index 56bc529007..caa435aca2 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:76c4f1674cda818e0684869050fbad2cb31c02146726d1ee5e57481940218d29 -size 30363 +oid sha256:455ad29386413801da964f034b284c3693ed2281510cfdb0e6a0e50478904098 +size 32472 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_4_en.png index 33ef3511ec..374acc4a7a 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f03643af6b4643c0fbfee2d98138aa0350d0fb541de0a8a627570030a8f3812 -size 20466 +oid sha256:f879dd8636314113c9962bedae376f34057fd7af62a3725ef9aca7913ef08abc +size 20453 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 be619b419b..740c6fd618 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:fc017e7707b83549cda8c06ffe8466596372132ba0b58dd91cfb20c451b6a417 -size 22303 +oid sha256:0ca62fd1055aef95b255d40b7f8933e455a7fd7014c96e9e5eef04a9cff5549a +size 22324 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 201c56516e..380f1ec5b2 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:2f5ca554e1ae330865af0d267934d8d1c6dfe42cc3958db3b15b13d376e8721c -size 26667 +oid sha256:1ddc6b2ec2417a2794e9ca0bfd88fae8f63e6d6f567582498157720092acd957 +size 26734 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 index 3d4aa9edc5..75f447d578 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd18d8bb6e61f616451439dff8690afc7473461c87adf11bb9870319d8e06fc4 -size 38447 +oid sha256:a205abcee059aef3f902cac7716a5bb53127b98ab29d97b0b44cbaa6ba5cdabe +size 42394 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 index fb4db2984e..d4f298adb5 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f8c9a2dd2c3677281b6486af6a0b8a5405dc59bff0390b6ce1bca1cc63d88b0d -size 42546 +oid sha256:d9a51a8b9c8799af008fca5e684c1fd107b6240f0e5f273b1559022c70ce5e31 +size 46363 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 index d194937309..f6c445eee1 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ebeb2f14074a9bc91dc892bfa056c9c67e83a64c64d645c77d312d64895e3815 -size 21611 +oid sha256:dbb35e33035a9c22164128414bde7f6df848193040eef3bd7f073b0b182a7306 +size 21670 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_0_en.png index 70de0a28d5..c07cad6219 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc9a8778869e47b9874c4300cac52045c4be5fac6590acbaa719a065249ed3f5 -size 19856 +oid sha256:8bd18f0f95a41705cb18e753f7b99492aeba1a994cb02c95275bd7c14b5d983a +size 19886 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png index d9f4faabc7..21eb862eda 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:124381cc86542b2704b619e798f62f58dc7f3b95ab8a1c4eec3fa4b849462f9e -size 34867 +oid sha256:e0cd7909eb2cce4ce2ad297791527468a18b43343c4f4c7b1bb7ab5ade6cfc9d +size 36959 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_2_en.png index 432cbde734..91d309165f 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f373df8ce07aa19d467d43306f5a8d6c78915e4e166e08e39bb39cb303b5faec -size 33305 +oid sha256:33c7e31962e562c4217629795ad0d79be10add9723e657f1a8dc3c4c16ac4ed4 +size 35476 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_3_en.png index 317a87e2e5..b9e79d2337 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ebbeb66a3f67e48668cadb96069f50feba5f4346119ea62c9dfd83ffd621b7b2 -size 31182 +oid sha256:8721e0c604b0e12ba22db934ab93794e6c2143d1b4bc4e2f3d297f9121c1e688 +size 29233 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_4_en.png index 70de0a28d5..c07cad6219 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc9a8778869e47b9874c4300cac52045c4be5fac6590acbaa719a065249ed3f5 -size 19856 +oid sha256:8bd18f0f95a41705cb18e753f7b99492aeba1a994cb02c95275bd7c14b5d983a +size 19886 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 d261494eb8..46f4412ab9 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:8a3d7220c216b6fee2384ba2cb263903a8cfa45f3f97302c722188a4a827c575 -size 21630 +oid sha256:299310684787f8c18e4219e69125ce48d32d229b4bb3087da7e102aa87ea1ac7 +size 21599 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 56ef074549..259466128e 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:24b8f832cbaa9aaad66187255adcefbb2d7c4407b911c2675a261b6f480aa277 -size 25858 +oid sha256:11c3fe98b80dd8823e3eeafccda7aa5430dc6a691d2568f2a186c14f6a340360 +size 25824 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 index e66ccc603d..5732afb34a 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1e31aa9639a3805e3644fadbb01ab3503aedee068655920555a4817ae38b6376 -size 40312 +oid sha256:dfaee97064c6391c9e611e30bfb36d3abb8d10d2e3312cd21afa3b2b362637cf +size 36805 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 index f2f4d7c766..549c353b64 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:77e1a15b548d944e57b7d71229c28692e32ad9340d04ec0c43c52dafe16e3ae1 -size 44172 +oid sha256:2b56fa8390836f84984130ac90af3a8e2244ab06d1460133883aa266e73b4567 +size 40742 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 index dcf2ab131b..1cf67b2855 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cab8ea5b016f20de07dd0134836c42f9fd51562837fe4da2be8a8d38ca1f95f8 -size 19914 +oid sha256:e68d95e8c4734d26e0853c886f8253c3ff21508fdf97dac8879e67d25a683e06 +size 19899 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Day_0_en.png index 3a22d6959f..72c3e43f5a 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2046f1225b2f58812502196f4b7d1c7a4d87f740b32e40dd82762fade1c42ea2 -size 16167 +oid sha256:24edc821b92f0686eb1cdc3a8214adacf490f9f586637e7c23adeaf904e6704a +size 16292 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Night_0_en.png index 10223f5bf6..5c49c08509 100644 --- a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.components_PinEntryTextField_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:62384687c273cb57dbd25bfaa558d83e3efc527fc4dfff4aca8bf85ab1ce9e4b -size 16446 +oid sha256:58a6cbe83f86bbd32c8576a4d62a26794560f53b60c9bf5dc74aa0dd50e2dc87 +size 16238 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 3192cf2a5e..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:1885bbe8b0ea497ac20d7bcdd0c6a93ba0533e898378d35e1cafdc8c9924fd56 -size 279984 +oid sha256:de82970da241172b94f822f8792e6fc721dcfc7f0f67e3523962e253e9750884 +size 255933 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 f899ad5d43..ccfdd7d9ed 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:1ca032575e4ebd75a2ebc5a4cb9f966e48cdfa56f4ff42d6d9309fa3577a1adb -size 310609 +oid sha256:fe6cb72de5079be2ac02ec39f74bac0d20492cd6f5509b71ad9cfc4cc52955d3 +size 326468 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en.png index 693a36b7dd..5f51b27f5e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3dbb8ef39b6a7a0c2f576d8bd101aa97c89da696f23e6d5836846494471c01a1 -size 55799 +oid sha256:3274314ab9e39c23a6b9d66adf80ac8bb7b364ce60a300f96582374a18bc821f +size 54590 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en.png index b1850a50a5..e1f6ee6430 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f1dd0da147212e13a6c0ad5ad8f85ce55666c444076c238ea27eba5605cfab1f -size 56909 +oid sha256:5e27c7c51fe07cca51b92a601aa9c58deab609bfa5e82f8f6f88eaab6ae59ec3 +size 64307 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png index 4185f46b51..5289eaca63 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:085963fcb425147d35a9ad947a7a3e4ba4712bd3d2f32e93099ff15cffe83b88 -size 64761 +oid sha256:65f9ee083a73669a0d3f9d88141a610ea53f3c39e89d8f706d414b04555b4764 +size 59321 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en.png index 2e70435fa5..d3f7da6320 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a3667390d9d88894bbdd5d72b0b714b29c9ff160653e310e97b0da87b6ba8b0 -size 54724 +oid sha256:8a94a4cc176b5d52ef9b21339749324adeef9857b6cdaa2ae973903e2408662a +size 55904 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en.png index 0f6de1b844..bd3b0196d6 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:28512b0fda0b71b98eab03cee15c9d3163825b1a3545670cfa277ddd5434c87a -size 58417 +oid sha256:6f7f7415abbe51858f938e16ad03c6aab983fb3d5e2a53a028bae3c031446646 +size 67848 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en.png index 6c774d4cec..f4d51ccc61 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6ed6a5f1a2055e19a6b8fb0af4738845bd2184f755c323022c52154cdfa07e05 -size 60909 +oid sha256:8a8f5aaaa7ebb0e61b07867590d99a8791c5d04cad1ce0f334d23dce6f26c6e6 +size 67276 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en.png index 02d0fc8eeb..bd73e322ab 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f77d8243c23d3f37dff86dec53671cbde9fafe1314f6e6b445abdfe47d751ad6 -size 56187 +oid sha256:12020ba97720f2374f9ace172693f08be01522e4ca30d3970efa91d802581e81 +size 3657 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en.png index bd73e322ab..93622cedfe 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12020ba97720f2374f9ace172693f08be01522e4ca30d3970efa91d802581e81 -size 3657 +oid sha256:87193a7c9eb9d40234970e5f5be02e80f2b3ffe91e2c9ca6afd58b8bccdd5911 +size 55075 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png index 0cf6c10c4e..bd73e322ab 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49f0bb16d3d57b59242e704e3dd4e8885c59721a42129837ff6a4f0d7d02de11 -size 54433 +oid sha256:12020ba97720f2374f9ace172693f08be01522e4ca30d3970efa91d802581e81 +size 3657 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en.png index adec213a8c..bd73e322ab 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ebee4aec3dbab6e1bb05fda7c5e423f0e931560743d0f0ccbac6b70fa9ad808 -size 52921 +oid sha256:12020ba97720f2374f9ace172693f08be01522e4ca30d3970efa91d802581e81 +size 3657 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 index 12bd190dd1..0ab00359b7 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce15ca9f89274620728715e3448ce671e2253f4fed22a44035460e9a3709ca0b -size 647404 +oid sha256:7b5e6f4c5ec97e67bb20f03f25f18d9f32d5d1aed5ff30d161b331894ad03443 +size 647384 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 index 160d58f9ec..0ccdcbb603 100644 --- 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 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c4e7b28b78cfbcbb6abf00317eea945859ac6465cecf81a3ad15801b0de721e4 -size 646216 +oid sha256:d0424685437a433b35b589668b409d55f26ab41bcae01af0121a54033c56a8c2 +size 646194 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 0435f55de6..ab6392a424 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:ff839731834d7d0c94fa9a2c412014ddbaeaa053c5af1c8cbd00a3f3a583f364 -size 379511 +oid sha256:94f89a37549a3f198442db467bc7d8539f0b5649d97927bfe731f090d6dfb03d +size 379505 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 9cbd5c1d95..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:d0e170b4bea262de612bf3374d475fcd25470ff91b7554d20809c51857a78cec -size 377963 +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 1f0fdabe6d..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:b8bb5a6de6601da8d7fe59f110a054577e2e25dae4bb449f60c04e7d7a1b9551 -size 365073 +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 86018764ac..195aa04fe2 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:8344427a0fe87cbf0883ff53a9ee4dcf90976a7011f6618d85961df48b2c53a9 -size 370228 +oid sha256:76e5ae44362792d570cd82f3910c8bd0acde509b8418c5892e0385e7d636f042 +size 370223 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 058a3992c3..29771235f0 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:00fe1e676086766a3eac3e4457eff52c989789fc5d8d0df2624c019ed25ce9af -size 363322 +oid sha256:60b9f2b920cd2a2a414805d1f0f77925232d9ae60bd607fa18d4395cda2dd73d +size 363291 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 c6d4541184..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:c00e504593d8eb61b598f05f46ee4d591757975a80c0b4227b240847d2cd4868 -size 368510 +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 84d9d4e5c3..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:7c609a633ab23eae5729ecb57a17a385bac65e81cbf0180c01e0847f1028039e -size 347890 +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 7ddac02717..73b7e674e2 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:a4ac79f3b8fb4e231244bd96b244a4f2526d6ed28d558f9d50734d83bbb74992 -size 363909 +oid sha256:991deacdfb7bc371a2df960a2364ae3b2187e588aa5afe7f39409e367040dd9c +size 363893 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 bac23aab98..22ff4965d1 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:e30686c7c037ef102717e0316543faf4d3ed2671c21eca96a667150daab380d6 -size 346614 +oid sha256:787151f8f242a8794a804bf14831f6ca680814d617e85feb3652103e8a0f20cd +size 346565 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 4e17de6908..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:c1e15400fa2c5ee6087316501445c551a3932b65e16de31e68acc5efbd16a559 -size 361603 +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 01d4dca84b..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:ef2bf449671b652cb152b3baab92ab100eab77a54229ab49daeab156f2f484d0 -size 369724 +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 f0dfbc3321..1600afff71 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:f7a6302320bd1e4258e03487539bf46b0b12781dfc8a22b3f9f267017a6146fa -size 354751 +oid sha256:273351cc9c533b2424859a0de00a8a3786628abc3a88175705c4205dedf7e9aa +size 354737 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 e38cf03ad6..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:41a0e404dea7f52359b24b3ec3926b1405429b165cfed44c63b3922ea6d3cb46 -size 368114 +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 68f8148879..b5dac8434c 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:6ca8cf82aa8ab1bdad56a27584b27789402aeb7ad8fadd038280a376fb75a72c -size 345094 +oid sha256:1a92f8af94682facac66d4aacb6e49f345561c15be2f8b689041b78aeaaae831 +size 345062 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 8aa2cca147..1b99468924 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:02ecb903124273e24151ea2088f6b99144f7dcadba00a582b6210dd23835b5c9 -size 357743 +oid sha256:3a9509411777f342261cab58b92a022b3c9f8f0f7a9e4d0527120a91976575f0 +size 357733 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 b5032c29b3..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:dce23463c335d01eb67293cfcede5d85e96ab2ba035cc9a188d42e8e6866bc63 -size 356831 +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 a332744358..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:588967869cbd25ed8b82aff5618175660a8a9e45a5a861b1c7867cf1913f575b -size 364646 +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 133fd3903f..d7b969fd5b 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:426d1c844a8c88281c5fa4c61916d93278fdfd38f8cdf2dc54bf1a821f2de3eb -size 397167 +oid sha256:2528df873713755f542f61cd794080929586c1bd5f316c0378ce9e837c21d50b +size 397145 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 0041a870b9..63bd9c3f6d 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:a2bd77c08be705c66225f16c29fd6826decd92b41922d0f8ffc0d1a63d8c59d2 -size 356193 +oid sha256:a6cd94664f89bdad2a9761ea8b20acb83fed3ed7cb5be41af8fe4852643c0bfc +size 356175 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 f67906a37c..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:ffa68c8398d789444151855496e5df4ffa03218a383db6ea46fd4f979829b823 -size 355831 +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 6e83d6491d..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:34152c742abc486a48234e22101833bc163cf11979890d06aac41e68e3c404d0 -size 364846 +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 b10f9741b9..0021619c44 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:3ec1b0244dab22414c6719b3309426e13128d0c70fb67dc66cd8a60d42521fd0 -size 355411 +oid sha256:7b23d3a37774283067a8919b8c332b1bb5a79e90dceb7216b484b985491282e5 +size 355389 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 77abe20982..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:5c3d87862c6d7fc88d0f23cd54c5b9f77028992fdd7c282a195b964dd17e85ac -size 367855 +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 1d34761a9b..448bcec677 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:f7d9b5fc0ff5d7828ad6f4dc0c9bd9520b4920553da97ed7b4e030ee844c0208 -size 353054 +oid sha256:fe0daf9161bc2da194992a2fc9505bf2009c5dbed78cdb35d2eb7ed1380a7df5 +size 353037 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 5243218ae3..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:9a85db2f5958db867578663533f204b2e803372d470da890fd8056ffed0cf46c -size 366254 +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 b6d1f07279..47a9a6b630 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:4bee12a6bdb18fea5ac6997671bfcb903296da7278cf69b2456330066ca31dfb -size 342870 +oid sha256:54372845e922d047408dd960d048b9b5eae2263d589117d8e7d197741aa34f32 +size 342827 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 ceca184bd7..5560c21967 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:8e82011a72f36889c53ab61ed2b9947c7fb5f868c9b7010904fc10f4ca587082 -size 356082 +oid sha256:af4a48ee80535f2c0a226c4ffa4344054fb63b7b0a88ea2c030a4eb8dd5e9644 +size 356078 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 5cdad1df92..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:9e2d8caf5aaae7d3406c703288e491f328552f0acd18e56afd5265b4ceaf1cd1 -size 355272 +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 a431a9429a..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:93c2df04d65f6078ce3f7067fbae8a7317ec42ed0fc013dee962a3953269f3b7 -size 362813 +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 0eb106f4a9..b51a89586b 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:217ac95bf476c53d2dc6d3d0143b21312bf38b8ab86c8dfd4f9360582b584f9d -size 395476 +oid sha256:e642229c58169775fe702769a306bbef22698516ae6f7ac75a761213c3f195fa +size 395446 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 ae8495618a..aa322fc2e4 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:08057fdc1e1184720b438ddd2a8753f00791baf2456cc30b45de8e6bdeb57e8e -size 354404 +oid sha256:5fae87094ea13b14e2dc7c16ca96e4f8096ff39e962799468fb4ead4c666620f +size 354381 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 9d617f6688..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:dabad9dcd5b8f0d4bb964a0187ad7c94b023b04552dacd29a077daddfd48d550 -size 354052 +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 1a8ea3e4e9..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:66aba7b4271a990fac85b0bbc7cbdc371fa1e38a4da5bb4e2f62a80b21cb3a8f -size 363012 +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 c8306263a0..c9227ebf94 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:756f0cff90ddd61adce2f467c0384d74d430f6d51c091e4980e45bcc9ee6f0fd -size 353705 +oid sha256:e614f4a8657637c584a283d69124236d00fe1251c2b8d739c5688a57a6fd152e +size 353693 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 144411969f..7a5e5e1512 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:84415250503d5e586af7b7504aaa915c1e24dec0a3d28446487c474c354e05c9 -size 55534 +oid sha256:0e3467a7606a5a7beaafb510faf008ed567b1e3a9915ede6e2ec09c491af0bb9 +size 56552 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 52e023ec49..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:c8420417cf8ba717747dead34b9646515f35eb94e1f71aa952b77c3ff433043e -size 49684 +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 adabb6dde5..ee23a7111d 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:9b071ba6e99b68dcc75f5aaed3a879f2e30614c954b88c6dc05e1dfec57f1079 -size 65771 +oid sha256:38ae233a128e887efc48da73be3d6ce50a7095601315ed49a3c9cb209ffdda26 +size 58352 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 6c2a7e8460..2a5991cf59 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:984536295516b542ec6aecf7d07baa3c6dfebbc66403b6d4258a6217616cec93 -size 39991 +oid sha256:115c725873fb206d8f732a8297a6548ba4fa45d7328196b79a2d9e35545de7d5 +size 40347 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 a1dc68a3d5..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:871d92a7565dd233ea87d53658be4e5202775def8e17fea8d386b8975c3b065e -size 53868 +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 479d07ae5f..f6456f0ec1 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:0d4f03ac10bbb676d272dba906e758b25d633a1da1e249fe23ba825f8d2f4901 -size 55298 +oid sha256:22153168f6f3e84ab789faea29c94fffbc1a5e4c1b9a98deccb0460192fdde23 +size 57213 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 c90dc8d08f..6a3ffb84b6 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:e48a364a28a67d7d090faa23ef88b27dbd47f0a2f552857490728cb6952ce08b -size 53454 +oid sha256:48b91e52306daa750b4b5792535e1f1865ae3b74a36215376a51dafdd0dcd506 +size 54837 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 6c0a7b4edc..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:f5aa22c3d79a392625ae231abc046f07f7cdabd91613d5e6f07aede5382aba9b -size 60410 +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 ac1d94a4dd..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:be5b086ab6934bae88b39987bc51e709c5adb81bdd04fa028e97832c725fd68a -size 50219 +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 2209fcb54f..b3af9d831a 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:bd0de7412503e93c33cf92dde0cff38bb68555ef176080d913320af5e4942e7a -size 58642 +oid sha256:ce795c4e32a1be3d57f6b1c87588d8c7ed0442996ab9d8a96f1ec5a07627e598 +size 59663 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 82ef5e7d6a..2c88d322d4 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:41c4bd5cd1bcbedd91de0a64967fb3f3e03b5f0937ae1ea1a93a7c4a1b24a4a0 -size 56262 +oid sha256:963fcec9647d0e5e57bd3fbe3edd389c17be7558c1da7e93fa44f34db34307ee +size 57726 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 135d84dd90..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:4ff538a81d013fdc90dd7be466f710088eea93e081d23448b0731d301a4a3bb2 -size 60702 +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 89fc6708d2..cfa6e4dbc3 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:89467c5b84d0a15210d4013013598d9994d3005a2299e44583d78355e6718ad8 -size 55538 +oid sha256:7a3281f35461edb900ea434c68543dc684a5fad7dab7c9aabac510bc59d442b3 +size 56479 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 17df34a50a..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:6548f5bf1906e1dddcbcc03bb8f76b42e604075751ea8efbc3ead826bf4cfad7 -size 51258 +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 b3109663f2..6e8468054f 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:10bce6df962a5198f019f509b1cdb55e28195587de4b74742ddc29833f1333a4 -size 69216 +oid sha256:262e8d4b8daa2d25593834fd0ab5d7019b0a3dd13707aa96e0701bf9240c6525 +size 59809 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 1ff5ace3e3..b32ee34f99 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:8d875f83a3a1977e2a2cf151dcf9d731108a8590eb3643eb057727421eb1e955 -size 38812 +oid sha256:bde66c53d81f882cde9ed527e8ff82c7e9d6cb1199b440d4b721659f7189bb42 +size 38906 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 f425dd2c4c..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:bd6dc088e16f722b36c2198d6a8611af87dec2451f94ca3c2b6880b97f709b98 -size 54095 +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 b0cd5bc6d4..3974618f39 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:5e900ff75d02c9db4200e2032444dd7e2f8635973cca3389dd96d7d2bb734061 -size 50757 +oid sha256:718d5c9f24c114f3bf88e000b637ea19598d7bb9b97001ba137fc12a6a1285e4 +size 52608 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 486d5da5c6..0ad1e67deb 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:e482603e6d03fffb57d4eb135edb6209c748c51b1f07e638a4ccf133b1b87a79 -size 52920 +oid sha256:82e6e38576a507b19e58fce9dda0734ec00bcedcb0baf8f4c7919dbaaf7d2b85 +size 55046 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 5a877a59e1..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:5a582219d3143acb08563193bf7106e1ee8f6612e359d0a192e9a2f67c6799e3 -size 55375 +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 0383bb8f95..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:7c88b3ed8cc69dee59d4d0a726a9e383d00f2815b6525315f7dcd96f9c25ec2a -size 45618 +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 952751a962..7261c9b671 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:ed13a2778b8ced86ee41d5460d274b42b714a87f59749e3b26bf75114ef40dd9 -size 58265 +oid sha256:7cf3d727da78b39ecf24d4df7db0884af9008db67cc92274849c1b0978f87726 +size 59252 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 0f7fe2db38..cfa62a6626 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:a576d52b840730334a38046cf8b57993693fc760b4fbdc00376cb48b7268d76e -size 55890 +oid sha256:bfe848e4c365cf4b4d663145f74e5f8b3f47a4c8994961c530603f0248400316 +size 57117 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 4d6afdbbb1..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:35069d4fae829d9afe479308dd72ad025fa011290d23133a231f4e70f601ee75 -size 62987 +oid sha256:a966c9a1fa4fdd933f4ef9239592e90458a2819ff4a45c857714d2e38c0df5b2 +size 64405 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png index 074820e157..7cca911c45 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7caacb336793b8ae4b83e9a10a82325e25e8b3c036f881898ed28688250eb6e0 -size 55744 +oid sha256:26e14b77fa3c3aeaea58782309e6de8b9047e07945009322990ebf5f4c283309 +size 52770 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png index 7cca911c45..2af459c158 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26e14b77fa3c3aeaea58782309e6de8b9047e07945009322990ebf5f4c283309 -size 52770 +oid sha256:28a95d4b7ebca92c4e0467f3ecd9acdaf7f6257604d190f5d088a9a25e87d637 +size 55305 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png index a68f886f73..616c06bf46 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5a2e306087a967849f61872b56a83f194d1a76df5723f0bbae6e6e2f4a98c63 -size 55725 +oid sha256:0ce2519906f1aaf34700ca9ba4bdeaa72030f1f5aff3f7e24352a1435ac67d98 +size 53966 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png index 36d19c6b72..616c06bf46 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7dfa2767c55a81d3f121b8fa55443b7b05f9369e91639b80e0be349863799ad7 -size 55438 +oid sha256:0ce2519906f1aaf34700ca9ba4bdeaa72030f1f5aff3f7e24352a1435ac67d98 +size 53966 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png index 82f344f714..2c15fd6a37 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d96eefa01a5de803b0cc9d9109c20df86eaff01b73ff24a91945b43d53d5d01 -size 11960 +oid sha256:7260abe16fc2ab4f6ada97ea0f756dc5c9908ff3b61d6ec1723ffde302bb3dc5 +size 11955 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png index fdd8fcd5a5..7c422591ad 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:22678a2a8505e1d9d5bfcb44459b6fac69c11a4bf72fae09c48ffa2e54f5a110 -size 12128 +oid sha256:2e16fc1daa0f284c442f66591e1d1f59161272a67998d26740b0b403bfe82495 +size 11866 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png index f6e27475da..acb8afa74a 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ee89826c8aa2ac0371ed31959243f62bf9968806a7b27117cd7b4d849423a33 -size 11667 +oid sha256:bed7565420e11c43acc06896ef298683d2f2dd1dc16c430eab7018e9ead9937a +size 11652 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png index b1bb69efb8..e0a4cb1c97 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.userstatus_UserStatusView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e27cb9e501ccbac54926f0252b4098867643a2d2683c5b267f86ad99edf6f5d7 -size 11817 +oid sha256:87811df502c760816e74beb006341627857c39380ce715f1a747ac9fce77b226 +size 11516 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png index 73b8b8e50c..5c597300e4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e8a3ad99763929d2783147814e44fa9ec7e7efb7b99949e3580f23c38fb5d971 -size 9398 +oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 +size 3853 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png index 5c597300e4..f8a1f24b34 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21aee17ee9a292bb2f0d3d2ec2db565ebb8d5df753454a5a002f033ed5ed39c5 -size 3853 +oid sha256:1342b6427f5b2e3075ae3ccee60bf1d3b11afaccf3e152643d6ef2d65c21b54e +size 9108 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png index d47bf90664..4ae7279fe7 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c -size 3664 +oid sha256:410a8596d4c70b9a3856d959d6d71ade8e831e8581ff410c9900957a93b3eb50 +size 8114 diff --git a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png index a87d89c701..d47bf90664 100644 --- a/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f3a0cb5d9bae6725a1c527f3d9575aabf85d3edf63a28d9faa23f4f0b65e2d0 -size 7624 +oid sha256:520cae2544153ba45f8fe4b021286c2d22da06aa1b60be7f1b13879723ff994c +size 3664 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png index 58546b8522..ee5c582240 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:30357bf18792db5ab20085010251170a724ffe8c00313facd04ee704e806af64 -size 10982 +oid sha256:75de341f705bb22955f9399180519b65ad59c2e1917317d56e50ea4db78f35bc +size 12102 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png index fedead0fa8..52fd9b9693 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4811667dec0f32accc5e2c8a5dd5c0b34017fcff8d1e0376ee7a4708426bca0f -size 9838 +oid sha256:58b9491aaa5554b89d86c62a5c9c44975367538c6baa5562f8dc5768f76d8264 +size 8705 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png index 83302d6ba4..38ad0e4b56 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:16dee1dfe746cd40dac9fe8f0af3ecb42cd14bab5cc490917b589beed065ed1b -size 14686 +oid sha256:326d59cf768b2dbd96eb7964d54c8eda509a5cd57c6e62087625e3314da0bb4d +size 13658 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png index 4da2a98aca..687e0d436a 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ef0dc4d53daeb986f378b6e4d85928b4b6729336c89cf21e642c88c53688a3ab -size 10292 +oid sha256:d57df7110371c9224e232b707d6a1b10ce14afcb56c803a78220792f2a0d4cf2 +size 11354 From df925c29e4005213355e671eef52e5b1556016dd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 14:06:22 +0200 Subject: [PATCH 276/383] Update dependency org.jsoup:jsoup to v1.23.1 (#7332) 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 ce602f0e93..f365c5cb3b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -199,7 +199,7 @@ serialization_json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-jso kotlinx_collections_immutable = "org.jetbrains.kotlinx:kotlinx-collections-immutable:0.5.1" 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.22.2" +jsoup = "org.jsoup:jsoup:1.23.1" 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 9b39843e694973d8bbb09d27b01da1e00c18a7f0 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 7 Aug 2026 14:22:52 +0200 Subject: [PATCH 277/383] Add withProfilesExtension override to FakeFfiSyncServiceBuilder --- .../matrix/impl/fixtures/fakes/FakeFfiSyncServiceBuilder.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSyncServiceBuilder.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSyncServiceBuilder.kt index 2cb67f2519..5a2615aa2b 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSyncServiceBuilder.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiSyncServiceBuilder.kt @@ -15,5 +15,6 @@ import org.matrix.rustcomponents.sdk.SyncServiceBuilder class FakeFfiSyncServiceBuilder : SyncServiceBuilder(NoHandle) { override fun withOfflineMode(): SyncServiceBuilder = this override fun withSharePos(enable: Boolean): SyncServiceBuilder = this + override fun withProfilesExtension(): SyncServiceBuilder = this override suspend fun finish(): SyncService = FakeFfiSyncService() } From 06862ff3b2b9bf4208eec6b247c871f65ee42ece Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 7 Aug 2026 16:30:03 +0200 Subject: [PATCH 278/383] Test synchronizes on profile persistence instead of advanceUntilIdle --- .../android/libraries/matrix/impl/RustMatrixClientTest.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt index 4ea4bb64e3..ea40104533 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt @@ -32,9 +32,9 @@ import io.element.android.services.toolbox.test.systemclock.FakeSystemClock 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.CompletableDeferred import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Test import org.matrix.rustcomponents.sdk.Client @@ -72,7 +72,8 @@ class RustMatrixClientTest { @Test fun `retrieving the UserProfile updates the database`() = runTest { - val updateUserProfileResult = lambdaRecorder { _, _, _ -> } + val profilePersisted = CompletableDeferred() + val updateUserProfileResult = lambdaRecorder { _, _, _ -> profilePersisted.complete(Unit) } val sessionStore = InMemorySessionStore( initialList = listOf( aSessionData( @@ -97,7 +98,7 @@ class RustMatrixClientTest { ), sessionStore = sessionStore, ) - advanceUntilIdle() + profilePersisted.await() updateUserProfileResult.assertions().isCalledOnce() .with( value(A_USER_ID.value), From 8f8c3af8c557b5b9ff95938c56575a8c4dc1ed76 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 7 Aug 2026 16:42:49 +0200 Subject: [PATCH 279/383] [LinkNewDevice] Log continuation / cancellation failure. --- .../impl/linknewdevice/RustContinuationMessageSender.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustContinuationMessageSender.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustContinuationMessageSender.kt index 98cf29418c..f4f17fb9a7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustContinuationMessageSender.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustContinuationMessageSender.kt @@ -11,6 +11,7 @@ import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.matrix.api.linknewdevice.ContinuationMessageSender import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.withContext +import timber.log.Timber import org.matrix.rustcomponents.sdk.ContinuationMessageSender as FfiContinuationMessageSender class RustContinuationMessageSender( @@ -20,12 +21,16 @@ class RustContinuationMessageSender( override suspend fun cancel(): Result = withContext(sessionDispatcher) { runCatchingExceptions { inner.cancel() + }.onFailure { + Timber.e(it, "Error cancelling continuation message") } } override suspend fun confirm(): Result = withContext(sessionDispatcher) { runCatchingExceptions { inner.confirm() + }.onFailure { + Timber.e(it, "Error confirming continuation message") } } } From 668243f658dc13b5f76f959f04a43f3172bacc2f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 7 Aug 2026 16:43:52 +0200 Subject: [PATCH 280/383] Use value instead of first(). --- .../features/linknewdevice/impl/LinkNewDeviceFlowNode.kt | 3 +-- 1 file changed, 1 insertion(+), 2 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 b1492f53cc..afa570f0a9 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 @@ -54,7 +54,6 @@ import io.element.android.libraries.matrix.api.linknewdevice.LinkMobileStep import io.element.android.libraries.matrix.api.logs.LoggerTags import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job -import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @@ -214,7 +213,7 @@ class LinkNewDeviceFlowNode( private fun onResume() = sessionCoroutineScope.launch { // Application is resumed, if the step is waiting for auth, send the confirmation - (linkNewMobileHandler.stepFlow.first() as? LinkMobileStep.WaitingForAuth)?.let { + (linkNewMobileHandler.stepFlow.value as? LinkMobileStep.WaitingForAuth)?.let { Timber.tag(tag.value).d("Resuming while waiting for auth on mobile, sending confirmation") it.continuationMessageSender.confirm() } From 33979b65747eef651a646c7809a17a1c81ffb32b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 7 Aug 2026 15:02:55 +0200 Subject: [PATCH 281/383] [LinkNewDevice] Add a 2 minutes timer to scan a QrCode #7303 --- .../linknewdevice/impl/LinkNewDesktopHandler.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDesktopHandler.kt b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDesktopHandler.kt index a8a8ff14b6..1b0883ec4e 100644 --- a/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDesktopHandler.kt +++ b/features/linknewdevice/impl/src/main/kotlin/io/element/android/features/linknewdevice/impl/LinkNewDesktopHandler.kt @@ -12,10 +12,12 @@ 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.LinkDesktopHandler import io.element.android.libraries.matrix.api.linknewdevice.LinkDesktopStep import io.element.android.libraries.matrix.api.logs.LoggerTags import kotlinx.coroutines.Job +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -23,6 +25,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import timber.log.Timber +import kotlin.time.Duration.Companion.minutes private val loggerTag = LoggerTag("LinkNewDesktopHandler", LoggerTags.linkNewDevice) @@ -40,17 +43,26 @@ class LinkNewDesktopHandler( get() = linkDesktopStepFlow.asStateFlow() private var currentJob: Job? = null + private var timerJob: Job? = null private var handler: LinkDesktopHandler? = null fun createNewHandler() { currentJob?.cancel() currentJob = null + timerJob?.cancel() + timerJob = null handler = matrixClient.createLinkDesktopHandler().getOrNull() + timerJob = sessionScope.launch { + delay(2.minutes) + linkDesktopStepFlow.emit(LinkDesktopStep.Error(ErrorType.Expired("Scanning QrCode took too long."))) + } } fun reset() { currentJob?.cancel() currentJob = null + timerJob?.cancel() + timerJob = null sessionScope.launch { linkDesktopStepFlow.emit(LinkDesktopStep.Uninitialized) } @@ -59,6 +71,8 @@ class LinkNewDesktopHandler( fun onScannedCode(data: ByteArray) { currentJob?.cancel() currentJob = null + timerJob?.cancel() + timerJob = null val currentHandler = handler if (currentHandler == null) { Timber.tag(loggerTag.value).e("onScannedCode: Handler is not initialized. Call createNewHandler() first.") From 4485c8a4c018dc2e1965316f54a845da9c865b1e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 7 Aug 2026 15:35:09 +0200 Subject: [PATCH 282/383] [LinkNewDevice] Fix second and next attempts to unlock using biometric failures. `cipher.doFinal` cannot be called several times. --- .../lockscreen/impl/biometric/BiometricAuthenticator.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 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 74d36b0834..f08d2fc1af 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 @@ -59,7 +59,7 @@ class DefaultBiometricAuthentication( private var cryptoObject: CryptoObject? = null override suspend fun setup() { - if (cryptoObject != null) return + Timber.d("Setup biometric authentication") try { val secretKey = ensureKey() val cipher = encryptionDecryptionService.createEncryptionCipher(secretKey) @@ -126,6 +126,9 @@ private class AuthenticationCallback( if (this == null) return false return runCatchingExceptions { doFinal("biometric_challenge".toByteArray()) - }.isSuccess + }.onFailure { + Timber.e(it, "Failed to validate cipher") + } + .isSuccess } } From 2b2d86a804bc26f2fd287575892a4f5ccb177dd1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 7 Aug 2026 15:45:16 +0200 Subject: [PATCH 283/383] Use Kotlin Duration. --- .../linknewdevice/impl/screens/qrcode/ShowQrCodePresenter.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 21071a6831..c496c69f92 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 @@ -26,6 +26,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch import timber.log.Timber +import kotlin.time.Duration.Companion.seconds private val tag = LoggerTag("ShowQrCodePresenter", LoggerTags.linkNewDevice) @@ -63,7 +64,7 @@ class ShowQrCodePresenter( linkNewMobileHandler.rotateQrCode() // Ensure that outdated data is not rendered too long while rotating QR code loadingJob = launch { - delay(1000) + delay(1.seconds) value = ShowQrCodeState( data = AsyncData.Loading(), ) From e66efcfc4392df4c656539a6465476d420ece935 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 7 Aug 2026 16:40:26 +0200 Subject: [PATCH 284/383] [LinkNewDevice] Disable QrCode rotation #7303 --- .../impl/screens/qrcode/ShowQrCodeNode.kt | 10 +++++++ .../screens/qrcode/ShowQrCodePresenter.kt | 12 ++++----- .../screens/qrcode/ShowQrCodePresenterTest.kt | 26 +++++++++++++++++++ 3 files changed, 42 insertions(+), 6 deletions(-) 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 20bd50f488..7032458860 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 @@ -39,6 +39,7 @@ class ShowQrCodeNode( private val callback: Callback = callback() private val showQrCodePresenter: ShowQrCodePresenter = showQrCodePresenterFactory.create( initialData = inputs.data, + maxQrCodeRotation = MAX_QR_CODE_ROTATION, ) @Composable @@ -50,4 +51,13 @@ class ShowQrCodeNode( onBackClick = callback::navigateBack, ) } + + companion object { + /** + * Max number of QrCode rotation. + * When QrCode is rotated this number of time, a TimeOut error is emitted. + * Set to 0 to disable QrCode rotation. + */ + const val MAX_QR_CODE_ROTATION = 0 + } } 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 c496c69f92..1a5eac0522 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 @@ -33,18 +33,22 @@ private val tag = LoggerTag("ShowQrCodePresenter", LoggerTags.linkNewDevice) @AssistedInject class ShowQrCodePresenter( @Assisted private val initialData: String, + @Assisted private val maxQrCodeRotation: Int, private val linkNewMobileHandler: LinkNewMobileHandler, ) : Presenter { @AssistedFactory interface Factory { - fun create(initialData: String): ShowQrCodePresenter + fun create( + initialData: String, + maxQrCodeRotation: Int, + ): ShowQrCodePresenter } private var loadingJob: Job? = null @Composable override fun present(): ShowQrCodeState { - var qrCodeRotationCounter by remember { mutableIntStateOf(MAX_QR_CODE_ROTATION) } + var qrCodeRotationCounter by remember { mutableIntStateOf(maxQrCodeRotation) } val state by produceState( initialValue = ShowQrCodeState( data = AsyncData.Success(initialData), @@ -81,8 +85,4 @@ class ShowQrCodePresenter( return state } - - companion object { - const val MAX_QR_CODE_ROTATION = 10 - } } 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 f92cf66102..db7c3e8c01 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 @@ -91,10 +91,36 @@ class ShowQrCodePresenterTest { } } + @Test + fun `present - when handler emits QrRotating, the presenter does not emit anything when rotation is disabled`() = runTest { + val linkMobileHandler = FakeLinkMobileHandler( + startResult = {}, + ) + val matrixClient = FakeMatrixClient( + sessionCoroutineScope = backgroundScope, + createLinkMobileHandlerResult = { Result.success(linkMobileHandler) }, + ) + val linkNewMobileHandler = LinkNewMobileHandler(matrixClient) + linkNewMobileHandler.createAndStartNewHandler() + createPresenter( + linkNewMobileHandler = linkNewMobileHandler, + maxQrCodeRotation = 0, + ).test { + awaitItem() + linkMobileHandler.emitStep( + LinkMobileStep.QrRotating + ) + runCurrent() + expectNoEvents() + } + } + private fun createPresenter( linkNewMobileHandler: LinkNewMobileHandler = LinkNewMobileHandler(FakeMatrixClient()), + maxQrCodeRotation: Int = 10, ) = ShowQrCodePresenter( initialData = "DATA", + maxQrCodeRotation = maxQrCodeRotation, linkNewMobileHandler = linkNewMobileHandler, ) } From c7d89735079db6ba20ce4dfe05ce2d5125c13e22 Mon Sep 17 00:00:00 2001 From: hayaksi1 <193020925+hayaksi1@users.noreply.github.com> Date: Sun, 9 Aug 2026 01:58:47 +0300 Subject: [PATCH 285/383] Do not append the application MapTiler key to a custom map style url When a homeserver publishes a map_style_url in its .well-known file, the app appended its own MapTiler API key to it, producing a URL with two query strings that the tile server rejects. The map then failed to load for every user of that homeserver, with no way for the operator to opt out. MapTilerTileServerStyleUriBuilder.build() now appends ?key= only to the URL it composes itself from the bundled base url and map ids. A non blank customMapStyleUrl is returned verbatim, so the operator's own credentials survive. This matches Element Web and the self-hosted tile server documentation, both of which treat map_style_url as complete. The two existing tests that pinned the old behaviour are updated, and cases are added for a custom URL that already carries a key, one that carries an unrelated query string, and a blank url falling back to the built-in style. Relates to https://github.com/element-hq/element-x-android/issues/7289 --- .../MapTilerTileServerStyleUriBuilder.kt | 17 +++++----- .../MapTilerTileServerStyleUriBuilderTest.kt | 34 +++++++++++++++++-- 2 files changed, 41 insertions(+), 10 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 054805d1ab..dd9d99fa04 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 @@ -29,14 +29,15 @@ internal class MapTilerTileServerStyleUriBuilder( customMapStyleUrl: String?, darkMode: Boolean, ): String { - return buildString { - if (customMapStyleUrl.isNullOrBlank()) { - val mapId = if (darkMode) darkMapId else lightMapId - append("$baseUrl/$mapId/style.json") - } else { - append(customMapStyleUrl) - } - append("?key=$apiKey") + return if (customMapStyleUrl.isNullOrBlank()) { + val mapId = if (darkMode) darkMapId else lightMapId + "$baseUrl/$mapId/style.json?key=$apiKey" + } else { + // A custom style url comes from the homeserver .well-known and is expected to be complete: + // it already carries the operator's own credentials, if any. Appending our api key to it + // adds a second query string and breaks the request. + // See https://github.com/element-hq/element-x-android/issues/7289 + customMapStyleUrl } } } 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 2e07204594..addc71c3b9 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 @@ -46,7 +46,7 @@ class MapTilerTileServerStyleUriBuilderTest { customMapStyleUrl = "https://custom.url/style.json", darkMode = false, ) - ).isEqualTo("https://custom.url/style.json?key=anApiKey") + ).isEqualTo("https://custom.url/style.json") } @Test @@ -56,6 +56,36 @@ class MapTilerTileServerStyleUriBuilderTest { customMapStyleUrl = "https://custom.url/style.json", darkMode = true, ) - ).isEqualTo("https://custom.url/style.json?key=anApiKey") + ).isEqualTo("https://custom.url/style.json") + } + + @Test + fun `custom map uri with its own api key is not altered`() { + assertThat( + builder.build( + customMapStyleUrl = "https://api.maptiler.com/maps/streets-v2/style.json?key=anOperatorKey", + darkMode = false, + ) + ).isEqualTo("https://api.maptiler.com/maps/streets-v2/style.json?key=anOperatorKey") + } + + @Test + fun `custom map uri with an existing query is not altered`() { + assertThat( + builder.build( + customMapStyleUrl = "https://self.hosted/style.json?foo=bar", + darkMode = true, + ) + ).isEqualTo("https://self.hosted/style.json?foo=bar") + } + + @Test + fun `blank custom map uri falls back to the built-in style`() { + assertThat( + builder.build( + customMapStyleUrl = " ", + darkMode = false, + ) + ).isEqualTo("https://base.url/aLightMapId/style.json?key=anApiKey") } } From e8ca16b74fefed6e81cd3473c9f41ad0910a5d4f Mon Sep 17 00:00:00 2001 From: hayaksi1 <193020925+hayaksi1@users.noreply.github.com> Date: Sun, 9 Aug 2026 01:59:01 +0300 Subject: [PATCH 286/383] Ignore a room list filter that is incompatible with an already selected one Some room list filters are mutually exclusive, and the UI expresses that by hiding the incompatible chips rather than disabling them. Nothing enforced the rule on the write path, so two chips tapped in the same frame, before the list could recompose, both applied. The room list then matched nothing while the offending chip was hidden, leaving no way to see or undo what was filtering the rooms. DefaultFilterSelectionStrategy.select() now ignores a filter that is incompatible with one already selected, so the same table buildFilters() uses to hide chips also governs the selection itself. The currently applied filters win and the late tap is dropped, which matches the existing design where an incompatible chip is already on its way out of the UI when it is tapped. toggle(), deselect(), clear() and the FilterSelectionStrategy interface are unchanged. Relates to https://github.com/element-hq/element-x-android/issues/5383 --- .../DefaultFilterSelectionStrategy.kt | 5 +++ .../filters/RoomListFiltersPresenterTest.kt | 45 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/filters/selection/DefaultFilterSelectionStrategy.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/filters/selection/DefaultFilterSelectionStrategy.kt index 847dbc2c39..4121ff9ab4 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/filters/selection/DefaultFilterSelectionStrategy.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/filters/selection/DefaultFilterSelectionStrategy.kt @@ -22,6 +22,11 @@ class DefaultFilterSelectionStrategy : FilterSelectionStrategy { override val filterSelectionStates = MutableStateFlow(buildFilters()) override fun select(filter: RoomListFilter) { + // Incompatible filters are hidden from the UI rather than disabled, so a filter can still be + // selected while its chip is on its way out, typically when two chips are tapped in the same + // frame. Ignore it, the currently applied filters win. + // See https://github.com/element-hq/element-x-android/issues/5383 + if (selectedFilters.any { it in filter.incompatibleFilters }) return selectedFilters.add(filter) filterSelectionStates.value = buildFilters() } diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/filters/RoomListFiltersPresenterTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/filters/RoomListFiltersPresenterTest.kt index 9fb87c0eec..ae1d7b5083 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/filters/RoomListFiltersPresenterTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/filters/RoomListFiltersPresenterTest.kt @@ -72,6 +72,51 @@ class RoomListFiltersPresenterTest { } } + @Test + @OptIn(ExperimentalCoroutinesApi::class) + fun `present - toggling two incompatible filters in the same frame keeps the first one`() = runTest { + val presenter = createRoomListFiltersPresenter() + presenter.test { + awaitItem().let { state -> + // Both events are sent on the same state, i.e. before any recomposition, which is what + // happens when the two chips are tapped simultaneously. + state.eventSink.invoke(RoomListFiltersEvent.ToggleFilter(RoomListFilter.Favourites)) + state.eventSink.invoke(RoomListFiltersEvent.ToggleFilter(RoomListFilter.Invites)) + } + advanceUntilIdle() + awaitLastSequentialItem().let { state -> + assertThat(state.selectedFilters()).containsExactly(RoomListFilter.Favourites) + assertThat(state.filterSelectionStates).containsExactly( + filterSelectionState(RoomListFilter.Favourites, true), + filterSelectionState(RoomListFilter.Unread, false), + filterSelectionState(RoomListFilter.People, false), + filterSelectionState(RoomListFilter.Rooms, false), + ).inOrder() + } + } + } + + @Test + @OptIn(ExperimentalCoroutinesApi::class) + fun `present - toggling two incompatible categories in the same frame keeps the first one`() = runTest { + val presenter = createRoomListFiltersPresenter() + presenter.test { + awaitItem().let { state -> + state.eventSink.invoke(RoomListFiltersEvent.ToggleFilter(RoomListFilter.People)) + state.eventSink.invoke(RoomListFiltersEvent.ToggleFilter(RoomListFilter.Rooms)) + } + advanceUntilIdle() + awaitLastSequentialItem().let { state -> + assertThat(state.selectedFilters()).containsExactly(RoomListFilter.People) + assertThat(state.filterSelectionStates).containsExactly( + filterSelectionState(RoomListFilter.People, true), + filterSelectionState(RoomListFilter.Unread, false), + filterSelectionState(RoomListFilter.Favourites, false), + ).inOrder() + } + } + } + @Test @OptIn(ExperimentalCoroutinesApi::class) fun `present - clear filters event`() = runTest { From de0e628512fc121021ff12e7f040f3c8dd977052 Mon Sep 17 00:00:00 2001 From: hayaksi1 <193020925+hayaksi1@users.noreply.github.com> Date: Sun, 9 Aug 2026 03:51:20 +0300 Subject: [PATCH 287/383] Show the account a UnifiedPush registration belongs to in the distributor A distributor such as ntfy or DAVx5 lists every registration it holds, but Element registered each one with no message for the distributor, so an account added from a second session was indistinguishable from the first. RegisterUnifiedPushUseCase.execute now takes the session id and passes it as messageForDistributor, which the connector has accepted since 3.x. The value is the raw Matrix ID, which is not personal data by the project's own logging rules, and no new string resource is needed. UnifiedPushProvider already has the MatrixClient in hand at the only call site, so the PushProvider interface is unchanged and nothing outside the module moves. Relates to https://github.com/element-hq/element-x-android/issues/6426 --- .../unifiedpush/RegisterUnifiedPushUseCase.kt | 10 +++++++--- .../pushproviders/unifiedpush/UnifiedPushProvider.kt | 2 +- .../DefaultRegisterUnifiedPushUseCaseTest.kt | 7 ++++--- .../unifiedpush/FakeRegisterUnifiedPushUseCase.kt | 7 ++++--- .../unifiedpush/UnifiedPushProviderTest.kt | 8 ++++---- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/RegisterUnifiedPushUseCase.kt b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/RegisterUnifiedPushUseCase.kt index 00e5649533..d76d69a653 100644 --- a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/RegisterUnifiedPushUseCase.kt +++ b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/RegisterUnifiedPushUseCase.kt @@ -12,6 +12,7 @@ import android.content.Context import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.pushproviders.api.Distributor import io.element.android.libraries.pushproviders.unifiedpush.registration.EndpointRegistrationHandler import kotlinx.coroutines.flow.filter @@ -21,7 +22,7 @@ import org.unifiedpush.android.connector.UnifiedPush import kotlin.time.Duration.Companion.seconds interface RegisterUnifiedPushUseCase { - suspend fun execute(distributor: Distributor, clientSecret: String): Result + suspend fun execute(distributor: Distributor, clientSecret: String, sessionId: SessionId): Result } @ContributesBinding(AppScope::class) @@ -29,11 +30,14 @@ class DefaultRegisterUnifiedPushUseCase( @ApplicationContext private val context: Context, private val endpointRegistrationHandler: EndpointRegistrationHandler, ) : RegisterUnifiedPushUseCase { - override suspend fun execute(distributor: Distributor, clientSecret: String): Result { + override suspend fun execute(distributor: Distributor, clientSecret: String, sessionId: SessionId): Result { UnifiedPush.saveDistributor(context, distributor.value) // This will trigger the callback // VectorUnifiedPushMessagingReceiver.onNewEndpoint - UnifiedPush.register(context = context, instance = clientSecret) + // The session id is passed as the message for the distributor, so that its UI can tell one + // registration from another when several accounts are registered. + // See https://github.com/element-hq/element-x-android/issues/6426 + UnifiedPush.register(context = context, instance = clientSecret, messageForDistributor = sessionId.value) // Wait for VectorUnifiedPushMessagingReceiver.onNewEndpoint to proceed @Suppress("RunCatchingNotAllowed") return runCatching { diff --git a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushProvider.kt b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushProvider.kt index 7288fccab2..f72a591faa 100644 --- a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushProvider.kt +++ b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushProvider.kt @@ -36,7 +36,7 @@ class UnifiedPushProvider( override suspend fun registerWith(matrixClient: MatrixClient, distributor: Distributor): Result { val clientSecret = pushClientSecret.getSecretForUser(matrixClient.sessionId) - return registerUnifiedPushUseCase.execute(distributor, clientSecret) + return registerUnifiedPushUseCase.execute(distributor, clientSecret, matrixClient.sessionId) .onSuccess { unifiedPushStore.setDistributorValue(matrixClient.sessionId, distributor.value) } diff --git a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/DefaultRegisterUnifiedPushUseCaseTest.kt b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/DefaultRegisterUnifiedPushUseCaseTest.kt index fe7da75951..5460005cef 100644 --- a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/DefaultRegisterUnifiedPushUseCaseTest.kt +++ b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/DefaultRegisterUnifiedPushUseCaseTest.kt @@ -12,6 +12,7 @@ import androidx.test.platform.app.InstrumentationRegistry import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.A_SECRET +import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.pushproviders.api.Distributor import io.element.android.libraries.pushproviders.unifiedpush.registration.EndpointRegistrationHandler import io.element.android.libraries.pushproviders.unifiedpush.registration.RegistrationResult @@ -41,7 +42,7 @@ class DefaultRegisterUnifiedPushUseCaseTest : RobolectricTest() { delay(100) endpointRegistrationHandler.registrationDone(RegistrationResult(A_SECRET, Result.success(Unit))) } - val result = useCase.execute(aDistributor, A_SECRET) + val result = useCase.execute(aDistributor, A_SECRET, A_SESSION_ID) assertThat(result.isSuccess).isTrue() } @@ -56,7 +57,7 @@ class DefaultRegisterUnifiedPushUseCaseTest : RobolectricTest() { delay(100) endpointRegistrationHandler.registrationDone(RegistrationResult(A_SECRET, Result.failure(AN_EXCEPTION))) } - val result = useCase.execute(aDistributor, A_SECRET) + val result = useCase.execute(aDistributor, A_SECRET, A_SESSION_ID) assertThat(result.isSuccess).isFalse() } @@ -67,7 +68,7 @@ class DefaultRegisterUnifiedPushUseCaseTest : RobolectricTest() { endpointRegistrationHandler = endpointRegistrationHandler ) val aDistributor = Distributor("aValue", "aName") - val result = useCase.execute(aDistributor, A_SECRET) + val result = useCase.execute(aDistributor, A_SECRET, A_SESSION_ID) assertThat(result.isSuccess).isFalse() } diff --git a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/FakeRegisterUnifiedPushUseCase.kt b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/FakeRegisterUnifiedPushUseCase.kt index 3055dad6b7..55729f29f8 100644 --- a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/FakeRegisterUnifiedPushUseCase.kt +++ b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/FakeRegisterUnifiedPushUseCase.kt @@ -8,13 +8,14 @@ package io.element.android.libraries.pushproviders.unifiedpush +import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.pushproviders.api.Distributor import io.element.android.tests.testutils.lambda.lambdaError class FakeRegisterUnifiedPushUseCase( - private val result: (Distributor, String) -> Result = { _, _ -> lambdaError() } + private val result: (Distributor, String, SessionId) -> Result = { _, _, _ -> lambdaError() } ) : RegisterUnifiedPushUseCase { - override suspend fun execute(distributor: Distributor, clientSecret: String): Result { - return result(distributor, clientSecret) + override suspend fun execute(distributor: Distributor, clientSecret: String, sessionId: SessionId): Result { + return result(distributor, clientSecret, sessionId) } } diff --git a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushProviderTest.kt b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushProviderTest.kt index e22c1c3bf4..e766068783 100644 --- a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushProviderTest.kt +++ b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/UnifiedPushProviderTest.kt @@ -62,7 +62,7 @@ class UnifiedPushProviderTest { @Test fun `register ok`() = runTest { val getSecretForUserResultLambda = lambdaRecorder { A_SECRET } - val executeLambda = lambdaRecorder> { _, _ -> Result.success(Unit) } + val executeLambda = lambdaRecorder> { _, _, _ -> Result.success(Unit) } val setDistributorValueResultLambda = lambdaRecorder { _, _ -> } val unifiedPushProvider = createUnifiedPushProvider( pushClientSecret = FakePushClientSecret( @@ -82,7 +82,7 @@ class UnifiedPushProviderTest { .with(value(A_SESSION_ID)) executeLambda.assertions() .isCalledOnce() - .with(value(Distributor("value", "Name")), value(A_SECRET)) + .with(value(Distributor("value", "Name")), value(A_SECRET), value(A_SESSION_ID)) setDistributorValueResultLambda.assertions() .isCalledOnce() .with(value(A_SESSION_ID), value("value")) @@ -91,7 +91,7 @@ class UnifiedPushProviderTest { @Test fun `register ko`() = runTest { val getSecretForUserResultLambda = lambdaRecorder { A_SECRET } - val executeLambda = lambdaRecorder> { _, _ -> Result.failure(AN_EXCEPTION) } + val executeLambda = lambdaRecorder> { _, _, _ -> Result.failure(AN_EXCEPTION) } val setDistributorValueResultLambda = lambdaRecorder(ensureNeverCalled = true) { _, _ -> } val unifiedPushProvider = createUnifiedPushProvider( pushClientSecret = FakePushClientSecret( @@ -111,7 +111,7 @@ class UnifiedPushProviderTest { .with(value(A_SESSION_ID)) executeLambda.assertions() .isCalledOnce() - .with(value(Distributor("value", "Name")), value(A_SECRET)) + .with(value(Distributor("value", "Name")), value(A_SECRET), value(A_SESSION_ID)) } @Test From e63c897ec274a5421fb22c9ed8b29bcae4f0fa9e Mon Sep 17 00:00:00 2001 From: hayaksi1 <193020925+hayaksi1@users.noreply.github.com> Date: Sun, 9 Aug 2026 03:51:20 +0300 Subject: [PATCH 288/383] Ignore a second voice recording start while one is already running The composer emits Start whenever the voice message state is Idle, and the state only leaves Idle once the recorder has produced its first audio buffer. A second tap inside that window started a second recording, which overwrote the output file, re-initialised the encoder while the first one was still encoding, and orphaned the first job together with its AudioReader. The orphan kept the microphone open and kept emitting Recording for the rest of the session, so Stop and Delete appeared to do nothing until the room was left and re-entered, and re-initialising the encoder under an active encode could crash natively. DefaultVoiceRecorder.startRecord now runs under the mutex it already owns and returns early when a recording job exists, so the second start is a no-op: no file, no encoder re-init and no second AudioReader. Relates to https://github.com/element-hq/element-x-android/issues/5780 --- .../impl/DefaultVoiceRecorder.kt | 16 ++++++--- .../impl/DefaultVoiceRecorderTest.kt | 33 +++++++++++++++++-- .../test/FakeAudioReaderFactory.kt | 5 +++ 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/libraries/voicerecorder/impl/src/main/kotlin/io/element/android/libraries/voicerecorder/impl/DefaultVoiceRecorder.kt b/libraries/voicerecorder/impl/src/main/kotlin/io/element/android/libraries/voicerecorder/impl/DefaultVoiceRecorder.kt index 5e4c9ae132..4dd68d25e7 100644 --- a/libraries/voicerecorder/impl/src/main/kotlin/io/element/android/libraries/voicerecorder/impl/DefaultVoiceRecorder.kt +++ b/libraries/voicerecorder/impl/src/main/kotlin/io/element/android/libraries/voicerecorder/impl/DefaultVoiceRecorder.kt @@ -71,14 +71,22 @@ class DefaultVoiceRecorder( override val state: StateFlow = _state @RequiresPermission(Manifest.permission.RECORD_AUDIO) - override suspend fun startRecord() { + override suspend fun startRecord() = lock.withLock { + // The composer can emit a second Start before the first recording has produced its first + // buffer, i.e. before the state flips away from Idle. Without this guard the second call + // orphans the first job and its AudioReader, which keeps the microphone open and keeps + // emitting Recording forever, so Stop and Delete appear to do nothing. + // See https://github.com/element-hq/element-x-android/issues/5780 + if (recordingJob != null) { + Timber.w("Voice recorder is already recording, ignoring this start") + return@withLock + } + Timber.i("Voice recorder started recording") outputFile = fileManager.createFile() .also(encoder::init) - lock.withLock { - levels.clear() - } + levels.clear() val audioRecorder = audioReaderFactory.create(config, dispatchers).also { audioReader = it } diff --git a/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/impl/DefaultVoiceRecorderTest.kt b/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/impl/DefaultVoiceRecorderTest.kt index e3ff6f9198..3a65d612bb 100644 --- a/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/impl/DefaultVoiceRecorderTest.kt +++ b/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/impl/DefaultVoiceRecorderTest.kt @@ -39,6 +39,7 @@ import kotlin.time.TestTimeSource class DefaultVoiceRecorderTest { private val fakeFileSystem = FakeFileSystem() private val timeSource = TestTimeSource() + private val audioReaderFactory = FakeAudioReaderFactory(audio = AUDIO) @Test fun `it emits the initial state`() = runTest { @@ -109,6 +110,34 @@ class DefaultVoiceRecorderTest { } } + @Test + fun `when startRecord is called twice, the second call is ignored`() = runTest { + val voiceRecorder = createDefaultVoiceRecorder() + voiceRecorder.state.test { + assertThat(awaitItem()).isEqualTo(VoiceRecorderState.Idle) + + // Two taps landing before the state has flipped away from Idle. + voiceRecorder.startRecord() + voiceRecorder.startRecord() + assertThat(audioReaderFactory.createdCount).isEqualTo(1) + + skipItems(1) + timeSource += 5.seconds + skipItems(2) + voiceRecorder.stopRecord() + assertThat(awaitItem()).isEqualTo( + VoiceRecorderState.Finished( + file = File(FILE_PATH), + mimeType = MimeTypes.Ogg, + waveform = List(100) { 1f }, + duration = 5.seconds, + ) + ) + // An orphaned recording job would keep emitting Recording after the stop. + expectNoEvents() + } + } + @Test fun `when cancelled, it deletes the file`() = runTest { val voiceRecorder = createDefaultVoiceRecorder() @@ -128,9 +157,7 @@ class DefaultVoiceRecorderTest { return DefaultVoiceRecorder( dispatchers = testCoroutineDispatchers(), timeSource = timeSource, - audioReaderFactory = FakeAudioReaderFactory( - audio = AUDIO, - ), + audioReaderFactory = audioReaderFactory, encoder = FakeEncoder(fakeFileSystem), config = AudioConfig( format = audioFormat, diff --git a/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/test/FakeAudioReaderFactory.kt b/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/test/FakeAudioReaderFactory.kt index d4bd241aaa..2c29b2635e 100644 --- a/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/test/FakeAudioReaderFactory.kt +++ b/libraries/voicerecorder/impl/src/test/kotlin/io/element/android/libraries/voicerecorder/test/FakeAudioReaderFactory.kt @@ -16,7 +16,12 @@ import io.element.android.libraries.voicerecorder.impl.audio.AudioReader class FakeAudioReaderFactory( private val audio: List