From 0bf846086f6ec6e987b7a58707c9e0ef13d7d61e Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 10 Sep 2024 13:49:12 +0200 Subject: [PATCH 001/106] Pinned messages : allow to unpin redacted message --- .../features/messages/impl/actionlist/ActionListPresenter.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 840e12583f..f4882ea7b0 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 @@ -190,9 +190,9 @@ private fun List.postFilter(content: TimelineItemEventConten when (content) { is TimelineItemCallNotifyContent, is TimelineItemLegacyCallInviteContent, - is TimelineItemStateContent, + is TimelineItemStateContent -> action == TimelineItemAction.ViewSource is TimelineItemRedactedContent -> { - action == TimelineItemAction.ViewSource + action == TimelineItemAction.ViewSource || action == TimelineItemAction.Unpin } else -> true } From 004cb7404a9a514ddd64d96375a48b882ea11e6c Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 10 Sep 2024 13:49:40 +0200 Subject: [PATCH 002/106] Pinned messages : remove redact action from the pinned message list action menu. --- .../list/PinnedMessagesListPresenter.kt | 8 ----- ...MessagesListTimelineActionPostProcessor.kt | 1 - .../list/PinnedMessagesListPresenterTest.kt | 29 ------------------- 3 files changed, 38 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt index c25675c7f7..4b6f3e64d4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt @@ -112,7 +112,6 @@ class PinnedMessagesListPresenter @AssistedInject constructor( targetEvent: TimelineItem.Event, ) = launch { when (action) { - TimelineItemAction.Redact -> handleActionRedact(targetEvent) TimelineItemAction.ViewSource -> { navigator.onShowEventDebugInfoClick(targetEvent.eventId, targetEvent.debugInfo) } @@ -142,13 +141,6 @@ class PinnedMessagesListPresenter @AssistedInject constructor( } } - private suspend fun handleActionRedact(event: TimelineItem.Event) { - timelineProvider.invokeOnTimeline { - redactEvent(eventId = event.eventId, transactionId = event.transactionId, reason = null) - .onFailure { Timber.e(it) } - } - } - @Composable private fun userEventPermissions(updateKey: Long): State { return produceState(UserEventPermissions.DEFAULT, key1 = updateKey) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListTimelineActionPostProcessor.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListTimelineActionPostProcessor.kt index 3e88a9d716..48fdb83d79 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListTimelineActionPostProcessor.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListTimelineActionPostProcessor.kt @@ -17,7 +17,6 @@ class PinnedMessagesListTimelineActionPostProcessor : TimelineItemActionPostProc actions.firstOrNull { it is TimelineItemAction.Unpin }?.let(::add) actions.firstOrNull { it is TimelineItemAction.Forward }?.let(::add) actions.firstOrNull { it is TimelineItemAction.ViewSource }?.let(::add) - actions.firstOrNull { it is TimelineItemAction.Redact }?.let(::add) } } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt index 0478e08934..48a0cf5e5e 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt @@ -19,7 +19,6 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatch 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.TransactionId import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo @@ -138,34 +137,6 @@ class PinnedMessagesListPresenterTest { } } - @Test - fun `present - redact event`() = runTest { - val redactEventLambda = lambdaRecorder { _: EventId?, _: TransactionId?, _: String? -> Result.success(true) } - val pinnedEventsTimeline = createPinnedMessagesTimeline().apply { - this.redactEventLambda = redactEventLambda - } - val room = FakeMatrixRoom( - pinnedEventsTimelineResult = { Result.success(pinnedEventsTimeline) }, - canRedactOwnResult = { Result.success(true) }, - canRedactOtherResult = { Result.success(true) }, - canUserPinUnpinResult = { Result.success(true) }, - ).apply { - givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID))) - } - val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true) - presenter.test { - skipItems(3) - val filledState = awaitItem() as PinnedMessagesListState.Filled - val eventItem = filledState.timelineItems.first() as TimelineItem.Event - filledState.eventSink(PinnedMessagesListEvents.HandleAction(TimelineItemAction.Redact, eventItem)) - advanceUntilIdle() - cancelAndIgnoreRemainingEvents() - assert(redactEventLambda) - .isCalledOnce() - .with(value(AN_EVENT_ID), value(null), value(null)) - } - } - @Test fun `present - unpin event`() = runTest { val successUnpinEventLambda = lambdaRecorder { _: EventId? -> Result.success(true) } From 9d6c9456a5fc9335dc633c53486c8386566c6149 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 09:21:27 +0200 Subject: [PATCH 003/106] SDK 0.2.44 --- 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 f01f7ce1a6..07898a0950 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -162,7 +162,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.43" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.44" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } From f87422a0224ef5d86247ff221a586f2e5ec00277 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 11 Sep 2024 15:50:55 +0200 Subject: [PATCH 004/106] Fix filtering of Event at the beginning of DM. --- .../matrix/api/room/MatrixRoomInfo.kt | 3 +- .../matrix/impl/room/MatrixRoomInfoMapper.kt | 1 + .../matrix/impl/timeline/RustTimeline.kt | 6 +- .../RoomBeginningPostProcessor.kt | 21 ++- .../roomlist/RoomSummaryListProcessorTest.kt | 3 + .../RoomBeginningPostProcessorTest.kt | 157 ++++++++++++++---- .../matrix/test/room/FakeMatrixRoom.kt | 2 + 7 files changed, 150 insertions(+), 43 deletions(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt index 32eddf7b00..b466a28da6 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt @@ -44,5 +44,6 @@ data class MatrixRoomInfo( val hasRoomCall: Boolean, val activeRoomCallParticipants: ImmutableList, val heroes: ImmutableList, - val pinnedEventIds: ImmutableList + val pinnedEventIds: ImmutableList, + val creator: UserId?, ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt index d5a0b86083..7fcef163b6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt @@ -28,6 +28,7 @@ class MatrixRoomInfoMapper { fun map(rustRoomInfo: RustRoomInfo): MatrixRoomInfo = rustRoomInfo.let { return MatrixRoomInfo( id = RoomId(it.id), + creator = it.creator?.let(::UserId), name = it.displayName, rawName = it.rawName, topic = it.topic, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt index 25d7c52c7b..bb8947b2ba 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt @@ -207,15 +207,17 @@ class RustTimeline( _timelineItems, backPaginationStatus.map { it.hasMoreToLoad }.distinctUntilChanged(), forwardPaginationStatus.map { it.hasMoreToLoad }.distinctUntilChanged(), + matrixRoom.roomInfoFlow.map { it.creator }, isInit, - ) { timelineItems, hasMoreToLoadBackward, hasMoreToLoadForward, isInit -> + ) { timelineItems, hasMoreToLoadBackward, hasMoreToLoadForward, roomCreator, isInit -> withContext(dispatcher) { timelineItems .process { items -> roomBeginningPostProcessor.process( items = items, isDm = matrixRoom.isDm, - hasMoreToLoadBackwards = hasMoreToLoadBackward + roomCreator = roomCreator, + hasMoreToLoadBackwards = hasMoreToLoadBackward, ) } .process(predicate = isInit) { items -> diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt index 2fb41a745c..7ed9de2fe3 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor import androidx.annotation.VisibleForTesting 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.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange @@ -25,12 +26,14 @@ class RoomBeginningPostProcessor(private val mode: Timeline.Mode) { fun process( items: List, isDm: Boolean, - hasMoreToLoadBackwards: Boolean + roomCreator: UserId?, + hasMoreToLoadBackwards: Boolean, ): List { return when { + items.isEmpty() -> items mode == Timeline.Mode.PINNED_EVENTS -> items + isDm -> processForDM(items, roomCreator) hasMoreToLoadBackwards -> items - isDm -> processForDM(items) else -> processForRoom(items) } } @@ -40,15 +43,18 @@ class RoomBeginningPostProcessor(private val mode: Timeline.Mode) { return listOf(roomBeginningItem) + items } - private fun processForDM(items: List): List { - // Find room creation event. This is usually index 0 + private fun processForDM(items: List, roomCreator: UserId?): List { + // Find room creation event. + // This is usually the first MatrixTimelineItem.Event (so index 1, index 0 is a date) val roomCreationEventIndex = items.indexOfFirst { val stateEventContent = (it as? MatrixTimelineItem.Event)?.event?.content as? StateContent stateEventContent?.content is OtherState.RoomCreate } - // Find self-join event for room creator. This is usually index 1 - val roomCreatorUserId = (items.getOrNull(roomCreationEventIndex) as? MatrixTimelineItem.Event)?.event?.sender + // If the parameter roomCreator is null, the creator is the sender of the RoomCreate Event. + val roomCreatorUserId = roomCreator ?: (items.getOrNull(roomCreationEventIndex) as? MatrixTimelineItem.Event)?.event?.sender + // Find self-join event for the room creator. + // This is usually the second MatrixTimelineItem.Event (so index 2) val selfUserJoinedEventIndex = roomCreatorUserId?.let { creatorUserId -> items.indexOfFirst { val stateEventContent = (it as? MatrixTimelineItem.Event)?.event?.content as? RoomMembershipContent @@ -56,6 +62,9 @@ class RoomBeginningPostProcessor(private val mode: Timeline.Mode) { } } ?: -1 + if (roomCreationEventIndex == -1 && selfUserJoinedEventIndex == -1) { + return items + } // Remove items at the indices we found val newItems = items.toMutableList() if (selfUserJoinedEventIndex in newItems.indices) { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt index f4b7f8a1d0..faa8a1102e 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt @@ -10,6 +10,7 @@ package io.element.android.libraries.matrix.impl.roomlist import com.google.common.truth.Truth.assertThat import com.sun.jna.Pointer 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.roomlist.RoomSummary import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID_2 @@ -215,6 +216,7 @@ private fun aRustRoomInfo( numUnreadNotifications: ULong = 0uL, numUnreadMentions: ULong = 0uL, pinnedEventIds: List = listOf(), + roomCreator: UserId? = null, ) = RoomInfo( id = id, displayName = displayName, @@ -245,6 +247,7 @@ private fun aRustRoomInfo( numUnreadNotifications = numUnreadNotifications, numUnreadMentions = numUnreadMentions, pinnedEventIds = pinnedEventIds, + creator = roomCreator?.value, ) class FakeRoomListItem( diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt index db93b86142..fadc174cd1 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt @@ -22,85 +22,174 @@ import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem import org.junit.Test class RoomBeginningPostProcessorTest { + private val roomCreateEvent = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.create"), + event = anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate)) + ) + private val roomCreatorJoinEvent = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.member"), + event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED)) + ) + private val otherMemberJoinEvent = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.member_other"), + event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED)) + ) + private val messageEvent = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.message"), + event = anEventTimelineItem(content = aMessageContent("hi")) + ) + + @Test + fun `processor returns empty list when empty list is provided`() { + val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE) + val processedItems = processor.process( + items = emptyList(), + isDm = true, + roomCreator = A_USER_ID, + hasMoreToLoadBackwards = false, + ) + assertThat(processedItems).isEmpty() + } + + @Test + fun `processor returns the provided list when it only contains a message`() { + val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE) + val processedItems = processor.process( + items = listOf(messageEvent), + isDm = true, + roomCreator = A_USER_ID, + hasMoreToLoadBackwards = false, + ) + assertThat(processedItems).isEqualTo(listOf(messageEvent)) + } + + @Test + fun `processor returns the provided list when it only contains a message and the roomCreator is not provided`() { + val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE) + val processedItems = processor.process( + items = listOf(messageEvent), + isDm = true, + roomCreator = null, + hasMoreToLoadBackwards = false, + ) + assertThat(processedItems).isEqualTo(listOf(messageEvent)) + } + @Test fun `processor removes room creation event and self-join event from DM timeline`() { val timelineItems = listOf( - MatrixTimelineItem.Event(UniqueId("m.room.create"), anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))), - MatrixTimelineItem.Event(UniqueId("m.room.member"), anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))), + roomCreateEvent, + roomCreatorJoinEvent, ) val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE) - val processedItems = processor.process(timelineItems, isDm = true, hasMoreToLoadBackwards = false) + val processedItems = processor.process( + items = timelineItems, + isDm = true, + roomCreator = A_USER_ID, + hasMoreToLoadBackwards = false, + ) assertThat(processedItems).isEmpty() } + @Test + fun `processor does not remove anything with PINNED_EVENTS mode`() { + val timelineItems = listOf( + roomCreateEvent, + roomCreatorJoinEvent, + ) + val processor = RoomBeginningPostProcessor(Timeline.Mode.PINNED_EVENTS) + val processedItems = processor.process( + items = timelineItems, + isDm = true, + roomCreator = A_USER_ID, + hasMoreToLoadBackwards = false, + ) + assertThat(processedItems).isEqualTo(timelineItems) + } + @Test fun `processor removes room creation event and self-join event from DM timeline even if they're not the first items`() { val timelineItems = listOf( - MatrixTimelineItem.Event( - UniqueId("m.room.member_other"), - anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED)) - ), - MatrixTimelineItem.Event(UniqueId("m.room.create"), anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))), - MatrixTimelineItem.Event(UniqueId("m.room.message"), anEventTimelineItem(content = aMessageContent("hi"))), - MatrixTimelineItem.Event(UniqueId("m.room.member"), anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))), + otherMemberJoinEvent, + roomCreateEvent, + messageEvent, + roomCreatorJoinEvent, ) val expected = listOf( - MatrixTimelineItem.Event( - UniqueId("m.room.member_other"), - anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED)) - ), - MatrixTimelineItem.Event(UniqueId("m.room.message"), anEventTimelineItem(content = aMessageContent("hi"))), + otherMemberJoinEvent, + messageEvent, ) val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE) - val processedItems = processor.process(timelineItems, isDm = true, hasMoreToLoadBackwards = false) + val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = false) assertThat(processedItems).isEqualTo(expected) } @Test fun `processor will add beginning of room item if it's not a DM`() { val timelineItems = listOf( - MatrixTimelineItem.Event(UniqueId("m.room.create"), anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))), - MatrixTimelineItem.Event(UniqueId("m.room.member"), anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))), + roomCreateEvent, + roomCreatorJoinEvent, ) val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE) - val processedItems = processor.process(timelineItems, isDm = false, hasMoreToLoadBackwards = false) + val processedItems = processor.process(timelineItems, isDm = false, roomCreator = A_USER_ID, hasMoreToLoadBackwards = false) assertThat(processedItems).isEqualTo( listOf(processor.createRoomBeginningItem()) + timelineItems ) } @Test - fun `processor won't remove items if it's not at the start of the timeline`() { + fun `processor will not add beginning of room item if it's not a DM but the room has more to load`() { val timelineItems = listOf( - MatrixTimelineItem.Event(UniqueId("m.room.create"), anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))), - MatrixTimelineItem.Event(UniqueId("m.room.member"), anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))), + roomCreateEvent, + roomCreatorJoinEvent, ) val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE) - val processedItems = processor.process(timelineItems, isDm = true, hasMoreToLoadBackwards = true) + val processedItems = processor.process(timelineItems, isDm = false, roomCreator = A_USER_ID, hasMoreToLoadBackwards = true) assertThat(processedItems).isEqualTo(timelineItems) } @Test - fun `processor won't remove the first member join event if it can't find the room creation event`() { + fun `processor will add beginning of room item if it's not a DM, when the parameter roomCreator is null`() { val timelineItems = listOf( - MatrixTimelineItem.Event(UniqueId("m.room.member"), anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))), + roomCreateEvent, + roomCreatorJoinEvent, ) val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE) - val processedItems = processor.process(timelineItems, isDm = true, hasMoreToLoadBackwards = true) - assertThat(processedItems).isEqualTo(timelineItems) + val processedItems = processor.process(timelineItems, isDm = false, roomCreator = null, hasMoreToLoadBackwards = false) + assertThat(processedItems).isEqualTo( + listOf(processor.createRoomBeginningItem()) + timelineItems + ) + } + + @Test + fun `processor removes items event it's not at the start of the timeline`() { + val timelineItems = listOf( + roomCreateEvent, + roomCreatorJoinEvent, + ) + val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE) + val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = true) + assertThat(processedItems).isEmpty() + } + + @Test + fun `processor removes the first member join event if it matches the roomCreator parameter`() { + val timelineItems = listOf( + roomCreatorJoinEvent, + ) + val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE) + val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = true) + assertThat(processedItems).isEmpty() } @Test fun `processor won't remove the first member join event if it's not from the room creator`() { val timelineItems = listOf( - MatrixTimelineItem.Event(UniqueId("m.room.create"), anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))), - MatrixTimelineItem.Event( - UniqueId("m.room.member"), - anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED)) - ), + roomCreateEvent, + otherMemberJoinEvent, ) val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE) - val processedItems = processor.process(timelineItems, isDm = true, hasMoreToLoadBackwards = true) - assertThat(processedItems).isEqualTo(timelineItems) + val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = true) + assertThat(processedItems).isEqualTo(listOf(otherMemberJoinEvent)) } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 8418d0c047..4f35c37d4d 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -523,6 +523,7 @@ fun aRoomInfo( activeRoomCallParticipants: List = emptyList(), heroes: List = emptyList(), pinnedEventIds: List = emptyList(), + roomCreator: UserId? = null, ) = MatrixRoomInfo( id = id, name = name, @@ -549,6 +550,7 @@ fun aRoomInfo( activeRoomCallParticipants = activeRoomCallParticipants.toImmutableList(), heroes = heroes.toImmutableList(), pinnedEventIds = pinnedEventIds.toImmutableList(), + creator = roomCreator, ) fun defaultRoomPowerLevels() = MatrixRoomPowerLevels( From fac919e93399f7af2ea66b3fc0e3a6be89ae6348 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 11 Sep 2024 16:10:29 +0200 Subject: [PATCH 005/106] Remove process extension and provide isInit parameter to the processors. --- .../matrix/impl/timeline/RustTimeline.kt | 29 +++++++++---------- .../LastForwardIndicatorsPostProcessor.kt | 2 ++ .../LoadingIndicatorsPostProcessor.kt | 2 ++ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt index bb8947b2ba..4694548b93 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt @@ -212,7 +212,7 @@ class RustTimeline( ) { timelineItems, hasMoreToLoadBackward, hasMoreToLoadForward, roomCreator, isInit -> withContext(dispatcher) { timelineItems - .process { items -> + .let { items -> roomBeginningPostProcessor.process( items = items, isDm = matrixRoom.isDm, @@ -220,12 +220,20 @@ class RustTimeline( hasMoreToLoadBackwards = hasMoreToLoadBackward, ) } - .process(predicate = isInit) { items -> - loadingIndicatorsPostProcessor.process(items, hasMoreToLoadBackward, hasMoreToLoadForward) + .let { items -> + loadingIndicatorsPostProcessor.process( + items = items, + isInit = isInit, + hasMoreToLoadBackward = hasMoreToLoadBackward, + hasMoreToLoadForward = hasMoreToLoadForward + ) } // Keep lastForwardIndicatorsPostProcessor last - .process(predicate = isInit) { items -> - lastForwardIndicatorsPostProcessor.process(items) + .let { items -> + lastForwardIndicatorsPostProcessor.process( + items = items, + isInit = isInit, + ) } } }.onStart { @@ -544,14 +552,3 @@ class RustTimeline( } } } - -private suspend fun List.process( - predicate: Boolean = true, - processor: suspend (List) -> List -): List { - return if (predicate) { - processor(this) - } else { - this - } -} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessor.kt index 193682f81b..441aa8149a 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessor.kt @@ -22,7 +22,9 @@ class LastForwardIndicatorsPostProcessor( fun process( items: List, + isInit: Boolean, ): List { + if (!isInit) return items // We don't need to add the last forward indicator if we are not in the FOCUSED_ON_EVENT mode if (mode != Timeline.Mode.FOCUSED_ON_EVENT) { return items diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt index a4aa6bf05a..cc6e851954 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt @@ -16,9 +16,11 @@ import io.element.android.services.toolbox.api.systemclock.SystemClock class LoadingIndicatorsPostProcessor(private val systemClock: SystemClock) { fun process( items: List, + isInit: Boolean, hasMoreToLoadBackward: Boolean, hasMoreToLoadForward: Boolean, ): List { + if (!isInit) return items val shouldAddForwardLoadingIndicator = hasMoreToLoadForward && items.isNotEmpty() val currentTimestamp = systemClock.epochMillis() return buildList { From d05947499842fd9fa0083aac246fb2deca1d9fc1 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 12 Sep 2024 11:51:43 +0200 Subject: [PATCH 006/106] Doc | Remove outdated comment about flags default values --- .../element/android/libraries/featureflag/api/FeatureFlags.kt | 2 -- 1 file changed, 2 deletions(-) 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 124d3a3318..d8ab4bb176 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 @@ -13,8 +13,6 @@ import io.element.android.libraries.core.meta.BuildType /** * To enable or disable a FeatureFlags, change the `defaultValue` value. - * Warning: to enable a flag for the release app, you MUST update the file - * [io.element.android.libraries.featureflag.impl.StaticFeatureFlagProvider] */ enum class FeatureFlags( override val key: String, From bb50d3eb96507e1832aae680a292a35cf0102d42 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 12 Sep 2024 11:52:59 +0200 Subject: [PATCH 007/106] crypto: Add configuration flag to enable invisible crypto --- .../libraries/featureflag/api/FeatureFlags.kt | 9 +++++ .../matrix/impl/RustMatrixClientFactory.kt | 11 +++++++ .../AlwaysEnabledFeatureFlagService.kt | 23 +++++++++++++ .../android/samples/minimal/MainActivity.kt | 1 + .../android/samples/minimal/RoomListScreen.kt | 33 +------------------ 5 files changed, 45 insertions(+), 32 deletions(-) create mode 100644 samples/minimal/src/main/kotlin/io/element/android/samples/minimal/AlwaysEnabledFeatureFlagService.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 d8ab4bb176..d71c0de360 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 @@ -123,4 +123,13 @@ enum class FeatureFlags( defaultValue = { true }, isFinished = false, ), + InvisibleCrypto( + key = "feature.invisibleCrypto", + title = "Invisible Crypto", + description = "This setting controls how end-to-end encryption (E2E) keys are shared." + + " Enabling it will prevent the inclusion of devices that have not been explicitly verified by their owners." + + " You'll have to stop and re-open the app manually for that setting to take effect.", + defaultValue = { false }, + isFinished = false, + ), } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 2fe4284f98..7681dda6f0 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 @@ -10,6 +10,8 @@ package io.element.android.libraries.matrix.impl import io.element.android.appconfig.AuthenticationConfig import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.di.CacheDirectory +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.impl.analytics.UtdTracker import io.element.android.libraries.matrix.impl.certificates.UserCertificatesProvider import io.element.android.libraries.matrix.impl.paths.SessionPaths @@ -30,6 +32,7 @@ import org.matrix.rustcomponents.sdk.SlidingSyncVersion import org.matrix.rustcomponents.sdk.SlidingSyncVersionBuilder import org.matrix.rustcomponents.sdk.use import timber.log.Timber +import uniffi.matrix_sdk_crypto.CollectStrategy import java.io.File import javax.inject.Inject @@ -45,6 +48,7 @@ class RustMatrixClientFactory @Inject constructor( private val clock: SystemClock, private val utdTracker: UtdTracker, private val appPreferencesStore: AppPreferencesStore, + private val featureFlagService: FeatureFlagService, ) { suspend fun create(sessionData: SessionData): RustMatrixClient = withContext(coroutineDispatchers.io) { val sessionDelegate = RustClientSessionDelegate(sessionStore, appCoroutineScope, coroutineDispatchers) @@ -104,6 +108,13 @@ class RustMatrixClientFactory @Inject constructor( .addRootCertificates(userCertificatesProvider.provides()) .autoEnableBackups(true) .autoEnableCrossSigning(true) + .roomKeyRecipientStrategy( + strategy = if (featureFlagService.isFeatureEnabled(FeatureFlags.InvisibleCrypto)) { + CollectStrategy.IdentityBasedStrategy + } else { + CollectStrategy.DeviceBasedStrategy(onlyAllowTrustedDevices = false, errorOnVerifiedUserProblem = false) + } + ) .run { // Apply sliding sync version settings when (slidingSync) { diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/AlwaysEnabledFeatureFlagService.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/AlwaysEnabledFeatureFlagService.kt new file mode 100644 index 0000000000..67151d5aa4 --- /dev/null +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/AlwaysEnabledFeatureFlagService.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.samples.minimal + +import io.element.android.libraries.featureflag.api.Feature +import io.element.android.libraries.featureflag.api.FeatureFlagService +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf + +class AlwaysEnabledFeatureFlagService : FeatureFlagService { + override fun isFeatureEnabledFlow(feature: Feature): Flow { + return flowOf(true) + } + + override suspend fun setFeatureEnabled(feature: Feature, enabled: Boolean): Boolean { + return true + } +} diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt index e1654a8fb7..5319baf10e 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt @@ -56,6 +56,7 @@ class MainActivity : ComponentActivity() { clock = DefaultSystemClock(), utdTracker = UtdTracker(NoopAnalyticsService()), appPreferencesStore = InMemoryAppPreferencesStore(), + featureFlagService = AlwaysEnabledFeatureFlagService(), ), passphraseGenerator = NullPassphraseGenerator(), oidcConfigurationProvider = OidcConfigurationProvider(baseDirectory), diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt index 70f2a1f8a4..c6a2d49c89 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt @@ -25,8 +25,6 @@ import io.element.android.features.roomlist.impl.filters.selection.DefaultFilter import io.element.android.features.roomlist.impl.search.RoomListSearchDataSource import io.element.android.features.roomlist.impl.search.RoomListSearchPresenter import io.element.android.libraries.core.coroutine.CoroutineDispatchers -import io.element.android.libraries.core.meta.BuildMeta -import io.element.android.libraries.core.meta.BuildType import io.element.android.libraries.dateformatter.impl.DateFormatters import io.element.android.libraries.dateformatter.impl.DefaultLastMessageTimestampFormatter import io.element.android.libraries.dateformatter.impl.LocalDateTimeProvider @@ -35,8 +33,6 @@ import io.element.android.libraries.eventformatter.impl.DefaultRoomLastMessageFo import io.element.android.libraries.eventformatter.impl.ProfileChangeContentFormatter import io.element.android.libraries.eventformatter.impl.RoomMembershipContentFormatter import io.element.android.libraries.eventformatter.impl.StateContentFormatter -import io.element.android.libraries.featureflag.impl.DefaultFeatureFlagService -import io.element.android.libraries.featureflag.impl.PreferencesFeatureFlagProvider import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsPresenter import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState import io.element.android.libraries.indicator.impl.DefaultIndicatorService @@ -70,13 +66,7 @@ class RoomListScreen( private val sessionVerificationService = matrixClient.sessionVerificationService() private val encryptionService = matrixClient.encryptionService() private val stringProvider = AndroidStringProvider(context.resources) - private val buildMeta = getBuildMeta(context) - private val featureFlagService = DefaultFeatureFlagService( - providers = setOf( - PreferencesFeatureFlagProvider(context = context, buildMeta = buildMeta) - ), - buildMeta = buildMeta, - ) + private val featureFlagService = AlwaysEnabledFeatureFlagService() private val roomListRoomSummaryFactory = RoomListRoomSummaryFactory( lastMessageTimestampFormatter = DefaultLastMessageTimestampFormatter( localDateTimeProvider = dateTimeProvider, @@ -191,25 +181,4 @@ class RoomListScreen( } } } - - private fun getBuildMeta(context: Context): BuildMeta { - val buildType = BuildType.valueOf(BuildConfig.BUILD_TYPE.uppercase()) - val name = context.getString(R.string.app_name) - return BuildMeta( - isDebuggable = BuildConfig.DEBUG, - buildType = buildType, - applicationName = name, - productionApplicationName = name, - desktopApplicationName = name, - applicationId = BuildConfig.APPLICATION_ID, - lowPrivacyLoggingEnabled = false, - versionName = BuildConfig.VERSION_NAME, - versionCode = BuildConfig.VERSION_CODE.toLong(), - gitRevision = "", - gitBranchName = "", - flavorDescription = "", - flavorShortDescription = "", - isEnterpriseBuild = false, - ) - } } From dac3c7285a61809fe0297dee2cdc0ef4c41c3c7e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 15:06:50 +0200 Subject: [PATCH 008/106] version++ --- plugins/src/main/kotlin/Versions.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index bfcfe937ff..0ea95396de 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -42,12 +42,12 @@ import org.gradle.jvm.toolchain.JavaLanguageVersion // Note: 2 digits max for each value private const val versionMajor = 0 -private const val versionMinor = 5 +private const val versionMinor = 6 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -private const val versionPatch = 4 +private const val versionPatch = 1 object Versions { val versionCode = 4_000_000 + versionMajor * 1_00_00 + versionMinor * 1_00 + versionPatch From ab5793ce75325fae4f2eb78f8eb783e7ac437e16 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 16:13:29 +0200 Subject: [PATCH 009/106] Changelog for version 0.6.0 --- CHANGES.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 2097277556..0cd6932883 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,22 @@ +Changes in Element X v0.6.0 (2024-09-12) +======================================== + +### 🙌 Improvements +* Enables pinned messages feature by default. by @ganfra in https://github.com/element-hq/element-x-android/pull/3439 +* Pinned messages list : hide reactions by @ganfra in https://github.com/element-hq/element-x-android/pull/3430 + +### 🐛 Bugfixes +* Feature/fga/pinned messages fix timeline provider by @ganfra in https://github.com/element-hq/element-x-android/pull/3432 + +### Dependency upgrades +* Update activity to v1.9.2 by @renovate in https://github.com/element-hq/element-x-android/pull/3397 +* Update peter-evans/create-pull-request action to v7 by @renovate in https://github.com/element-hq/element-x-android/pull/3383 +* Rust sdk upgrade to 0.2.43 by @bmarty in https://github.com/element-hq/element-x-android/pull/3446 + +### Others +* DeviceId and cleanup. by @bmarty in https://github.com/element-hq/element-x-android/pull/3442 +* Update application store assets by @bmarty in https://github.com/element-hq/element-x-android/pull/3441 + Changes in Element X v0.5.3 (2024-09-10) ======================================== From e4d1428bed09b1098f7a0f289e5aa7c1d48a5ad9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 16:27:52 +0200 Subject: [PATCH 010/106] Rename `isInit` to `isTimelineInitialized` for clarity. --- .../matrix/impl/timeline/RustTimeline.kt | 18 +++++++++++------- .../impl/timeline/TimelineItemsSubscriber.kt | 6 +++--- .../LastForwardIndicatorsPostProcessor.kt | 4 ++-- .../LoadingIndicatorsPostProcessor.kt | 4 ++-- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt index 4694548b93..1fa43c4e7c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt @@ -86,7 +86,7 @@ class RustTimeline( onNewSyncedEvent: () -> Unit, ) : Timeline { private val initLatch = CompletableDeferred() - private val isInit = MutableStateFlow(false) + private val isTimelineInitialized = MutableStateFlow(false) private val _timelineItems: MutableStateFlow> = MutableStateFlow(emptyList()) @@ -110,7 +110,7 @@ class RustTimeline( timelineCoroutineScope = coroutineScope, timelineDiffProcessor = timelineDiffProcessor, initLatch = initLatch, - isInit = isInit, + isTimelineInitialized = isTimelineInitialized, dispatcher = dispatcher, onNewSyncedEvent = onNewSyncedEvent, ) @@ -189,7 +189,7 @@ class RustTimeline( } private fun canPaginate(direction: Timeline.PaginationDirection): Boolean { - if (!isInit.value) return false + if (!isTimelineInitialized.value) return false return when (direction) { Timeline.PaginationDirection.BACKWARDS -> backPaginationStatus.value.canPaginate Timeline.PaginationDirection.FORWARDS -> forwardPaginationStatus.value.canPaginate @@ -208,8 +208,12 @@ class RustTimeline( backPaginationStatus.map { it.hasMoreToLoad }.distinctUntilChanged(), forwardPaginationStatus.map { it.hasMoreToLoad }.distinctUntilChanged(), matrixRoom.roomInfoFlow.map { it.creator }, - isInit, - ) { timelineItems, hasMoreToLoadBackward, hasMoreToLoadForward, roomCreator, isInit -> + isTimelineInitialized, + ) { timelineItems, + hasMoreToLoadBackward, + hasMoreToLoadForward, + roomCreator, + isTimelineInitialized -> withContext(dispatcher) { timelineItems .let { items -> @@ -223,7 +227,7 @@ class RustTimeline( .let { items -> loadingIndicatorsPostProcessor.process( items = items, - isInit = isInit, + isTimelineInitialized = isTimelineInitialized, hasMoreToLoadBackward = hasMoreToLoadBackward, hasMoreToLoadForward = hasMoreToLoadForward ) @@ -232,7 +236,7 @@ class RustTimeline( .let { items -> lastForwardIndicatorsPostProcessor.process( items = items, - isInit = isInit, + isTimelineInitialized = isTimelineInitialized, ) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriber.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriber.kt index 0269c48bae..5e9c6ac37a 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriber.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriber.kt @@ -38,7 +38,7 @@ internal class TimelineItemsSubscriber( private val timeline: Timeline, private val timelineDiffProcessor: MatrixTimelineDiffProcessor, private val initLatch: CompletableDeferred, - private val isInit: MutableStateFlow, + private val isTimelineInitialized: MutableStateFlow, private val onNewSyncedEvent: () -> Unit, ) { private var subscriptionCount = 0 @@ -85,13 +85,13 @@ internal class TimelineItemsSubscriber( ensureActive() timelineDiffProcessor.postItems(it) } - isInit.value = true + isTimelineInitialized.value = true initLatch.complete(Unit) } private suspend fun postDiffs(diffs: List) { val diffsToProcess = diffs.toMutableList() - if (!isInit.value) { + if (!isTimelineInitialized.value) { val resetDiff = diffsToProcess.firstOrNull { it.change() == TimelineChange.RESET } if (resetDiff != null) { // Keep using the postItems logic so we can post the timelineItems asap. diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessor.kt index 441aa8149a..7f89c40a0e 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessor.kt @@ -22,9 +22,9 @@ class LastForwardIndicatorsPostProcessor( fun process( items: List, - isInit: Boolean, + isTimelineInitialized: Boolean, ): List { - if (!isInit) return items + if (!isTimelineInitialized) return items // We don't need to add the last forward indicator if we are not in the FOCUSED_ON_EVENT mode if (mode != Timeline.Mode.FOCUSED_ON_EVENT) { return items diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt index cc6e851954..216ccd6f89 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessor.kt @@ -16,11 +16,11 @@ import io.element.android.services.toolbox.api.systemclock.SystemClock class LoadingIndicatorsPostProcessor(private val systemClock: SystemClock) { fun process( items: List, - isInit: Boolean, + isTimelineInitialized: Boolean, hasMoreToLoadBackward: Boolean, hasMoreToLoadForward: Boolean, ): List { - if (!isInit) return items + if (!isTimelineInitialized) return items val shouldAddForwardLoadingIndicator = hasMoreToLoadForward && items.isNotEmpty() val currentTimestamp = systemClock.epochMillis() return buildList { From d22d9f0bd2a7871dcc9cdfea2bba6b246db3d952 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 12 Sep 2024 17:20:49 +0200 Subject: [PATCH 011/106] Send failure verified user : set the room key recipient strategy --- .../android/libraries/matrix/impl/RustMatrixClientFactory.kt | 3 +++ 1 file changed, 3 insertions(+) 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 7681dda6f0..d29a233aa1 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 @@ -60,6 +60,9 @@ class RustMatrixClientFactory @Inject constructor( .homeserverUrl(sessionData.homeserverUrl) .username(sessionData.userId) .setSessionDelegate(sessionDelegate) + .roomKeyRecipientStrategy( + strategy = CollectStrategy.DeviceBasedStrategy(false, true) + ) .use { it.build() } client.restoreSession(sessionData.toSession()) From b2c7ea02fbccbe82a5509bff61dbb5659dc9f682 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 12 Sep 2024 17:21:19 +0200 Subject: [PATCH 012/106] Design : allow passing ListItemColor to ListItem composable to customise as you want. --- .../designsystem/theme/components/ListItem.kt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) 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 25f5009299..3e2fd6dcd5 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 @@ -65,7 +65,41 @@ fun ListItem( disabledLeadingIconColor = ListItemDefaultColors.iconDisabled, disabledTrailingIconColor = ListItemDefaultColors.iconDisabled, ) + ListItem( + headlineContent = headlineContent, + modifier = modifier, + supportingContent = supportingContent, + leadingContent = leadingContent, + trailingContent = trailingContent, + colors = colors, + enabled = enabled, + onClick = onClick, + ) +} +/** + * 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 colors The colors to use for the list item. + * @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 onClick The callback to be called when the list item is clicked. + */ +@Suppress("LongParameterList") +@Composable +fun ListItem( + headlineContent: @Composable () -> Unit, + colors: ListItemColors, + modifier: Modifier = Modifier, + supportingContent: @Composable (() -> Unit)? = null, + leadingContent: ListItemContent? = null, + trailingContent: ListItemContent? = null, + enabled: Boolean = true, + onClick: (() -> Unit)? = null, +) { // We cannot just pass the disabled colors, they must be set manually: https://issuetracker.google.com/issues/280480132 val headlineColor = if (enabled) colors.headlineColor else colors.disabledHeadlineColor val leadingContentColor = if (enabled) colors.leadingIconColor else colors.disabledLeadingIconColor From e0bc026d5fe18ff0fad12d293c93f4bc36583ad4 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 12 Sep 2024 17:24:01 +0200 Subject: [PATCH 013/106] Send failure verified user : display in ActionListView --- .../features/messages/impl/MessagesView.kt | 3 ++ .../impl/actionlist/ActionListPresenter.kt | 35 +++++++++++-- .../impl/actionlist/ActionListState.kt | 21 ++++++++ .../actionlist/ActionListStateProvider.kt | 20 ++++++++ .../impl/actionlist/ActionListView.kt | 50 +++++++++++++++++++ .../pinned/list/PinnedMessagesListView.kt | 1 + .../src/main/res/values/localazy.xml | 9 ++++ 7 files changed, 136 insertions(+), 3 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index 8eabf156af..05329c3fea 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 @@ -241,6 +241,9 @@ fun MessagesView( state.customReactionState.eventSink(CustomReactionEvents.ShowCustomReactionSheet(event)) }, onEmojiReactionClick = ::onEmojiReactionClick, + onVerifiedUserSendFailureClick = { event -> + + } ) CustomReactionBottomSheet( 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 840e12583f..802fdbf9ed 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 @@ -36,6 +36,7 @@ import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.di.RoomScope import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.preferences.api.store.AppPreferencesStore import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -115,12 +116,14 @@ class DefaultActionListPresenter @AssistedInject constructor( isEventPinned = pinnedEventIds.contains(timelineItem.eventId), ) - val displayEmojiReactions = usersEventPermissions.canSendReaction && - timelineItem.content.canReact() - if (actions.isNotEmpty() || displayEmojiReactions) { + val verifiedUserSendFailure = buildVerifiedUserSendFailure(timelineItem) + val displayEmojiReactions = usersEventPermissions.canSendReaction && timelineItem.content.canReact() + + if (actions.isNotEmpty() || displayEmojiReactions || verifiedUserSendFailure != ActionListState.VerifiedUserSendFailure.None) { target.value = ActionListState.Target.Success( event = timelineItem, displayEmojiReactions = displayEmojiReactions, + verifiedUserSendFailure = verifiedUserSendFailure, actions = actions.toImmutableList() ) } else { @@ -128,6 +131,32 @@ class DefaultActionListPresenter @AssistedInject constructor( } } + private suspend fun buildVerifiedUserSendFailure( + timelineItem: TimelineItem.Event, + ): ActionListState.VerifiedUserSendFailure { + return when (val sendState = timelineItem.localSendState) { + is LocalEventSendState.Failed.VerifiedUserHasUnsignedDevice -> { + val userId = sendState.devices.keys.firstOrNull() + if (userId == null) { + ActionListState.VerifiedUserSendFailure.None + } else { + val displayName = room.userDisplayName(userId).getOrNull() ?: userId.value + ActionListState.VerifiedUserSendFailure.UnsignedDevice(displayName) + } + } + is LocalEventSendState.Failed.VerifiedUserChangedIdentity -> { + val userId = sendState.users.firstOrNull() + if (userId == null) { + ActionListState.VerifiedUserSendFailure.None + } else { + val displayName = room.userDisplayName(userId).getOrNull() ?: userId.value + ActionListState.VerifiedUserSendFailure.ChangedIdentity(displayName) + } + } + else -> ActionListState.VerifiedUserSendFailure.None + } + } + private fun buildActions( timelineItem: TimelineItem.Event, usersEventPermissions: UserEventPermissions, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListState.kt index bb3bd92fbe..614dcd3776 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListState.kt @@ -7,9 +7,12 @@ package io.element.android.features.messages.impl.actionlist +import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable +import androidx.compose.ui.res.stringResource import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList @Immutable @@ -17,13 +20,31 @@ data class ActionListState( val target: Target, val eventSink: (ActionListEvents) -> Unit, ) { + @Immutable sealed interface Target { data object None : Target data class Loading(val event: TimelineItem.Event) : Target data class Success( val event: TimelineItem.Event, val displayEmojiReactions: Boolean, + val verifiedUserSendFailure: VerifiedUserSendFailure, val actions: ImmutableList, ) : Target } + + @Immutable + sealed interface VerifiedUserSendFailure { + data object None : VerifiedUserSendFailure + data class UnsignedDevice(val displayName: String) : VerifiedUserSendFailure + data class ChangedIdentity(val displayName: String) : VerifiedUserSendFailure + + @Composable + fun formatted(): String { + return when (this) { + is None -> "" + is UnsignedDevice -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_unsigned_device, displayName) + is ChangedIdentity -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_changed_identity, displayName) + } + } + } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt index 722d8af11e..e53f3f11b2 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt @@ -18,6 +18,8 @@ import io.element.android.features.messages.impl.timeline.model.event.aTimelineI import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent 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.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -35,6 +37,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = true, + verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ) ), @@ -47,6 +50,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState, ), displayEmojiReactions = true, + verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ) ), @@ -56,6 +60,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = true, + verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ) ), @@ -65,6 +70,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = true, + verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ) ), @@ -74,6 +80,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = true, + verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ) ), @@ -83,6 +90,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = true, + verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ) ), @@ -92,6 +100,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = true, + verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ) ), @@ -101,6 +110,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = false, + verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ), ), @@ -110,6 +120,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = false, + verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, actions = aTimelineItemPollActionList(), ), ), @@ -120,6 +131,15 @@ open class ActionListStateProvider : PreviewParameterProvider { messageShield = MessageShield.UnknownDevice(isCritical = true) ), displayEmojiReactions = true, + verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, + actions = aTimelineItemActionList(), + ) + ), + anActionListState().copy( + target = ActionListState.Target.Success( + event = aTimelineItemEvent(), + displayEmojiReactions = true, + verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.UnsignedDevice(displayName = "Alice"), actions = aTimelineItemActionList(), ) ), 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 8316bddb32..e56a1e63f5 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 @@ -27,6 +27,7 @@ import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.ripple.rememberRipple import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ListItemDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable @@ -90,6 +91,7 @@ fun ActionListView( onSelectAction: (action: TimelineItemAction, TimelineItem.Event) -> Unit, onEmojiReactionClick: (String, TimelineItem.Event) -> Unit, onCustomReactionClick: (TimelineItem.Event) -> Unit, + onVerifiedUserSendFailureClick: (TimelineItem.Event) -> Unit, modifier: Modifier = Modifier, ) { val sheetState = rememberModalBottomSheetState() @@ -126,6 +128,14 @@ fun ActionListView( state.eventSink(ActionListEvents.Clear) } + fun onVerifiedUserSendFailureClick() { + if (targetItem == null) return + sheetState.hide(coroutineScope) { + state.eventSink(ActionListEvents.Clear) + onVerifiedUserSendFailureClick(targetItem) + } + } + if (targetItem != null) { ModalBottomSheet( sheetState = sheetState, @@ -137,6 +147,7 @@ fun ActionListView( onActionClick = ::onItemActionClick, onEmojiReactionClick = ::onEmojiReactionClick, onCustomReactionClick = ::onCustomReactionClick, + onVerifiedUserSendFailureClick = ::onVerifiedUserSendFailureClick, modifier = Modifier .navigationBarsPadding() .imePadding() @@ -151,6 +162,7 @@ private fun SheetContent( onActionClick: (TimelineItemAction) -> Unit, onEmojiReactionClick: (String) -> Unit, onCustomReactionClick: () -> Unit, + onVerifiedUserSendFailureClick: () -> Unit, modifier: Modifier = Modifier, ) { when (val target = state.target) { @@ -184,6 +196,16 @@ private fun SheetContent( HorizontalDivider() } } + if (target.verifiedUserSendFailure != ActionListState.VerifiedUserSendFailure.None) { + item { + VerifiedUserSendFailureView( + sendFailure = target.verifiedUserSendFailure, + modifier = Modifier.fillMaxWidth(), + onClick = onVerifiedUserSendFailureClick + ) + HorizontalDivider() + } + } if (target.displayEmojiReactions) { item { EmojiReactionsRow( @@ -338,6 +360,33 @@ private fun EmojiReactionsRow( } } +@Composable +private fun VerifiedUserSendFailureView( + sendFailure: ActionListState.VerifiedUserSendFailure, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + ListItem( + modifier = modifier + .clickable(onClick = onClick) + .padding(horizontal = 16.dp, vertical = 8.dp), + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Error())), + trailingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ChevronRight())), + headlineContent = { + Text( + text = sendFailure.formatted(), + style = ElementTheme.typography.fontBodySmMedium, + ) + }, + colors = ListItemDefaults.colors( + containerColor = Color.Transparent, + leadingIconColor = ElementTheme.colors.iconCriticalPrimary, + trailingIconColor = ElementTheme.colors.iconPrimary, + headlineColor = ElementTheme.colors.textCriticalPrimary, + ), + ) +} + @Composable private fun EmojiButton( emoji: String, @@ -387,5 +436,6 @@ internal fun SheetContentPreview( onActionClick = {}, onEmojiReactionClick = {}, onCustomReactionClick = {}, + onVerifiedUserSendFailureClick = {}, ) } 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 8a03ed857c..f853b7c971 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 @@ -181,6 +181,7 @@ private fun PinnedMessagesListLoaded( onSelectAction = ::onActionSelected, onCustomReactionClick = {}, onEmojiReactionClick = { _, _ -> }, + onVerifiedUserSendFailureClick = {} ) LazyColumn( modifier = modifier.fillMaxSize(), diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index f7c3213ba4..b4fec91a0c 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -36,6 +36,7 @@ "Back" "Call" "Cancel" + "Cancel for now" "Choose photo" "Clear" "Close" @@ -283,6 +284,12 @@ Reason: %1$s." "Pinned messages" "You\'re about to go to your %1$s account to reset your identity. Afterwards you\'ll be taken back to the app." "Can\'t confirm? Go to your account to reset your identity." + "Withdraw verification and send" + "You can withdraw your verification and send this message anyway, or you can cancel for now and try again later after reverifying %1$s." + "Your message was not sent because %1$s’s verified identity has changed" + "Send message anyway" + "%1$s is using one or more unverified devices. You can send the message anyway, or you can cancel for now and try again later after %2$s has verified all their devices." + "Your message was not sent because %1$s has not verified one or more devices" "Pinned messages" "Failed processing media to upload, please try again." "Could not retrieve user details" @@ -304,6 +311,8 @@ Reason: %1$s." "Open in Google Maps" "Open in OpenStreetMap" "Share this location" + "Message not sent because %1$s’s verified identity has changed." + "Message not sent because %1$s has not verified one or more devices." "Location" "Version: %1$s (%2$s)" "en" From de933b1f3403c938ed180acc1440dad98cb702b2 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 12 Sep 2024 19:06:19 +0200 Subject: [PATCH 014/106] Send failure verified user : expose new methods on MatrixRoom. --- .../libraries/matrix/api/room/MatrixRoom.kt | 5 +++++ .../matrix/impl/room/RustMatrixRoom.kt | 21 +++++++++++++++++-- .../matrix/test/room/FakeMatrixRoom.kt | 14 ++++++++++++- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 2d8c807ce0..25340684d6 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -7,6 +7,7 @@ package io.element.android.libraries.matrix.api.room +import io.element.android.libraries.matrix.api.core.DeviceId import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomAlias @@ -349,5 +350,9 @@ interface MatrixRoom : Closeable { */ suspend fun clearComposerDraft(): Result + suspend fun ignoreDeviceTrustAndResend(devices: Map>, transactionId: TransactionId): Result + suspend fun withdrawVerificationAndResend(userIds: List, transactionId: TransactionId): Result + override fun close() = destroy() + } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index aad3777071..381063f0e1 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -459,8 +459,8 @@ class RustMatrixRoom( return liveTimeline.forwardEvent(eventId, roomIds) } - override suspend fun retrySendMessage(transactionId: TransactionId): Result { - return Result.failure(UnsupportedOperationException("Not supported")) + override suspend fun retrySendMessage(transactionId: TransactionId): Result = runCatching { + innerRoom.tryResend(transactionId.value) } override suspend fun cancelSend(transactionId: TransactionId): Result { @@ -645,6 +645,23 @@ class RustMatrixRoom( innerRoom.clearComposerDraft() } + override suspend fun ignoreDeviceTrustAndResend(devices: Map>, transactionId: TransactionId) = runCatching { + innerRoom.ignoreDeviceTrustAndResend( + devices = devices + .entries.associate { entry -> + entry.key.value to entry.value.map { it.value } + }, + transactionId = transactionId.value + ) + } + + override suspend fun withdrawVerificationAndResend(userIds: List, transactionId: TransactionId) = runCatching { + innerRoom.withdrawVerificationAndResend( + userIds = userIds.map { it.value }, + transactionId = transactionId.value + ) + } + private fun createTimeline( timeline: InnerTimeline, mode: Timeline.Mode, diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 4f35c37d4d..2290897f11 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -7,6 +7,7 @@ package io.element.android.libraries.matrix.test.room +import io.element.android.libraries.matrix.api.core.DeviceId import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.ProgressCallback import io.element.android.libraries.matrix.api.core.RoomAlias @@ -134,7 +135,10 @@ class FakeMatrixRoom( private val loadComposerDraftLambda: () -> Result = { Result.success(null) }, private val clearComposerDraftLambda: () -> Result = { Result.success(Unit) }, private val subscribeToSyncLambda: () -> Unit = { lambdaError() }, -) : MatrixRoom { + private val ignoreDeviceTrustAndResendResult: (Map>, TransactionId) -> Result = { _, _ -> lambdaError() }, + private val withdrawVerificationAndResendResult: (List, TransactionId) -> Result = { _, _ -> lambdaError() }, + + ) : MatrixRoom { private val _roomInfoFlow: MutableSharedFlow = MutableSharedFlow(replay = 1) override val roomInfoFlow: Flow = _roomInfoFlow @@ -492,6 +496,14 @@ class FakeMatrixRoom( return getWidgetDriverResult(widgetSettings) } + override suspend fun ignoreDeviceTrustAndResend(devices: Map>, transactionId: TransactionId): Result { + return ignoreDeviceTrustAndResendResult(devices, transactionId) + } + + override suspend fun withdrawVerificationAndResend(userIds: List, transactionId: TransactionId): Result { + return withdrawVerificationAndResendResult(userIds, transactionId) + } + fun givenRoomMembersState(state: MatrixRoomMembersState) { membersStateFlow.value = state } From 416810accad293d5f053385a2b89981c81e9ac5f Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 13 Sep 2024 11:43:41 +0200 Subject: [PATCH 015/106] Send state : introduce Failed.VerifiedUser interface. --- .../api/timeline/item/event/LocalEventSendState.kt | 10 +++++++--- .../timeline/item/event/EventTimelineItemMapper.kt | 5 ++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/LocalEventSendState.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/LocalEventSendState.kt index 92242faf18..452073bb25 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/LocalEventSendState.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/LocalEventSendState.kt @@ -8,6 +8,7 @@ package io.element.android.libraries.matrix.api.timeline.item.event import androidx.compose.runtime.Immutable +import io.element.android.libraries.matrix.api.core.DeviceId import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UserId @@ -18,21 +19,24 @@ sealed interface LocalEventSendState { data class Unknown(val error: String) : Failed data object CrossSigningNotSetup : Failed data object SendingFromUnverifiedDevice : Failed + + sealed interface VerifiedUser : Failed data class VerifiedUserHasUnsignedDevice( /** * The unsigned devices belonging to verified users. A map from user ID * to a list of device IDs. */ - val devices: Map> - ) : Failed + val devices: Map> + ) : VerifiedUser data class VerifiedUserChangedIdentity( /** * The users that were previously verified but are no longer. */ val users: List - ) : Failed + ) : VerifiedUser } + data class Sent( val eventId: EventId ) : LocalEventSendState 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 5f170c9387..f83d6d0672 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 @@ -7,6 +7,7 @@ package io.element.android.libraries.matrix.impl.timeline.item.event +import io.element.android.libraries.matrix.api.core.DeviceId import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.TransactionId import io.element.android.libraries.matrix.api.core.UserId @@ -87,7 +88,9 @@ fun RustEventSendState?.map(): LocalEventSendState? { } is RustEventSendState.VerifiedUserHasUnsignedDevice -> { LocalEventSendState.Failed.VerifiedUserHasUnsignedDevice( - devices = devices.mapKeys { UserId(it.key) } + devices = devices.entries.associate { entry -> + UserId(entry.key) to entry.value.map { DeviceId(it) } + } ) } EventSendState.CrossSigningNotSetup -> LocalEventSendState.Failed.CrossSigningNotSetup From ff368b407220c95d06c2d4d49af5084ffb58e2df Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 13 Sep 2024 11:44:19 +0200 Subject: [PATCH 016/106] Send failure verified user : resolve ui and logic --- .../messages/impl/MessagesPresenter.kt | 4 + .../features/messages/impl/MessagesState.kt | 2 + .../messages/impl/MessagesStateProvider.kt | 4 + .../features/messages/impl/MessagesView.kt | 8 +- .../impl/actionlist/ActionListPresenter.kt | 34 +- .../impl/actionlist/ActionListState.kt | 20 +- .../actionlist/ActionListStateProvider.kt | 26 +- .../impl/actionlist/ActionListView.kt | 19 +- .../sendfailure/VerifiedUserSendFailure.kt | 23 ++ .../VerifiedUserSendFailureFactory.kt | 42 +++ .../ResolveVerifiedUserSendFailureEvents.kt | 20 + ...ResolveVerifiedUserSendFailurePresenter.kt | 95 +++++ .../ResolveVerifiedUserSendFailureState.kt | 18 + ...lveVerifiedUserSendFailureStateProvider.kt | 45 +++ .../ResolveVerifiedUserSendFailureView.kt | 156 ++++++++ .../VerifiedUserSendFailureIterator.kt | 60 +++ .../VerifiedUserSendFailureResolver.kt | 64 ++++ .../messages/impl/di/MessagesModule.kt | 5 + .../messages/impl/MessagesPresenterTest.kt | 2 + .../messages/impl/MessagesViewTest.kt | 34 ++ .../actionlist/ActionListPresenterTest.kt | 52 ++- ...lveVerifiedUserSendFailurePresenterTest.kt | 353 ++++++++++++++++++ .../ResolveVerifiedUserSendFailureViewTest.kt | 61 +++ .../atomic/atoms/RoundedIconAtom.kt | 6 +- .../molecules/IconTitleSubtitleMolecule.kt | 4 + .../designsystem/theme/components/ListItem.kt | 12 +- .../libraries/matrix/api/room/MatrixRoom.kt | 1 - .../matrix/impl/room/RustMatrixRoom.kt | 7 +- .../matrix/test/room/FakeMatrixRoom.kt | 11 +- 29 files changed, 1103 insertions(+), 85 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureEvents.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenter.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureState.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureIterator.kt create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureResolver.kt create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureViewTest.kt 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 5284af15a5..f657fb6393 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 @@ -30,6 +30,7 @@ import io.element.android.features.messages.impl.actionlist.ActionListEvents import io.element.android.features.messages.impl.actionlist.ActionListPresenter import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter import io.element.android.features.messages.impl.messagecomposer.MessageComposerState @@ -95,6 +96,7 @@ class MessagesPresenter @AssistedInject constructor( private val reactionSummaryPresenter: ReactionSummaryPresenter, private val readReceiptBottomSheetPresenter: ReadReceiptBottomSheetPresenter, private val pinnedMessagesBannerPresenter: Presenter, + private val resolveVerifiedUserSendFailurePresenter: Presenter, private val networkMonitor: NetworkMonitor, private val snackbarDispatcher: SnackbarDispatcher, private val dispatchers: CoroutineDispatchers, @@ -128,6 +130,7 @@ class MessagesPresenter @AssistedInject constructor( val reactionSummaryState = reactionSummaryPresenter.present() val readReceiptBottomSheetState = readReceiptBottomSheetPresenter.present() val pinnedMessagesBannerState = pinnedMessagesBannerPresenter.present() + val resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailurePresenter.present() val syncUpdateFlow = room.syncUpdateFlow.collectAsState() @@ -227,6 +230,7 @@ class MessagesPresenter @AssistedInject constructor( appName = buildMeta.applicationName, callState = callState, pinnedMessagesBannerState = pinnedMessagesBannerState, + resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, eventSink = { handleEvents(it) } ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt index 546e558ba8..c3b4b9183e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt @@ -9,6 +9,7 @@ package io.element.android.features.messages.impl import androidx.compose.runtime.Immutable import io.element.android.features.messages.impl.actionlist.ActionListState +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.messagecomposer.MessageComposerState import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState import io.element.android.features.messages.impl.timeline.TimelineState @@ -47,6 +48,7 @@ data class MessagesState( val callState: RoomCallState, val appName: String, val pinnedMessagesBannerState: PinnedMessagesBannerState, + val resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState, val eventSink: (MessagesEvents) -> Unit ) 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 96e55aac91..cc651bc978 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 @@ -10,6 +10,8 @@ package io.element.android.features.messages.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.messages.impl.actionlist.ActionListState import io.element.android.features.messages.impl.actionlist.anActionListState +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.aResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.messagecomposer.AttachmentsState import io.element.android.features.messages.impl.messagecomposer.MessageComposerState import io.element.android.features.messages.impl.messagecomposer.aMessageComposerState @@ -113,6 +115,7 @@ fun aMessagesState( enableVoiceMessages: Boolean = true, callState: RoomCallState = RoomCallState.ENABLED, pinnedMessagesBannerState: PinnedMessagesBannerState = aLoadedPinnedMessagesBannerState(), + resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState = aResolveVerifiedUserSendFailureState(), eventSink: (MessagesEvents) -> Unit = {}, ) = MessagesState( roomId = RoomId("!id:domain"), @@ -137,6 +140,7 @@ fun aMessagesState( callState = callState, appName = "Element", pinnedMessagesBannerState = pinnedMessagesBannerState, + resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, 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 05329c3fea..d56ef675c3 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 @@ -57,6 +57,8 @@ import io.element.android.features.messages.impl.actionlist.ActionListEvents import io.element.android.features.messages.impl.actionlist.ActionListView import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.attachments.Attachment +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureEvents +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureView import io.element.android.features.messages.impl.messagecomposer.AttachmentsBottomSheet import io.element.android.features.messages.impl.messagecomposer.AttachmentsState import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents @@ -242,8 +244,12 @@ fun MessagesView( }, onEmojiReactionClick = ::onEmojiReactionClick, onVerifiedUserSendFailureClick = { event -> + state.resolveVerifiedUserSendFailureState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(event)) + }, + ) - } + ResolveVerifiedUserSendFailureView( + state = state.resolveVerifiedUserSendFailureState, ) CustomReactionBottomSheet( 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 802fdbf9ed..88b7128b76 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 @@ -22,6 +22,8 @@ import io.element.android.features.messages.api.pinned.IsPinnedMessagesFeatureEn import io.element.android.features.messages.impl.UserEventPermissions import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailureFactory import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.TimelineItemCallNotifyContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent @@ -36,7 +38,6 @@ import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.di.RoomScope import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.MatrixRoom -import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.preferences.api.store.AppPreferencesStore import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -57,6 +58,7 @@ class DefaultActionListPresenter @AssistedInject constructor( private val appPreferencesStore: AppPreferencesStore, private val isPinnedMessagesFeatureEnabled: IsPinnedMessagesFeatureEnabled, private val room: MatrixRoom, + private val userSendFailureFactory: VerifiedUserSendFailureFactory, ) : ActionListPresenter { @AssistedFactory @ContributesBinding(RoomScope::class) @@ -116,10 +118,10 @@ class DefaultActionListPresenter @AssistedInject constructor( isEventPinned = pinnedEventIds.contains(timelineItem.eventId), ) - val verifiedUserSendFailure = buildVerifiedUserSendFailure(timelineItem) + val verifiedUserSendFailure = userSendFailureFactory.create(timelineItem.localSendState) val displayEmojiReactions = usersEventPermissions.canSendReaction && timelineItem.content.canReact() - if (actions.isNotEmpty() || displayEmojiReactions || verifiedUserSendFailure != ActionListState.VerifiedUserSendFailure.None) { + if (actions.isNotEmpty() || displayEmojiReactions || verifiedUserSendFailure != VerifiedUserSendFailure.None) { target.value = ActionListState.Target.Success( event = timelineItem, displayEmojiReactions = displayEmojiReactions, @@ -131,32 +133,6 @@ class DefaultActionListPresenter @AssistedInject constructor( } } - private suspend fun buildVerifiedUserSendFailure( - timelineItem: TimelineItem.Event, - ): ActionListState.VerifiedUserSendFailure { - return when (val sendState = timelineItem.localSendState) { - is LocalEventSendState.Failed.VerifiedUserHasUnsignedDevice -> { - val userId = sendState.devices.keys.firstOrNull() - if (userId == null) { - ActionListState.VerifiedUserSendFailure.None - } else { - val displayName = room.userDisplayName(userId).getOrNull() ?: userId.value - ActionListState.VerifiedUserSendFailure.UnsignedDevice(displayName) - } - } - is LocalEventSendState.Failed.VerifiedUserChangedIdentity -> { - val userId = sendState.users.firstOrNull() - if (userId == null) { - ActionListState.VerifiedUserSendFailure.None - } else { - val displayName = room.userDisplayName(userId).getOrNull() ?: userId.value - ActionListState.VerifiedUserSendFailure.ChangedIdentity(displayName) - } - } - else -> ActionListState.VerifiedUserSendFailure.None - } - } - private fun buildActions( timelineItem: TimelineItem.Event, usersEventPermissions: UserEventPermissions, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListState.kt index 614dcd3776..75c598df36 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListState.kt @@ -7,12 +7,10 @@ package io.element.android.features.messages.impl.actionlist -import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable -import androidx.compose.ui.res.stringResource import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure import io.element.android.features.messages.impl.timeline.model.TimelineItem -import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList @Immutable @@ -31,20 +29,4 @@ data class ActionListState( val actions: ImmutableList, ) : Target } - - @Immutable - sealed interface VerifiedUserSendFailure { - data object None : VerifiedUserSendFailure - data class UnsignedDevice(val displayName: String) : VerifiedUserSendFailure - data class ChangedIdentity(val displayName: String) : VerifiedUserSendFailure - - @Composable - fun formatted(): String { - return when (this) { - is None -> "" - is UnsignedDevice -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_unsigned_device, displayName) - is ChangedIdentity -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_changed_identity, displayName) - } - } - } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt index e53f3f11b2..4f92bc72ba 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt @@ -9,6 +9,8 @@ package io.element.android.features.messages.impl.actionlist import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.anUnsignedDeviceSendFailure import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineItemReactions import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemAudioContent @@ -18,8 +20,6 @@ import io.element.android.features.messages.impl.timeline.model.event.aTimelineI import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemPollContent 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.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -37,7 +37,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = true, - verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ) ), @@ -50,7 +50,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState, ), displayEmojiReactions = true, - verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ) ), @@ -60,7 +60,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = true, - verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ) ), @@ -70,7 +70,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = true, - verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ) ), @@ -80,7 +80,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = true, - verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ) ), @@ -90,7 +90,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = true, - verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ) ), @@ -100,7 +100,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = true, - verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ) ), @@ -110,7 +110,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = false, - verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ), ), @@ -120,7 +120,7 @@ open class ActionListStateProvider : PreviewParameterProvider { reactionsState = reactionsState ), displayEmojiReactions = false, - verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = aTimelineItemPollActionList(), ), ), @@ -131,7 +131,7 @@ open class ActionListStateProvider : PreviewParameterProvider { messageShield = MessageShield.UnknownDevice(isCritical = true) ), displayEmojiReactions = true, - verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.None, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = aTimelineItemActionList(), ) ), @@ -139,7 +139,7 @@ open class ActionListStateProvider : PreviewParameterProvider { target = ActionListState.Target.Success( event = aTimelineItemEvent(), displayEmojiReactions = true, - verifiedUserSendFailure = ActionListState.VerifiedUserSendFailure.UnsignedDevice(displayName = "Alice"), + verifiedUserSendFailure = anUnsignedDeviceSendFailure(), actions = aTimelineItemActionList(), ) ), 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 e56a1e63f5..8c950012db 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 @@ -47,6 +47,10 @@ 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.actionlist.model.TimelineItemAction +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure.ChangedIdentity +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure.None +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure.UnsignedDevice import io.element.android.features.messages.impl.timeline.components.MessageShieldView import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent @@ -196,7 +200,7 @@ private fun SheetContent( HorizontalDivider() } } - if (target.verifiedUserSendFailure != ActionListState.VerifiedUserSendFailure.None) { + if (target.verifiedUserSendFailure != None) { item { VerifiedUserSendFailureView( sendFailure = target.verifiedUserSendFailure, @@ -362,10 +366,19 @@ private fun EmojiReactionsRow( @Composable private fun VerifiedUserSendFailureView( - sendFailure: ActionListState.VerifiedUserSendFailure, + sendFailure: VerifiedUserSendFailure, onClick: () -> Unit, modifier: Modifier = Modifier, ) { + @Composable + fun VerifiedUserSendFailure.headline(): String { + return when (this) { + is None -> "" + is UnsignedDevice -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_unsigned_device, userDisplayName) + is ChangedIdentity -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_changed_identity, userDisplayName) + } + } + ListItem( modifier = modifier .clickable(onClick = onClick) @@ -374,7 +387,7 @@ private fun VerifiedUserSendFailureView( trailingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.ChevronRight())), headlineContent = { Text( - text = sendFailure.formatted(), + text = sendFailure.headline(), style = ElementTheme.typography.fontBodySmMedium, ) }, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt new file mode 100644 index 0000000000..e3c798f7df --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.sendfailure + +import androidx.compose.runtime.Immutable + +@Immutable +sealed interface VerifiedUserSendFailure { + data object None : VerifiedUserSendFailure + + data class UnsignedDevice( + val userDisplayName: String, + ) : VerifiedUserSendFailure + + data class ChangedIdentity( + val userDisplayName: String, + ) : VerifiedUserSendFailure +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt new file mode 100644 index 0000000000..de5817c909 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.sendfailure + +import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState +import javax.inject.Inject + +class VerifiedUserSendFailureFactory @Inject constructor( + private val room: MatrixRoom, +) { + suspend fun create( + sendState: LocalEventSendState?, + ): VerifiedUserSendFailure { + return when (sendState) { + is LocalEventSendState.Failed.VerifiedUserHasUnsignedDevice -> { + val userId = sendState.devices.keys.firstOrNull() + if (userId == null) { + VerifiedUserSendFailure.None + } else { + val displayName = room.userDisplayName(userId).getOrNull() ?: userId.value + VerifiedUserSendFailure.UnsignedDevice(displayName) + } + } + is LocalEventSendState.Failed.VerifiedUserChangedIdentity -> { + val userId = sendState.users.firstOrNull() + if (userId == null) { + VerifiedUserSendFailure.None + } else { + val displayName = room.userDisplayName(userId).getOrNull() ?: userId.value + VerifiedUserSendFailure.ChangedIdentity(displayName) + } + } + else -> VerifiedUserSendFailure.None + } + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureEvents.kt new file mode 100644 index 0000000000..7743ef9dcd --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureEvents.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.sendfailure.resolve + +import io.element.android.features.messages.impl.timeline.model.TimelineItem + +sealed interface ResolveVerifiedUserSendFailureEvents { + data class ComputeForMessage( + val messageEvent: TimelineItem.Event, + ) : ResolveVerifiedUserSendFailureEvents + + data object ResolveAndResend : ResolveVerifiedUserSendFailureEvents + data object Retry : ResolveVerifiedUserSendFailureEvents + data object Dismiss : ResolveVerifiedUserSendFailureEvents +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenter.kt new file mode 100644 index 0000000000..c96e695375 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenter.kt @@ -0,0 +1,95 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.sendfailure.resolve + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.produceState +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailureFactory +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.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState +import kotlinx.coroutines.launch +import javax.inject.Inject + +class ResolveVerifiedUserSendFailurePresenter @Inject constructor( + private val room: MatrixRoom, + private val verifiedUserSendFailureFactory: VerifiedUserSendFailureFactory, +) : Presenter { + @Composable + override fun present(): ResolveVerifiedUserSendFailureState { + var resolver by remember { + mutableStateOf(null) + } + val verifiedUserSendFailure by produceState(VerifiedUserSendFailure.None, resolver?.currentSendFailure?.value) { + val currentSendFailure = resolver?.currentSendFailure?.value + value = verifiedUserSendFailureFactory.create(currentSendFailure) + } + + val resolveAction = remember { + mutableStateOf>(AsyncAction.Uninitialized) + } + val retryAction = remember { + mutableStateOf>(AsyncAction.Uninitialized) + } + val coroutineScope = rememberCoroutineScope() + + fun handleEvents(event: ResolveVerifiedUserSendFailureEvents) { + when (event) { + is ResolveVerifiedUserSendFailureEvents.ComputeForMessage -> { + val sendState = event.messageEvent.localSendState as? LocalEventSendState.Failed.VerifiedUser + val transactionId = event.messageEvent.transactionId + resolver = if (sendState != null && transactionId != null) { + VerifiedUserSendFailureResolver( + room = room, + transactionId = transactionId, + iterator = VerifiedUserSendFailureIterator.from(sendState) + ) + } else { + null + } + } + ResolveVerifiedUserSendFailureEvents.Dismiss -> { + resolver = null + } + ResolveVerifiedUserSendFailureEvents.Retry -> { + coroutineScope.launch { + resolver?.run { + runUpdatingState(retryAction) { + resend() + } + } + } + } + ResolveVerifiedUserSendFailureEvents.ResolveAndResend -> { + coroutineScope.launch { + resolver?.run { + runUpdatingState(resolveAction) { + resolveAndResend() + } + } + } + } + } + } + + return ResolveVerifiedUserSendFailureState( + verifiedUserSendFailure = verifiedUserSendFailure, + resolveAction = resolveAction.value, + retryAction = retryAction.value, + eventSink = ::handleEvents + ) + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureState.kt new file mode 100644 index 0000000000..44ec6640b0 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureState.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.sendfailure.resolve + +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure +import io.element.android.libraries.architecture.AsyncAction + +data class ResolveVerifiedUserSendFailureState( + val verifiedUserSendFailure: VerifiedUserSendFailure, + val resolveAction: AsyncAction, + val retryAction: AsyncAction, + val eventSink: (ResolveVerifiedUserSendFailureEvents) -> Unit +) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt new file mode 100644 index 0000000000..1f8335b648 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.sendfailure.resolve + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure +import io.element.android.libraries.architecture.AsyncAction + +open class ResolveVerifiedUserSendFailureStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aResolveVerifiedUserSendFailureState(), + aResolveVerifiedUserSendFailureState( + verifiedUserSendFailure = anUnsignedDeviceSendFailure() + ), + aResolveVerifiedUserSendFailureState( + verifiedUserSendFailure = aChangedIdentitySendFailure() + ) + ) +} + +fun aResolveVerifiedUserSendFailureState( + verifiedUserSendFailure: VerifiedUserSendFailure = VerifiedUserSendFailure.None, + resolveAction: AsyncAction = AsyncAction.Uninitialized, + retryAction: AsyncAction = AsyncAction.Uninitialized, + eventSink: (ResolveVerifiedUserSendFailureEvents) -> Unit = {} +) = ResolveVerifiedUserSendFailureState( + verifiedUserSendFailure = verifiedUserSendFailure, + resolveAction = resolveAction, + retryAction = retryAction, + eventSink = eventSink +) + +fun anUnsignedDeviceSendFailure(userDisplayName: String = "Alice") = VerifiedUserSendFailure.UnsignedDevice( + userDisplayName = userDisplayName, +) + +fun aChangedIdentitySendFailure(userDisplayName: String = "Alice") = VerifiedUserSendFailure.ChangedIdentity( + userDisplayName = userDisplayName, +) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt new file mode 100644 index 0000000000..10c3236f46 --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt @@ -0,0 +1,156 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.sendfailure.resolve + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.rememberModalBottomSheetState +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 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.compound.tokens.generated.CompoundIcons +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure +import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule +import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule +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.ModalBottomSheet +import io.element.android.libraries.designsystem.theme.components.OutlinedButton +import io.element.android.libraries.designsystem.theme.components.TextButton +import io.element.android.libraries.ui.strings.CommonStrings + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ResolveVerifiedUserSendFailureView( + state: ResolveVerifiedUserSendFailureState, + modifier: Modifier = Modifier, +) { + val sheetState = rememberModalBottomSheetState() + var showSheet by remember { mutableStateOf(false) } + + fun dismiss() { + state.eventSink(ResolveVerifiedUserSendFailureEvents.Dismiss) + } + + fun onRetryClick() { + state.eventSink(ResolveVerifiedUserSendFailureEvents.Retry) + } + + fun onResolveAndResendClick() { + state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + } + + LaunchedEffect(state.verifiedUserSendFailure) { + if (state.verifiedUserSendFailure is VerifiedUserSendFailure.None) { + sheetState.hide() + showSheet = false + } else { + showSheet = true + } + } + + Box(modifier = modifier) { + if (showSheet) { + ModalBottomSheet( + modifier = Modifier + .systemBarsPadding() + .navigationBarsPadding(), + sheetState = sheetState, + onDismissRequest = ::dismiss, + ) { + IconTitleSubtitleMolecule( + modifier = Modifier.padding(24.dp), + title = state.verifiedUserSendFailure.title(), + subTitle = state.verifiedUserSendFailure.subtitle(), + iconImageVector = CompoundIcons.Error(), + iconTint = ElementTheme.colors.iconCriticalPrimary, + iconBackgroundTint = ElementTheme.colors.bgCriticalSubtle, + ) + ButtonColumnMolecule( + modifier = Modifier.padding(horizontal = 16.dp, vertical = 16.dp), + ) { + Button( + modifier = Modifier.fillMaxWidth(), + text = state.verifiedUserSendFailure.resolveAction(), + showProgress = state.resolveAction.isLoading(), + onClick = ::onResolveAndResendClick + ) + OutlinedButton( + modifier = Modifier.fillMaxWidth(), + text = stringResource(id = CommonStrings.action_retry), + showProgress = state.retryAction.isLoading(), + onClick = ::onRetryClick + ) + TextButton( + modifier = Modifier.fillMaxWidth(), + text = stringResource(id = CommonStrings.action_cancel_for_now), + onClick = ::dismiss, + ) + } + } + } + } +} + +@Composable +private fun VerifiedUserSendFailure.title(): String { + return when (this) { + is VerifiedUserSendFailure.UnsignedDevice -> stringResource(id = CommonStrings.screen_resolve_send_failure_unsigned_device_title, userDisplayName) + is VerifiedUserSendFailure.ChangedIdentity -> stringResource( + id = CommonStrings.screen_resolve_send_failure_changed_identity_title, + userDisplayName + ) + VerifiedUserSendFailure.None -> "" + } +} + +@Composable +private fun VerifiedUserSendFailure.subtitle(): String { + return when (this) { + is VerifiedUserSendFailure.UnsignedDevice -> stringResource( + id = CommonStrings.screen_resolve_send_failure_unsigned_device_subtitle, + userDisplayName, + userDisplayName, + ) + is VerifiedUserSendFailure.ChangedIdentity -> stringResource( + id = CommonStrings.screen_resolve_send_failure_changed_identity_subtitle, + userDisplayName + ) + VerifiedUserSendFailure.None -> "" + } +} + +@Composable +private fun VerifiedUserSendFailure.resolveAction(): String { + return when (this) { + is VerifiedUserSendFailure.UnsignedDevice -> stringResource(id = CommonStrings.screen_resolve_send_failure_unsigned_device_primary_button_title) + is VerifiedUserSendFailure.ChangedIdentity -> stringResource(id = CommonStrings.screen_resolve_send_failure_changed_identity_primary_button_title) + VerifiedUserSendFailure.None -> "" + } +} + +@PreviewsDayNight +@Composable +internal fun ResolveVerifiedUserSendFailureViewPreview( + @PreviewParameter(ResolveVerifiedUserSendFailureStateProvider::class) state: ResolveVerifiedUserSendFailureState +) = ElementPreview { + ResolveVerifiedUserSendFailureView(state) +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureIterator.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureIterator.kt new file mode 100644 index 0000000000..ccdcfb509b --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureIterator.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.sendfailure.resolve + +import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState + +/** + * Iterator for [LocalEventSendState.Failed.VerifiedUser] + * Allow to iterate through the internal state of the failure. + * This is useful to allow solving the failure step by step (e.g. for each user). + */ +interface VerifiedUserSendFailureIterator : Iterator { + companion object { + fun from(failure: LocalEventSendState.Failed.VerifiedUser): VerifiedUserSendFailureIterator { + return when (failure) { + is LocalEventSendState.Failed.VerifiedUserHasUnsignedDevice -> UnsignedDeviceSendFailureIterator(failure) + is LocalEventSendState.Failed.VerifiedUserChangedIdentity -> ChangedIdentitySendFailureIterator(failure) + } + } + } +} + +class UnsignedDeviceSendFailureIterator( + failure: LocalEventSendState.Failed.VerifiedUserHasUnsignedDevice +) : VerifiedUserSendFailureIterator { + private val iterator = failure.devices.iterator() + + override fun hasNext(): Boolean { + return iterator.hasNext() + } + + override fun next(): LocalEventSendState.Failed.VerifiedUser { + val (userId, deviceIds) = iterator.next() + return LocalEventSendState.Failed.VerifiedUserHasUnsignedDevice( + mapOf(userId to deviceIds) + ) + } +} + +class ChangedIdentitySendFailureIterator( + failure: LocalEventSendState.Failed.VerifiedUserChangedIdentity +) : VerifiedUserSendFailureIterator { + private val iterator = failure.users.iterator() + + override fun hasNext(): Boolean { + return iterator.hasNext() + } + + override fun next(): LocalEventSendState.Failed.VerifiedUser { + val userId = iterator.next() + return LocalEventSendState.Failed.VerifiedUserChangedIdentity( + listOf(userId) + ) + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureResolver.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureResolver.kt new file mode 100644 index 0000000000..0f6049b11f --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureResolver.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.sendfailure.resolve + +import androidx.compose.runtime.mutableStateOf +import io.element.android.libraries.matrix.api.core.TransactionId +import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState +import timber.log.Timber + +class VerifiedUserSendFailureResolver( + private val room: MatrixRoom, + private val transactionId: TransactionId, + private val iterator: VerifiedUserSendFailureIterator, +) { + val currentSendFailure = mutableStateOf(null) + + init { + if (iterator.hasNext()) { + currentSendFailure.value = iterator.next() + } + } + + suspend fun resend(): Result { + return room.retrySendMessage(transactionId) + .onSuccess { + Timber.d("Succeed to resend message with transactionId: $transactionId") + currentSendFailure.value = null + } + .onFailure { + Timber.e(it, "Failed to resend message with transactionId: $transactionId") + } + } + + suspend fun resolveAndResend(): Result { + return when (val failure = currentSendFailure.value) { + is LocalEventSendState.Failed.VerifiedUserHasUnsignedDevice -> { + room.ignoreDeviceTrustAndResend(failure.devices, transactionId) + } + is LocalEventSendState.Failed.VerifiedUserChangedIdentity -> { + room.withdrawVerificationAndResend(failure.users, transactionId) + } + else -> { + Result.failure(IllegalStateException("Unknown send failure type")) + } + }.onSuccess { + Timber.d("Succeed to resolve and resend message with transactionId: $transactionId") + if (iterator.hasNext()) { + val failure = iterator.next() + currentSendFailure.value = failure + } else { + currentSendFailure.value = null + Timber.d("No more failure to resolve for transactionId: $transactionId") + } + }.onFailure { + Timber.e(it, "Failed to resolve and resend message with transactionId: $transactionId") + } + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesModule.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesModule.kt index e6cb916aef..8c488d61da 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesModule.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/di/MessagesModule.kt @@ -10,6 +10,8 @@ package io.element.android.features.messages.impl.di import com.squareup.anvil.annotations.ContributesTo import dagger.Binds import dagger.Module +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailurePresenter +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerPresenter import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState import io.element.android.libraries.architecture.Presenter @@ -20,4 +22,7 @@ import io.element.android.libraries.di.RoomScope interface MessagesModule { @Binds fun bindPinnedMessagesBannerPresenter(presenter: PinnedMessagesBannerPresenter): Presenter + + @Binds + fun bindResolveVerifiedUserSendFailurePresenter(presenter: ResolveVerifiedUserSendFailurePresenter): Presenter } 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 df873d2328..fec6ea000e 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 @@ -16,6 +16,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.actionlist.ActionListState import io.element.android.features.messages.impl.actionlist.FakeActionListPresenter import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.aResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.draft.FakeComposerDraftService import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.fixtures.aTimelineItemsFactoryCreator @@ -1062,6 +1063,7 @@ class MessagesPresenterTest { reactionSummaryPresenter = reactionSummaryPresenter, readReceiptBottomSheetPresenter = readReceiptBottomSheetPresenter, pinnedMessagesBannerPresenter = { aLoadedPinnedMessagesBannerState() }, + resolveVerifiedUserSendFailurePresenter = { aResolveVerifiedUserSendFailureState() }, networkMonitor = FakeNetworkMonitor(), snackbarDispatcher = SnackbarDispatcher(), navigator = navigator, 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 52387f821a..08c1119a6a 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 @@ -34,6 +34,10 @@ import io.element.android.features.messages.impl.actionlist.ActionListState import io.element.android.features.messages.impl.actionlist.anActionListState import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.attachments.Attachment +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureEvents +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.aChangedIdentitySendFailure +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.aResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.messagecomposer.aMessageComposerState import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerItem import io.element.android.features.messages.impl.pinned.banner.aLoadedPinnedMessagesBannerState @@ -329,6 +333,7 @@ class MessagesViewTest { event = timelineItem, displayEmojiReactions = true, actions = persistentListOf(TimelineItemAction.Edit), + verifiedUserSendFailure = VerifiedUserSendFailure.None, ) ), ) @@ -399,6 +404,7 @@ class MessagesViewTest { target = ActionListState.Target.Success( event = timelineItem, displayEmojiReactions = true, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf(TimelineItemAction.Edit), ), ), @@ -416,6 +422,34 @@ class MessagesViewTest { eventsRecorder.assertSingle(CustomReactionEvents.ShowCustomReactionSheet(timelineItem)) } + @Test + fun `clicking on verified user send failure from action list emits the expected Event`() { + val eventsRecorder = EventsRecorder() + val state = aMessagesState() + val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event + val stateWithActionListState = state.copy( + actionListState = anActionListState( + target = ActionListState.Target.Success( + event = timelineItem, + displayEmojiReactions = true, + verifiedUserSendFailure = aChangedIdentitySendFailure(), + actions = persistentListOf(), + ), + ), + resolveVerifiedUserSendFailureState = aResolveVerifiedUserSendFailureState( + eventSink = eventsRecorder + ), + ) + rule.setMessagesView( + state = stateWithActionListState, + ) + val verifiedUserSendFailure = rule.activity.getString(CommonStrings.screen_timeline_item_menu_send_failure_changed_identity, "Alice") + rule.onNodeWithText(verifiedUserSendFailure).performClick() + // Give time for the close animation to complete + rule.mainClock.advanceTimeBy(milliseconds = 1_000) + eventsRecorder.assertSingle(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(timelineItem)) + } + @Test fun `clicking on a custom emoji emits the expected Events`() { val aUnicode = "🙈" 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 bd580b5f98..078fb9e676 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 @@ -14,6 +14,8 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.aUserEventPermissions import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailureFactory import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemCallNotifyContent @@ -25,8 +27,10 @@ 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.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_MESSAGE +import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.matrix.test.room.aRoomInfo import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore @@ -79,6 +83,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = false, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.ViewSource, ) @@ -120,6 +125,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = false, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.ViewSource, ) @@ -161,6 +167,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = true, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, @@ -208,6 +215,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = true, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.Forward, TimelineItemAction.Pin, @@ -252,6 +260,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = true, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, @@ -298,6 +307,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = false, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, @@ -345,6 +355,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = true, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, @@ -392,6 +403,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = true, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, @@ -439,6 +451,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = true, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, @@ -484,6 +497,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = stateEvent, displayEmojiReactions = false, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.ViewSource, ) @@ -553,6 +567,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = true, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, @@ -599,6 +614,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = true, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, @@ -652,6 +668,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = true, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, @@ -748,6 +765,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = true, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.Edit, TimelineItemAction.Copy, @@ -787,6 +805,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = true, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Edit, @@ -829,6 +848,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = true, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.EndPoll, @@ -870,6 +890,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = true, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Pin, @@ -910,6 +931,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = true, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.Reply, TimelineItemAction.Forward, @@ -949,6 +971,7 @@ class ActionListPresenterTest { ActionListState.Target.Success( event = messageEvent, displayEmojiReactions = false, + verifiedUserSendFailure = VerifiedUserSendFailure.None, actions = persistentListOf( TimelineItemAction.ViewSource ) @@ -956,6 +979,32 @@ class ActionListPresenterTest { ) } } + + @Test + fun `present - compute for verified user send failure`() = runTest { + val room = FakeMatrixRoom( + userDisplayNameResult = { Result.success("Alice") } + ) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = false, room = room) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + val messageEvent = aMessageEvent( + sendState = LocalEventSendState.Failed.VerifiedUserChangedIdentity(users = listOf(A_USER_ID)), + ) + initialState.eventSink.invoke( + ActionListEvents.ComputeForMessage( + event = messageEvent, + userEventPermissions = aUserEventPermissions(), + ) + ) + skipItems(1) + val successState = awaitItem() + val target = successState.target as ActionListState.Target.Success + assertThat(target.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.ChangedIdentity(userDisplayName = "Alice")) + } + } } private fun createActionListPresenter( @@ -968,6 +1017,7 @@ private fun createActionListPresenter( postProcessor = TimelineItemActionPostProcessor.Default, appPreferencesStore = preferencesStore, isPinnedMessagesFeatureEnabled = { isPinFeatureEnabled }, - room = room + room = room, + userSendFailureFactory = VerifiedUserSendFailureFactory(room) ) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt new file mode 100644 index 0000000000..8d5884cf08 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt @@ -0,0 +1,353 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.sendfailure.resolve + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure +import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailureFactory +import io.element.android.features.messages.impl.fixtures.aMessageEvent +import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState +import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.A_TRANSACTION_ID +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.A_USER_ID_2 +import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.test +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test + +class ResolveVerifiedUserSendFailurePresenterTest { + @get:Rule + val warmUpRule = WarmUpRule() + + @Test + fun `present - initial state`() = runTest { + val presenter = createResolveVerifiedUserSendFailurePresenter() + presenter.test { + val initialState = awaitItem() + assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + } + } + + @Test + fun `present - remote message scenario`() = runTest { + val presenter = createResolveVerifiedUserSendFailurePresenter() + presenter.test { + val sentMessage = aMessageEvent() + val initialState = awaitItem() + assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(sentMessage)) + ensureAllEventsConsumed() + } + } + + @Test + fun `present - sent message scenario`() = runTest { + val presenter = createResolveVerifiedUserSendFailurePresenter() + presenter.test { + val sentMessage = aMessageEvent( + sendState = LocalEventSendState.Sent(AN_EVENT_ID) + ) + val initialState = awaitItem() + assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(sentMessage)) + ensureAllEventsConsumed() + } + } + + @Test + fun `present - unknown failed message scenario`() = runTest { + val presenter = createResolveVerifiedUserSendFailurePresenter() + presenter.test { + val failedMessage = aMessageEvent( + sendState = LocalEventSendState.Failed.Unknown("") + ) + val initialState = awaitItem() + assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + ensureAllEventsConsumed() + } + } + + @Test + fun `present - verified user unsigned device failure dismiss scenario`() = runTest { + val room = FakeMatrixRoom( + userDisplayNameResult = { userId -> + Result.success(userId.value) + }, + ) + val presenter = createResolveVerifiedUserSendFailurePresenter(room) + presenter.test { + val failedMessage = aVerifiedUserHasUnsignedDeviceFailedMessage() + val initialState = awaitItem() + assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + skipItems(1) + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + state.eventSink(ResolveVerifiedUserSendFailureEvents.Dismiss) + } + skipItems(1) + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + } + ensureAllEventsConsumed() + } + } + + @Test + fun `present - verified user unsigned device failure retry scenario`() = runTest { + val room = FakeMatrixRoom( + userDisplayNameResult = { userId -> + Result.success(userId.value) + }, + retrySendMessageResult = { + Result.success(Unit) + }, + ) + val presenter = createResolveVerifiedUserSendFailurePresenter(room) + presenter.test { + val failedMessage = aVerifiedUserHasUnsignedDeviceFailedMessage() + val initialState = awaitItem() + assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + + skipItems(1) + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + state.eventSink(ResolveVerifiedUserSendFailureEvents.Retry) + } + awaitItem().also { state -> + assertThat(state.retryAction).isEqualTo(AsyncAction.Loading) + } + skipItems(2) + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + assertThat(state.retryAction).isEqualTo(AsyncAction.Success(Unit)) + } + ensureAllEventsConsumed() + } + } + + @Test + fun `present - verified user unsigned device failure resolve and resend scenario`() = runTest { + val room = FakeMatrixRoom( + userDisplayNameResult = { userId -> + Result.success(userId.value) + }, + ignoreDeviceTrustAndResendResult = { _, _ -> + Result.success(Unit) + }, + ) + val presenter = createResolveVerifiedUserSendFailurePresenter(room) + presenter.test { + val failedMessage = aVerifiedUserHasUnsignedDeviceFailedMessage() + val initialState = awaitItem() + assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + + skipItems(1) + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + } + awaitItem().also { state -> + assertThat(state.resolveAction).isEqualTo(AsyncAction.Loading) + } + // This should move to the next user + skipItems(2) + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID_2.value)) + assertThat(state.resolveAction).isEqualTo(AsyncAction.Success(Unit)) + state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + } + + skipItems(3) + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + } + ensureAllEventsConsumed() + } + } + + @Test + fun `present - verified user unsigned device failure resolve and resend scenario with error`() = runTest { + val room = FakeMatrixRoom( + userDisplayNameResult = { userId -> + Result.success(userId.value) + }, + ignoreDeviceTrustAndResendResult = { _, _ -> + Result.failure(Exception()) + }, + ) + val presenter = createResolveVerifiedUserSendFailurePresenter(room) + presenter.test { + val failedMessage = aVerifiedUserHasUnsignedDeviceFailedMessage() + val initialState = awaitItem() + assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + + skipItems(1) + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + } + awaitItem().also { state -> + assertThat(state.resolveAction).isEqualTo(AsyncAction.Loading) + } + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.resolveAction).isInstanceOf(AsyncAction.Failure::class.java) + } + ensureAllEventsConsumed() + } + } + + @Test + fun `present - verified user changed identity failure retry scenario`() = runTest { + val room = FakeMatrixRoom( + userDisplayNameResult = { userId -> + Result.success(userId.value) + }, + retrySendMessageResult = { + Result.success(Unit) + }, + ) + val presenter = createResolveVerifiedUserSendFailurePresenter(room) + presenter.test { + val failedMessage = aVerifiedUserChangedIdentityMessage() + val initialState = awaitItem() + assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + + skipItems(1) + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.ChangedIdentity(A_USER_ID.value)) + state.eventSink(ResolveVerifiedUserSendFailureEvents.Retry) + } + awaitItem().also { state -> + assertThat(state.retryAction).isEqualTo(AsyncAction.Loading) + } + skipItems(2) + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + assertThat(state.retryAction).isEqualTo(AsyncAction.Success(Unit)) + } + ensureAllEventsConsumed() + } + } + + @Test + fun `present - verified user changed identity failure resolve and resend scenario`() = runTest { + val room = FakeMatrixRoom( + userDisplayNameResult = { userId -> + Result.success(userId.value) + }, + withdrawVerificationAndResendResult = { _, _ -> + Result.success(Unit) + }, + ) + val presenter = createResolveVerifiedUserSendFailurePresenter(room) + presenter.test { + val failedMessage = aVerifiedUserChangedIdentityMessage() + val initialState = awaitItem() + assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + + skipItems(1) + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.ChangedIdentity(A_USER_ID.value)) + state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + } + awaitItem().also { state -> + assertThat(state.resolveAction).isEqualTo(AsyncAction.Loading) + } + // This should move to the next user + skipItems(2) + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.ChangedIdentity(A_USER_ID_2.value)) + assertThat(state.resolveAction).isEqualTo(AsyncAction.Success(Unit)) + state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + } + + skipItems(3) + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + } + ensureAllEventsConsumed() + } + } + + @Test + fun `present - verified user changed identity failure resolve and resend scenario with error`() = runTest { + val room = FakeMatrixRoom( + userDisplayNameResult = { userId -> + Result.success(userId.value) + }, + withdrawVerificationAndResendResult = { _, _ -> + Result.failure(Exception()) + }, + ) + val presenter = createResolveVerifiedUserSendFailurePresenter(room) + presenter.test { + val failedMessage = aVerifiedUserChangedIdentityMessage() + val initialState = awaitItem() + assertThat(initialState.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.None) + initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) + + skipItems(1) + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.ChangedIdentity(A_USER_ID.value)) + state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + } + awaitItem().also { state -> + assertThat(state.resolveAction).isEqualTo(AsyncAction.Loading) + } + awaitItem().also { state -> + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.ChangedIdentity(A_USER_ID.value)) + assertThat(state.resolveAction).isInstanceOf(AsyncAction.Failure::class.java) + } + ensureAllEventsConsumed() + } + } + + private fun aVerifiedUserHasUnsignedDeviceFailedMessage(): TimelineItem.Event { + return aMessageEvent( + transactionId = A_TRANSACTION_ID, + sendState = LocalEventSendState.Failed.VerifiedUserHasUnsignedDevice( + mapOf( + A_USER_ID to emptyList(), + A_USER_ID_2 to emptyList() + ) + ) + ) + } + + private fun aVerifiedUserChangedIdentityMessage(): TimelineItem.Event { + return aMessageEvent( + transactionId = A_TRANSACTION_ID, + sendState = LocalEventSendState.Failed.VerifiedUserChangedIdentity( + listOf(A_USER_ID, A_USER_ID_2) + ) + ) + } + + private fun createResolveVerifiedUserSendFailurePresenter( + room: MatrixRoom = FakeMatrixRoom(), + ): ResolveVerifiedUserSendFailurePresenter { + return ResolveVerifiedUserSendFailurePresenter( + room = room, + verifiedUserSendFailureFactory = VerifiedUserSendFailureFactory(room), + ) + } +} diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureViewTest.kt new file mode 100644 index 0000000000..e5d67848dd --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureViewTest.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.messages.impl.crypto.sendfailure.resolve + +import androidx.activity.ComponentActivity +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.tests.testutils.EventsRecorder +import io.element.android.tests.testutils.clickOn +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TestRule +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class ResolveVerifiedUserSendFailureViewTest { + @get:Rule val rule = createAndroidComposeRule() + + @Test + fun `clicking on resolve and resend emit the expected event`() { + val eventsRecorder = EventsRecorder() + rule.setResolveVerifiedUserSendFailureView( + state = aResolveVerifiedUserSendFailureState( + verifiedUserSendFailure = aChangedIdentitySendFailure(), + eventSink = eventsRecorder, + ), + ) + + rule.clickOn(res = CommonStrings.screen_resolve_send_failure_changed_identity_primary_button_title) + eventsRecorder.assertSingle(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) + } + + @Test + fun `clicking on retry emit the expected event`() { + val eventsRecorder = EventsRecorder() + rule.setResolveVerifiedUserSendFailureView( + state = aResolveVerifiedUserSendFailureState( + verifiedUserSendFailure = aChangedIdentitySendFailure(), + eventSink = eventsRecorder, + ), + ) + + rule.clickOn(res = CommonStrings.action_retry) + eventsRecorder.assertSingle(ResolveVerifiedUserSendFailureEvents.Retry) + } + + private fun AndroidComposeTestRule.setResolveVerifiedUserSendFailureView( + state: ResolveVerifiedUserSendFailureState, + ) { + setContent { + ResolveVerifiedUserSendFailureView(state = state) + } + } +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoundedIconAtom.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoundedIconAtom.kt index 9dc739da96..c21e1a5f38 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoundedIconAtom.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/atoms/RoundedIconAtom.kt @@ -37,6 +37,7 @@ import io.element.android.libraries.designsystem.theme.temporaryColorBgSpecial * @param resourceId the resource id of the icon to display, exclusive with [imageVector] * @param imageVector the image vector of the icon to display, exclusive with [resourceId] * @param tint the tint to apply to the icon + * @param backgroundTint the tint to apply to the icon background */ @Composable fun RoundedIconAtom( @@ -44,13 +45,14 @@ fun RoundedIconAtom( size: RoundedIconAtomSize = RoundedIconAtomSize.Large, resourceId: Int? = null, imageVector: ImageVector? = null, - tint: Color = MaterialTheme.colorScheme.secondary + tint: Color = MaterialTheme.colorScheme.secondary, + backgroundTint: Color = ElementTheme.colors.temporaryColorBgSpecial, ) { Box( modifier = modifier .size(size.toContainerSize()) .background( - color = ElementTheme.colors.temporaryColorBgSpecial, + color = backgroundTint, shape = RoundedCornerShape(size.toCornerSize()) ) ) { diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/IconTitleSubtitleMolecule.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/IconTitleSubtitleMolecule.kt index f4c88ab59b..4812eaddee 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/IconTitleSubtitleMolecule.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/IconTitleSubtitleMolecule.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.designsystem.icons.CompoundDrawables import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.temporaryColorBgSpecial /** * IconTitleSubtitleMolecule is a molecule which displays an icon, a title and a subtitle. @@ -37,6 +38,7 @@ import io.element.android.libraries.designsystem.theme.components.Text * @param iconResourceId the resource id of the icon to display, exclusive with [iconImageVector] * @param iconImageVector the image vector of the icon to display, exclusive with [iconResourceId] * @param iconTint the tint to apply to the icon + * @param iconBackgroundTint the tint to apply to the icon background */ @Composable fun IconTitleSubtitleMolecule( @@ -46,6 +48,7 @@ fun IconTitleSubtitleMolecule( iconResourceId: Int? = null, iconImageVector: ImageVector? = null, iconTint: Color = MaterialTheme.colorScheme.primary, + iconBackgroundTint: Color = ElementTheme.colors.temporaryColorBgSpecial, ) { Column(modifier) { RoundedIconAtom( @@ -55,6 +58,7 @@ fun IconTitleSubtitleMolecule( resourceId = iconResourceId, imageVector = iconImageVector, tint = iconTint, + backgroundTint = iconBackgroundTint, ) Spacer(modifier = Modifier.height(16.dp)) Text( 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 3e2fd6dcd5..f09ccad5d9 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 @@ -80,11 +80,11 @@ fun ListItem( /** * 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 colors The colors to use for the list item. * @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 onClick The callback to be called when the list item is clicked. */ @@ -412,8 +412,8 @@ private object PreviewItems { ) { ElementThemedPreview { ListItem( - headlineContent = PreviewItems.headline(), - supportingContent = PreviewItems.text(), + headlineContent = headline(), + supportingContent = text(), leadingContent = leadingContent, trailingContent = trailingContent, style = style, @@ -431,8 +431,8 @@ private object PreviewItems { ) { ElementThemedPreview { ListItem( - headlineContent = PreviewItems.headline(), - supportingContent = PreviewItems.textSingleLine(), + headlineContent = headline(), + supportingContent = textSingleLine(), leadingContent = leadingContent, trailingContent = trailingContent, style = style, @@ -451,7 +451,7 @@ private object PreviewItems { ) { ElementThemedPreview { ListItem( - headlineContent = PreviewItems.headline(), + headlineContent = headline(), leadingContent = leadingContent, trailingContent = trailingContent, enabled = enabled, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 25340684d6..1936b9f60c 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -354,5 +354,4 @@ interface MatrixRoom : Closeable { suspend fun withdrawVerificationAndResend(userIds: List, transactionId: TransactionId): Result override fun close() = destroy() - } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index 381063f0e1..b871062f70 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -647,10 +647,9 @@ class RustMatrixRoom( override suspend fun ignoreDeviceTrustAndResend(devices: Map>, transactionId: TransactionId) = runCatching { innerRoom.ignoreDeviceTrustAndResend( - devices = devices - .entries.associate { entry -> - entry.key.value to entry.value.map { it.value } - }, + devices = devices.entries.associate { entry -> + entry.key.value to entry.value.map { it.value } + }, transactionId = transactionId.value ) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 2290897f11..54b52c6fb7 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -80,7 +80,7 @@ class FakeMatrixRoom( private var roomPermalinkResult: () -> Result = { lambdaError() }, private var eventPermalinkResult: (EventId) -> Result = { lambdaError() }, private val sendCallNotificationIfNeededResult: () -> Result = { lambdaError() }, - private val userDisplayNameResult: () -> Result = { lambdaError() }, + private val userDisplayNameResult: (UserId) -> Result = { lambdaError() }, private val userAvatarUrlResult: () -> Result = { lambdaError() }, private val userRoleResult: () -> Result = { lambdaError() }, private val getUpdatedMemberResult: (UserId) -> Result = { lambdaError() }, @@ -137,7 +137,6 @@ class FakeMatrixRoom( private val subscribeToSyncLambda: () -> Unit = { lambdaError() }, private val ignoreDeviceTrustAndResendResult: (Map>, TransactionId) -> Result = { _, _ -> lambdaError() }, private val withdrawVerificationAndResendResult: (List, TransactionId) -> Result = { _, _ -> lambdaError() }, - ) : MatrixRoom { private val _roomInfoFlow: MutableSharedFlow = MutableSharedFlow(replay = 1) override val roomInfoFlow: Flow = _roomInfoFlow @@ -203,7 +202,7 @@ class FakeMatrixRoom( override fun destroy() = Unit override suspend fun userDisplayName(userId: UserId): Result = simulateLongTask { - userDisplayNameResult() + userDisplayNameResult(userId) } override suspend fun userAvatarUrl(userId: UserId): Result = simulateLongTask { @@ -230,7 +229,7 @@ class FakeMatrixRoom( return toggleReactionResult(emoji, uniqueId) } - override suspend fun retrySendMessage(transactionId: TransactionId): Result { + override suspend fun retrySendMessage(transactionId: TransactionId): Result = simulateLongTask { return retrySendMessageResult(transactionId) } @@ -496,11 +495,11 @@ class FakeMatrixRoom( return getWidgetDriverResult(widgetSettings) } - override suspend fun ignoreDeviceTrustAndResend(devices: Map>, transactionId: TransactionId): Result { + override suspend fun ignoreDeviceTrustAndResend(devices: Map>, transactionId: TransactionId): Result = simulateLongTask { return ignoreDeviceTrustAndResendResult(devices, transactionId) } - override suspend fun withdrawVerificationAndResend(userIds: List, transactionId: TransactionId): Result { + override suspend fun withdrawVerificationAndResend(userIds: List, transactionId: TransactionId): Result = simulateLongTask { return withdrawVerificationAndResendResult(userIds, transactionId) } From e16adb9b856149feaf1eed65a00fbe9e06b3b504 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 13 Sep 2024 16:32:29 +0200 Subject: [PATCH 017/106] Send failure verified user : handle click on failed send icon. --- .../messages/impl/MessagesPresenter.kt | 4 -- .../features/messages/impl/MessagesState.kt | 2 - .../messages/impl/MessagesStateProvider.kt | 4 -- .../features/messages/impl/MessagesView.kt | 8 +--- .../ResolveVerifiedUserSendFailureView.kt | 2 +- .../pinned/list/PinnedMessagesListView.kt | 7 ++- .../messages/impl/timeline/TimelineEvents.kt | 4 +- .../impl/timeline/TimelinePresenter.kt | 8 ++++ .../messages/impl/timeline/TimelineState.kt | 2 + .../impl/timeline/TimelineStateProvider.kt | 4 ++ .../messages/impl/timeline/TimelineView.kt | 22 +++++----- .../components/ATimelineItemEventRow.kt | 3 +- .../components/TimelineEventTimestampView.kt | 23 ++++++---- .../components/TimelineItemEventRow.kt | 44 +++++++++---------- .../TimelineItemGroupedEventsRow.kt | 13 ++---- .../timeline/components/TimelineItemRow.kt | 6 +-- 16 files changed, 75 insertions(+), 81 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index f657fb6393..5284af15a5 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 @@ -30,7 +30,6 @@ import io.element.android.features.messages.impl.actionlist.ActionListEvents import io.element.android.features.messages.impl.actionlist.ActionListPresenter import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor -import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents import io.element.android.features.messages.impl.messagecomposer.MessageComposerPresenter import io.element.android.features.messages.impl.messagecomposer.MessageComposerState @@ -96,7 +95,6 @@ class MessagesPresenter @AssistedInject constructor( private val reactionSummaryPresenter: ReactionSummaryPresenter, private val readReceiptBottomSheetPresenter: ReadReceiptBottomSheetPresenter, private val pinnedMessagesBannerPresenter: Presenter, - private val resolveVerifiedUserSendFailurePresenter: Presenter, private val networkMonitor: NetworkMonitor, private val snackbarDispatcher: SnackbarDispatcher, private val dispatchers: CoroutineDispatchers, @@ -130,7 +128,6 @@ class MessagesPresenter @AssistedInject constructor( val reactionSummaryState = reactionSummaryPresenter.present() val readReceiptBottomSheetState = readReceiptBottomSheetPresenter.present() val pinnedMessagesBannerState = pinnedMessagesBannerPresenter.present() - val resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailurePresenter.present() val syncUpdateFlow = room.syncUpdateFlow.collectAsState() @@ -230,7 +227,6 @@ class MessagesPresenter @AssistedInject constructor( appName = buildMeta.applicationName, callState = callState, pinnedMessagesBannerState = pinnedMessagesBannerState, - resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, eventSink = { handleEvents(it) } ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt index c3b4b9183e..546e558ba8 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt @@ -9,7 +9,6 @@ package io.element.android.features.messages.impl import androidx.compose.runtime.Immutable import io.element.android.features.messages.impl.actionlist.ActionListState -import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.messagecomposer.MessageComposerState import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState import io.element.android.features.messages.impl.timeline.TimelineState @@ -48,7 +47,6 @@ data class MessagesState( val callState: RoomCallState, val appName: String, val pinnedMessagesBannerState: PinnedMessagesBannerState, - val resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState, val eventSink: (MessagesEvents) -> Unit ) 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 cc651bc978..96e55aac91 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 @@ -10,8 +10,6 @@ package io.element.android.features.messages.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.messages.impl.actionlist.ActionListState import io.element.android.features.messages.impl.actionlist.anActionListState -import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState -import io.element.android.features.messages.impl.crypto.sendfailure.resolve.aResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.messagecomposer.AttachmentsState import io.element.android.features.messages.impl.messagecomposer.MessageComposerState import io.element.android.features.messages.impl.messagecomposer.aMessageComposerState @@ -115,7 +113,6 @@ fun aMessagesState( enableVoiceMessages: Boolean = true, callState: RoomCallState = RoomCallState.ENABLED, pinnedMessagesBannerState: PinnedMessagesBannerState = aLoadedPinnedMessagesBannerState(), - resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState = aResolveVerifiedUserSendFailureState(), eventSink: (MessagesEvents) -> Unit = {}, ) = MessagesState( roomId = RoomId("!id:domain"), @@ -140,7 +137,6 @@ fun aMessagesState( callState = callState, appName = "Element", pinnedMessagesBannerState = pinnedMessagesBannerState, - resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, 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 d56ef675c3..777412e5e3 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 @@ -57,8 +57,6 @@ import io.element.android.features.messages.impl.actionlist.ActionListEvents import io.element.android.features.messages.impl.actionlist.ActionListView import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.attachments.Attachment -import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureEvents -import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureView import io.element.android.features.messages.impl.messagecomposer.AttachmentsBottomSheet import io.element.android.features.messages.impl.messagecomposer.AttachmentsState import io.element.android.features.messages.impl.messagecomposer.MessageComposerEvents @@ -244,14 +242,10 @@ fun MessagesView( }, onEmojiReactionClick = ::onEmojiReactionClick, onVerifiedUserSendFailureClick = { event -> - state.resolveVerifiedUserSendFailureState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(event)) + state.timelineState.eventSink(TimelineEvents.ComputeVerifiedUserSendFailure(event)) }, ) - ResolveVerifiedUserSendFailureView( - state = state.resolveVerifiedUserSendFailureState, - ) - CustomReactionBottomSheet( state = state.customReactionState, onSelectEmoji = { uniqueId, emoji -> diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt index 10c3236f46..e0d964fa51 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt @@ -43,7 +43,7 @@ fun ResolveVerifiedUserSendFailureView( state: ResolveVerifiedUserSendFailureState, modifier: Modifier = Modifier, ) { - val sheetState = rememberModalBottomSheetState() + val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) var showSheet by remember { mutableStateOf(false) } fun dismiss() { 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 f853b7c971..f340d005f5 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 @@ -200,19 +200,18 @@ private fun PinnedMessagesListLoaded( renderReadReceipts = false, isLastOutgoingMessage = false, focusedEventId = null, - onClick = onEventClick, - onLongClick = ::onMessageLongClick, onUserDataClick = onUserDataClick, onLinkClick = onLinkClick, + onClick = onEventClick, + onLongClick = ::onMessageLongClick, inReplyToClick = {}, onReactionClick = { _, _ -> }, onReactionLongClick = { _, _ -> }, onMoreReactionsClick = {}, onReadReceiptClick = {}, - eventSink = {}, onSwipeToReply = {}, onJoinCallClick = {}, - onShieldClick = {}, + eventSink = {}, eventContentView = { event, contentModifier, onContentLayoutChange -> TimelineItemEventContentViewWrapper( event = event, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt index 1aa1afe0f0..e886251b64 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvents.kt @@ -7,6 +7,7 @@ package io.element.android.features.messages.impl.timeline +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.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield @@ -19,7 +20,6 @@ sealed interface TimelineEvents { data object OnFocusEventRender : TimelineEvents data object JumpToLive : TimelineEvents - data class ShowShieldDialog(val messageShield: MessageShield) : TimelineEvents data object HideShieldDialog : TimelineEvents /** @@ -27,6 +27,8 @@ sealed interface TimelineEvents { */ sealed interface EventFromTimelineItem : TimelineEvents + data class ComputeVerifiedUserSendFailure(val event: TimelineItem.Event) : EventFromTimelineItem + data class ShowShieldDialog(val messageShield: MessageShield) : EventFromTimelineItem data class LoadMore(val direction: Timeline.PaginationDirection) : EventFromTimelineItem /** 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 e4287cb3ed..088354f245 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 @@ -21,6 +21,8 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import io.element.android.features.messages.impl.MessagesNavigator +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureEvents +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactory import io.element.android.features.messages.impl.timeline.factories.TimelineItemsFactoryConfig import io.element.android.features.messages.impl.timeline.model.NewEventState @@ -66,6 +68,7 @@ class TimelinePresenter @AssistedInject constructor( private val endPollAction: EndPollAction, private val sessionPreferencesStore: SessionPreferencesStore, private val timelineController: TimelineController, + private val resolveVerifiedUserSendFailurePresenter: Presenter, ) : Presenter { @AssistedFactory interface Factory { @@ -101,6 +104,7 @@ class TimelinePresenter @AssistedInject constructor( val newEventState = remember { mutableStateOf(NewEventState.None) } val messageShield: MutableState = remember { mutableStateOf(null) } + val resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailurePresenter.present() val isSendPublicReadReceiptsEnabled by sessionPreferencesStore.isSendPublicReadReceiptsEnabled().collectAsState(initial = true) val renderReadReceipts by sessionPreferencesStore.isRenderReadReceiptsEnabled().collectAsState(initial = true) val isLive by timelineController.isLive().collectAsState(initial = true) @@ -156,6 +160,9 @@ class TimelinePresenter @AssistedInject constructor( } TimelineEvents.HideShieldDialog -> messageShield.value = null is TimelineEvents.ShowShieldDialog -> messageShield.value = event.messageShield + is TimelineEvents.ComputeVerifiedUserSendFailure -> { + resolveVerifiedUserSendFailureState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(event.event)) + } } } @@ -232,6 +239,7 @@ class TimelinePresenter @AssistedInject constructor( isLive = isLive, focusRequestState = focusRequestState.value, messageShield = messageShield.value, + resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, eventSink = { handleEvents(it) } ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt index 114cbf8128..18630f62d4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineState.kt @@ -8,6 +8,7 @@ package io.element.android.features.messages.impl.timeline import androidx.compose.runtime.Immutable +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.libraries.matrix.api.core.EventId @@ -25,6 +26,7 @@ data class TimelineState( val focusRequestState: FocusRequestState, // If not null, info will be rendered in a dialog val messageShield: MessageShield?, + val resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState, val eventSink: (TimelineEvents) -> Unit, ) { val hasAnyEvent = timelineItems.any { it is TimelineItem.Event } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index 516559cc37..3317c2976c 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 @@ -7,6 +7,8 @@ package io.element.android.features.messages.impl.timeline +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureState +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.aResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.timeline.components.receipt.aReadReceiptData import io.element.android.features.messages.impl.timeline.model.NewEventState import io.element.android.features.messages.impl.timeline.model.ReadReceiptData @@ -44,6 +46,7 @@ fun aTimelineState( focusedEventIndex: Int = -1, isLive: Boolean = true, messageShield: MessageShield? = null, + resolveVerifiedUserSendFailureState: ResolveVerifiedUserSendFailureState = aResolveVerifiedUserSendFailureState(), eventSink: (TimelineEvents) -> Unit = {}, ): TimelineState { val focusedEventId = timelineItems.filterIsInstance().getOrNull(focusedEventIndex)?.eventId @@ -60,6 +63,7 @@ fun aTimelineState( isLive = isLive, focusRequestState = focusRequestState, messageShield = messageShield, + resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailureState, eventSink = eventSink, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index c3f7d53bb6..17ce5264fc 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -48,6 +48,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureView import io.element.android.features.messages.impl.timeline.components.TimelineItemRow import io.element.android.features.messages.impl.timeline.components.toText import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories @@ -127,8 +128,8 @@ fun TimelineView( Box(modifier) { LazyColumn( modifier = Modifier - .fillMaxSize() - .nestedScroll(nestedScrollConnection), + .fillMaxSize() + .nestedScroll(nestedScrollConnection), state = lazyListState, reverseLayout = useReverseLayout, contentPadding = PaddingValues(vertical = 8.dp), @@ -150,19 +151,18 @@ fun TimelineView( isLastOutgoingMessage = (timelineItem as? TimelineItem.Event)?.isMine == true && state.timelineItems.first().identifier() == timelineItem.identifier(), focusedEventId = state.focusedEventId, - onClick = onMessageClick, - onLongClick = onMessageLongClick, - onShieldClick = ::onShieldClick, onUserDataClick = onUserDataClick, onLinkClick = onLinkClick, + onClick = onMessageClick, + onLongClick = onMessageLongClick, inReplyToClick = ::inReplyToClick, onReactionClick = onReactionClick, onReactionLongClick = onReactionLongClick, onMoreReactionsClick = onMoreReactionsClick, onReadReceiptClick = onReadReceiptClick, - eventSink = state.eventSink, onSwipeToReply = onSwipeToReply, onJoinCallClick = onJoinCallClick, + eventSink = state.eventSink, ) } } @@ -186,6 +186,8 @@ fun TimelineView( } } + ResolveVerifiedUserSendFailureView(state = state.resolveVerifiedUserSendFailureState) + MessageShieldDialog(state) } @@ -267,8 +269,8 @@ private fun BoxScope.TimelineScrollHelper( // Use inverse of canAutoScroll otherwise we might briefly see the before the scroll animation is triggered isVisible = !canAutoScroll || forceJumpToBottomVisibility || !isLive, modifier = Modifier - .align(Alignment.BottomEnd) - .padding(end = 24.dp, bottom = 12.dp), + .align(Alignment.BottomEnd) + .padding(end = 24.dp, bottom = 12.dp), onClick = { jumpToBottom() }, ) } @@ -295,8 +297,8 @@ private fun JumpToBottomButton( ) { Icon( modifier = Modifier - .size(24.dp) - .rotate(90f), + .size(24.dp) + .rotate(90f), imageVector = CompoundIcons.ArrowRight(), contentDescription = stringResource(id = CommonStrings.a11y_jump_to_bottom) ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt index a73dbef79c..0db7a8ac52 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/ATimelineItemEventRow.kt @@ -28,9 +28,8 @@ internal fun ATimelineItemEventRow( isHighlighted = isHighlighted, onClick = {}, onLongClick = {}, - onShieldClick = {}, - onUserDataClick = {}, onLinkClick = {}, + onUserDataClick = {}, inReplyToClick = {}, onReactionClick = { _, _ -> }, onReactionLongClick = { _, _ -> }, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt index 08c72a1060..a6692bd4ec 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineEventTimestampView.kt @@ -23,6 +23,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.features.messages.impl.timeline.TimelineEvents import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.isEdited import io.element.android.libraries.core.bool.orFalse @@ -31,14 +32,13 @@ 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.api.timeline.item.event.LocalEventSendState -import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.api.timeline.item.event.isCritical import io.element.android.libraries.ui.strings.CommonStrings @Composable fun TimelineEventTimestampView( event: TimelineItem.Event, - onShieldClick: (MessageShield) -> Unit, + eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, modifier: Modifier = Modifier, ) { val formattedTime = event.sentTime @@ -48,8 +48,8 @@ fun TimelineEventTimestampView( val tint = if (hasError || hasEncryptionCritical) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.secondary Row( modifier = Modifier - .padding(PaddingValues(start = TimelineEventTimestampViewDefaults.spacing)) - .then(modifier), + .padding(PaddingValues(start = TimelineEventTimestampViewDefaults.spacing)) + .then(modifier), verticalAlignment = Alignment.CenterVertically, ) { if (isMessageEdited) { @@ -66,12 +66,17 @@ fun TimelineEventTimestampView( color = tint, ) if (hasError) { + val isVerifiedUserSendFailure = event.localSendState is LocalEventSendState.Failed.VerifiedUser Spacer(modifier = Modifier.width(2.dp)) Icon( imageVector = CompoundIcons.Error(), contentDescription = stringResource(id = CommonStrings.common_sending_failed), tint = tint, - modifier = Modifier.size(15.dp, 18.dp), + modifier = Modifier + .size(15.dp, 18.dp) + .clickable(isVerifiedUserSendFailure) { + eventSink(TimelineEvents.ComputeVerifiedUserSendFailure(event)) + }, ) } event.messageShield?.let { shield -> @@ -80,8 +85,10 @@ fun TimelineEventTimestampView( imageVector = shield.toIcon(), contentDescription = shield.toText(), modifier = Modifier - .size(15.dp) - .clickable { onShieldClick(shield) }, + .size(15.dp) + .clickable { + eventSink(TimelineEvents.ShowShieldDialog(shield)) + }, tint = shield.toIconColor(), ) Spacer(modifier = Modifier.width(4.dp)) @@ -94,7 +101,7 @@ fun TimelineEventTimestampView( internal fun TimelineEventTimestampViewPreview(@PreviewParameter(TimelineItemEventForTimestampViewProvider::class) event: TimelineItem.Event) = ElementPreview { TimelineEventTimestampView( event = event, - onShieldClick = {}, + eventSink = {}, ) } 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 c03162efc6..e068eb5522 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 @@ -81,7 +81,6 @@ import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails import io.element.android.libraries.matrix.ui.messages.reply.InReplyToDetails import io.element.android.libraries.matrix.ui.messages.reply.InReplyToView @@ -110,7 +109,6 @@ fun TimelineItemEventRow( isHighlighted: Boolean, onClick: () -> Unit, onLongClick: () -> Unit, - onShieldClick: (MessageShield) -> Unit, onLinkClick: (String) -> Unit, onUserDataClick: (UserId) -> Unit, inReplyToClick: (EventId) -> Unit, @@ -161,6 +159,17 @@ fun TimelineItemEventRow( ReplySwipeIndicator({ offset / 120 }) } TimelineItemEventRowContent( + event = event, + isHighlighted = isHighlighted, + timelineRoomInfo = timelineRoomInfo, + interactionSource = interactionSource, + onClick = onClick, + onLongClick = onLongClick, + inReplyToClick = ::inReplyToClick, + onUserDataClick = ::onUserDataClick, + onReactionClick = { emoji -> onReactionClick(emoji, event) }, + onReactionLongClick = { emoji -> onReactionLongClick(emoji, event) }, + onMoreReactionsClick = { onMoreReactionsClick(event) }, modifier = Modifier .absoluteOffset { IntOffset(x = offset.roundToInt(), y = 0) } .draggable( @@ -176,18 +185,7 @@ fun TimelineItemEventRow( }, state = state.draggableState, ), - event = event, - isHighlighted = isHighlighted, - timelineRoomInfo = timelineRoomInfo, - interactionSource = interactionSource, - onClick = onClick, - onLongClick = onLongClick, - onShieldClick = onShieldClick, - inReplyToClick = ::inReplyToClick, - onUserDataClick = ::onUserDataClick, - onReactionClick = { emoji -> onReactionClick(emoji, event) }, - onReactionLongClick = { emoji -> onReactionLongClick(emoji, event) }, - onMoreReactionsClick = { onMoreReactionsClick(event) }, + eventSink = eventSink, eventContentView = eventContentView, ) } @@ -200,12 +198,12 @@ fun TimelineItemEventRow( interactionSource = interactionSource, onClick = onClick, onLongClick = onLongClick, - onShieldClick = onShieldClick, inReplyToClick = ::inReplyToClick, onUserDataClick = ::onUserDataClick, onReactionClick = { emoji -> onReactionClick(emoji, event) }, onReactionLongClick = { emoji -> onReactionLongClick(emoji, event) }, onMoreReactionsClick = { onMoreReactionsClick(event) }, + eventSink = eventSink, eventContentView = eventContentView, ) } @@ -255,12 +253,12 @@ private fun TimelineItemEventRowContent( interactionSource: MutableInteractionSource, onClick: () -> Unit, onLongClick: () -> Unit, - onShieldClick: (MessageShield) -> Unit, inReplyToClick: () -> Unit, onUserDataClick: () -> Unit, onReactionClick: (emoji: String) -> Unit, onReactionLongClick: (emoji: String) -> Unit, onMoreReactionsClick: (event: TimelineItem.Event) -> Unit, + eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, modifier: Modifier = Modifier, eventContentView: @Composable (Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit, ) { @@ -322,9 +320,9 @@ private fun TimelineItemEventRowContent( ) { MessageEventBubbleContent( event = event, - onShieldClick = onShieldClick, onMessageLongClick = onLongClick, inReplyToClick = inReplyToClick, + eventSink = eventSink, eventContentView = eventContentView, ) } @@ -382,9 +380,9 @@ private fun MessageSenderInformation( @Composable private fun MessageEventBubbleContent( event: TimelineItem.Event, - onShieldClick: (MessageShield) -> Unit, onMessageLongClick: () -> Unit, inReplyToClick: () -> Unit, + eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, @SuppressLint("ModifierParameter") // need to rename this modifier to prevent linter false positives @Suppress("ModifierNaming") @@ -422,7 +420,7 @@ private fun MessageEventBubbleContent( @Composable fun WithTimestampLayout( timestampPosition: TimestampPosition, - onShieldClick: (MessageShield) -> Unit, + eventSink: (TimelineEvents.EventFromTimelineItem) -> Unit, modifier: Modifier = Modifier, canShrinkContent: Boolean = false, content: @Composable (onContentLayoutChange: (ContentAvoidingLayoutData) -> Unit) -> Unit, @@ -433,7 +431,7 @@ private fun MessageEventBubbleContent( content {} TimelineEventTimestampView( event = event, - onShieldClick = onShieldClick, + eventSink = eventSink, modifier = Modifier // Outer padding .padding(horizontal = 4.dp, vertical = 4.dp) @@ -454,7 +452,7 @@ private fun MessageEventBubbleContent( overlay = { TimelineEventTimestampView( event = event, - onShieldClick = onShieldClick, + eventSink = eventSink, modifier = Modifier .padding(horizontal = 8.dp, vertical = 4.dp) ) @@ -465,7 +463,7 @@ private fun MessageEventBubbleContent( content {} TimelineEventTimestampView( event = event, - onShieldClick = onShieldClick, + eventSink = eventSink, modifier = Modifier .align(Alignment.End) .padding(horizontal = 8.dp, vertical = 4.dp) @@ -513,7 +511,7 @@ private fun MessageEventBubbleContent( val contentWithTimestamp = @Composable { WithTimestampLayout( timestampPosition = timestampPosition, - onShieldClick = onShieldClick, + eventSink = eventSink, canShrinkContent = canShrinkContent, modifier = timestampLayoutModifier, content = { onContentLayoutChange -> 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 000ce19bd2..75f1ccc02c 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 @@ -29,7 +29,6 @@ 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.timeline.item.event.MessageShield @Composable fun TimelineItemGroupedEventsRow( @@ -40,7 +39,6 @@ fun TimelineItemGroupedEventsRow( focusedEventId: EventId?, onClick: (TimelineItem.Event) -> Unit, onLongClick: (TimelineItem.Event) -> Unit, - onShieldClick: (MessageShield) -> Unit, inReplyToClick: (EventId) -> Unit, onUserDataClick: (UserId) -> Unit, onLinkClick: (String) -> Unit, @@ -77,7 +75,6 @@ fun TimelineItemGroupedEventsRow( isLastOutgoingMessage = isLastOutgoingMessage, onClick = onClick, onLongClick = onLongClick, - onShieldClick = onShieldClick, inReplyToClick = inReplyToClick, onUserDataClick = onUserDataClick, onLinkClick = onLinkClick, @@ -102,7 +99,6 @@ private fun TimelineItemGroupedEventsRowContent( isLastOutgoingMessage: Boolean, onClick: (TimelineItem.Event) -> Unit, onLongClick: (TimelineItem.Event) -> Unit, - onShieldClick: (MessageShield) -> Unit, inReplyToClick: (EventId) -> Unit, onUserDataClick: (UserId) -> Unit, onLinkClick: (String) -> Unit, @@ -143,19 +139,18 @@ private fun TimelineItemGroupedEventsRowContent( renderReadReceipts = renderReadReceipts, isLastOutgoingMessage = isLastOutgoingMessage, focusedEventId = focusedEventId, + onUserDataClick = onUserDataClick, + onLinkClick = onLinkClick, onClick = onClick, onLongClick = onLongClick, - onShieldClick = onShieldClick, inReplyToClick = inReplyToClick, - onUserDataClick = onUserDataClick, - onLinkClick = onLinkClick, onReactionClick = onReactionClick, onReactionLongClick = onReactionLongClick, onMoreReactionsClick = onMoreReactionsClick, onReadReceiptClick = onReadReceiptClick, - eventSink = eventSink, onSwipeToReply = {}, onJoinCallClick = {}, + eventSink = eventSink, eventContentView = eventContentView, ) } @@ -188,7 +183,6 @@ internal fun TimelineItemGroupedEventsRowContentExpandedPreview() = ElementPrevi isLastOutgoingMessage = false, onClick = {}, onLongClick = {}, - onShieldClick = {}, inReplyToClick = {}, onUserDataClick = {}, onLinkClick = {}, @@ -213,7 +207,6 @@ internal fun TimelineItemGroupedEventsRowContentCollapsePreview() = ElementPrevi isLastOutgoingMessage = false, onClick = {}, onLongClick = {}, - onShieldClick = {}, inReplyToClick = {}, onUserDataClick = {}, onLinkClick = {}, 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 4af30081a0..56f509f9fb 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 @@ -30,7 +30,6 @@ import io.element.android.libraries.designsystem.text.toPx import io.element.android.libraries.designsystem.theme.highlightedMessageBackgroundColor import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield @Composable internal fun TimelineItemRow( @@ -43,7 +42,6 @@ internal fun TimelineItemRow( onLinkClick: (String) -> Unit, onClick: (TimelineItem.Event) -> Unit, onLongClick: (TimelineItem.Event) -> Unit, - onShieldClick: (MessageShield) -> Unit, inReplyToClick: (EventId) -> Unit, onReactionClick: (key: String, TimelineItem.Event) -> Unit, onReactionLongClick: (key: String, TimelineItem.Event) -> Unit, @@ -115,9 +113,8 @@ internal fun TimelineItemRow( isHighlighted = timelineItem.isEvent(focusedEventId), onClick = { onClick(timelineItem) }, onLongClick = { onLongClick(timelineItem) }, - onShieldClick = onShieldClick, - onUserDataClick = onUserDataClick, onLinkClick = onLinkClick, + onUserDataClick = onUserDataClick, inReplyToClick = inReplyToClick, onReactionClick = onReactionClick, onReactionLongClick = onReactionLongClick, @@ -141,7 +138,6 @@ internal fun TimelineItemRow( focusedEventId = focusedEventId, onClick = onClick, onLongClick = onLongClick, - onShieldClick = onShieldClick, inReplyToClick = inReplyToClick, onUserDataClick = onUserDataClick, onLinkClick = onLinkClick, From b245c69322f7ff5872464f37dbeecf5f4ce0eb96 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 13 Sep 2024 16:41:44 +0200 Subject: [PATCH 018/106] Send failure verified user : set the room key recipient strategy --- .../android/libraries/matrix/impl/RustMatrixClientFactory.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) 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 d29a233aa1..b0b89f4e07 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 @@ -60,9 +60,6 @@ class RustMatrixClientFactory @Inject constructor( .homeserverUrl(sessionData.homeserverUrl) .username(sessionData.userId) .setSessionDelegate(sessionDelegate) - .roomKeyRecipientStrategy( - strategy = CollectStrategy.DeviceBasedStrategy(false, true) - ) .use { it.build() } client.restoreSession(sessionData.toSession()) @@ -115,7 +112,7 @@ class RustMatrixClientFactory @Inject constructor( strategy = if (featureFlagService.isFeatureEnabled(FeatureFlags.InvisibleCrypto)) { CollectStrategy.IdentityBasedStrategy } else { - CollectStrategy.DeviceBasedStrategy(onlyAllowTrustedDevices = false, errorOnVerifiedUserProblem = false) + CollectStrategy.DeviceBasedStrategy(onlyAllowTrustedDevices = false, errorOnVerifiedUserProblem = true) } ) .run { From 16bf8f04fe49f96f9110fd7ea55e44539c37f191 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 13 Sep 2024 15:04:13 +0000 Subject: [PATCH 019/106] Update screenshots --- ...eatures.messages.impl.actionlist_SheetContent_Day_12_en.png | 3 +++ ...tures.messages.impl.actionlist_SheetContent_Night_12_en.png | 3 +++ ...ure.resolve_ResolveVerifiedUserSendFailureView_Day_0_en.png | 3 +++ ...ure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en.png | 3 +++ ...ure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en.png | 3 +++ ...e.resolve_ResolveVerifiedUserSendFailureView_Night_0_en.png | 3 +++ ...e.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png | 3 +++ ...e.resolve_ResolveVerifiedUserSendFailureView_Night_2_en.png | 3 +++ 8 files changed, 24 insertions(+) create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Day_12_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Night_12_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Day_12_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Day_12_en.png new file mode 100644 index 0000000000..362a9d5f95 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Day_12_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dccf918b02e10cc95f48de10ed7fbbf1d09fed2629d73ec09308a6604c02c0e3 +size 47777 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Night_12_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Night_12_en.png new file mode 100644 index 0000000000..b028117445 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Night_12_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa076d0959c240108d948841358a5f485f3ab53d470de58c9c81e6d0b32cbd43 +size 46843 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_0_en.png new file mode 100644 index 0000000000..1b6fb4bab8 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:96a867cb12498cbdc97957bee07855dfaa13602baddaf933aff2b666ef4c7650 +size 3642 diff --git a/tests/uitests/src/test/snapshots/images/features.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 new file mode 100644 index 0000000000..8b48d2c346 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad9fa358acfb3257129c6ad0966af876cb469bab06969bef1e56b286ce99fe8b +size 58822 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 new file mode 100644 index 0000000000..5b7b58e615 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a6261c5a443005e4cb8f3e8f8f176c4e367feca6d6c1eb89ecc6b72aac119d3 +size 55135 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_0_en.png new file mode 100644 index 0000000000..d6fd8eeb70 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5bb36ccd718f3fec5b04f1bc812dc7718b5ea7fa4619c8b031466297a8d016fd +size 3659 diff --git a/tests/uitests/src/test/snapshots/images/features.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 new file mode 100644 index 0000000000..7056928a24 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5704cb8201901bcb0a4a3a28a21390133fe1010fb928cae94530a2900f01e336 +size 57172 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 new file mode 100644 index 0000000000..59542a02f9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:423d72e2dab1e87c9ee52b170c730e189cb642e22d218cf4b2c7a99783cdda5f +size 53333 From aeea99196b4d018d32e2070bb4a46ce494e34087 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 13 Sep 2024 18:04:16 +0200 Subject: [PATCH 020/106] Send failure verified user : fix tests. --- .../features/messages/impl/MessagesPresenterTest.kt | 2 +- .../android/features/messages/impl/MessagesViewTest.kt | 10 +++------- .../messages/impl/timeline/TimelinePresenterTest.kt | 2 ++ .../android/features/roomdetails/MatrixRoomFixture.kt | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) 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 fec6ea000e..3d6af28f3d 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 @@ -1036,6 +1036,7 @@ class MessagesPresenterTest { sessionPreferencesStore = sessionPreferencesStore, timelineItemIndexer = TimelineItemIndexer(), timelineController = TimelineController(matrixRoom), + resolveVerifiedUserSendFailurePresenter = { aResolveVerifiedUserSendFailureState() }, ) val timelinePresenterFactory = object : TimelinePresenter.Factory { override fun create(navigator: MessagesNavigator): TimelinePresenter { @@ -1063,7 +1064,6 @@ class MessagesPresenterTest { reactionSummaryPresenter = reactionSummaryPresenter, readReceiptBottomSheetPresenter = readReceiptBottomSheetPresenter, pinnedMessagesBannerPresenter = { aLoadedPinnedMessagesBannerState() }, - resolveVerifiedUserSendFailurePresenter = { aResolveVerifiedUserSendFailureState() }, networkMonitor = FakeNetworkMonitor(), snackbarDispatcher = SnackbarDispatcher(), navigator = navigator, 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 08c1119a6a..210ffb4fe6 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 @@ -35,9 +35,7 @@ import io.element.android.features.messages.impl.actionlist.anActionListState import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUserSendFailure -import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureEvents import io.element.android.features.messages.impl.crypto.sendfailure.resolve.aChangedIdentitySendFailure -import io.element.android.features.messages.impl.crypto.sendfailure.resolve.aResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.messagecomposer.aMessageComposerState import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerItem import io.element.android.features.messages.impl.pinned.banner.aLoadedPinnedMessagesBannerState @@ -424,7 +422,7 @@ class MessagesViewTest { @Test fun `clicking on verified user send failure from action list emits the expected Event`() { - val eventsRecorder = EventsRecorder() + val eventsRecorder = EventsRecorder() val state = aMessagesState() val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event val stateWithActionListState = state.copy( @@ -436,9 +434,7 @@ class MessagesViewTest { actions = persistentListOf(), ), ), - resolveVerifiedUserSendFailureState = aResolveVerifiedUserSendFailureState( - eventSink = eventsRecorder - ), + timelineState = aTimelineState(eventSink = eventsRecorder) ) rule.setMessagesView( state = stateWithActionListState, @@ -447,7 +443,7 @@ class MessagesViewTest { rule.onNodeWithText(verifiedUserSendFailure).performClick() // Give time for the close animation to complete rule.mainClock.advanceTimeBy(milliseconds = 1_000) - eventsRecorder.assertSingle(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(timelineItem)) + eventsRecorder.assertSingle(TimelineEvents.ComputeVerifiedUserSendFailure(timelineItem)) } @Test 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 9df9dfc9f8..a0712907cc 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 @@ -13,6 +13,7 @@ import app.cash.turbine.ReceiveTurbine import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.FakeMessagesNavigator +import io.element.android.features.messages.impl.crypto.sendfailure.resolve.aResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.fixtures.aTimelineItemsFactoryCreator import io.element.android.features.messages.impl.timeline.components.aCriticalShield @@ -680,6 +681,7 @@ import kotlin.time.Duration.Companion.seconds sessionPreferencesStore = sessionPreferencesStore, timelineItemIndexer = timelineItemIndexer, timelineController = TimelineController(room), + resolveVerifiedUserSendFailurePresenter = { aResolveVerifiedUserSendFailureState() }, ) } } diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/MatrixRoomFixture.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/MatrixRoomFixture.kt index 0bcb881af6..8ff03a69b9 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/MatrixRoomFixture.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/MatrixRoomFixture.kt @@ -31,7 +31,7 @@ fun aMatrixRoom( emitRoomInfo: Boolean = false, canInviteResult: (UserId) -> Result = { lambdaError() }, canSendStateResult: (UserId, StateEventType) -> Result = { _, _ -> lambdaError() }, - userDisplayNameResult: () -> Result = { lambdaError() }, + userDisplayNameResult: (UserId) -> Result = { lambdaError() }, userAvatarUrlResult: () -> Result = { lambdaError() }, setNameResult: (String) -> Result = { lambdaError() }, setTopicResult: (String) -> Result = { lambdaError() }, From 1035f9ae602f5173ef87d0b88c59cd8bd6242e62 Mon Sep 17 00:00:00 2001 From: bmarty <3940906+bmarty@users.noreply.github.com> Date: Mon, 16 Sep 2024 00:25:04 +0000 Subject: [PATCH 021/106] Sync Strings from Localazy --- .../src/main/res/values-be/translations.xml | 6 - .../src/main/res/values-bg/translations.xml | 1 - .../src/main/res/values-cs/translations.xml | 6 - .../src/main/res/values-de/translations.xml | 6 - .../src/main/res/values-el/translations.xml | 6 - .../src/main/res/values-es/translations.xml | 6 - .../src/main/res/values-et/translations.xml | 6 - .../src/main/res/values-fr/translations.xml | 6 - .../src/main/res/values-hu/translations.xml | 6 - .../src/main/res/values-in/translations.xml | 6 - .../src/main/res/values-it/translations.xml | 6 - .../src/main/res/values-ka/translations.xml | 6 - .../src/main/res/values-nl/translations.xml | 6 - .../src/main/res/values-pl/translations.xml | 6 - .../main/res/values-pt-rBR/translations.xml | 6 - .../src/main/res/values-pt/translations.xml | 6 - .../src/main/res/values-ro/translations.xml | 6 - .../src/main/res/values-ru/translations.xml | 6 - .../src/main/res/values-sk/translations.xml | 6 - .../src/main/res/values-sv/translations.xml | 6 - .../src/main/res/values-uk/translations.xml | 6 - .../src/main/res/values-uz/translations.xml | 6 - .../main/res/values-zh-rTW/translations.xml | 1 - .../src/main/res/values-zh/translations.xml | 6 - .../impl/src/main/res/values/localazy.xml | 6 - .../src/main/res/values-cs/translations.xml | 4 + .../src/main/res/values-el/translations.xml | 6 + .../src/main/res/values-et/translations.xml | 4 + .../src/main/res/values-sk/translations.xml | 4 + .../impl/src/main/res/values/localazy.xml | 1 + .../src/main/res/values-be/translations.xml | 1 - .../src/main/res/values-cs/translations.xml | 1 - .../src/main/res/values-de/translations.xml | 4 - .../src/main/res/values-el/translations.xml | 14 +- .../src/main/res/values-et/translations.xml | 1 - .../src/main/res/values-fr/translations.xml | 1 - .../src/main/res/values-hu/translations.xml | 1 - .../src/main/res/values-in/translations.xml | 1 - .../src/main/res/values-it/translations.xml | 1 - .../src/main/res/values-pl/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 | 4 - .../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-zh/translations.xml | 1 - .../impl/src/main/res/values/localazy.xml | 1 - .../src/main/res/values-el/translations.xml | 2 + .../src/main/res/values-el/translations.xml | 6 + .../src/main/res/values-el/translations.xml | 1 + .../src/main/res/values-cs/translations.xml | 9 + .../src/main/res/values-el/translations.xml | 27 + .../src/main/res/values-et/translations.xml | 11 + .../src/main/res/values-sk/translations.xml | 9 + .../src/main/res/values/localazy.xml | 11 + ...al_EncryptedHistoryBannerView_Day_0_de.png | 3 - ...omponents_RoomListContentView_Day_4_de.png | 3 + screenshots/html/data.js | 1176 ++++++++--------- 59 files changed, 697 insertions(+), 757 deletions(-) delete mode 100644 screenshots/de/features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_de.png create mode 100644 screenshots/de/features.roomlist.impl.components_RoomListContentView_Day_4_de.png diff --git a/features/login/impl/src/main/res/values-be/translations.xml b/features/login/impl/src/main/res/values-be/translations.xml index f8e675854e..777acc423d 100644 --- a/features/login/impl/src/main/res/values-be/translations.xml +++ b/features/login/impl/src/main/res/values-be/translations.xml @@ -78,10 +78,4 @@ "Тут будуць захоўвацца вашыя размовы - сапраўды гэтак жа, як вы выкарыстоўваеце паштовага правайдара для захоўвання сваіх лістоў." "Вы збіраецеся ўвайсці ў %1$s" "Вы збіраецеся стварыць уліковы запіс на %1$s" - "Зараз існуе высокі попыт на %1$s на %2$s. Калі ласка, вярніцеся ў праграму праз некалькі дзён і паспрабуйце зноў. - -Дзякуй за цярпенне!" - "Вітаем у %1$s!" - "Амаль гатова." - "Вы зарэгістраваны." diff --git a/features/login/impl/src/main/res/values-bg/translations.xml b/features/login/impl/src/main/res/values-bg/translations.xml index cfc51c3f8c..eced3ef828 100644 --- a/features/login/impl/src/main/res/values-bg/translations.xml +++ b/features/login/impl/src/main/res/values-bg/translations.xml @@ -24,5 +24,4 @@ "Това е мястото, където ще живеят вашите разговори — точно както бихте използвали имейл доставчик, за да съхранявате вашите имейли." "На път сте да влезете в %1$s" "На път сте да създадете акаунт в %1$s" - "Добре дошли в %1$s!" diff --git a/features/login/impl/src/main/res/values-cs/translations.xml b/features/login/impl/src/main/res/values-cs/translations.xml index c0f00a87af..d65a5571e4 100644 --- a/features/login/impl/src/main/res/values-cs/translations.xml +++ b/features/login/impl/src/main/res/values-cs/translations.xml @@ -78,10 +78,4 @@ Zkuste se přihlásit ručně nebo naskenujte QR kód pomocí jiného zařízen "Zde budou uloženy vaše konverzace - podobně jako u poskytovatele e-mailových služeb uchováváte své e-maily." "Chystáte se přihlásit do služby %1$s" "Chystáte se vytvořit účet na %1$s" - "Na %2$s je momentálně vysoká poptávka po %1$s. Vraťte se do aplikace za pár dní a zkuste to znovu. - -Díky za trpělivost!" - "Vítá vás %1$s!" - "Jste v pořadníku!" - "Jdete do toho!" diff --git a/features/login/impl/src/main/res/values-de/translations.xml b/features/login/impl/src/main/res/values-de/translations.xml index 2399ec86ba..c2bdf37ca7 100644 --- a/features/login/impl/src/main/res/values-de/translations.xml +++ b/features/login/impl/src/main/res/values-de/translations.xml @@ -78,10 +78,4 @@ Versuche, dich manuell anzumelden, oder scanne den QR-Code mit einem anderen Ger "Hier werden deine Gespräche gespeichert - so wie du deine E-Mails bei einem E-Mail-Anbieter aufbewahren würden." "Du bist dabei, dich bei %1$s anzumelden" "Du bist dabei, ein Konto auf %1$s zu erstellen" - "Derzeit besteht eine hohe Nachfrage nach %1$s auf %2$s. Kehre in ein paar Tagen zur App zurück und versuche es erneut. - -Danke für deine Geduld!" - "Willkommen bei %1$s!" - "Du bist fast am Ziel." - "Du bist dabei." diff --git a/features/login/impl/src/main/res/values-el/translations.xml b/features/login/impl/src/main/res/values-el/translations.xml index 8ff0227168..24f26483fb 100644 --- a/features/login/impl/src/main/res/values-el/translations.xml +++ b/features/login/impl/src/main/res/values-el/translations.xml @@ -78,10 +78,4 @@ "Εδώ θα ζουν οι συνομιλίες σου - όπως θα χρησιμοποιούσες έναν πάροχο email για να διατηρήσεις τα email σου." "Πρόκειται να συνδεθείς στο %1$s" "Πρόκειται να δημιουργήσεις έναν λογαριασμό στο %1$s" - "Υπάρχει μεγάλη ζήτηση για το %1$s στον %2$s αυτή τη στιγμή. Επέστρεψε στην εφαρμογή σε λίγες μέρες και δοκίμασε ξανά. - -Ευχαριστώ για την υπομονή σου!" - "Καλώς ήρθες στο %1$s!" - "Σχεδόν τα κατάφερες." - "Είσαι μέσα." diff --git a/features/login/impl/src/main/res/values-es/translations.xml b/features/login/impl/src/main/res/values-es/translations.xml index c7537c9d7e..60324ae89d 100644 --- a/features/login/impl/src/main/res/values-es/translations.xml +++ b/features/login/impl/src/main/res/values-es/translations.xml @@ -37,10 +37,4 @@ "Aquí es donde se alojarán tus conversaciones — justo como utilizarías un proveedor de correo electrónico para guardar tus correos electrónicos." "Estás a punto de iniciar sesión en %1$s" "Estás a punto de crear una cuenta en %1$s" - "Hay una gran demanda para %1$s en %2$s en este momento. Vuelve a la aplicación en unos días e inténtalo de nuevo. - -¡Gracias por tu paciencia!" - "¡Bienvenido a %1$s!" - "Ya casi has terminado." - "Estás dentro." diff --git a/features/login/impl/src/main/res/values-et/translations.xml b/features/login/impl/src/main/res/values-et/translations.xml index 0558b349b4..f82ea50b91 100644 --- a/features/login/impl/src/main/res/values-et/translations.xml +++ b/features/login/impl/src/main/res/values-et/translations.xml @@ -78,10 +78,4 @@ Proovi käsitsi sisselogimist või skaneeri QR-koodi mõne muu seadmega.""See on koht, kus sinu vestlused elavad – just nagu kasutaksid oma e-kirjade säilitamiseks e-postitenuse pakkujat." "Sa oled sisselogimas koduserverisse %1$s" "Sa oled loomas kasutajakontot koduserveris %1$s" - "%1$s kasutamiseks %2$s koduserveris on hetkel palju huvilisi. Proovi seda samast rakendusest mõne päeva pärast. - -Täname kannatlikkuse eest!" - "Tere tulemast rakendusse %1$s!" - "Peaaegu olemas." - "Oled nüüd jututoas." diff --git a/features/login/impl/src/main/res/values-fr/translations.xml b/features/login/impl/src/main/res/values-fr/translations.xml index 49e513c2a8..a5928ffb3f 100644 --- a/features/login/impl/src/main/res/values-fr/translations.xml +++ b/features/login/impl/src/main/res/values-fr/translations.xml @@ -76,10 +76,4 @@ "C’est ici que vos conversations seront enregistrées, comme vous le feriez avec un fournisseur de messagerie pour conserver vos e-mails." "Vous êtes sur le point de vous connecter à %1$s" "Vous êtes sur le point de créer un compte sur %1$s" - "Il y a une forte demande pour %1$s sur %2$s à l’heure actuelle. Revenez sur l’application dans quelques jours et réessayez. - -Merci pour votre patience !" - "Bienvenue dans %1$s !" - "Vous y êtes presque." - "Vous y êtes." diff --git a/features/login/impl/src/main/res/values-hu/translations.xml b/features/login/impl/src/main/res/values-hu/translations.xml index 8d8bf40f3f..a37288fd6f 100644 --- a/features/login/impl/src/main/res/values-hu/translations.xml +++ b/features/login/impl/src/main/res/values-hu/translations.xml @@ -78,10 +78,4 @@ Próbáljon meg kézileg bejelentkezni, vagy olvassa be a QR-kódot egy másik e "Itt lesznek a beszélgetései – ahogyan egy e-mail-szolgáltatást is használna a levelei kezeléséhez." "Hamarosan bejelentkezik ebbe: %1$s" "Hamarosan létrehoz egy fiókot ezen: %1$s" - "Jelenleg nagy a kereslet a(z) %2$s oldalon futó %1$s iránt. Térjen vissza néhány nap múlva az alkalmazáshoz, és próbálja újra. - -Köszönjük a türelmét!" - "Üdvözli az %1$s!" - "Már majdnem kész van." - "Bent van." 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 97d84ff1f4..749406da04 100644 --- a/features/login/impl/src/main/res/values-in/translations.xml +++ b/features/login/impl/src/main/res/values-in/translations.xml @@ -78,10 +78,4 @@ Coba masuk secara manual, atau pindai kode QR dengan perangkat lain." "Di sinilah percakapan Anda akan berlangsung — sama seperti Anda menggunakan penyedia surel untuk menyimpan surel Anda." "Anda akan masuk ke %1$s" "Anda akan membuat akun di %1$s" - "Ada permintaan tinggi untuk %1$s di %2$s saat ini. Kembalilah ke aplikasi dalam beberapa hari dan coba lagi. - -Terima kasih atas kesabaran Anda!" - "Selamat datang di %1$s!" - "Anda hampir selesai." - "Anda sudah masuk." diff --git a/features/login/impl/src/main/res/values-it/translations.xml b/features/login/impl/src/main/res/values-it/translations.xml index dcd9a7c2ae..eaa5313b03 100644 --- a/features/login/impl/src/main/res/values-it/translations.xml +++ b/features/login/impl/src/main/res/values-it/translations.xml @@ -78,10 +78,4 @@ Prova ad accedere manualmente o scansiona il codice QR con un altro dispositivo. "Qui è dove vivranno le tue conversazioni — proprio come useresti un fornitore di posta elettronica per conservare le tue email." "Stai per accedere a %1$s" "Stai per creare un account su %1$s" - "Al momento c\'è una grande richiesta per %1$s su %2$s. Torna a visitare l\'app tra qualche giorno e riprova. - -Grazie per la pazienza!" - "Benvenuti in %1$s!" - "Ci sei quasi." - "Sei dentro." diff --git a/features/login/impl/src/main/res/values-ka/translations.xml b/features/login/impl/src/main/res/values-ka/translations.xml index 84e97e0a34..6fc49e7b41 100644 --- a/features/login/impl/src/main/res/values-ka/translations.xml +++ b/features/login/impl/src/main/res/values-ka/translations.xml @@ -34,10 +34,4 @@ "აქ იქნება თქვენი საუბრები - ისევე, როგორც თქვენ ელ. ფოსტაში ინახება თქვენი ელ.წერილები." "თქვენ აპირებთ შესვლას %1$s-ში" "თქვენ აპირებთ ანგარიშის შექმნას %1$s-ში" - "ახლა დიდი მოთხოვნაა %1$s-ზე %2$s-ში. დაბრუნდით რამდენიმე დღეში და სცადეთ ერთხელაც. - -მადლობა მოთმენისათვის!" - "კეთილი იყოს თქვენი მობრძანება %1$s-ში!" - "თითქმის მზადაა." - "თქვენ შეხვედით." diff --git a/features/login/impl/src/main/res/values-nl/translations.xml b/features/login/impl/src/main/res/values-nl/translations.xml index 80fbe57afb..0e351f8498 100644 --- a/features/login/impl/src/main/res/values-nl/translations.xml +++ b/features/login/impl/src/main/res/values-nl/translations.xml @@ -35,10 +35,4 @@ "Dit is waar je gesprekken zullen worden bewaard — net zoals je een e-mailprovider zou gebruiken om je e-mails te bewaren." "Je staat op het punt je aan te melden bij %1$s" "Je staat op het punt een account aan te maken op %1$s" - "Er is momenteel veel vraag naar %1$s op %2$s. Kom over een paar dagen terug naar de app en probeer het opnieuw. - -Bedankt voor je geduld!" - "Welkom bij %1$s!" - "Je bent er bijna." - "Je bent binnen." diff --git a/features/login/impl/src/main/res/values-pl/translations.xml b/features/login/impl/src/main/res/values-pl/translations.xml index 4d23e15fe8..6990121a43 100644 --- a/features/login/impl/src/main/res/values-pl/translations.xml +++ b/features/login/impl/src/main/res/values-pl/translations.xml @@ -78,10 +78,4 @@ Spróbuj zalogować się ręcznie lub zeskanuj kod QR na innym urządzeniu.""Tutaj będą przechowywane Twoje konwersacje - w podobnej formie jak wiadomości widnieją na skrzynce e-mail." "Zamierzasz się zalogować do %1$s" "Zamierzasz utworzyć konto na %1$s" - "Obecnie istnieje duże zapotrzebowanie na %1$s na %2$s. Wróć do aplikacji za kilka dni i spróbuj ponownie. - -Dziękujemy za Twoją cierpliwość!" - "Witamy w %1$s!" - "Już prawie gotowe!" - "Witamy!" diff --git a/features/login/impl/src/main/res/values-pt-rBR/translations.xml b/features/login/impl/src/main/res/values-pt-rBR/translations.xml index 4cb9b4f7b0..7b753ffb9f 100644 --- a/features/login/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/login/impl/src/main/res/values-pt-rBR/translations.xml @@ -34,10 +34,4 @@ "Aqui é onde suas conversas vão ficar — assim como você usa um provedor de e-mails para manter seus e-mails." "Você está prestes a fazer login em %1$s" "Você está prestes a criar uma conta em %1$s" - "Há uma grande demanda por %1$s sobre %2$s no momento. Volte ao aplicativo em alguns dias e tente novamente. - -Obrigado pela sua paciência!" - "Bem-vindo ao %1$s!" - "Você está quase lá." - "Você está dentro." diff --git a/features/login/impl/src/main/res/values-pt/translations.xml b/features/login/impl/src/main/res/values-pt/translations.xml index f5feb0cbdd..f03b48c5dd 100644 --- a/features/login/impl/src/main/res/values-pt/translations.xml +++ b/features/login/impl/src/main/res/values-pt/translations.xml @@ -78,10 +78,4 @@ Tenta iniciar a sessão manualmente ou digitaliza o código QR com outro disposi "É aqui que as tuas conversas vão ficar — tal como num serviço de e-mail." "Irás iniciar sessão em %1$s" "Irás criar uma conta em %1$s" - "Há uma grande procura pela %1$s no %2$s, de momento. Volta à aplicação daqui a uns dias e tenta novamente. - -Obrigado!" - "Bem-vindo à %1$s!" - "Estás quase lá." - "Estás dentro." diff --git a/features/login/impl/src/main/res/values-ro/translations.xml b/features/login/impl/src/main/res/values-ro/translations.xml index 1ff3fe2436..261f16d9f6 100644 --- a/features/login/impl/src/main/res/values-ro/translations.xml +++ b/features/login/impl/src/main/res/values-ro/translations.xml @@ -78,10 +78,4 @@ "Aici vor trăi conversațiile dvs. - la fel cum ați folosi un furnizor de e-mail pentru a vă păstra e-mailurile." "Sunteți pe cale să vă conectați la %1$s" "Sunteți pe cale să creați un cont pe %1$s" - "Există o cerere mare pentru %1$s pentru %2$s în acest moment. Reveniți la aplicație în câteva zile și încercați din nou. - -Vă mulțumim pentru răbdare!" - "Bun venit la%1$s!" - "Sunteți pe lista de așteptare" - "Sunteți conectat!" diff --git a/features/login/impl/src/main/res/values-ru/translations.xml b/features/login/impl/src/main/res/values-ru/translations.xml index c64d683a12..71a2691b4c 100644 --- a/features/login/impl/src/main/res/values-ru/translations.xml +++ b/features/login/impl/src/main/res/values-ru/translations.xml @@ -78,10 +78,4 @@ "Здесь будут храниться ваши разговоры - точно так же, как вы используете почтового провайдера для хранения своих писем." "Вы собираетесь войти в %1$s" "Вы собираетесь создать учетную запись на %1$s" - "В настоящее время существует высокий спрос на %1$s на %2$s. Вернитесь в приложение через несколько дней и попробуйте снова. - -Спасибо за терпение!" - "Добро пожаловать в %1$s!" - "Почти готово." - "Вы зарегистрированы." diff --git a/features/login/impl/src/main/res/values-sk/translations.xml b/features/login/impl/src/main/res/values-sk/translations.xml index fea7879d01..8d862609b7 100644 --- a/features/login/impl/src/main/res/values-sk/translations.xml +++ b/features/login/impl/src/main/res/values-sk/translations.xml @@ -78,10 +78,4 @@ Skúste sa prihlásiť manuálne alebo naskenujte QR kód pomocou iného zariade "Tu budú žiť vaše konverzácie - podobne ako používate poskytovateľa e-mailových služieb na uchovávanie e-mailov." "Chystáte sa prihlásiť do %1$s" "Chystáte sa vytvoriť účet na %1$s" - "Momentálne je veľký dopyt po %1$s na %2$s. Vráťte sa do aplikácie za pár dní a skúste to znova. - -Ďakujeme za trpezlivosť!" - "Vitajte v %1$s!" - "Ste na čakanej listine!" - "Ste dnu!" diff --git a/features/login/impl/src/main/res/values-sv/translations.xml b/features/login/impl/src/main/res/values-sv/translations.xml index d50610adcc..de290469ca 100644 --- a/features/login/impl/src/main/res/values-sv/translations.xml +++ b/features/login/impl/src/main/res/values-sv/translations.xml @@ -78,10 +78,4 @@ Prova att logga in manuellt eller skanna QR-koden med en annan enhet." "Det är här dina konversationer kommer att sparas - precis som du skulle använda en e-postleverantör för att spara dina e-brev." "Du är på väg att logga in på %1$s" "Du är på väg att skapa ett konto på %1$s" - "Det finns en stor efterfrågan på %1$s på %2$s just nu. Kom tillbaka till appen om några dagar och försök igen. - -Tack för ditt tålamod!" - "Välkommen till %1$s!" - "Du är nästan framme." - "Du är inne." diff --git a/features/login/impl/src/main/res/values-uk/translations.xml b/features/login/impl/src/main/res/values-uk/translations.xml index 9cb6eb1f5f..df436a9a69 100644 --- a/features/login/impl/src/main/res/values-uk/translations.xml +++ b/features/login/impl/src/main/res/values-uk/translations.xml @@ -78,10 +78,4 @@ "Тут будуть зберігатися Ваші розмови - так само, як Ви використовуєте поштову скриньку для зберігання своїх електронних листів." "Ви збираєтесь увійти в %1$s" "Ви збираєтеся створити обліковий запис на %1$s" - "На цей момент існує високий попит на %1$s в %2$s. Поверніться до застосунку через кілька днів і спробуйте ще раз. - -Дякуємо за терпіння!" - "Ласкаво просимо до %1$s!" - "Майже готово." - "Готово." diff --git a/features/login/impl/src/main/res/values-uz/translations.xml b/features/login/impl/src/main/res/values-uz/translations.xml index 67dc5129d7..db16e17b09 100644 --- a/features/login/impl/src/main/res/values-uz/translations.xml +++ b/features/login/impl/src/main/res/values-uz/translations.xml @@ -33,10 +33,4 @@ "Bu sizning suhbatlaringiz yashaydigan joy - xuddi siz elektron pochta xabarlaringizni saqlash uchun elektron pochta provayderidan foydalanganingiz kabi." "Siz tizimga kirmoqchisiz%1$s" "Hisob yaratmoqchisiz%1$s" - "Hozirgi paytda %2$sga %1$sda talab yuqori. Bir necha kundan keyin ilovaga qayting va qaytadan urining. - -Sabr-toqatingiz uchun rahmat!" - "%1$sga Xush kelibsiz!" - "Siz deyarli keldingiz." - "Siz kirdingiz." diff --git a/features/login/impl/src/main/res/values-zh-rTW/translations.xml b/features/login/impl/src/main/res/values-zh-rTW/translations.xml index d345095c4b..b66cfca31f 100644 --- a/features/login/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/login/impl/src/main/res/values-zh-rTW/translations.xml @@ -29,5 +29,4 @@ "您的所有對話將保存於此,就如同您的電子郵件供應商會保存您的電子郵件一樣。" "您即將登入 %1$s" "您即將在 %1$s 建立帳號" - "歡迎使用 %1$s!" diff --git a/features/login/impl/src/main/res/values-zh/translations.xml b/features/login/impl/src/main/res/values-zh/translations.xml index 0afd6dad93..2f24aacf69 100644 --- a/features/login/impl/src/main/res/values-zh/translations.xml +++ b/features/login/impl/src/main/res/values-zh/translations.xml @@ -78,10 +78,4 @@ "这是您的对话将进行的地方,就像您使用电子邮件提供商来保存电子邮件一样。" "即将登录 %1$s" "即将在 %1$s 上创建一个账户" - "目前 %1$s 上 %2$s 的负载很大。过几天再回来试试吧。 - -感谢您的耐心!" - "欢迎使用 %1$s" - "马上就好。" - "您已加入。" diff --git a/features/login/impl/src/main/res/values/localazy.xml b/features/login/impl/src/main/res/values/localazy.xml index cade81c4f2..b0b6252d52 100644 --- a/features/login/impl/src/main/res/values/localazy.xml +++ b/features/login/impl/src/main/res/values/localazy.xml @@ -78,10 +78,4 @@ Try signing in manually, or scan the QR code with another device." "This is where your conversations will live — just like you would use an email provider to keep your emails." "You’re about to sign in to %1$s" "You’re about to create an account on %1$s" - "There\'s a high demand for %1$s on %2$s at the moment. Come back to the app in a few days and try again. - -Thanks for your patience!" - "Welcome to %1$s!" - "You’re almost there." - "You\'re in." diff --git a/features/roomlist/impl/src/main/res/values-cs/translations.xml b/features/roomlist/impl/src/main/res/values-cs/translations.xml index 69779542a9..52a18f8e9c 100644 --- a/features/roomlist/impl/src/main/res/values-cs/translations.xml +++ b/features/roomlist/impl/src/main/res/values-cs/translations.xml @@ -1,5 +1,9 @@ + "Odhlásit se a upgradovat" + "Váš server nyní podporuje nový, rychlejší protokol. Chcete-li upgradovat, odhlaste se a znovu se přihlaste. Pokud to uděláte nyní, pomůže vám vyhnout se nucenému odhlášení, když bude starý protokol později odstraněn." + "Váš domovský server již nepodporuje starý protokol. Chcete-li pokračovat v používání aplikace, odhlaste se a znovu se přihlaste." + "Upgrade k dispozici" "Vygenerujte nový klíč pro obnovení, který lze použít k obnovení historie šifrovaných zpráv v případě, že ztratíte přístup ke svým zařízením." "Nastavení obnovy" "Vaše záloha chatu není aktuálně synchronizována. Abyste si zachovali přístup k záloze chatu, musíte potvrdit klíč pro obnovení." diff --git a/features/roomlist/impl/src/main/res/values-el/translations.xml b/features/roomlist/impl/src/main/res/values-el/translations.xml index 71aca711ad..a7e2a0f79f 100644 --- a/features/roomlist/impl/src/main/res/values-el/translations.xml +++ b/features/roomlist/impl/src/main/res/values-el/translations.xml @@ -1,5 +1,11 @@ + "Αποσύνδεση &amp; Αναβάθμιση" + "Ο διακομιστής σου υποστηρίζει τώρα ένα νέο, ταχύτερο πρωτόκολλο. Αποσυνδέσου και συνδέσου ξανά για αναβάθμιση τώρα. Κάνοντας αυτό τώρα θα σε βοηθήσει να αποφύγεις μια αναγκαστική αποσύνδεση όταν το παλιό πρωτόκολλο καταργηθεί αργότερα." + "Ο οικιακός διακομιστής σου δεν υποστηρίζει πλέον το παλιό πρωτόκολλο. Αποσυνδέσου και συνδέσου ξανά για να συνεχίσεις να χρησιμοποιείς την εφαρμογή." + "Διαθέσιμη αναβάθμιση" + "Δημιούργησε ένα νέο κλειδί ανάκτησης που μπορεί να χρησιμοποιηθεί για την επαναφορά του ιστορικού των κρυπτογραφημένων μηνυμάτων σου σε περίπτωση που χάσεις την πρόσβαση στις συσκευές σου." + "Ρύθμιση ανάκτησης" "Το αντίγραφο ασφαλείας της συνομιλίας σου δεν είναι συγχρονισμένο αυτήν τη στιγμή. Πρέπει να εισαγάγεις το κλειδί ανάκτησης για να διατηρήσεις την πρόσβαση στο αντίγραφο ασφαλείας της συνομιλίας σου." "Εισήγαγε το κλειδί ανάκτησης" "Για να διασφαλίσεις ότι δεν θα χάσεις ποτέ μια σημαντική κλήση, άλλαξε τις ρυθμίσεις σου για να επιτρέψεις τις ειδοποιήσεις πλήρους οθόνης όταν το τηλέφωνό σου είναι κλειδωμένο." diff --git a/features/roomlist/impl/src/main/res/values-et/translations.xml b/features/roomlist/impl/src/main/res/values-et/translations.xml index e64e0fc6e0..a8f61ea37a 100644 --- a/features/roomlist/impl/src/main/res/values-et/translations.xml +++ b/features/roomlist/impl/src/main/res/values-et/translations.xml @@ -1,5 +1,9 @@ + "Logi välja ja uuenda" + "Sinu koduserver toetab uut ja kiiremat protokolli. Uuendamiseks logi korraks rakendusest välja ja siis tagasi. Mingil hetkel tulevikus vana protokoll eemaldatakse kasutusest ja tehes uuenduse nüüd väldid hilisemat sundkorras uuendust." + "Sinu koduserver enam ei toeta vana protokolli. Jätkamaks rakenduse kasutamist palun logi välja ning seejärel tagasi." + "Saadaval on uuendus" "Loo uus taastevõti, mida saad kasutada oma krüptitud sõnumite ajaloo taastamisel olukorras, kus kaotad ligipääsu oma seadmetele." "Seadista taastamine" "Sinu vestluste varukoopia pole hetkel sünkroonis. Säilitamaks ligipääsu vestluse varukoopiale palun sisesta oma taastevõti." diff --git a/features/roomlist/impl/src/main/res/values-sk/translations.xml b/features/roomlist/impl/src/main/res/values-sk/translations.xml index 3d6e215cc6..f1d15ebbf1 100644 --- a/features/roomlist/impl/src/main/res/values-sk/translations.xml +++ b/features/roomlist/impl/src/main/res/values-sk/translations.xml @@ -1,5 +1,9 @@ + "Odhlásiť sa a aktualizovať" + "Váš server teraz podporuje nový, rýchlejší protokol. Odhláste sa a prihláste sa znova, aby ste mohli aktualizovať. Ak to urobíte teraz, pomôže vám vyhnúť sa nútenému odhláseniu, keď sa starý protokol neskôr odstráni." + "Váš domovský server už nepodporuje starý protokol. Ak chcete pokračovať v používaní aplikácie, odhláste sa a znova sa prihláste." + "Aktualizácia je k dispozícii" "Vytvorte nový kľúč na obnovenie, ktorý môžete použiť na obnovenie vašej histórie šifrovaných správ v prípade straty prístupu k vašim zariadeniam." "Nastaviť obnovenie" "Vaša záloha konverzácie nie je momentálne synchronizovaná. Na zachovanie prístupu k zálohe konverzácie musíte potvrdiť svoj kľúč na obnovu." diff --git a/features/roomlist/impl/src/main/res/values/localazy.xml b/features/roomlist/impl/src/main/res/values/localazy.xml index ff6c626c63..36dc4b8d65 100644 --- a/features/roomlist/impl/src/main/res/values/localazy.xml +++ b/features/roomlist/impl/src/main/res/values/localazy.xml @@ -2,6 +2,7 @@ "Log Out & Upgrade" "Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later." + "Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app." "Upgrade available" "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices." "Set up recovery" diff --git a/features/securebackup/impl/src/main/res/values-be/translations.xml b/features/securebackup/impl/src/main/res/values-be/translations.xml index 75e4c2ccb9..910350f41e 100644 --- a/features/securebackup/impl/src/main/res/values-be/translations.xml +++ b/features/securebackup/impl/src/main/res/values-be/translations.xml @@ -38,7 +38,6 @@ "Паўтарыце спробу, каб пацвердзіць доступ да рэзервовай копіі чата." "Няправільны ключ аднаўлення" "Калі ў вас ёсць ключ аднаўлення або парольная фраза, гэта таксама будзе працаваць." - "Ключ аднаўлення або код доступу" "Увесці…" "Страцілі ключ аднаўлення?" "Ключ аднаўлення пацверджаны" diff --git a/features/securebackup/impl/src/main/res/values-cs/translations.xml b/features/securebackup/impl/src/main/res/values-cs/translations.xml index 6425f52b66..ba113f9c89 100644 --- a/features/securebackup/impl/src/main/res/values-cs/translations.xml +++ b/features/securebackup/impl/src/main/res/values-cs/translations.xml @@ -39,7 +39,6 @@ "Zkuste prosím znovu potvrdit přístup k záloze chatu." "Nesprávný klíč pro obnovení" "Pokud máte bezpečnostní klíč nebo bezpečnostní frázi, bude to fungovat také." - "Klíč pro obnovení nebo přístupový kód" "Zadejte…" "Ztratili jste klíč pro obnovení?" "Klíč pro obnovení potvrzen" diff --git a/features/securebackup/impl/src/main/res/values-de/translations.xml b/features/securebackup/impl/src/main/res/values-de/translations.xml index c95e51db7e..413ae1ea81 100644 --- a/features/securebackup/impl/src/main/res/values-de/translations.xml +++ b/features/securebackup/impl/src/main/res/values-de/translations.xml @@ -51,10 +51,6 @@ Das bedeutet:" "Bitte versuche es noch einmal, um den Zugriff auf dein Chat-Backup zu bestätigen." "Falscher Wiederherstellungsschlüssel" "Dies funktioniert auch mit einem Sicherheitsschlüssel oder Sicherheitsphrase." - - "Wiederherstellungsschlüssel" - " oder Passcode" - "Eingeben…" "Hast du deinen Wiederherstellungschlüssel vergessen?" "Wiederherstellungsschlüssel bestätigt" diff --git a/features/securebackup/impl/src/main/res/values-el/translations.xml b/features/securebackup/impl/src/main/res/values-el/translations.xml index e62f465743..f4574b523d 100644 --- a/features/securebackup/impl/src/main/res/values-el/translations.xml +++ b/features/securebackup/impl/src/main/res/values-el/translations.xml @@ -16,6 +16,12 @@ "Ακολούθησε τις οδηγίες για να δημιουργήσεις ένα νέο κλειδί ανάκτησης" "Αποθήκευσε το νέο κλειδί ανάκτησης σε έναν διαχειριστή κωδικών πρόσβασης ή σε κρυπτογραφημένη σημείωση" "Επανάφερε την κρυπτογράφηση για το λογαριασμό σου χρησιμοποιώντας άλλη συσκευή" + "Συνέχιση επαναφοράς" + "Τα στοιχεία του λογαριασμού σου, οι επαφές, οι προτιμήσεις και η λίστα συνομιλιών θα διατηρηθούν" + "Θα χάσεις το υπάρχον ιστορικό μηνυμάτων σου" + "Θα χρειαστεί να επαληθεύσεις ξανά όλες τις υπάρχουσες συσκευές και επαφές σου" + "Επανάφερε την ταυτότητά σου μόνο εάν δεν έχεις πρόσβαση σε άλλη συνδεδεμένη συσκευή και έχεις χάσει το κλειδί ανάκτησης." + "Δεν μπορείς να επιβεβαιώσεις; Θα χρειαστεί να επαναφέρεις την ταυτότητά σου." "Απενεργοποίηση" "Θα χάσεις τα κρυπτογραφημένα μηνύματά σου εάν αποσυνδεθείς από όλες τις συσκευές." "Σίγουρα θες να απενεργοποιήσεις τα αντίγραφα ασφαλείας;" @@ -33,7 +39,6 @@ "Προσπάθησε ξανά για να επιβεβαιώσεις την πρόσβαση στο αντίγραφο ασφαλείας της συνομιλίας σου." "Λανθασμένο κλειδί ανάκτησης" "Εάν έχεις ένα κλειδί ασφαλείας ή μια φράση ασφαλείας, θα λειτουργήσει επίσης." - "Κλειδί ανάκτησης ή κωδικός πρόσβασης" "Εισαγωγή…" "Έχασες το κλειδί ανάκτησης;" "Επιβεβαιώθηκε το κλειδί ανάκτησης" @@ -51,4 +56,11 @@ "Βεβαιώσου ότι μπορείς να αποθηκεύσεις το κλειδί ανάκτησης κάπου ασφαλές" "Επιτυχής ρύθμιση ανάκτησης" "Ρύθμιση ανάκτησης" + "Ναι, επαναφορά τώρα" + "Η διαδικασία είναι μη αναστρέψιμη." + "Σίγουρα θες να επαναφέρεις την ταυτότητά σου;" + "Συνέβη ένα άγνωστο σφάλμα. Έλεγξε ότι ο κωδικός πρόσβασης του λογαριασμού σου είναι σωστός και δοκίμασε ξανά." + "Εισαγωγή…" + "Επιβεβαίωσε ότι θες να επαναφέρεις την ταυτότητά σου." + "Εισήγαγε τον κωδικό πρόσβασης του λογαριασμού σου για να συνεχίσεις" diff --git a/features/securebackup/impl/src/main/res/values-et/translations.xml b/features/securebackup/impl/src/main/res/values-et/translations.xml index 2c3aa2d12b..b618432839 100644 --- a/features/securebackup/impl/src/main/res/values-et/translations.xml +++ b/features/securebackup/impl/src/main/res/values-et/translations.xml @@ -39,7 +39,6 @@ "Kinnitamaks ligipääsu sinu vestluse varukoopiale, palun proovi uuesti" "Vigane taastevõti" "Kui sul on turvavõti või turvafraas, siis need toimivad ka." - "Taastevõti või turvafraas" "Sisesta…" "Kas sa oled taastevõtme kaotanud?" "Taastevõti on kinnitatud" diff --git a/features/securebackup/impl/src/main/res/values-fr/translations.xml b/features/securebackup/impl/src/main/res/values-fr/translations.xml index 6656e0a8e3..1b36266924 100644 --- a/features/securebackup/impl/src/main/res/values-fr/translations.xml +++ b/features/securebackup/impl/src/main/res/values-fr/translations.xml @@ -37,7 +37,6 @@ "Veuillez réessayer afin de pouvoir accéder à vos anciens messages." "Clé de récupération incorrecte" "Si vous avez une clé de sécurité ou une phrase de sécurité, cela fonctionnera également." - "Clé de récupération" "Saisissez la clé ici…" "Clé de récupération perdue?" "Clé de récupération confirmée" diff --git a/features/securebackup/impl/src/main/res/values-hu/translations.xml b/features/securebackup/impl/src/main/res/values-hu/translations.xml index 20575540b7..48fe08a31b 100644 --- a/features/securebackup/impl/src/main/res/values-hu/translations.xml +++ b/features/securebackup/impl/src/main/res/values-hu/translations.xml @@ -39,7 +39,6 @@ "Próbálja meg újra megerősíteni a csevegés biztonsági mentéséhez való hozzáférését." "Helytelen helyreállítási kulcs" "Ha van biztonsági kulcsa vagy biztonsági jelmondata, akkor ez is fog működni." - "Helyreállítási kulcs vagy jelkód" "Megadás…" "Elvesztette a helyreállítási kulcsát?" "Helyreállítási kulcs megerősítve" 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 83fa1f8092..62968d3471 100644 --- a/features/securebackup/impl/src/main/res/values-in/translations.xml +++ b/features/securebackup/impl/src/main/res/values-in/translations.xml @@ -33,7 +33,6 @@ "Silakan coba lagi untuk mengonfirmasi akses ke cadangan percakapan Anda." "Kunci pemulihan salah" "Jika Anda memiliki kunci keamanan atau frasa keamanan, ini juga bisa digunakan." - "Kunci pemulihan atau kode sandi" "Masukkan…" "Kehilangan kunci pemulihan Anda?" "Kunci pemulihan dikonfirmasi" 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 c1d67299ba..0e069b0ab2 100644 --- a/features/securebackup/impl/src/main/res/values-it/translations.xml +++ b/features/securebackup/impl/src/main/res/values-it/translations.xml @@ -38,7 +38,6 @@ "Riprova per confermare l\'accesso al backup della chat." "Chiave di recupero errata" "Se hai una chiave di sicurezza o una password, andrà bene anche questo." - "Chiave di recupero o codice di accesso" "Inserisci…" "Hai perso la chiave di recupero?" "Chiave di recupero confermata" diff --git a/features/securebackup/impl/src/main/res/values-pl/translations.xml b/features/securebackup/impl/src/main/res/values-pl/translations.xml index eea550627f..d708e18bab 100644 --- a/features/securebackup/impl/src/main/res/values-pl/translations.xml +++ b/features/securebackup/impl/src/main/res/values-pl/translations.xml @@ -38,7 +38,6 @@ "Spróbuj ponownie, aby potwierdzić dostęp do backupu czatu." "Nieprawidłowy klucz przywracania" "To też zadziała, jeśli posiadasz klucz lub frazę bezpieczeństwa." - "Klucz przywracania lub hasło" "Wprowadź…" "Zgubiłeś swój kod przywracania?" "Potwierdzono klucz przywracania" diff --git a/features/securebackup/impl/src/main/res/values-pt/translations.xml b/features/securebackup/impl/src/main/res/values-pt/translations.xml index f93e5dedf4..0e409ea22c 100644 --- a/features/securebackup/impl/src/main/res/values-pt/translations.xml +++ b/features/securebackup/impl/src/main/res/values-pt/translations.xml @@ -38,7 +38,6 @@ "Por favor, tenta novamente para confirmar o acesso à tua cópia de segurança das conversas." "Chave de recuperação incorreta" "Também funciona se tiveres uma chave ou frase de segurança." - "Chave ou código de recuperação" "Inserir…" "Perdeste a tua chave?" "Chave de recuperação confirmada" diff --git a/features/securebackup/impl/src/main/res/values-ro/translations.xml b/features/securebackup/impl/src/main/res/values-ro/translations.xml index 6b2f2e31dc..7266533d78 100644 --- a/features/securebackup/impl/src/main/res/values-ro/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ro/translations.xml @@ -33,7 +33,6 @@ "Vă rugăm să încercați din nou să confirmați accesul la backup." "Cheie de recuperare incorectă" "Dacă aveți o cheie de securitate sau o frază de securitate, aceasta va funcționa și ea." - "Cheie de recuperare sau cod de acces" "Introduceți…" "Ați pierdut cheia de recuperare?" "Cheia de recuperare confirmată" 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 8866dc9613..ae45ab45eb 100644 --- a/features/securebackup/impl/src/main/res/values-ru/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ru/translations.xml @@ -60,10 +60,6 @@ "ключ восстановления" "Если у вас есть пароль для восстановления или секретный пароль/ключ, это тоже сработает." - - "Ключ восстановления" - " или пароль" - "Вход…" "Потеряли ключ восстановления?" diff --git a/features/securebackup/impl/src/main/res/values-sk/translations.xml b/features/securebackup/impl/src/main/res/values-sk/translations.xml index 8a088f4245..24d80c6b00 100644 --- a/features/securebackup/impl/src/main/res/values-sk/translations.xml +++ b/features/securebackup/impl/src/main/res/values-sk/translations.xml @@ -39,7 +39,6 @@ "Skúste prosím znova potvrdiť prístup k vašej zálohe konverzácie." "Nesprávny kľúč na obnovenie" "Ak máte bezpečnostný kľúč alebo bezpečnostnú frázu, bude to fungovať tiež." - "Kľúč na obnovenie alebo prístupový kód" "Zadať…" "Stratili ste kľúč na obnovenie?" "Kľúč na obnovu potvrdený" diff --git a/features/securebackup/impl/src/main/res/values-sv/translations.xml b/features/securebackup/impl/src/main/res/values-sv/translations.xml index 3599320cd8..7b2364f450 100644 --- a/features/securebackup/impl/src/main/res/values-sv/translations.xml +++ b/features/securebackup/impl/src/main/res/values-sv/translations.xml @@ -39,7 +39,6 @@ "Vänligen pröva igen för att bekräfta åtkomsten till din chattsäkerhetskopia." "Felaktig återställningsnyckel" "Om du har en säkerhetsnyckel eller säkerhetsfras så funkar den också." - "Återställningsnyckel eller lösenkod" "Ange …" "Blivit av med din återställningsnyckel?" "Återställningsnyckel bekräftad" diff --git a/features/securebackup/impl/src/main/res/values-uk/translations.xml b/features/securebackup/impl/src/main/res/values-uk/translations.xml index 14e47f8bad..7d88980f8b 100644 --- a/features/securebackup/impl/src/main/res/values-uk/translations.xml +++ b/features/securebackup/impl/src/main/res/values-uk/translations.xml @@ -38,7 +38,6 @@ "Будь ласка, спробуйте ще раз, щоб підтвердити доступ до резервної копії чату." "Неправильний ключ відновлення" "Якщо у вас є ключ безпеки або фраза безпеки, це теж спрацює." - "Ключ відновлення або код допуску" "Ввести…" "Загубили ключ відновлення?" "Ключ відновлення підтверджено" diff --git a/features/securebackup/impl/src/main/res/values-zh/translations.xml b/features/securebackup/impl/src/main/res/values-zh/translations.xml index 0b4f12b17a..c8f2b7d9ed 100644 --- a/features/securebackup/impl/src/main/res/values-zh/translations.xml +++ b/features/securebackup/impl/src/main/res/values-zh/translations.xml @@ -38,7 +38,6 @@ "请重试以访问您的聊天备份。" "恢复密钥不正确" "如果您有安全密钥或安全短语,也可以用。" - "恢复密钥或密码" "输入……" "丢失了恢复密钥?" "恢复密钥已确认" diff --git a/features/securebackup/impl/src/main/res/values/localazy.xml b/features/securebackup/impl/src/main/res/values/localazy.xml index f4795c23da..55c6c547f5 100644 --- a/features/securebackup/impl/src/main/res/values/localazy.xml +++ b/features/securebackup/impl/src/main/res/values/localazy.xml @@ -39,7 +39,6 @@ "Please try again to confirm access to your chat backup." "Incorrect recovery key" "If you have a security key or security phrase, this will work too." - "Recovery key or passcode" "Enter…" "Lost your recovery key?" "Recovery key confirmed" diff --git a/features/verifysession/impl/src/main/res/values-el/translations.xml b/features/verifysession/impl/src/main/res/values-el/translations.xml index cc99091441..e53bd54e00 100644 --- a/features/verifysession/impl/src/main/res/values-el/translations.xml +++ b/features/verifysession/impl/src/main/res/values-el/translations.xml @@ -1,9 +1,11 @@ + "Δεν μπορείς να επιβεβαιώσεις;" "Δημιουργία νέου κλειδιού ανάκτησης" "Επαλήθευσε αυτήν τη συσκευή για να ρυθμίσεις την ασφαλή επικοινωνία." "Επιβεβαίωσε ότι είσαι εσύ" "Χρήση άλλης συσκευής" + "Χρήση κλειδιού ανάκτησης" "Τώρα μπορείς να διαβάζεις ή να στέλνεις μηνύματα με ασφάλεια και επίσης μπορεί να εμπιστευτεί αυτήν τη συσκευή οποιοσδήποτε με τον οποίο συνομιλείς." "Επαληθευμένη συσκευή" "Χρήση άλλης συσκευής" diff --git a/libraries/eventformatter/impl/src/main/res/values-el/translations.xml b/libraries/eventformatter/impl/src/main/res/values-el/translations.xml index 71adc9ed56..4e476d3c4b 100644 --- a/libraries/eventformatter/impl/src/main/res/values-el/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-el/translations.xml @@ -45,6 +45,12 @@ "Αφαίρεσες το όνομα του δωματίου" "Ο χρήστης %1$s δεν έκανε καμία αλλαγή" "Δεν έκανες καμία αλλαγή" + "Ο χρήστης %1$s άλλαξε τα καρφιτσωμένα μηνύματα" + "Άλλαξες τα καρφιτσωμένα μηνύματα" + "Ο χρήστης %1$s καρφίτσωσε ένα μήνυμα" + "Καρφίτσωσες ένα μήνυμα" + "Ο χρήστης %1$s ξεκαρφίτσωσε ένα μήνυμα" + "Ξεκαρφίτσωσες ένα μήνυμα" "Ο χρήστης %1$s απέρριψε την πρόσκληση" "Απέρριψες την πρόσκληση" "Ο χρήστης %1$s αφαίρεσε τον χρήστη %2$s" diff --git a/libraries/push/impl/src/main/res/values-el/translations.xml b/libraries/push/impl/src/main/res/values-el/translations.xml index 081adb46b8..b008447c80 100644 --- a/libraries/push/impl/src/main/res/values-el/translations.xml +++ b/libraries/push/impl/src/main/res/values-el/translations.xml @@ -34,6 +34,7 @@ "Γρήγορη απάντηση" "Σέ προσκάλεσε να συμμετάσχεις στο δωμάτιο" "Εγώ" + "Ο χρήστης %1$s αναφέρθηκε ή απάντησε" "Βλέπεις την ειδοποίηση! Κάνε μου κλικ!" "%1$s: %2$s" "%1$s: %2$s %3$s" diff --git a/libraries/ui-strings/src/main/res/values-cs/translations.xml b/libraries/ui-strings/src/main/res/values-cs/translations.xml index 6fcecc495b..164aed50f3 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -38,6 +38,7 @@ "Zpět" "Hovor" "Zrušit" + "Prozatím zrušit" "Vybrat fotku" "Vymazat" "Zavřít" @@ -288,6 +289,12 @@ Důvod: %1$s." "Připnuté zprávy" "Chystáte se přejít na svůj %1$s účet a obnovit svou identitu. Poté budete přesměrováni zpět do aplikace." "Nemůžete to potvrdit? Přejděte na svůj účet a resetujte svou identitu." + "Zrušit ověření a odeslat" + "Ověření můžete zrušit a přesto odeslat tuto zprávu, nebo můžete prozatím zrušit a zkusit to znovu později po opětovném ověření %1$s." + "Vaše zpráva nebyla odeslána, protože ověřená identita uživatele %1$s se změnila" + "Přesto odeslat zprávu" + "%1$s používá jedno nebo více neověřených zařízení. Zprávu můžete přesto odeslat, nebo můžete prozatím zrušit a zkusit to znovu později poté, co %2$s ověří všechna svá zařízení." + "Vaše zpráva nebyla odeslána, protože%1$s neověřil jedno nebo více zařízení" "Připnuté zprávy" "Nahrání média se nezdařilo, zkuste to prosím znovu." "Nepodařilo se načíst údaje o uživateli" @@ -309,6 +316,8 @@ Důvod: %1$s." "Otevřít v Mapách Google" "Otevřít v OpenStreetMap" "Sdílet tuto polohu" + "Zpráva nebyla odeslána, protože ověřená identita uživatele %1$s se změnila." + "Zpráva nebyla odeslána, protože%1$s neověřil jedno nebo více zařízení." "Poloha" "Verze: %1$s (%2$s)" "en" 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 b38211a60d..15d9c7244d 100644 --- a/libraries/ui-strings/src/main/res/values-el/translations.xml +++ b/libraries/ui-strings/src/main/res/values-el/translations.xml @@ -36,6 +36,7 @@ "Πίσω" "Κάλεσε" "Άκυρο" + "Ακύρωση προς το παρόν" "Επιλογή φωτογραφίας" "Εκκαθάριση" "Κλείσιμο" @@ -91,6 +92,7 @@ "Αναφορά σφάλματος" "Αναφορά περιεχομένου" "Επαναφορά" + "Επαναφορά ταυτότητας" "Επανάληψη" "Επανάληψη αποκρυπτογράφησης" "Αποθήκευση" @@ -111,6 +113,7 @@ "Πάτα για επιλογές" "Προσπάθησε ξανά" "Ξεκαρφίτσωμα" + "Προβολή στο χρονοδιάγραμμα" "Προβολή πηγής" "Ναι" "Σχετικά" @@ -176,6 +179,7 @@ "Άτομα" "Μόνιμος σύνδεσμος" "Αδεια" + "Καρφιτσωμένο" "Παρακαλώ περίμενε…" "Θες σίγουρα να τερματίσεις αυτή τη δημοσκόπηση;" "Δημοσκόπηση: %1$s" @@ -247,6 +251,7 @@ "Προειδοποίηση" "Οι αλλαγές σου δεν έχουν αποθηκευτεί. Σίγουρα θες να πας πίσω;" "Αποθήκευση αλλαγών;" + "Ο οικιακός διακομιστής σου πρέπει να αναβαθμιστεί για να υποστηρίζει το Matrix Authentication Server και τη δημιουργία λογαριασμού." "Αποτυχία δημιουργίας του μόνιμου συνδέσμου" "%1$s δεν ήταν δυνατή η φόρτωση του χάρτη. Παρακαλώ δοκίμασε ξανά αργότερα." "Αποτυχία φόρτωσης μηνυμάτων" @@ -259,6 +264,8 @@ "Ορισμένα μηνύματα δεν έχουν σταλεί" "Λυπούμαστε, παρουσιάστηκε σφάλμα" "Η αυθεντικότητα αυτού του κρυπτογραφημένου μηνύματος δεν είναι εγγυημένη σε αυτήν τη συσκευή." + "Κρυπτογραφημένο από έναν προηγουμένως επαληθευμένο χρήστη." + "Μη κρυπτογραφημένο." "Κρυπτογραφημένο από άγνωστη ή διαγεγραμμένη συσκευή." "Κρυπτογραφημένο από μια συσκευή που δεν έχει επαληθευτεί από τον ιδιοκτήτη της." "Κρυπτογραφημένο από μη επαληθευμένο χρήστη." @@ -266,9 +273,26 @@ "Γεια, μίλα μου στην εφαρμογή %1$s :%2$s" "%1$s Android" "Κούνησε δυνατά τη συσκευή σου για να αναφέρεις κάποιο σφάλμα" + "Δημιουργία λογαριασμού" "Αποτυχία επιλογής πολυμέσου, δοκίμασε ξανά." "Αποτυχία μεταφόρτωσης μέσου, δοκίμασε ξανά." "Αποτυχία μεταφόρτωσης πολυμέσων, δοκίμασε ξανά." + "Πάτα σε ένα μήνυμα και επέλεξε «%1$s» για να συμπεριληφθεί εδώ." + "Καρφίτσωσε σημαντικά μηνύματα, ώστε να μπορούν να εντοπιστούν εύκολα" + + "%1$d Καρφιτσωμένο μήνυμα" + "%1$d Καρφιτσωμένα μηνύματα" + + "Καρφιτσωμένα μηνύματα" + "Πρόκειται να μεταβείς στον λογαριασμό σου %1$s για να επαναφέρεις την ταυτότητά σου. Στη συνέχεια, θα επιστρέψεις στην εφαρμογή." + "Δεν μπορείς να επιβεβαιώσεις; Πήγαινε στον λογαριασμό σου για να επαναφέρεις την ταυτότητά σου." + "Ανάκληση επαλήθευσης και αποστολή" + "Μπορείτε να ανακαλέσεις την επαλήθευσή σου και να στείλεις αυτό το μήνυμα όπως και να \'χει ή μπορείς να το ακυρώσεις προς το παρόν και να προσπαθήσεις ξανά αργότερα μετά την επαλήθευση του χρήστη %1$s." + "Το μήνυμά σου δεν στάλθηκε επειδή η επαληθευμένη ταυτότητα του χρήστη %1$s έχει αλλάξει" + "Αποστολή μηνύματος ούτως ή άλλως" + "Ο χρήστης %1$s χρησιμοποιεί τουλάχιστον μία μη επαληθευμένη συσκευή. Μπορείς να στείλεις το μήνυμα όπως και να \'χει ή μπορείς να το ακυρώσεις προς το παρόν και να δοκιμάσεις ξανά αργότερα αφού ο χρήστης %2$s επαληθεύσει όλες τις συσκευές του." + "Το μήνυμά σου δεν στάλθηκε επειδή ο χρήστης %1$s δεν έχει επαληθεύσει τουλάχιστον μία συσκευή" + "Καρφιτσωμένα μηνύματα" "Αποτυχία μεταφόρτωσης μέσου, δοκίμασε ξανά." "Δεν ήταν δυνατή η ανάκτηση στοιχείων χρήστη" "Αποκλεισμός" @@ -280,6 +304,7 @@ "Κατάργηση αποκλεισμού χρήστη" "%1$s από %2$s" "%1$s Καρφιτσωμένα μηνύματα" + "Φόρτωση μηνύματος…" "Προβολή Όλων" "Συνομιλία" "Κοινή χρήση τοποθεσίας" @@ -288,6 +313,8 @@ "Άνοιγμα στο Google Maps" "Άνοιγμα στο OpenStreetMap" "Κοινή χρήση αυτής της τοποθεσίας" + "Το μήνυμα δεν στάλθηκε επειδή η επαληθευμένη ταυτότητα του χρήστη %1$s έχει αλλάξει." + "Το μήνυμα δεν στάλθηκε επειδή ο χρήστης %1$s δεν έχει επαληθεύσει τουλάχιστον μία συσκευή." "Τοποθεσία" "Έκδοση: %1$s (%2$s)" "el" 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 8f6c8740e6..74a646fb66 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -36,6 +36,7 @@ "Tagasi" "Helista kasutajale" "Loobu" + "Hetkel jäta tegemata" "Vali foto" "Selge" "Sulge" @@ -250,6 +251,7 @@ Põhjus: %1$s." "Hoiatus" "Sinu tehtud muudatused pole veel salvestatud. Kas sa oled kindel, et soovid minna tagasi?" "Kas salvestame muudatused?" + "Selleks et koos kasutajakonto loomisega toimiks Matrix Authentication Serveri tugi, vajab sinu koduserver uuendamist." "Püsilingi loomine ei õnnestumud" "%1$s kaardi laadimine ei õnnestunud. Palun proovi hiljem uuesti." "Sõnumite laadimine ei õnnestunud" @@ -271,6 +273,7 @@ Põhjus: %1$s." "Hei, suhtle minuga %1$s võrgus: %2$s" "%1$s Android" "Veast teatamiseks raputa nutiseadet ägedalt" + "Loo kasutajakonto" "Meediafaili valimine ei õnnestunud. Palun proovi uuesti." "Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti." "Meediafaili üleslaadimine ei õnnestunud. Palun proovi uuesti." @@ -283,6 +286,12 @@ Põhjus: %1$s." "Esiletõstetud sõnumid" "Oma võrguidentiteedi lähtestamiseks suuname sind %1$s kasutajakonto halduse lehele. Hiljem suunatakse sind tagasi sama rakenduse juurde." "Sa ei saa seda kinnitada? Ava oma kasutajakonto haldus ja lähtesta oma võrguidentiteet." + "Unusta verifitseerimine ja saada ikkagi" + "Sa võid jätta verifitseerimisvea tähelepanuta ja sõnumi ikkagi saata või katkestad saatmise ja peale kasutaja %1$s verifitseerimist proovid seda uuesti." + "Sinu sõnum on saatmata, kuna kasutaja %1$s verifitseeritud identiteet on muutunud." + "Saada sõnum ikkagi" + "%1$s kasutab ühte või enamat verifitseerimata seadet. Sa võid sõnumi ikkagi saata või katkestad selle ning ootad kuni %2$s on kõik oma seadmed verifitseerinud ning proovid seejärel uuesti." + "Sinu sõnum on saatmata, kuna %1$s pole verifitseerinud ühte või enamat oma seadet" "Esiletõstetud sõnumid" "Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti." "Kasutaja andmete laadimine ei õnnestunud" @@ -304,6 +313,8 @@ Põhjus: %1$s." "Ava Google Mapsis" "Ava OpenStreetMapis" "Jaga seda asukohta" + "Sõnum on saatmata, kuna kasutaja %1$s verifitseeritud identiteet on muutunud." + "Sõnum on saatmata, kuna %1$s pole verifitseerinud ühte või enamat oma seadet." "Asukoht" "Versioon: %1$s (%2$s)" "et" 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 5fbe3c55e7..3486ebeb15 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -38,6 +38,7 @@ "Späť" "Zavolať" "Zrušiť" + "Zatiaľ zrušiť" "Vybrať fotku" "Vyčistiť" "Zavrieť" @@ -288,6 +289,12 @@ Dôvod: %1$s." "Pripnuté správy" "Chystáte sa prejsť na svoj %1$s účet, aby ste obnovili svoju identitu. Potom budete vrátení späť do aplikácie." "Neviete potvrdiť? Prejdite do svojho účtu a obnovte svoju identitu." + "Odvolať overenie a odoslať" + "Svoje overenie môžete odvolať a odoslať túto správu aj tak, alebo ju môžete zatiaľ zrušiť a po opätovnom overení to skúsiť znova %1$s ." + "Vaša správa nebola odoslaná, pretože sa zmenila overená totožnosť používateľa %1$s." + "Odoslať správu aj tak" + "%1$s používa jedno alebo viac neoverených zariadení. Správu môžete odoslať aj tak, alebo ju môžete zatiaľ zrušiť a skúsiť to znova neskôr po %2$s overení všetkých zariadení." + "Vaša správa nebola odoslaná, pretože %1$s neoveril/a jedno alebo viac zariadení" "Pripnuté správy" "Nepodarilo sa spracovať médiá na odoslanie, skúste to prosím znova." "Nepodarilo sa získať údaje o používateľovi" @@ -309,6 +316,8 @@ Dôvod: %1$s." "Otvoriť v Mapách Google" "Otvoriť v OpenStreetMap" "Zdieľajte túto polohu" + "Správa nebola odoslaná, pretože sa zmenila overená totožnosť používateľa %1$s." + "Správa nebola odoslaná, pretože %1$s neoveril/a jedno alebo viac zariadení." "Poloha" "Verzia: %1$s (%2$s)" "sk" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index f7c3213ba4..3b8ad9ec24 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -36,6 +36,7 @@ "Back" "Call" "Cancel" + "Cancel for now" "Choose photo" "Clear" "Close" @@ -250,6 +251,7 @@ Reason: %1$s." "Warning" "Your changes have not been saved. Are you sure you want to go back?" "Save changes?" + "Your homeserver needs to be upgraded to support Matrix Authentication Server and account creation." "Failed creating the permalink" "%1$s could not load the map. Please try again later." "Failed loading messages" @@ -271,6 +273,7 @@ Reason: %1$s." "Hey, talk to me on %1$s: %2$s" "%1$s Android" "Rageshake to report bug" + "Create account" "Failed selecting media, please try again." "Failed processing media to upload, please try again." "Failed uploading media, please try again." @@ -283,6 +286,12 @@ Reason: %1$s." "Pinned messages" "You\'re about to go to your %1$s account to reset your identity. Afterwards you\'ll be taken back to the app." "Can\'t confirm? Go to your account to reset your identity." + "Withdraw verification and send" + "You can withdraw your verification and send this message anyway, or you can cancel for now and try again later after reverifying %1$s." + "Your message was not sent because %1$s’s verified identity has changed" + "Send message anyway" + "%1$s is using one or more unverified devices. You can send the message anyway, or you can cancel for now and try again later after %2$s has verified all their devices." + "Your message was not sent because %1$s has not verified one or more devices" "Pinned messages" "Failed processing media to upload, please try again." "Could not retrieve user details" @@ -304,6 +313,8 @@ Reason: %1$s." "Open in Google Maps" "Open in OpenStreetMap" "Share this location" + "Message not sent because %1$s’s verified identity has changed." + "Message not sent because %1$s has not verified one or more devices." "Location" "Version: %1$s (%2$s)" "en" diff --git a/screenshots/de/features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_de.png deleted file mode 100644 index b4f8b0f49a..0000000000 --- a/screenshots/de/features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:705b83e220abea5b572dab15e9a08414dbbe6beaa135086b9200653c781a51c9 -size 12658 diff --git a/screenshots/de/features.roomlist.impl.components_RoomListContentView_Day_4_de.png b/screenshots/de/features.roomlist.impl.components_RoomListContentView_Day_4_de.png new file mode 100644 index 0000000000..82bcfe7d5b --- /dev/null +++ b/screenshots/de/features.roomlist.impl.components_RoomListContentView_Day_4_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:afa1fbbfeafb9c3265c005b919d1da8d09ff10cd0e8ec60d7a1f42587c57a1b7 +size 73911 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 4e00986bda..8ae51996f2 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,41 +1,41 @@ // Generated file, do not edit export const screenshots = [ ["en","en-dark","de",], -["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",19972,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",19978,], ["features.invite.impl.response_AcceptDeclineInviteView_Day_0_en","features.invite.impl.response_AcceptDeclineInviteView_Night_0_en",0,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19972,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19972,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19972,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19972,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19978,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19978,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19978,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19978,], ["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,], ["features.login.impl.accountprovider_AccountProviderView_Day_4_en","features.login.impl.accountprovider_AccountProviderView_Night_4_en",0,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19972,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19972,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19972,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19972,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19972,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19972,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19972,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19972,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",19972,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",19972,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19972,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19972,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19972,], -["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19972,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19978,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19978,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19978,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19978,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19978,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19978,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19978,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19978,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",19978,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",19978,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19978,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19978,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19978,], +["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19978,], ["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",19972,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",19978,], ["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",19972,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",19978,], ["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",19972,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",19978,], ["libraries.designsystem.components.async_AsyncIndicatorFailure_Day_0_en","libraries.designsystem.components.async_AsyncIndicatorFailure_Night_0_en",0,], ["libraries.designsystem.components.async_AsyncIndicatorLoading_Day_0_en","libraries.designsystem.components.async_AsyncIndicatorLoading_Night_0_en",0,], ["libraries.designsystem.components.async_AsyncLoading_Day_0_en","libraries.designsystem.components.async_AsyncLoading_Night_0_en",0,], -["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",19972,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",19978,], ["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,], @@ -45,11 +45,11 @@ 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_AttachmentsView_0_en","",19972,], -["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19972,], -["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19972,], -["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19972,], -["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19972,], +["features.messages.impl.attachments.preview_AttachmentsView_0_en","",19978,], +["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19978,], +["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19978,], +["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19978,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19978,], ["libraries.designsystem.components.avatar_Avatar_Avatars_0_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_10_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_11_en","",0,], @@ -129,13 +129,13 @@ export const screenshots = [ ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], ["libraries.designsystem.components_BigCheckmark_Day_0_en","libraries.designsystem.components_BigCheckmark_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",19972,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19972,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19972,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19972,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19972,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19972,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19972,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",19978,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19978,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19978,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19978,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19978,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19978,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19978,], ["libraries.designsystem.components_BloomInitials_Day_0_en","libraries.designsystem.components_BloomInitials_Night_0_en",0,], ["libraries.designsystem.components_BloomInitials_Day_1_en","libraries.designsystem.components_BloomInitials_Night_1_en",0,], ["libraries.designsystem.components_BloomInitials_Day_2_en","libraries.designsystem.components_BloomInitials_Night_2_en",0,], @@ -146,87 +146,87 @@ export const screenshots = [ ["libraries.designsystem.components_BloomInitials_Day_7_en","libraries.designsystem.components_BloomInitials_Night_7_en",0,], ["libraries.designsystem.components_Bloom_Day_0_en","libraries.designsystem.components_Bloom_Night_0_en",0,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19972,], -["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19972,], -["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19972,], -["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19972,], -["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19972,], +["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19978,], +["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19978,], +["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19978,], +["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19978,], +["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19978,], ["libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_ButtonRowMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonRowMolecule_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_0_en","features.call.impl.ui_CallScreenPipView_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_1_en","features.call.impl.ui_CallScreenPipView_Night_1_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",19972,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19972,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19972,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19972,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19972,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19972,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19972,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19972,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19972,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19972,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19972,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19972,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19972,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19972,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19972,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19972,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19972,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19972,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19972,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19972,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19972,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",19978,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19978,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19978,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19978,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19978,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19978,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19978,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19978,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19978,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19978,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19978,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19978,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19978,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19978,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19978,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19978,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19978,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19978,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19978,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19978,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19978,], ["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",19972,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19972,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",19978,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19978,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19972,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19978,], ["libraries.designsystem.theme.components_Checkboxes_Toggles_en","",0,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], ["libraries.designsystem.theme_ColorAliases_Day_0_en","libraries.designsystem.theme_ColorAliases_Night_0_en",0,], ["libraries.textcomposer.components_ComposerOptionsButton_Day_0_en","libraries.textcomposer.components_ComposerOptionsButton_Night_0_en",0,], ["libraries.designsystem.components.avatar_CompositeAvatar_Avatars_en","",0,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19972,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19972,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19978,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19978,], ["features.preferences.impl.developer.tracing_ConfigureTracingView_Day_0_en","features.preferences.impl.developer.tracing_ConfigureTracingView_Night_0_en",0,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19972,], -["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19972,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19978,], +["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19978,], ["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_ConnectivityIndicatorView_Day_0_en","features.networkmonitor.api.ui_ConnectivityIndicatorView_Night_0_en",0,], -["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19972,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19972,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19972,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19972,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19972,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19972,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19972,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19972,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19972,], -["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19972,], -["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19972,], -["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19972,], -["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19972,], -["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19972,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19972,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19978,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19978,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19978,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19978,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19978,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19978,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19978,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19978,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19978,], +["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19978,], +["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19978,], +["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19978,], +["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19978,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19978,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19978,], ["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",19972,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19972,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19972,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",19978,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19978,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19978,], ["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",19972,], -["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19972,], -["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19972,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",19978,], +["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19978,], +["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19978,], ["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",19975,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",19975,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",19975,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19972,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19972,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19972,], -["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19972,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",19978,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",19978,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",19978,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19978,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19978,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19978,], +["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19978,], ["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,], @@ -238,12 +238,12 @@ 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",19972,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19972,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19972,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19972,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19972,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19972,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",19978,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19978,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19978,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19978,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19978,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19978,], ["libraries.matrix.ui.components_EditableAvatarView_Day_0_en","libraries.matrix.ui.components_EditableAvatarView_Night_0_en",0,], ["libraries.matrix.ui.components_EditableAvatarView_Day_1_en","libraries.matrix.ui.components_EditableAvatarView_Night_1_en",0,], ["libraries.matrix.ui.components_EditableAvatarView_Day_2_en","libraries.matrix.ui.components_EditableAvatarView_Night_2_en",0,], @@ -253,10 +253,9 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiPicker_Night_0_en",0,], -["features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Day_0_en","features.messages.impl.timeline.components.virtual_EncryptedHistoryBannerView_Night_0_en",19972,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19972,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19972,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19972,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19978,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19978,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19978,], ["features.messages.impl.timeline.debug_EventDebugInfoView_Day_0_en","features.messages.impl.timeline.debug_EventDebugInfoView_Night_0_en",0,], ["libraries.featureflag.ui_FeatureListView_Day_0_en","libraries.featureflag.ui_FeatureListView_Night_0_en",0,], ["libraries.designsystem.theme.components_FilledButtonLargeLowPadding_Buttons_en","",0,], @@ -267,15 +266,15 @@ export const screenshots = [ ["libraries.designsystem.theme.components_FloatingActionButton_Floating Action Buttons_en","",0,], ["libraries.designsystem.atomic.pages_FlowStepPage_Day_0_en","libraries.designsystem.atomic.pages_FlowStepPage_Night_0_en",0,], ["features.messages.impl.timeline.focus_FocusRequestStateView_Day_0_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_0_en",0,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19972,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19972,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19972,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19978,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19978,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19978,], ["libraries.textcomposer.components_FormattingOption_Day_0_en","libraries.textcomposer.components_FormattingOption_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_0_en","features.messages.impl.forward_ForwardMessagesView_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_1_en","features.messages.impl.forward_ForwardMessagesView_Night_1_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_2_en","features.messages.impl.forward_ForwardMessagesView_Night_2_en",0,], -["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19972,], -["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19972,], +["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19978,], +["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19978,], ["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,], @@ -302,37 +301,37 @@ 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",19972,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",19978,], ["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",19972,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",19978,], ["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",19972,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",19978,], ["libraries.designsystem.atomic.molecules_InfoListItemMolecule_Day_0_en","libraries.designsystem.atomic.molecules_InfoListItemMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.organisms_InfoListOrganism_Day_0_en","libraries.designsystem.atomic.organisms_InfoListOrganism_Night_0_en",0,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19972,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19978,], ["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",0,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19972,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19972,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19972,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19972,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19972,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19972,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19972,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19972,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19972,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19978,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19978,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19978,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19978,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19978,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19978,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19978,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19978,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19978,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], ["libraries.designsystem.components_LabelledOutlinedTextField_Day_0_en","libraries.designsystem.components_LabelledOutlinedTextField_Night_0_en",0,], ["libraries.designsystem.components_LabelledTextField_Day_0_en","libraries.designsystem.components_LabelledTextField_Night_0_en",0,], ["features.leaveroom.api_LeaveRoomView_Day_0_en","features.leaveroom.api_LeaveRoomView_Night_0_en",0,], -["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19972,], -["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19972,], -["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19972,], -["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19972,], -["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19972,], -["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19972,], +["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19978,], +["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19978,], +["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19978,], +["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19978,], +["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19978,], +["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19978,], ["libraries.designsystem.background_LightGradientBackground_Day_0_en","libraries.designsystem.background_LightGradientBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_LinearProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components.dialogs_ListDialogContent_Dialogs_en","",0,], @@ -383,28 +382,28 @@ export const screenshots = [ ["libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List supporting text - small padding_List sections_en","",0,], ["libraries.textcomposer.components_LiveWaveformView_Day_0_en","libraries.textcomposer.components_LiveWaveformView_Night_0_en",0,], ["appnav.room.joined_LoadingRoomNodeView_Day_0_en","appnav.room.joined_LoadingRoomNodeView_Night_0_en",0,], -["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",19972,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19972,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19972,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19972,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",19978,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19978,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19978,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19978,], ["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",19972,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19972,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19972,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19972,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19972,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19972,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19972,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19972,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19972,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19972,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19972,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19972,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19972,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19972,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19972,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",19978,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19978,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19978,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19978,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19978,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19978,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19978,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19978,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19978,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19978,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19978,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19978,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19978,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19978,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19978,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19972,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19978,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en","libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeader_Day_0_en","libraries.matrix.ui.components_MatrixUserHeader_Night_0_en",0,], @@ -414,7 +413,7 @@ export const screenshots = [ ["libraries.mediaviewer.api.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_10_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19972,], +["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19978,], ["libraries.mediaviewer.api.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_5_en","",0,], @@ -426,7 +425,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",19972,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",19978,], ["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_10_en","features.messages.impl.timeline.components_MessageEventBubble_Night_10_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_11_en","features.messages.impl.timeline.components_MessageEventBubble_Night_11_en",0,], @@ -443,7 +442,7 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessageEventBubble_Day_7_en","features.messages.impl.timeline.components_MessageEventBubble_Night_7_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_8_en","features.messages.impl.timeline.components_MessageEventBubble_Night_8_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_9_en","features.messages.impl.timeline.components_MessageEventBubble_Night_9_en",0,], -["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",19972,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",19978,], ["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,], @@ -451,25 +450,25 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessagesReactionButton_Day_1_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_1_en",0,], ["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.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19972,], -["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19972,], -["features.messages.impl.typing_MessagesViewWithTyping_Day_2_en","features.messages.impl.typing_MessagesViewWithTyping_Night_2_en",19972,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19972,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19972,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19972,], -["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19972,], -["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",19972,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",19972,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19972,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19972,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19972,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19972,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19972,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19972,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19972,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19972,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19978,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19978,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_2_en","features.messages.impl.typing_MessagesViewWithTyping_Night_2_en",19978,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19978,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19978,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19978,], +["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19978,], +["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",19978,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",19978,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19978,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19978,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19978,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19978,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19978,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19978,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19978,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19978,], ["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",19972,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",19978,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom Sheets_en","",0,], ["appicon.element_MonochromeIcon_en","",0,], @@ -478,28 +477,29 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelectedTrailingContent_Multiple selection List item - selection in trailing content_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple selection List item - selection in supporting text_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple selection List item - no selection_List items_en","",0,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19972,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19972,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19972,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19972,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19972,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19972,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19972,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19972,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19972,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19972,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19972,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19972,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19972,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19972,], +["features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Day_0_en","features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Night_0_en",0,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19978,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19978,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19978,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19978,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19978,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19978,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19978,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19978,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19978,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19978,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19978,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19978,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19978,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19978,], ["libraries.oidc.impl.webview_OidcView_Day_0_en","libraries.oidc.impl.webview_OidcView_Night_0_en",0,], ["libraries.oidc.impl.webview_OidcView_Day_1_en","libraries.oidc.impl.webview_OidcView_Night_1_en",0,], ["libraries.designsystem.atomic.pages_OnBoardingPage_Day_0_en","libraries.designsystem.atomic.pages_OnBoardingPage_Night_0_en",0,], -["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19972,], -["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19972,], -["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19972,], -["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19972,], -["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19972,], +["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19978,], +["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19978,], +["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19978,], +["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19978,], +["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19978,], ["libraries.designsystem.background_OnboardingBackground_Day_0_en","libraries.designsystem.background_OnboardingBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_OutlinedButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonLarge_Buttons_en","",0,], @@ -514,62 +514,62 @@ export const screenshots = [ ["libraries.designsystem.components_PageTitleWithIconFull_Day_3_en","libraries.designsystem.components_PageTitleWithIconFull_Night_3_en",0,], ["libraries.designsystem.components_PageTitleWithIconFull_Day_4_en","libraries.designsystem.components_PageTitleWithIconFull_Night_4_en",0,], ["libraries.designsystem.components_PageTitleWithIconMinimal_Day_0_en","libraries.designsystem.components_PageTitleWithIconMinimal_Night_0_en",0,], -["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19972,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19972,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19972,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19972,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19972,], +["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19978,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19978,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19978,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19978,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19978,], ["features.lockscreen.impl.components_PinEntryTextField_Day_0_en","features.lockscreen.impl.components_PinEntryTextField_Night_0_en",0,], ["libraries.designsystem.components_PinIcon_Day_0_en","libraries.designsystem.components_PinIcon_Night_0_en",0,], ["features.lockscreen.impl.unlock.keypad_PinKeypad_Day_0_en","features.lockscreen.impl.unlock.keypad_PinKeypad_Night_0_en",0,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",19972,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19972,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19972,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19972,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19972,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19972,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19972,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19972,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19972,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19972,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19972,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19972,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19972,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19972,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",19978,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19978,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19978,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19978,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19978,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19978,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19978,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19978,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19978,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19978,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19978,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19978,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19978,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19978,], ["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",19975,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",19978,], ["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",0,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",19972,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",19972,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",19972,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",19972,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",19972,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",19972,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",19972,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",19972,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",19975,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",19978,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",19978,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",19978,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",19978,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",19978,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",19978,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",19978,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",19978,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",19978,], ["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",0,], ["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",0,], ["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",0,], ["libraries.designsystem.atomic.atoms_PlaceholderAtom_Day_0_en","libraries.designsystem.atomic.atoms_PlaceholderAtom_Night_0_en",0,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",19972,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19972,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19972,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19972,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19972,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",19978,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19978,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19978,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19978,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19978,], ["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",19972,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19972,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19972,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19972,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19972,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19972,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19972,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19972,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19972,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19972,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19972,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",19978,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19978,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19978,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19978,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19978,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19978,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19978,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19978,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19978,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19978,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19978,], ["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,], @@ -586,191 +586,192 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceTextLight_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeDark_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeLight_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19972,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19972,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19972,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19972,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19978,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19978,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19978,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19978,], ["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","",19972,], -["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19972,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19972,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19972,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19972,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19972,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19972,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19972,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19972,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19972,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19972,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19972,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19972,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19972,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19972,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19972,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19972,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19972,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",19978,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19978,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19978,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19978,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19978,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19978,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19978,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19978,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19978,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19978,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19978,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19978,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19978,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19978,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19978,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19978,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19978,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19978,], ["libraries.designsystem.theme.components_RadioButton_Toggles_en","",0,], -["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19972,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19972,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19978,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19978,], ["features.rageshake.api.preferences_RageshakePreferencesView_Day_1_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_1_en",0,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19972,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19972,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19972,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19972,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19972,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19972,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19972,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19972,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19972,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",19975,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",19975,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19972,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19972,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19972,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19972,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19972,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19972,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19972,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19972,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19972,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19978,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19978,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19978,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19978,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19978,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19978,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19978,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19978,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19978,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",19978,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",19978,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19978,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19978,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19978,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19978,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19978,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19978,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19978,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19978,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19978,], ["libraries.designsystem.atomic.atoms_RedIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_RedIndicatorAtom_Night_0_en",0,], ["features.messages.impl.timeline.components_ReplySwipeIndicator_Day_0_en","features.messages.impl.timeline.components_ReplySwipeIndicator_Night_0_en",0,], -["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",19972,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19972,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19972,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19972,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19972,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19972,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",19972,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",19972,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",19972,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",19972,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",19978,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19978,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19978,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19978,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19978,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19978,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",19978,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",19978,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",19978,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",19978,], ["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",0,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",19972,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19972,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19972,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19972,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19972,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19972,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19972,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19972,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19972,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19972,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19972,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",19978,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19978,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19978,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19978,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19978,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19978,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19978,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19978,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19978,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19978,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19978,], ["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",0,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19972,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19978,], ["features.roomdetails.impl.components_RoomBadgeNegative_Day_0_en","features.roomdetails.impl.components_RoomBadgeNegative_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgeNeutral_Day_0_en","features.roomdetails.impl.components_RoomBadgeNeutral_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgePositive_Day_0_en","features.roomdetails.impl.components_RoomBadgePositive_Night_0_en",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",19972,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",19972,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",19972,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",19972,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",19975,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",19972,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",19972,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",19972,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",19972,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",19972,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",19972,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",19972,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",19972,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",19972,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19972,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19972,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19972,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19972,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19972,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19972,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19972,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19972,], -["features.roomdetails.impl_RoomDetails_0_en","",19972,], -["features.roomdetails.impl_RoomDetails_10_en","",19972,], -["features.roomdetails.impl_RoomDetails_11_en","",19972,], -["features.roomdetails.impl_RoomDetails_12_en","",19972,], -["features.roomdetails.impl_RoomDetails_13_en","",19975,], -["features.roomdetails.impl_RoomDetails_1_en","",19972,], -["features.roomdetails.impl_RoomDetails_2_en","",19972,], -["features.roomdetails.impl_RoomDetails_3_en","",19972,], -["features.roomdetails.impl_RoomDetails_4_en","",19972,], -["features.roomdetails.impl_RoomDetails_5_en","",19972,], -["features.roomdetails.impl_RoomDetails_6_en","",19972,], -["features.roomdetails.impl_RoomDetails_7_en","",19972,], -["features.roomdetails.impl_RoomDetails_8_en","",19972,], -["features.roomdetails.impl_RoomDetails_9_en","",19972,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19972,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19972,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19972,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19972,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19972,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19972,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19972,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19972,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19972,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19972,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19972,], -["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19972,], -["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19972,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",19978,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",19978,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",19978,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",19978,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",19978,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",19978,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",19978,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",19978,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",19978,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",19978,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",19978,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",19978,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",19978,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",19978,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19978,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19978,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19978,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19978,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19978,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19978,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19978,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19978,], +["features.roomdetails.impl_RoomDetails_0_en","",19978,], +["features.roomdetails.impl_RoomDetails_10_en","",19978,], +["features.roomdetails.impl_RoomDetails_11_en","",19978,], +["features.roomdetails.impl_RoomDetails_12_en","",19978,], +["features.roomdetails.impl_RoomDetails_13_en","",19978,], +["features.roomdetails.impl_RoomDetails_1_en","",19978,], +["features.roomdetails.impl_RoomDetails_2_en","",19978,], +["features.roomdetails.impl_RoomDetails_3_en","",19978,], +["features.roomdetails.impl_RoomDetails_4_en","",19978,], +["features.roomdetails.impl_RoomDetails_5_en","",19978,], +["features.roomdetails.impl_RoomDetails_6_en","",19978,], +["features.roomdetails.impl_RoomDetails_7_en","",19978,], +["features.roomdetails.impl_RoomDetails_8_en","",19978,], +["features.roomdetails.impl_RoomDetails_9_en","",19978,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19978,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19978,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19978,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19978,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19978,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19978,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19978,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19978,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19978,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19978,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19978,], +["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19978,], +["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19978,], ["features.roomlist.impl.components_RoomListContentView_Day_2_en","features.roomlist.impl.components_RoomListContentView_Night_2_en",0,], -["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19972,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19972,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19972,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19972,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19972,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19972,], +["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19978,], +["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19982,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19978,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19978,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19978,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19978,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19978,], ["features.roomlist.impl.search_RoomListSearchContent_Day_0_en","features.roomlist.impl.search_RoomListSearchContent_Night_0_en",0,], -["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19972,], -["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19972,], -["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19972,], -["features.roomlist.impl_RoomListView_Day_10_en","features.roomlist.impl_RoomListView_Night_10_en",19975,], -["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19972,], -["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19972,], -["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19972,], -["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19972,], -["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19972,], -["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19972,], -["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19972,], +["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19978,], +["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19978,], +["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19978,], +["features.roomlist.impl_RoomListView_Day_10_en","features.roomlist.impl_RoomListView_Night_10_en",19978,], +["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19978,], +["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19978,], +["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19978,], +["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19978,], +["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19978,], +["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19978,], +["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19978,], ["features.roomlist.impl_RoomListView_Day_8_en","features.roomlist.impl_RoomListView_Night_8_en",0,], ["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",0,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19972,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19972,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19972,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19972,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19972,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19972,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19972,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19972,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19978,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19978,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19978,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19978,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19978,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19978,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19978,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19978,], ["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",0,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19972,], -["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19972,], -["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19972,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19978,], +["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19978,], +["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19978,], ["libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Day_0_en","libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Night_0_en",0,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19972,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19972,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19972,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19972,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19972,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19972,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19972,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19972,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19972,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19978,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19978,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19978,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19978,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19978,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19978,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19978,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19978,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19978,], ["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_9_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_9_en",0,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19972,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19972,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19972,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19972,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19972,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19972,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19972,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19972,], -["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19972,], -["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19972,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19972,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19972,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19972,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19972,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19972,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19978,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19978,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19978,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19978,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19978,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19978,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19978,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19978,], +["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19978,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19978,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19978,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19978,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19978,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19978,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19978,], ["features.roomlist.impl.components_RoomSummaryPlaceholderRow_Day_0_en","features.roomlist.impl.components_RoomSummaryPlaceholderRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_0_en","features.roomlist.impl.components_RoomSummaryRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_10_en","features.roomlist.impl.components_RoomSummaryRow_Night_10_en",0,], @@ -793,10 +794,10 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_26_en","features.roomlist.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_27_en","features.roomlist.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_28_en","features.roomlist.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19972,], -["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19972,], -["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19972,], -["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19972,], +["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19978,], +["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19978,], +["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19978,], +["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19978,], ["features.roomlist.impl.components_RoomSummaryRow_Day_3_en","features.roomlist.impl.components_RoomSummaryRow_Night_3_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_4_en","features.roomlist.impl.components_RoomSummaryRow_Night_4_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_5_en","features.roomlist.impl.components_RoomSummaryRow_Night_5_en",0,], @@ -804,64 +805,64 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_7_en","features.roomlist.impl.components_RoomSummaryRow_Night_7_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_8_en","features.roomlist.impl.components_RoomSummaryRow_Night_8_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_9_en","features.roomlist.impl.components_RoomSummaryRow_Night_9_en",0,], -["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19972,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19972,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19972,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19978,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19978,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19978,], ["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",19972,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19972,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19972,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",19978,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19978,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19978,], ["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","",19972,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search views_en","",19978,], ["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,], -["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19972,], -["features.createroom.impl.components_SearchSingleUserResultItem_en","",19972,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19972,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19972,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19972,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19972,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19972,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19972,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19972,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19972,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19972,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19972,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19972,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19972,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19972,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19972,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19972,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19972,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19972,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19972,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19972,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19972,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19972,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19972,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19972,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19972,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19972,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19972,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19972,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19972,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19972,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19972,], +["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19978,], +["features.createroom.impl.components_SearchSingleUserResultItem_en","",19978,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19978,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19978,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19978,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19978,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19978,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19978,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19978,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19978,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19978,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19978,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19978,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19978,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19978,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19978,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19978,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19978,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19978,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19978,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19978,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19978,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19978,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19978,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19978,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19978,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19978,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19978,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19978,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19978,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19978,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19978,], ["libraries.matrix.ui.components_SelectedRoom_Day_0_en","libraries.matrix.ui.components_SelectedRoom_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoom_Day_1_en","libraries.matrix.ui.components_SelectedRoom_Night_1_en",0,], ["libraries.matrix.ui.components_SelectedUserCannotRemove_Day_0_en","libraries.matrix.ui.components_SelectedUserCannotRemove_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUser_Day_0_en","libraries.matrix.ui.components_SelectedUser_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUsersRowList_Day_0_en","libraries.matrix.ui.components_SelectedUsersRowList_Night_0_en",0,], ["libraries.textcomposer.components_SendButton_Day_0_en","libraries.textcomposer.components_SendButton_Night_0_en",0,], -["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19972,], -["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19972,], -["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19972,], -["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19972,], -["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19972,], +["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19978,], +["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19978,], +["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19978,], +["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19978,], +["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19978,], ["libraries.matrix.ui.messages.sender_SenderName_Day_0_en","libraries.matrix.ui.messages.sender_SenderName_Night_0_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_1_en","libraries.matrix.ui.messages.sender_SenderName_Night_1_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_2_en","libraries.matrix.ui.messages.sender_SenderName_Night_2_en",0,], @@ -871,39 +872,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.roomlist.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_SetUpRecoveryKeyBanner_Night_0_en",19975,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19972,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19972,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19972,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19972,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19972,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19972,], +["features.roomlist.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_SetUpRecoveryKeyBanner_Night_0_en",19978,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19978,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19978,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19978,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19978,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19978,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19978,], ["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",19972,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",19978,], ["features.messages.impl.actionlist_SheetContent_Day_0_en","features.messages.impl.actionlist_SheetContent_Night_0_en",0,], ["features.messages.impl.timeline.components.reactionsummary_SheetContent_Day_0_en","features.messages.impl.timeline.components.reactionsummary_SheetContent_Night_0_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19972,], -["features.messages.impl.actionlist_SheetContent_Day_11_en","features.messages.impl.actionlist_SheetContent_Night_11_en",19972,], +["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19978,], +["features.messages.impl.actionlist_SheetContent_Day_11_en","features.messages.impl.actionlist_SheetContent_Night_11_en",19978,], ["features.messages.impl.actionlist_SheetContent_Day_1_en","features.messages.impl.actionlist_SheetContent_Night_1_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19972,], -["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19972,], -["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19972,], -["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19972,], -["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19972,], -["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19972,], -["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19972,], -["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19972,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19972,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19972,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19972,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19972,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19972,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19972,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19972,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19972,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19972,], +["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19978,], +["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19978,], +["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19978,], +["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19978,], +["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19978,], +["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19978,], +["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19978,], +["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19978,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19978,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19978,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19978,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19978,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19978,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19978,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19978,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19978,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19978,], ["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,], ["libraries.designsystem.components.list_SingleSelectionListItemCustomFormattert_Single selection List item - custom formatter_List items_en","",0,], @@ -912,7 +913,7 @@ export const screenshots = [ ["libraries.designsystem.components.list_SingleSelectionListItemUnselectedWithSupportingText_Single selection List item - no selection, supporting text_List items_en","",0,], ["libraries.designsystem.components.list_SingleSelectionListItem_Single selection List item - no selection_List items_en","",0,], ["libraries.designsystem.theme.components_Sliders_Sliders_en","",0,], -["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19972,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19978,], ["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,], @@ -922,37 +923,37 @@ export const screenshots = [ ["libraries.designsystem.modifiers_SquareSizeModifierLargeHeight_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeWidth_en","",0,], ["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",0,], -["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19972,], +["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19978,], ["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",19972,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",19978,], ["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",19972,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",19978,], ["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_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19972,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19972,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19972,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19972,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19972,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19972,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19972,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19972,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19972,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19972,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19972,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19972,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19972,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19972,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19972,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19972,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19972,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19972,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19978,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19978,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19978,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19978,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19978,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19978,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19978,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19978,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19978,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19978,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19978,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19978,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19978,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19978,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19978,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19978,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19978,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19978,], ["libraries.textcomposer_TextComposerVoice_Day_0_en","libraries.textcomposer_TextComposerVoice_Night_0_en",0,], ["libraries.designsystem.theme.components_TextDark_Text_en","",0,], ["libraries.designsystem.theme.components_TextFieldDark_TextFields_en","",0,], @@ -964,26 +965,26 @@ export const screenshots = [ ["libraries.designsystem.theme.components_TextFieldValueTextFieldDark_TextFields_en","",0,], ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19972,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19972,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19972,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19978,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19978,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19978,], ["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",19972,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19972,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",19978,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19978,], ["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.event_TimelineImageWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_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_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19972,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19978,], ["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",19972,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19972,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19972,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",19978,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19978,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19978,], ["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,], @@ -991,16 +992,16 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",19972,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19972,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",19978,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19978,], ["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_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19972,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19978,], ["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",19972,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19972,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",19978,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19978,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en",0,], @@ -1009,36 +1010,36 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",19972,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",19978,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",19972,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",19978,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",0,], ["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","",19972,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",19978,], ["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_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19972,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19972,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19978,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19978,], ["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_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",19972,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",19978,], ["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",19972,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19972,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19972,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19972,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19972,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",19978,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19978,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19978,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19978,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19978,], ["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",19972,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19972,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",19978,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19978,], ["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",19972,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",19978,], ["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,], @@ -1047,8 +1048,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",19972,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19972,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",19978,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19978,], ["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,], @@ -1060,7 +1061,7 @@ 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",19972,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",19978,], ["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,], @@ -1082,84 +1083,84 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemVoiceView_Day_9_en","features.messages.impl.timeline.components.event_TimelineItemVoiceView_Night_9_en",0,], ["features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en",0,], -["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",19972,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19972,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",19978,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19978,], ["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",0,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",19972,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19972,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19972,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19972,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19972,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19972,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",19975,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19972,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",19978,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19978,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19978,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19978,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19978,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19978,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",19978,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19978,], ["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",19972,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",19978,], ["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",19972,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",19978,], ["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",19972,], +["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",19978,], ["features.messages.impl.timeline_TimelineView_Day_9_en","features.messages.impl.timeline_TimelineView_Night_9_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",19972,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19972,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19972,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19972,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19972,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19972,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19972,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19972,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",19978,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19978,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19978,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19978,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19978,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19978,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19978,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19978,], ["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",19972,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19972,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19972,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19972,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19972,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19972,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",19978,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19978,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19978,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19978,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19978,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19978,], ["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","",19972,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",19978,], ["libraries.matrix.ui.components_UnsavedAvatar_Day_0_en","libraries.matrix.ui.components_UnsavedAvatar_Night_0_en",0,], ["libraries.designsystem.components.avatar_UserAvatarColors_Day_0_en","libraries.designsystem.components.avatar_UserAvatarColors_Night_0_en",0,], -["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19972,], -["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19972,], -["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19972,], -["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19972,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19978,], +["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19978,], +["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19978,], +["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19978,], ["features.createroom.impl.components_UserListView_Day_3_en","features.createroom.impl.components_UserListView_Night_3_en",0,], ["features.createroom.impl.components_UserListView_Day_4_en","features.createroom.impl.components_UserListView_Night_4_en",0,], ["features.createroom.impl.components_UserListView_Day_5_en","features.createroom.impl.components_UserListView_Night_5_en",0,], ["features.createroom.impl.components_UserListView_Day_6_en","features.createroom.impl.components_UserListView_Night_6_en",0,], -["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19972,], +["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19978,], ["features.createroom.impl.components_UserListView_Day_8_en","features.createroom.impl.components_UserListView_Night_8_en",0,], -["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19972,], +["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19978,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], ["features.preferences.impl.user_UserPreferences_Day_2_en","features.preferences.impl.user_UserPreferences_Night_2_en",0,], ["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",0,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19972,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19972,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19972,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19972,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19972,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19972,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19972,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19972,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19972,], -["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19972,], -["features.verifysession.impl_VerifySelfSessionView_Day_10_en","features.verifysession.impl_VerifySelfSessionView_Night_10_en",19975,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19978,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19978,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19978,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19978,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19978,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19978,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19978,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19978,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19978,], +["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19978,], +["features.verifysession.impl_VerifySelfSessionView_Day_10_en","features.verifysession.impl_VerifySelfSessionView_Night_10_en",19978,], ["features.verifysession.impl_VerifySelfSessionView_Day_11_en","features.verifysession.impl_VerifySelfSessionView_Night_11_en",0,], ["features.verifysession.impl_VerifySelfSessionView_Day_12_en","features.verifysession.impl_VerifySelfSessionView_Night_12_en",0,], -["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19972,], -["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19972,], -["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19972,], -["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19972,], -["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19972,], -["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19972,], -["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19972,], -["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19972,], -["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19972,], +["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19978,], +["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19978,], +["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19978,], +["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19978,], +["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19978,], +["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19978,], +["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19978,], +["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19978,], +["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19978,], ["libraries.designsystem.ruler_VerticalRuler_Day_0_en","libraries.designsystem.ruler_VerticalRuler_Night_0_en",0,], ["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,], @@ -1173,12 +1174,7 @@ export const screenshots = [ ["libraries.textcomposer.components_VoiceMessageRecorderButton_Day_0_en","libraries.textcomposer.components_VoiceMessageRecorderButton_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessageRecording_Day_0_en","libraries.textcomposer.components_VoiceMessageRecording_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessage_Day_0_en","libraries.textcomposer.components_VoiceMessage_Night_0_en",0,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_0_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_0_en",19972,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_1_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_1_en",19972,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_2_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_2_en",19972,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_3_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_3_en",19972,], -["features.login.impl.screens.waitlistscreen_WaitListView_Day_4_en","features.login.impl.screens.waitlistscreen_WaitListView_Night_4_en",19972,], ["libraries.designsystem.components.media_WaveformPlaybackView_Day_0_en","libraries.designsystem.components.media_WaveformPlaybackView_Night_0_en",0,], -["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19972,], +["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19978,], ["libraries.designsystem.ruler_WithRulers_Day_0_en","libraries.designsystem.ruler_WithRulers_Night_0_en",0,], ]; From 663362ac7f85f2b53de6405737fedd2c2dc78de8 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 16 Sep 2024 11:13:02 +0200 Subject: [PATCH 022/106] Add forced logout flow when the proxy is no longer available (#3458) * Add `MatrixClient.isSlidingSyncProxySupported` function * Update localazy strings * Modify `ErrorDialog` to have an `onSubmit` call, which will be used for the submit action. Also make the title text optional and dismissing the dialog by tapping outside/going back configurable. * Check if a forced migration to SSS is needed because the proxy is no longer available. In that case, display the non-dismissable dialog and force the user to log out after enabling SSS. * Enable native/simplified sliding sync by default. * Refactor the login to make sure we: 1. Always try native/simplified sliding sync login first, if available. 2. Then, if it wasn't available or failed with an sliding sync not supported error, try with the proxy instead (either discovered proxy or forced custom one). * Move logic to `LoggedInPresenter` and the UI to `LoggedInView` * Update screenshots --------- Co-authored-by: ElementBot --- appnav/build.gradle.kts | 1 + .../android/appnav/loggedin/LoggedInEvents.kt | 2 + .../appnav/loggedin/LoggedInPresenter.kt | 17 +++ .../android/appnav/loggedin/LoggedInState.kt | 1 + .../appnav/loggedin/LoggedInStateProvider.kt | 3 + .../android/appnav/loggedin/LoggedInView.kt | 29 +++++ appnav/src/main/res/values/localazy.xml | 5 + .../appnav/loggedin/LoggedInPresenterTest.kt | 92 +++++++++++++- .../features/call/impl/ui/CallScreenView.kt | 2 +- .../features/leaveroom/api/LeaveRoomView.kt | 2 +- .../lockscreen/impl/setup/pin/SetupPinView.kt | 2 +- .../lockscreen/impl/unlock/PinUnlockView.kt | 4 +- .../impl/changeserver/ChangeServerView.kt | 2 +- .../ConfirmAccountProviderView.kt | 2 +- .../loginpassword/LoginPasswordView.kt | 2 +- .../src/main/res/values-be/translations.xml | 6 - .../src/main/res/values-bg/translations.xml | 1 - .../src/main/res/values-cs/translations.xml | 6 - .../src/main/res/values-de/translations.xml | 6 - .../src/main/res/values-el/translations.xml | 6 - .../src/main/res/values-es/translations.xml | 6 - .../src/main/res/values-et/translations.xml | 6 - .../src/main/res/values-fr/translations.xml | 6 - .../src/main/res/values-hu/translations.xml | 6 - .../src/main/res/values-in/translations.xml | 6 - .../src/main/res/values-it/translations.xml | 6 - .../src/main/res/values-ka/translations.xml | 6 - .../src/main/res/values-nl/translations.xml | 6 - .../src/main/res/values-pl/translations.xml | 6 - .../main/res/values-pt-rBR/translations.xml | 6 - .../src/main/res/values-pt/translations.xml | 6 - .../src/main/res/values-ro/translations.xml | 6 - .../src/main/res/values-ru/translations.xml | 6 - .../src/main/res/values-sk/translations.xml | 6 - .../src/main/res/values-sv/translations.xml | 6 - .../src/main/res/values-uk/translations.xml | 6 - .../src/main/res/values-uz/translations.xml | 6 - .../main/res/values-zh-rTW/translations.xml | 1 - .../src/main/res/values-zh/translations.xml | 6 - .../impl/src/main/res/values/localazy.xml | 6 - .../pinned/list/PinnedMessagesListView.kt | 2 +- .../timeline/focus/FocusRequestStateView.kt | 2 +- .../VoiceMessageSendingFailedDialog.kt | 2 +- .../notifications/NotificationSettingsView.kt | 2 +- .../RolesAndPermissionsView.kt | 2 +- .../changeroles/ChangeRolesView.kt | 2 +- .../impl/src/main/res/values/localazy.xml | 1 + .../src/main/res/values-be/translations.xml | 1 - .../src/main/res/values-cs/translations.xml | 1 - .../src/main/res/values-de/translations.xml | 4 - .../src/main/res/values-el/translations.xml | 1 - .../src/main/res/values-et/translations.xml | 1 - .../src/main/res/values-fr/translations.xml | 1 - .../src/main/res/values-hu/translations.xml | 1 - .../src/main/res/values-in/translations.xml | 1 - .../src/main/res/values-it/translations.xml | 1 - .../src/main/res/values-pl/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 | 4 - .../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-zh/translations.xml | 1 - .../impl/src/main/res/values/localazy.xml | 1 - .../components/async/AsyncActionView.kt | 2 +- .../components/dialogs/ErrorDialog.kt | 19 ++- .../libraries/matrix/api/MatrixClient.kt | 5 +- .../libraries/matrix/impl/RustMatrixClient.kt | 4 + .../matrix/impl/RustMatrixClientFactory.kt | 20 +-- .../auth/RustMatrixAuthenticationService.kt | 120 ++++++++++++++---- .../libraries/matrix/test/FakeMatrixClient.kt | 5 + .../impl/store/DefaultAppPreferencesStore.kt | 2 +- .../src/main/res/values/localazy.xml | 9 ++ .../android/samples/minimal/MainActivity.kt | 2 +- .../services/apperror/impl/AppErrorView.kt | 2 +- .../appnav.loggedin_LoggedInView_Day_3_en.png | 3 + ...ppnav.loggedin_LoggedInView_Night_3_en.png | 3 + tools/localazy/config.json | 7 + 79 files changed, 315 insertions(+), 231 deletions(-) create mode 100644 appnav/src/main/res/values/localazy.xml create mode 100644 tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_3_en.png diff --git a/appnav/build.gradle.kts b/appnav/build.gradle.kts index fae6fc9c15..fd389645a9 100644 --- a/appnav/build.gradle.kts +++ b/appnav/build.gradle.kts @@ -59,6 +59,7 @@ dependencies { testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.oidc.impl) + testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.push.test) testImplementation(projects.libraries.pushproviders.test) testImplementation(projects.features.networkmonitor.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 cd156bce02..4f60e543bb 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 @@ -9,4 +9,6 @@ package io.element.android.appnav.loggedin sealed interface LoggedInEvents { data class CloseErrorDialog(val doNotShowAgain: Boolean) : LoggedInEvents + data object CheckSlidingSyncProxyAvailability : LoggedInEvents + data object LogoutAndMigrateToNativeSlidingSync : 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 e6779c2c99..c619629152 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 @@ -16,6 +16,7 @@ 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 im.vector.app.features.analytics.plan.CryptoSessionStateChange import im.vector.app.features.analytics.plan.UserProperties import io.element.android.features.networkmonitor.api.NetworkMonitor @@ -29,6 +30,7 @@ import io.element.android.libraries.matrix.api.encryption.RecoveryState import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus +import io.element.android.libraries.preferences.api.store.EnableNativeSlidingSyncUseCase import io.element.android.libraries.push.api.PushService import io.element.android.libraries.pushproviders.api.RegistrationFailure import io.element.android.services.analytics.api.AnalyticsService @@ -48,6 +50,7 @@ class LoggedInPresenter @Inject constructor( private val sessionVerificationService: SessionVerificationService, private val analyticsService: AnalyticsService, private val encryptionService: EncryptionService, + private val enableNativeSlidingSyncUseCase: EnableNativeSlidingSyncUseCase, ) : Presenter { @Composable override fun present(): LoggedInState { @@ -78,6 +81,7 @@ class LoggedInPresenter @Inject constructor( networkStatus == NetworkStatus.Online && syncIndicator == RoomListService.SyncIndicator.Show } } + var forceNativeSlidingSyncMigration by remember { mutableStateOf(false) } LaunchedEffect(Unit) { combine( sessionVerificationService.sessionVerifiedStatus, @@ -97,6 +101,18 @@ class LoggedInPresenter @Inject constructor( } } } + LoggedInEvents.CheckSlidingSyncProxyAvailability -> coroutineScope.launch { + // Force the user to log out if they were using the proxy sliding sync and it's no longer available, but native sliding sync is. + forceNativeSlidingSyncMigration = !matrixClient.isUsingNativeSlidingSync() && + matrixClient.isNativeSlidingSyncSupported() && + !matrixClient.isSlidingSyncProxySupported() + } + LoggedInEvents.LogoutAndMigrateToNativeSlidingSync -> coroutineScope.launch { + // Enable native sliding sync if it wasn't already the case + enableNativeSlidingSyncUseCase() + // Then force the logout + matrixClient.logout(userInitiated = true, ignoreSdkError = true) + } } } @@ -104,6 +120,7 @@ class LoggedInPresenter @Inject constructor( showSyncSpinner = showSyncSpinner, pusherRegistrationState = pusherRegistrationState.value, ignoreRegistrationError = ignoreRegistrationError, + forceNativeSlidingSyncMigration = forceNativeSlidingSyncMigration, 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 7ef0e6f549..2735b02706 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 @@ -13,5 +13,6 @@ data class LoggedInState( val showSyncSpinner: Boolean, val pusherRegistrationState: AsyncData, val ignoreRegistrationError: Boolean, + val forceNativeSlidingSyncMigration: Boolean, val eventSink: (LoggedInEvents) -> Unit, ) 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 bcc88b1c3a..13d100820b 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 @@ -16,15 +16,18 @@ open class LoggedInStateProvider : PreviewParameterProvider { aLoggedInState(), aLoggedInState(showSyncSpinner = true), aLoggedInState(pusherRegistrationState = AsyncData.Failure(PusherRegistrationFailure.NoDistributorsAvailable())), + aLoggedInState(forceNativeSlidingSyncMigration = true), ) } fun aLoggedInState( showSyncSpinner: Boolean = false, pusherRegistrationState: AsyncData = AsyncData.Uninitialized, + forceNativeSlidingSyncMigration: Boolean = false, ) = LoggedInState( showSyncSpinner = showSyncSpinner, pusherRegistrationState = pusherRegistrationState, ignoreRegistrationError = false, + forceNativeSlidingSyncMigration = forceNativeSlidingSyncMigration, 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 0af150e0b7..3134270965 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 @@ -15,10 +15,14 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource 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.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.ui.strings.CommonStrings @@ -28,6 +32,11 @@ fun LoggedInView( navigateToNotificationTroubleshoot: () -> Unit, modifier: Modifier = Modifier ) { + OnLifecycleEvent { _, event -> + if (event == Lifecycle.Event.ON_RESUME) { + state.eventSink(LoggedInEvents.CheckSlidingSyncProxyAvailability) + } + } Box( modifier = modifier .fillMaxSize() @@ -61,6 +70,13 @@ fun LoggedInView( } } } + + // Set the force migration dialog here so it's always displayed over every screen + if (state.forceNativeSlidingSyncMigration) { + ForceNativeSlidingSyncMigrationDialog(onSubmit = { + state.eventSink(LoggedInEvents.LogoutAndMigrateToNativeSlidingSync) + }) + } } private fun Throwable.getReason(): String? { @@ -80,6 +96,19 @@ private fun Throwable.getReason(): String? { } } +@Composable +private fun ForceNativeSlidingSyncMigrationDialog( + onSubmit: () -> Unit, +) { + ErrorDialog( + title = null, + content = stringResource(R.string.banner_migrate_to_native_sliding_sync_force_logout_title), + submitText = stringResource(R.string.banner_migrate_to_native_sliding_sync_action), + onSubmit = onSubmit, + canDismiss = false, + ) +} + @PreviewsDayNight @Composable internal fun LoggedInViewPreview(@PreviewParameter(LoggedInStateProvider::class) state: LoggedInState) = ElementPreview { diff --git a/appnav/src/main/res/values/localazy.xml b/appnav/src/main/res/values/localazy.xml new file mode 100644 index 0000000000..bb6df44051 --- /dev/null +++ b/appnav/src/main/res/values/localazy.xml @@ -0,0 +1,5 @@ + + + "Log Out & Upgrade" + "Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app." + 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 ee060f3444..519cceddfe 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 @@ -29,6 +29,8 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient 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.verification.FakeSessionVerificationService +import io.element.android.libraries.preferences.api.store.EnableNativeSlidingSyncUseCase +import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.libraries.push.api.PushService import io.element.android.libraries.push.test.FakePushService import io.element.android.libraries.pushproviders.api.Distributor @@ -42,6 +44,10 @@ import io.element.android.tests.testutils.lambda.any import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -91,7 +97,8 @@ class LoggedInPresenterTest { pushService = FakePushService(), sessionVerificationService = verificationService, analyticsService = analyticsService, - encryptionService = encryptionService + encryptionService = encryptionService, + enableNativeSlidingSyncUseCase = EnableNativeSlidingSyncUseCase(InMemoryAppPreferencesStore(), this), ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -487,26 +494,103 @@ class LoggedInPresenterTest { ) } + @Test + fun `present - CheckSlidingSyncProxyAvailability forces the sliding sync migration under the right circumstances`() = runTest { + // The migration will be forced if: + // - The user is not using the native sliding sync + // - The sliding sync proxy is no longer supported + // - The native sliding sync is supported + val matrixClient = FakeMatrixClient( + isUsingNativeSlidingSyncLambda = { false }, + isSlidingSyncProxySupportedLambda = { false }, + isNativeSlidingSyncSupportedLambda = { true }, + ) + val presenter = createLoggedInPresenter(matrixClient = matrixClient) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.forceNativeSlidingSyncMigration).isFalse() + + initialState.eventSink(LoggedInEvents.CheckSlidingSyncProxyAvailability) + + assertThat(awaitItem().forceNativeSlidingSyncMigration).isTrue() + } + } + + @Test + fun `present - CheckSlidingSyncProxyAvailability will not force the migration if native sliding sync is not supported too`() = runTest { + val matrixClient = FakeMatrixClient( + isUsingNativeSlidingSyncLambda = { false }, + isSlidingSyncProxySupportedLambda = { false }, + isNativeSlidingSyncSupportedLambda = { false }, + ) + val presenter = createLoggedInPresenter(matrixClient = matrixClient) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.forceNativeSlidingSyncMigration).isFalse() + + initialState.eventSink(LoggedInEvents.CheckSlidingSyncProxyAvailability) + + expectNoEvents() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `present - LogoutAndMigrateToNativeSlidingSync enables native sliding sync and logs out the user`() = runTest { + val logoutLambda = lambdaRecorder { userInitiated, ignoreSdkError -> + assertThat(userInitiated).isTrue() + assertThat(ignoreSdkError).isTrue() + null + } + val matrixClient = FakeMatrixClient().apply { + this.logoutLambda = logoutLambda + } + val appPreferencesStore = InMemoryAppPreferencesStore() + val enableNativeSlidingSyncUseCase = EnableNativeSlidingSyncUseCase(appPreferencesStore, this) + val presenter = createLoggedInPresenter(matrixClient = matrixClient, enableNativeSlidingSyncUseCase = enableNativeSlidingSyncUseCase) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + + assertThat(appPreferencesStore.isSimplifiedSlidingSyncEnabledFlow().first()).isFalse() + + initialState.eventSink(LoggedInEvents.LogoutAndMigrateToNativeSlidingSync) + + advanceUntilIdle() + + assertThat(appPreferencesStore.isSimplifiedSlidingSyncEnabledFlow().first()).isTrue() + assertThat(logoutLambda.assertions().isCalledOnce()) + } + } + private suspend fun ReceiveTurbine.awaitFirstItem(): T { skipItems(1) return awaitItem() } - private fun createLoggedInPresenter( + private fun TestScope.createLoggedInPresenter( roomListService: RoomListService = FakeRoomListService(), networkStatus: NetworkStatus = NetworkStatus.Offline, analyticsService: AnalyticsService = FakeAnalyticsService(), sessionVerificationService: SessionVerificationService = FakeSessionVerificationService(), encryptionService: EncryptionService = FakeEncryptionService(), pushService: PushService = FakePushService(), + enableNativeSlidingSyncUseCase: EnableNativeSlidingSyncUseCase = EnableNativeSlidingSyncUseCase(InMemoryAppPreferencesStore(), this), + matrixClient: MatrixClient = FakeMatrixClient(roomListService = roomListService), ): LoggedInPresenter { return LoggedInPresenter( - matrixClient = FakeMatrixClient(roomListService = roomListService), + matrixClient = matrixClient, networkMonitor = FakeNetworkMonitor(networkStatus), pushService = pushService, sessionVerificationService = sessionVerificationService, analyticsService = analyticsService, - encryptionService = encryptionService + encryptionService = encryptionService, + enableNativeSlidingSyncUseCase = enableNativeSlidingSyncUseCase, ) } } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt index 7d0f1f6676..4641e4e7bc 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt @@ -111,7 +111,7 @@ internal fun CallScreenView( is AsyncData.Failure -> ErrorDialog( content = state.urlState.error.message.orEmpty(), - onDismiss = { state.eventSink(CallScreenEvents.Hangup) }, + onSubmit = { state.eventSink(CallScreenEvents.Hangup) }, ) is AsyncData.Success -> Unit } diff --git a/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomView.kt b/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomView.kt index 6ee2990c5b..a98bfbff2f 100644 --- a/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomView.kt +++ b/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomView.kt @@ -105,7 +105,7 @@ private fun LeaveRoomErrorDialog( is LeaveRoomState.Error.Hidden -> {} is LeaveRoomState.Error.Shown -> ErrorDialog( content = stringResource(CommonStrings.error_unknown), - onDismiss = { state.eventSink(LeaveRoomEvent.HideError) } + onSubmit = { state.eventSink(LeaveRoomEvent.HideError) } ) } } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinView.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinView.kt index b794f2eed4..b3cd532487 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinView.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinView.kt @@ -116,7 +116,7 @@ private fun SetupPinContent( ErrorDialog( title = state.setupPinFailure.title(), content = state.setupPinFailure.content(), - onDismiss = { + onSubmit = { state.eventSink(SetupPinEvents.ClearFailure) } ) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt index 702e253f03..8667b3806a 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt @@ -104,7 +104,7 @@ fun PinUnlockView( if (state.showBiometricUnlockError) { ErrorDialog( content = state.biometricUnlockErrorMessage ?: "", - onDismiss = { state.eventSink(PinUnlockEvents.ClearBiometricError) } + onSubmit = { state.eventSink(PinUnlockEvents.ClearBiometricError) } ) } } @@ -206,7 +206,7 @@ private fun SignOutPrompt( ErrorDialog( title = stringResource(id = R.string.screen_app_lock_signout_alert_title), content = stringResource(id = R.string.screen_app_lock_signout_alert_message), - onDismiss = onSignOut, + onSubmit = onSignOut, ) } } 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 a2c3b48251..c6139ae492 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 @@ -36,7 +36,7 @@ fun ChangeServerView( ErrorDialog( modifier = modifier, content = error.message(), - onDismiss = { + onSubmit = { eventSink.invoke(ChangeServerEvents.ClearError) } ) 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 a516c1b4a6..da1106d463 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 @@ -103,7 +103,7 @@ fun ConfirmAccountProviderView( is ChangeServerError.Error -> { ErrorDialog( content = error.message(), - onDismiss = { + onSubmit = { eventSink.invoke(ConfirmAccountProviderEvents.ClearError) } ) 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 bd6437ddba..48fe71e0fc 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 @@ -283,7 +283,7 @@ private fun LoginErrorDialog(error: Throwable, onDismiss: () -> Unit) { ErrorDialog( title = stringResource(id = CommonStrings.dialog_title_error), content = stringResource(loginError(error)), - onDismiss = onDismiss + onSubmit = onDismiss ) } diff --git a/features/login/impl/src/main/res/values-be/translations.xml b/features/login/impl/src/main/res/values-be/translations.xml index f8e675854e..777acc423d 100644 --- a/features/login/impl/src/main/res/values-be/translations.xml +++ b/features/login/impl/src/main/res/values-be/translations.xml @@ -78,10 +78,4 @@ "Тут будуць захоўвацца вашыя размовы - сапраўды гэтак жа, як вы выкарыстоўваеце паштовага правайдара для захоўвання сваіх лістоў." "Вы збіраецеся ўвайсці ў %1$s" "Вы збіраецеся стварыць уліковы запіс на %1$s" - "Зараз існуе высокі попыт на %1$s на %2$s. Калі ласка, вярніцеся ў праграму праз некалькі дзён і паспрабуйце зноў. - -Дзякуй за цярпенне!" - "Вітаем у %1$s!" - "Амаль гатова." - "Вы зарэгістраваны." diff --git a/features/login/impl/src/main/res/values-bg/translations.xml b/features/login/impl/src/main/res/values-bg/translations.xml index cfc51c3f8c..eced3ef828 100644 --- a/features/login/impl/src/main/res/values-bg/translations.xml +++ b/features/login/impl/src/main/res/values-bg/translations.xml @@ -24,5 +24,4 @@ "Това е мястото, където ще живеят вашите разговори — точно както бихте използвали имейл доставчик, за да съхранявате вашите имейли." "На път сте да влезете в %1$s" "На път сте да създадете акаунт в %1$s" - "Добре дошли в %1$s!" diff --git a/features/login/impl/src/main/res/values-cs/translations.xml b/features/login/impl/src/main/res/values-cs/translations.xml index c0f00a87af..d65a5571e4 100644 --- a/features/login/impl/src/main/res/values-cs/translations.xml +++ b/features/login/impl/src/main/res/values-cs/translations.xml @@ -78,10 +78,4 @@ Zkuste se přihlásit ručně nebo naskenujte QR kód pomocí jiného zařízen "Zde budou uloženy vaše konverzace - podobně jako u poskytovatele e-mailových služeb uchováváte své e-maily." "Chystáte se přihlásit do služby %1$s" "Chystáte se vytvořit účet na %1$s" - "Na %2$s je momentálně vysoká poptávka po %1$s. Vraťte se do aplikace za pár dní a zkuste to znovu. - -Díky za trpělivost!" - "Vítá vás %1$s!" - "Jste v pořadníku!" - "Jdete do toho!" diff --git a/features/login/impl/src/main/res/values-de/translations.xml b/features/login/impl/src/main/res/values-de/translations.xml index 2399ec86ba..c2bdf37ca7 100644 --- a/features/login/impl/src/main/res/values-de/translations.xml +++ b/features/login/impl/src/main/res/values-de/translations.xml @@ -78,10 +78,4 @@ Versuche, dich manuell anzumelden, oder scanne den QR-Code mit einem anderen Ger "Hier werden deine Gespräche gespeichert - so wie du deine E-Mails bei einem E-Mail-Anbieter aufbewahren würden." "Du bist dabei, dich bei %1$s anzumelden" "Du bist dabei, ein Konto auf %1$s zu erstellen" - "Derzeit besteht eine hohe Nachfrage nach %1$s auf %2$s. Kehre in ein paar Tagen zur App zurück und versuche es erneut. - -Danke für deine Geduld!" - "Willkommen bei %1$s!" - "Du bist fast am Ziel." - "Du bist dabei." diff --git a/features/login/impl/src/main/res/values-el/translations.xml b/features/login/impl/src/main/res/values-el/translations.xml index 8ff0227168..24f26483fb 100644 --- a/features/login/impl/src/main/res/values-el/translations.xml +++ b/features/login/impl/src/main/res/values-el/translations.xml @@ -78,10 +78,4 @@ "Εδώ θα ζουν οι συνομιλίες σου - όπως θα χρησιμοποιούσες έναν πάροχο email για να διατηρήσεις τα email σου." "Πρόκειται να συνδεθείς στο %1$s" "Πρόκειται να δημιουργήσεις έναν λογαριασμό στο %1$s" - "Υπάρχει μεγάλη ζήτηση για το %1$s στον %2$s αυτή τη στιγμή. Επέστρεψε στην εφαρμογή σε λίγες μέρες και δοκίμασε ξανά. - -Ευχαριστώ για την υπομονή σου!" - "Καλώς ήρθες στο %1$s!" - "Σχεδόν τα κατάφερες." - "Είσαι μέσα." diff --git a/features/login/impl/src/main/res/values-es/translations.xml b/features/login/impl/src/main/res/values-es/translations.xml index c7537c9d7e..60324ae89d 100644 --- a/features/login/impl/src/main/res/values-es/translations.xml +++ b/features/login/impl/src/main/res/values-es/translations.xml @@ -37,10 +37,4 @@ "Aquí es donde se alojarán tus conversaciones — justo como utilizarías un proveedor de correo electrónico para guardar tus correos electrónicos." "Estás a punto de iniciar sesión en %1$s" "Estás a punto de crear una cuenta en %1$s" - "Hay una gran demanda para %1$s en %2$s en este momento. Vuelve a la aplicación en unos días e inténtalo de nuevo. - -¡Gracias por tu paciencia!" - "¡Bienvenido a %1$s!" - "Ya casi has terminado." - "Estás dentro." diff --git a/features/login/impl/src/main/res/values-et/translations.xml b/features/login/impl/src/main/res/values-et/translations.xml index 0558b349b4..f82ea50b91 100644 --- a/features/login/impl/src/main/res/values-et/translations.xml +++ b/features/login/impl/src/main/res/values-et/translations.xml @@ -78,10 +78,4 @@ Proovi käsitsi sisselogimist või skaneeri QR-koodi mõne muu seadmega.""See on koht, kus sinu vestlused elavad – just nagu kasutaksid oma e-kirjade säilitamiseks e-postitenuse pakkujat." "Sa oled sisselogimas koduserverisse %1$s" "Sa oled loomas kasutajakontot koduserveris %1$s" - "%1$s kasutamiseks %2$s koduserveris on hetkel palju huvilisi. Proovi seda samast rakendusest mõne päeva pärast. - -Täname kannatlikkuse eest!" - "Tere tulemast rakendusse %1$s!" - "Peaaegu olemas." - "Oled nüüd jututoas." diff --git a/features/login/impl/src/main/res/values-fr/translations.xml b/features/login/impl/src/main/res/values-fr/translations.xml index 49e513c2a8..a5928ffb3f 100644 --- a/features/login/impl/src/main/res/values-fr/translations.xml +++ b/features/login/impl/src/main/res/values-fr/translations.xml @@ -76,10 +76,4 @@ "C’est ici que vos conversations seront enregistrées, comme vous le feriez avec un fournisseur de messagerie pour conserver vos e-mails." "Vous êtes sur le point de vous connecter à %1$s" "Vous êtes sur le point de créer un compte sur %1$s" - "Il y a une forte demande pour %1$s sur %2$s à l’heure actuelle. Revenez sur l’application dans quelques jours et réessayez. - -Merci pour votre patience !" - "Bienvenue dans %1$s !" - "Vous y êtes presque." - "Vous y êtes." diff --git a/features/login/impl/src/main/res/values-hu/translations.xml b/features/login/impl/src/main/res/values-hu/translations.xml index 8d8bf40f3f..a37288fd6f 100644 --- a/features/login/impl/src/main/res/values-hu/translations.xml +++ b/features/login/impl/src/main/res/values-hu/translations.xml @@ -78,10 +78,4 @@ Próbáljon meg kézileg bejelentkezni, vagy olvassa be a QR-kódot egy másik e "Itt lesznek a beszélgetései – ahogyan egy e-mail-szolgáltatást is használna a levelei kezeléséhez." "Hamarosan bejelentkezik ebbe: %1$s" "Hamarosan létrehoz egy fiókot ezen: %1$s" - "Jelenleg nagy a kereslet a(z) %2$s oldalon futó %1$s iránt. Térjen vissza néhány nap múlva az alkalmazáshoz, és próbálja újra. - -Köszönjük a türelmét!" - "Üdvözli az %1$s!" - "Már majdnem kész van." - "Bent van." 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 97d84ff1f4..749406da04 100644 --- a/features/login/impl/src/main/res/values-in/translations.xml +++ b/features/login/impl/src/main/res/values-in/translations.xml @@ -78,10 +78,4 @@ Coba masuk secara manual, atau pindai kode QR dengan perangkat lain." "Di sinilah percakapan Anda akan berlangsung — sama seperti Anda menggunakan penyedia surel untuk menyimpan surel Anda." "Anda akan masuk ke %1$s" "Anda akan membuat akun di %1$s" - "Ada permintaan tinggi untuk %1$s di %2$s saat ini. Kembalilah ke aplikasi dalam beberapa hari dan coba lagi. - -Terima kasih atas kesabaran Anda!" - "Selamat datang di %1$s!" - "Anda hampir selesai." - "Anda sudah masuk." diff --git a/features/login/impl/src/main/res/values-it/translations.xml b/features/login/impl/src/main/res/values-it/translations.xml index dcd9a7c2ae..eaa5313b03 100644 --- a/features/login/impl/src/main/res/values-it/translations.xml +++ b/features/login/impl/src/main/res/values-it/translations.xml @@ -78,10 +78,4 @@ Prova ad accedere manualmente o scansiona il codice QR con un altro dispositivo. "Qui è dove vivranno le tue conversazioni — proprio come useresti un fornitore di posta elettronica per conservare le tue email." "Stai per accedere a %1$s" "Stai per creare un account su %1$s" - "Al momento c\'è una grande richiesta per %1$s su %2$s. Torna a visitare l\'app tra qualche giorno e riprova. - -Grazie per la pazienza!" - "Benvenuti in %1$s!" - "Ci sei quasi." - "Sei dentro." diff --git a/features/login/impl/src/main/res/values-ka/translations.xml b/features/login/impl/src/main/res/values-ka/translations.xml index 84e97e0a34..6fc49e7b41 100644 --- a/features/login/impl/src/main/res/values-ka/translations.xml +++ b/features/login/impl/src/main/res/values-ka/translations.xml @@ -34,10 +34,4 @@ "აქ იქნება თქვენი საუბრები - ისევე, როგორც თქვენ ელ. ფოსტაში ინახება თქვენი ელ.წერილები." "თქვენ აპირებთ შესვლას %1$s-ში" "თქვენ აპირებთ ანგარიშის შექმნას %1$s-ში" - "ახლა დიდი მოთხოვნაა %1$s-ზე %2$s-ში. დაბრუნდით რამდენიმე დღეში და სცადეთ ერთხელაც. - -მადლობა მოთმენისათვის!" - "კეთილი იყოს თქვენი მობრძანება %1$s-ში!" - "თითქმის მზადაა." - "თქვენ შეხვედით." diff --git a/features/login/impl/src/main/res/values-nl/translations.xml b/features/login/impl/src/main/res/values-nl/translations.xml index 80fbe57afb..0e351f8498 100644 --- a/features/login/impl/src/main/res/values-nl/translations.xml +++ b/features/login/impl/src/main/res/values-nl/translations.xml @@ -35,10 +35,4 @@ "Dit is waar je gesprekken zullen worden bewaard — net zoals je een e-mailprovider zou gebruiken om je e-mails te bewaren." "Je staat op het punt je aan te melden bij %1$s" "Je staat op het punt een account aan te maken op %1$s" - "Er is momenteel veel vraag naar %1$s op %2$s. Kom over een paar dagen terug naar de app en probeer het opnieuw. - -Bedankt voor je geduld!" - "Welkom bij %1$s!" - "Je bent er bijna." - "Je bent binnen." diff --git a/features/login/impl/src/main/res/values-pl/translations.xml b/features/login/impl/src/main/res/values-pl/translations.xml index 4d23e15fe8..6990121a43 100644 --- a/features/login/impl/src/main/res/values-pl/translations.xml +++ b/features/login/impl/src/main/res/values-pl/translations.xml @@ -78,10 +78,4 @@ Spróbuj zalogować się ręcznie lub zeskanuj kod QR na innym urządzeniu.""Tutaj będą przechowywane Twoje konwersacje - w podobnej formie jak wiadomości widnieją na skrzynce e-mail." "Zamierzasz się zalogować do %1$s" "Zamierzasz utworzyć konto na %1$s" - "Obecnie istnieje duże zapotrzebowanie na %1$s na %2$s. Wróć do aplikacji za kilka dni i spróbuj ponownie. - -Dziękujemy za Twoją cierpliwość!" - "Witamy w %1$s!" - "Już prawie gotowe!" - "Witamy!" diff --git a/features/login/impl/src/main/res/values-pt-rBR/translations.xml b/features/login/impl/src/main/res/values-pt-rBR/translations.xml index 4cb9b4f7b0..7b753ffb9f 100644 --- a/features/login/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/login/impl/src/main/res/values-pt-rBR/translations.xml @@ -34,10 +34,4 @@ "Aqui é onde suas conversas vão ficar — assim como você usa um provedor de e-mails para manter seus e-mails." "Você está prestes a fazer login em %1$s" "Você está prestes a criar uma conta em %1$s" - "Há uma grande demanda por %1$s sobre %2$s no momento. Volte ao aplicativo em alguns dias e tente novamente. - -Obrigado pela sua paciência!" - "Bem-vindo ao %1$s!" - "Você está quase lá." - "Você está dentro." diff --git a/features/login/impl/src/main/res/values-pt/translations.xml b/features/login/impl/src/main/res/values-pt/translations.xml index f5feb0cbdd..f03b48c5dd 100644 --- a/features/login/impl/src/main/res/values-pt/translations.xml +++ b/features/login/impl/src/main/res/values-pt/translations.xml @@ -78,10 +78,4 @@ Tenta iniciar a sessão manualmente ou digitaliza o código QR com outro disposi "É aqui que as tuas conversas vão ficar — tal como num serviço de e-mail." "Irás iniciar sessão em %1$s" "Irás criar uma conta em %1$s" - "Há uma grande procura pela %1$s no %2$s, de momento. Volta à aplicação daqui a uns dias e tenta novamente. - -Obrigado!" - "Bem-vindo à %1$s!" - "Estás quase lá." - "Estás dentro." diff --git a/features/login/impl/src/main/res/values-ro/translations.xml b/features/login/impl/src/main/res/values-ro/translations.xml index 1ff3fe2436..261f16d9f6 100644 --- a/features/login/impl/src/main/res/values-ro/translations.xml +++ b/features/login/impl/src/main/res/values-ro/translations.xml @@ -78,10 +78,4 @@ "Aici vor trăi conversațiile dvs. - la fel cum ați folosi un furnizor de e-mail pentru a vă păstra e-mailurile." "Sunteți pe cale să vă conectați la %1$s" "Sunteți pe cale să creați un cont pe %1$s" - "Există o cerere mare pentru %1$s pentru %2$s în acest moment. Reveniți la aplicație în câteva zile și încercați din nou. - -Vă mulțumim pentru răbdare!" - "Bun venit la%1$s!" - "Sunteți pe lista de așteptare" - "Sunteți conectat!" diff --git a/features/login/impl/src/main/res/values-ru/translations.xml b/features/login/impl/src/main/res/values-ru/translations.xml index c64d683a12..71a2691b4c 100644 --- a/features/login/impl/src/main/res/values-ru/translations.xml +++ b/features/login/impl/src/main/res/values-ru/translations.xml @@ -78,10 +78,4 @@ "Здесь будут храниться ваши разговоры - точно так же, как вы используете почтового провайдера для хранения своих писем." "Вы собираетесь войти в %1$s" "Вы собираетесь создать учетную запись на %1$s" - "В настоящее время существует высокий спрос на %1$s на %2$s. Вернитесь в приложение через несколько дней и попробуйте снова. - -Спасибо за терпение!" - "Добро пожаловать в %1$s!" - "Почти готово." - "Вы зарегистрированы." diff --git a/features/login/impl/src/main/res/values-sk/translations.xml b/features/login/impl/src/main/res/values-sk/translations.xml index fea7879d01..8d862609b7 100644 --- a/features/login/impl/src/main/res/values-sk/translations.xml +++ b/features/login/impl/src/main/res/values-sk/translations.xml @@ -78,10 +78,4 @@ Skúste sa prihlásiť manuálne alebo naskenujte QR kód pomocou iného zariade "Tu budú žiť vaše konverzácie - podobne ako používate poskytovateľa e-mailových služieb na uchovávanie e-mailov." "Chystáte sa prihlásiť do %1$s" "Chystáte sa vytvoriť účet na %1$s" - "Momentálne je veľký dopyt po %1$s na %2$s. Vráťte sa do aplikácie za pár dní a skúste to znova. - -Ďakujeme za trpezlivosť!" - "Vitajte v %1$s!" - "Ste na čakanej listine!" - "Ste dnu!" diff --git a/features/login/impl/src/main/res/values-sv/translations.xml b/features/login/impl/src/main/res/values-sv/translations.xml index d50610adcc..de290469ca 100644 --- a/features/login/impl/src/main/res/values-sv/translations.xml +++ b/features/login/impl/src/main/res/values-sv/translations.xml @@ -78,10 +78,4 @@ Prova att logga in manuellt eller skanna QR-koden med en annan enhet." "Det är här dina konversationer kommer att sparas - precis som du skulle använda en e-postleverantör för att spara dina e-brev." "Du är på väg att logga in på %1$s" "Du är på väg att skapa ett konto på %1$s" - "Det finns en stor efterfrågan på %1$s på %2$s just nu. Kom tillbaka till appen om några dagar och försök igen. - -Tack för ditt tålamod!" - "Välkommen till %1$s!" - "Du är nästan framme." - "Du är inne." diff --git a/features/login/impl/src/main/res/values-uk/translations.xml b/features/login/impl/src/main/res/values-uk/translations.xml index 9cb6eb1f5f..df436a9a69 100644 --- a/features/login/impl/src/main/res/values-uk/translations.xml +++ b/features/login/impl/src/main/res/values-uk/translations.xml @@ -78,10 +78,4 @@ "Тут будуть зберігатися Ваші розмови - так само, як Ви використовуєте поштову скриньку для зберігання своїх електронних листів." "Ви збираєтесь увійти в %1$s" "Ви збираєтеся створити обліковий запис на %1$s" - "На цей момент існує високий попит на %1$s в %2$s. Поверніться до застосунку через кілька днів і спробуйте ще раз. - -Дякуємо за терпіння!" - "Ласкаво просимо до %1$s!" - "Майже готово." - "Готово." diff --git a/features/login/impl/src/main/res/values-uz/translations.xml b/features/login/impl/src/main/res/values-uz/translations.xml index 67dc5129d7..db16e17b09 100644 --- a/features/login/impl/src/main/res/values-uz/translations.xml +++ b/features/login/impl/src/main/res/values-uz/translations.xml @@ -33,10 +33,4 @@ "Bu sizning suhbatlaringiz yashaydigan joy - xuddi siz elektron pochta xabarlaringizni saqlash uchun elektron pochta provayderidan foydalanganingiz kabi." "Siz tizimga kirmoqchisiz%1$s" "Hisob yaratmoqchisiz%1$s" - "Hozirgi paytda %2$sga %1$sda talab yuqori. Bir necha kundan keyin ilovaga qayting va qaytadan urining. - -Sabr-toqatingiz uchun rahmat!" - "%1$sga Xush kelibsiz!" - "Siz deyarli keldingiz." - "Siz kirdingiz." diff --git a/features/login/impl/src/main/res/values-zh-rTW/translations.xml b/features/login/impl/src/main/res/values-zh-rTW/translations.xml index d345095c4b..b66cfca31f 100644 --- a/features/login/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/login/impl/src/main/res/values-zh-rTW/translations.xml @@ -29,5 +29,4 @@ "您的所有對話將保存於此,就如同您的電子郵件供應商會保存您的電子郵件一樣。" "您即將登入 %1$s" "您即將在 %1$s 建立帳號" - "歡迎使用 %1$s!" diff --git a/features/login/impl/src/main/res/values-zh/translations.xml b/features/login/impl/src/main/res/values-zh/translations.xml index 0afd6dad93..2f24aacf69 100644 --- a/features/login/impl/src/main/res/values-zh/translations.xml +++ b/features/login/impl/src/main/res/values-zh/translations.xml @@ -78,10 +78,4 @@ "这是您的对话将进行的地方,就像您使用电子邮件提供商来保存电子邮件一样。" "即将登录 %1$s" "即将在 %1$s 上创建一个账户" - "目前 %1$s 上 %2$s 的负载很大。过几天再回来试试吧。 - -感谢您的耐心!" - "欢迎使用 %1$s" - "马上就好。" - "您已加入。" diff --git a/features/login/impl/src/main/res/values/localazy.xml b/features/login/impl/src/main/res/values/localazy.xml index cade81c4f2..b0b6252d52 100644 --- a/features/login/impl/src/main/res/values/localazy.xml +++ b/features/login/impl/src/main/res/values/localazy.xml @@ -78,10 +78,4 @@ Try signing in manually, or scan the QR code with another device." "This is where your conversations will live — just like you would use an email provider to keep your emails." "You’re about to sign in to %1$s" "You’re about to create an account on %1$s" - "There\'s a high demand for %1$s on %2$s at the moment. Come back to the app in a few days and try again. - -Thanks for your patience!" - "Welcome to %1$s!" - "You’re almost there." - "You\'re in." 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 8a03ed857c..a9c12fe732 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 @@ -108,7 +108,7 @@ private fun PinnedMessagesListContent( ErrorDialog( title = stringResource(id = CommonStrings.error_unknown), content = stringResource(id = CommonStrings.error_failed_loading_messages), - onDismiss = onErrorDismiss + onSubmit = onErrorDismiss ) } PinnedMessagesListState.Empty -> PinnedMessagesListEmpty() diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/focus/FocusRequestStateView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/focus/FocusRequestStateView.kt index 7bd5301208..75d4d5ebac 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/focus/FocusRequestStateView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/focus/FocusRequestStateView.kt @@ -36,7 +36,7 @@ fun FocusRequestStateView( } ErrorDialog( content = errorMessage, - onDismiss = onClearFocusRequestState, + onSubmit = onClearFocusRequestState, modifier = modifier, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/VoiceMessageSendingFailedDialog.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/VoiceMessageSendingFailedDialog.kt index f2cc385553..ffed5f31ac 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/VoiceMessageSendingFailedDialog.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/VoiceMessageSendingFailedDialog.kt @@ -19,7 +19,7 @@ internal fun VoiceMessageSendingFailedDialog( ErrorDialog( title = stringResource(CommonStrings.common_error), content = stringResource(CommonStrings.error_failed_uploading_voice_message), - onDismiss = onDismiss, + onSubmit = onDismiss, submitText = stringResource(CommonStrings.action_ok), ) } 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 25cc166103..22884bc6ed 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 @@ -259,7 +259,7 @@ private fun InvalidNotificationSettingsView( ErrorDialog( title = stringResource(id = CommonStrings.dialog_title_error), content = stringResource(id = R.string.screen_notification_settings_failed_fixing_configuration), - onDismiss = onDismissError + onSubmit = onDismissError ) } } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/RolesAndPermissionsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/RolesAndPermissionsView.kt index bfc19026a9..a3f39895df 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/RolesAndPermissionsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/RolesAndPermissionsView.kt @@ -124,7 +124,7 @@ fun RolesAndPermissionsView( is AsyncAction.Failure -> { ErrorDialog( content = stringResource(CommonStrings.error_unknown), - onDismiss = { state.eventSink(RolesAndPermissionsEvents.CancelPendingAction) } + onSubmit = { state.eventSink(RolesAndPermissionsEvents.CancelPendingAction) } ) } else -> Unit diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/changeroles/ChangeRolesView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/changeroles/ChangeRolesView.kt index 2f7cfb16a0..ce362373f2 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/changeroles/ChangeRolesView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/rolesandpermissions/changeroles/ChangeRolesView.kt @@ -210,7 +210,7 @@ fun ChangeRolesView( is AsyncAction.Failure -> { ErrorDialog( content = stringResource(CommonStrings.error_unknown), - onDismiss = { state.eventSink(ChangeRolesEvent.ClearError) } + onSubmit = { state.eventSink(ChangeRolesEvent.ClearError) } ) } is AsyncAction.Success -> { diff --git a/features/roomlist/impl/src/main/res/values/localazy.xml b/features/roomlist/impl/src/main/res/values/localazy.xml index ff6c626c63..36dc4b8d65 100644 --- a/features/roomlist/impl/src/main/res/values/localazy.xml +++ b/features/roomlist/impl/src/main/res/values/localazy.xml @@ -2,6 +2,7 @@ "Log Out & Upgrade" "Your server now supports a new, faster protocol. Log out and log back in to upgrade now. Doing this now will help you avoid a forced logout when the old protocol is removed later." + "Your homeserver no longer supports the old protocol. Please log out and log back in to continue using the app." "Upgrade available" "Generate a new recovery key that can be used to restore your encrypted message history in case you lose access to your devices." "Set up recovery" diff --git a/features/securebackup/impl/src/main/res/values-be/translations.xml b/features/securebackup/impl/src/main/res/values-be/translations.xml index 75e4c2ccb9..910350f41e 100644 --- a/features/securebackup/impl/src/main/res/values-be/translations.xml +++ b/features/securebackup/impl/src/main/res/values-be/translations.xml @@ -38,7 +38,6 @@ "Паўтарыце спробу, каб пацвердзіць доступ да рэзервовай копіі чата." "Няправільны ключ аднаўлення" "Калі ў вас ёсць ключ аднаўлення або парольная фраза, гэта таксама будзе працаваць." - "Ключ аднаўлення або код доступу" "Увесці…" "Страцілі ключ аднаўлення?" "Ключ аднаўлення пацверджаны" diff --git a/features/securebackup/impl/src/main/res/values-cs/translations.xml b/features/securebackup/impl/src/main/res/values-cs/translations.xml index 6425f52b66..ba113f9c89 100644 --- a/features/securebackup/impl/src/main/res/values-cs/translations.xml +++ b/features/securebackup/impl/src/main/res/values-cs/translations.xml @@ -39,7 +39,6 @@ "Zkuste prosím znovu potvrdit přístup k záloze chatu." "Nesprávný klíč pro obnovení" "Pokud máte bezpečnostní klíč nebo bezpečnostní frázi, bude to fungovat také." - "Klíč pro obnovení nebo přístupový kód" "Zadejte…" "Ztratili jste klíč pro obnovení?" "Klíč pro obnovení potvrzen" diff --git a/features/securebackup/impl/src/main/res/values-de/translations.xml b/features/securebackup/impl/src/main/res/values-de/translations.xml index c95e51db7e..413ae1ea81 100644 --- a/features/securebackup/impl/src/main/res/values-de/translations.xml +++ b/features/securebackup/impl/src/main/res/values-de/translations.xml @@ -51,10 +51,6 @@ Das bedeutet:" "Bitte versuche es noch einmal, um den Zugriff auf dein Chat-Backup zu bestätigen." "Falscher Wiederherstellungsschlüssel" "Dies funktioniert auch mit einem Sicherheitsschlüssel oder Sicherheitsphrase." - - "Wiederherstellungsschlüssel" - " oder Passcode" - "Eingeben…" "Hast du deinen Wiederherstellungschlüssel vergessen?" "Wiederherstellungsschlüssel bestätigt" diff --git a/features/securebackup/impl/src/main/res/values-el/translations.xml b/features/securebackup/impl/src/main/res/values-el/translations.xml index e62f465743..b3c6eb5a54 100644 --- a/features/securebackup/impl/src/main/res/values-el/translations.xml +++ b/features/securebackup/impl/src/main/res/values-el/translations.xml @@ -33,7 +33,6 @@ "Προσπάθησε ξανά για να επιβεβαιώσεις την πρόσβαση στο αντίγραφο ασφαλείας της συνομιλίας σου." "Λανθασμένο κλειδί ανάκτησης" "Εάν έχεις ένα κλειδί ασφαλείας ή μια φράση ασφαλείας, θα λειτουργήσει επίσης." - "Κλειδί ανάκτησης ή κωδικός πρόσβασης" "Εισαγωγή…" "Έχασες το κλειδί ανάκτησης;" "Επιβεβαιώθηκε το κλειδί ανάκτησης" diff --git a/features/securebackup/impl/src/main/res/values-et/translations.xml b/features/securebackup/impl/src/main/res/values-et/translations.xml index 2c3aa2d12b..b618432839 100644 --- a/features/securebackup/impl/src/main/res/values-et/translations.xml +++ b/features/securebackup/impl/src/main/res/values-et/translations.xml @@ -39,7 +39,6 @@ "Kinnitamaks ligipääsu sinu vestluse varukoopiale, palun proovi uuesti" "Vigane taastevõti" "Kui sul on turvavõti või turvafraas, siis need toimivad ka." - "Taastevõti või turvafraas" "Sisesta…" "Kas sa oled taastevõtme kaotanud?" "Taastevõti on kinnitatud" diff --git a/features/securebackup/impl/src/main/res/values-fr/translations.xml b/features/securebackup/impl/src/main/res/values-fr/translations.xml index 6656e0a8e3..1b36266924 100644 --- a/features/securebackup/impl/src/main/res/values-fr/translations.xml +++ b/features/securebackup/impl/src/main/res/values-fr/translations.xml @@ -37,7 +37,6 @@ "Veuillez réessayer afin de pouvoir accéder à vos anciens messages." "Clé de récupération incorrecte" "Si vous avez une clé de sécurité ou une phrase de sécurité, cela fonctionnera également." - "Clé de récupération" "Saisissez la clé ici…" "Clé de récupération perdue?" "Clé de récupération confirmée" diff --git a/features/securebackup/impl/src/main/res/values-hu/translations.xml b/features/securebackup/impl/src/main/res/values-hu/translations.xml index 20575540b7..48fe08a31b 100644 --- a/features/securebackup/impl/src/main/res/values-hu/translations.xml +++ b/features/securebackup/impl/src/main/res/values-hu/translations.xml @@ -39,7 +39,6 @@ "Próbálja meg újra megerősíteni a csevegés biztonsági mentéséhez való hozzáférését." "Helytelen helyreállítási kulcs" "Ha van biztonsági kulcsa vagy biztonsági jelmondata, akkor ez is fog működni." - "Helyreállítási kulcs vagy jelkód" "Megadás…" "Elvesztette a helyreállítási kulcsát?" "Helyreállítási kulcs megerősítve" 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 83fa1f8092..62968d3471 100644 --- a/features/securebackup/impl/src/main/res/values-in/translations.xml +++ b/features/securebackup/impl/src/main/res/values-in/translations.xml @@ -33,7 +33,6 @@ "Silakan coba lagi untuk mengonfirmasi akses ke cadangan percakapan Anda." "Kunci pemulihan salah" "Jika Anda memiliki kunci keamanan atau frasa keamanan, ini juga bisa digunakan." - "Kunci pemulihan atau kode sandi" "Masukkan…" "Kehilangan kunci pemulihan Anda?" "Kunci pemulihan dikonfirmasi" 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 c1d67299ba..0e069b0ab2 100644 --- a/features/securebackup/impl/src/main/res/values-it/translations.xml +++ b/features/securebackup/impl/src/main/res/values-it/translations.xml @@ -38,7 +38,6 @@ "Riprova per confermare l\'accesso al backup della chat." "Chiave di recupero errata" "Se hai una chiave di sicurezza o una password, andrà bene anche questo." - "Chiave di recupero o codice di accesso" "Inserisci…" "Hai perso la chiave di recupero?" "Chiave di recupero confermata" diff --git a/features/securebackup/impl/src/main/res/values-pl/translations.xml b/features/securebackup/impl/src/main/res/values-pl/translations.xml index eea550627f..d708e18bab 100644 --- a/features/securebackup/impl/src/main/res/values-pl/translations.xml +++ b/features/securebackup/impl/src/main/res/values-pl/translations.xml @@ -38,7 +38,6 @@ "Spróbuj ponownie, aby potwierdzić dostęp do backupu czatu." "Nieprawidłowy klucz przywracania" "To też zadziała, jeśli posiadasz klucz lub frazę bezpieczeństwa." - "Klucz przywracania lub hasło" "Wprowadź…" "Zgubiłeś swój kod przywracania?" "Potwierdzono klucz przywracania" diff --git a/features/securebackup/impl/src/main/res/values-pt/translations.xml b/features/securebackup/impl/src/main/res/values-pt/translations.xml index f93e5dedf4..0e409ea22c 100644 --- a/features/securebackup/impl/src/main/res/values-pt/translations.xml +++ b/features/securebackup/impl/src/main/res/values-pt/translations.xml @@ -38,7 +38,6 @@ "Por favor, tenta novamente para confirmar o acesso à tua cópia de segurança das conversas." "Chave de recuperação incorreta" "Também funciona se tiveres uma chave ou frase de segurança." - "Chave ou código de recuperação" "Inserir…" "Perdeste a tua chave?" "Chave de recuperação confirmada" diff --git a/features/securebackup/impl/src/main/res/values-ro/translations.xml b/features/securebackup/impl/src/main/res/values-ro/translations.xml index 6b2f2e31dc..7266533d78 100644 --- a/features/securebackup/impl/src/main/res/values-ro/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ro/translations.xml @@ -33,7 +33,6 @@ "Vă rugăm să încercați din nou să confirmați accesul la backup." "Cheie de recuperare incorectă" "Dacă aveți o cheie de securitate sau o frază de securitate, aceasta va funcționa și ea." - "Cheie de recuperare sau cod de acces" "Introduceți…" "Ați pierdut cheia de recuperare?" "Cheia de recuperare confirmată" 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 8866dc9613..ae45ab45eb 100644 --- a/features/securebackup/impl/src/main/res/values-ru/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ru/translations.xml @@ -60,10 +60,6 @@ "ключ восстановления" "Если у вас есть пароль для восстановления или секретный пароль/ключ, это тоже сработает." - - "Ключ восстановления" - " или пароль" - "Вход…" "Потеряли ключ восстановления?" diff --git a/features/securebackup/impl/src/main/res/values-sk/translations.xml b/features/securebackup/impl/src/main/res/values-sk/translations.xml index 8a088f4245..24d80c6b00 100644 --- a/features/securebackup/impl/src/main/res/values-sk/translations.xml +++ b/features/securebackup/impl/src/main/res/values-sk/translations.xml @@ -39,7 +39,6 @@ "Skúste prosím znova potvrdiť prístup k vašej zálohe konverzácie." "Nesprávny kľúč na obnovenie" "Ak máte bezpečnostný kľúč alebo bezpečnostnú frázu, bude to fungovať tiež." - "Kľúč na obnovenie alebo prístupový kód" "Zadať…" "Stratili ste kľúč na obnovenie?" "Kľúč na obnovu potvrdený" diff --git a/features/securebackup/impl/src/main/res/values-sv/translations.xml b/features/securebackup/impl/src/main/res/values-sv/translations.xml index 3599320cd8..7b2364f450 100644 --- a/features/securebackup/impl/src/main/res/values-sv/translations.xml +++ b/features/securebackup/impl/src/main/res/values-sv/translations.xml @@ -39,7 +39,6 @@ "Vänligen pröva igen för att bekräfta åtkomsten till din chattsäkerhetskopia." "Felaktig återställningsnyckel" "Om du har en säkerhetsnyckel eller säkerhetsfras så funkar den också." - "Återställningsnyckel eller lösenkod" "Ange …" "Blivit av med din återställningsnyckel?" "Återställningsnyckel bekräftad" diff --git a/features/securebackup/impl/src/main/res/values-uk/translations.xml b/features/securebackup/impl/src/main/res/values-uk/translations.xml index 14e47f8bad..7d88980f8b 100644 --- a/features/securebackup/impl/src/main/res/values-uk/translations.xml +++ b/features/securebackup/impl/src/main/res/values-uk/translations.xml @@ -38,7 +38,6 @@ "Будь ласка, спробуйте ще раз, щоб підтвердити доступ до резервної копії чату." "Неправильний ключ відновлення" "Якщо у вас є ключ безпеки або фраза безпеки, це теж спрацює." - "Ключ відновлення або код допуску" "Ввести…" "Загубили ключ відновлення?" "Ключ відновлення підтверджено" diff --git a/features/securebackup/impl/src/main/res/values-zh/translations.xml b/features/securebackup/impl/src/main/res/values-zh/translations.xml index 0b4f12b17a..c8f2b7d9ed 100644 --- a/features/securebackup/impl/src/main/res/values-zh/translations.xml +++ b/features/securebackup/impl/src/main/res/values-zh/translations.xml @@ -38,7 +38,6 @@ "请重试以访问您的聊天备份。" "恢复密钥不正确" "如果您有安全密钥或安全短语,也可以用。" - "恢复密钥或密码" "输入……" "丢失了恢复密钥?" "恢复密钥已确认" diff --git a/features/securebackup/impl/src/main/res/values/localazy.xml b/features/securebackup/impl/src/main/res/values/localazy.xml index f4795c23da..55c6c547f5 100644 --- a/features/securebackup/impl/src/main/res/values/localazy.xml +++ b/features/securebackup/impl/src/main/res/values/localazy.xml @@ -39,7 +39,6 @@ "Please try again to confirm access to your chat backup." "Incorrect recovery key" "If you have a security key or security phrase, this will work too." - "Recovery key or passcode" "Enter…" "Lost your recovery key?" "Recovery key confirmed" diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncActionView.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncActionView.kt index 08c2f352e6..6e42909f0b 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncActionView.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/async/AsyncActionView.kt @@ -48,7 +48,7 @@ fun AsyncActionView( ErrorDialog( title = errorTitle(async.error), content = errorMessage(async.error), - onDismiss = onErrorDismiss + onSubmit = onErrorDismiss ) } else { RetryDialog( diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ErrorDialog.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ErrorDialog.kt index acef5bf9f9..add7bf2904 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ErrorDialog.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ErrorDialog.kt @@ -13,6 +13,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.window.DialogProperties import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.PreviewGroup @@ -25,17 +26,23 @@ import io.element.android.libraries.ui.strings.CommonStrings @Composable fun ErrorDialog( content: String, - onDismiss: () -> Unit, + onSubmit: () -> Unit, modifier: Modifier = Modifier, - title: String = ErrorDialogDefaults.title, + title: String? = ErrorDialogDefaults.title, submitText: String = ErrorDialogDefaults.submitText, + onDismiss: () -> Unit = onSubmit, + canDismiss: Boolean = true, ) { - BasicAlertDialog(modifier = modifier, onDismissRequest = onDismiss) { + BasicAlertDialog( + modifier = modifier, + onDismissRequest = onDismiss, + properties = DialogProperties(dismissOnClickOutside = canDismiss, dismissOnBackPress = canDismiss) + ) { ErrorDialogContent( title = title, content = content, submitText = submitText, - onSubmitClick = onDismiss, + onSubmitClick = onSubmit, ) } } @@ -44,7 +51,7 @@ fun ErrorDialog( private fun ErrorDialogContent( content: String, onSubmitClick: () -> Unit, - title: String = ErrorDialogDefaults.title, + title: String? = ErrorDialogDefaults.title, submitText: String = ErrorDialogDefaults.submitText, ) { SimpleAlertDialogContent( @@ -78,6 +85,6 @@ internal fun ErrorDialogContentPreview() { internal fun ErrorDialogPreview() = ElementPreview { ErrorDialog( content = "Content", - onDismiss = {}, + onSubmit = {}, ) } 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 e45686b1a2..3b7441395a 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 @@ -131,6 +131,9 @@ interface MatrixClient : Closeable { /** Returns `true` if the home server supports native sliding sync. */ suspend fun isNativeSlidingSyncSupported(): Boolean - /** Returns `true` if the current session is using native sliding sync. */ + /** Returns `true` if the home server supports sliding sync using a proxy. */ + suspend fun isSlidingSyncProxySupported(): Boolean + + /** Returns `true` if the current session is using native sliding sync, `false` if it's using a proxy. */ fun isUsingNativeSlidingSync(): Boolean } 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 0fc9f6695b..c9989796e5 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 @@ -534,6 +534,10 @@ class RustMatrixClient( return client.availableSlidingSyncVersions().contains(SlidingSyncVersion.Native) } + override suspend fun isSlidingSyncProxySupported(): Boolean { + return client.availableSlidingSyncVersions().any { it is SlidingSyncVersion.Proxy } + } + override fun isUsingNativeSlidingSync(): Boolean { return client.session().slidingSyncVersion == SlidingSyncVersion.Native } 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 7681dda6f0..ad4c2d1549 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 @@ -7,7 +7,6 @@ package io.element.android.libraries.matrix.impl -import io.element.android.appconfig.AuthenticationConfig import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.di.CacheDirectory import io.element.android.libraries.featureflag.api.FeatureFlagService @@ -19,12 +18,10 @@ 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.util.anonymizedTokens import io.element.android.libraries.network.useragent.UserAgentProvider -import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.sessionstorage.api.SessionData import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.services.toolbox.api.systemclock.SystemClock import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.first import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.ClientBuilder import org.matrix.rustcomponents.sdk.Session @@ -47,7 +44,6 @@ class RustMatrixClientFactory @Inject constructor( private val proxyProvider: ProxyProvider, private val clock: SystemClock, private val utdTracker: UtdTracker, - private val appPreferencesStore: AppPreferencesStore, private val featureFlagService: FeatureFlagService, ) { suspend fun create(sessionData: SessionData): RustMatrixClient = withContext(coroutineDispatchers.io) { @@ -55,7 +51,7 @@ class RustMatrixClientFactory @Inject constructor( val client = getBaseClientBuilder( sessionPaths = sessionData.getSessionPaths(), passphrase = sessionData.passphrase, - restore = true, + slidingSyncType = ClientBuilderSlidingSync.Restored, ) .homeserverUrl(sessionData.homeserverUrl) .username(sessionData.userId) @@ -88,16 +84,8 @@ class RustMatrixClientFactory @Inject constructor( internal suspend fun getBaseClientBuilder( sessionPaths: SessionPaths, passphrase: String?, - restore: Boolean, + slidingSyncType: ClientBuilderSlidingSync, ): ClientBuilder { - val slidingSync = when { - // Always check restore first, since otherwise other values could accidentally override the already persisted config - restore -> ClientBuilderSlidingSync.Restored - AuthenticationConfig.SLIDING_SYNC_PROXY_URL != null -> ClientBuilderSlidingSync.CustomProxy(AuthenticationConfig.SLIDING_SYNC_PROXY_URL!!) - appPreferencesStore.isSimplifiedSlidingSyncEnabledFlow().first() -> ClientBuilderSlidingSync.Simplified - else -> ClientBuilderSlidingSync.Discovered - } - return ClientBuilder() .sessionPaths( dataPath = sessionPaths.fileDirectory.absolutePath, @@ -117,9 +105,9 @@ class RustMatrixClientFactory @Inject constructor( ) .run { // Apply sliding sync version settings - when (slidingSync) { + when (slidingSyncType) { ClientBuilderSlidingSync.Restored -> this - is ClientBuilderSlidingSync.CustomProxy -> slidingSyncVersionBuilder(SlidingSyncVersionBuilder.Proxy(slidingSync.url)) + is ClientBuilderSlidingSync.CustomProxy -> slidingSyncVersionBuilder(SlidingSyncVersionBuilder.Proxy(slidingSyncType.url)) ClientBuilderSlidingSync.Discovered -> slidingSyncVersionBuilder(SlidingSyncVersionBuilder.DiscoverProxy) ClientBuilderSlidingSync.Simplified -> slidingSyncVersionBuilder(SlidingSyncVersionBuilder.DiscoverNative) ClientBuilderSlidingSync.ForcedSimplified -> slidingSyncVersionBuilder(SlidingSyncVersionBuilder.Native) 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 344ae588a1..47a010cf2d 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 @@ -8,6 +8,7 @@ package io.element.android.libraries.matrix.impl.auth import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.appconfig.AuthenticationConfig import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.extensions.mapFailure import io.element.android.libraries.di.AppScope @@ -19,6 +20,7 @@ import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.impl.ClientBuilderSlidingSync import io.element.android.libraries.matrix.impl.RustMatrixClientFactory import io.element.android.libraries.matrix.impl.auth.qrlogin.QrErrorMapper import io.element.android.libraries.matrix.impl.auth.qrlogin.SdkQrCodeLoginData @@ -28,6 +30,7 @@ import io.element.android.libraries.matrix.impl.keys.PassphraseGenerator import io.element.android.libraries.matrix.impl.mapper.toSessionData import io.element.android.libraries.matrix.impl.paths.SessionPaths import io.element.android.libraries.matrix.impl.paths.SessionPathsFactory +import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.sessionstorage.api.LoggedInState import io.element.android.libraries.sessionstorage.api.LoginType import io.element.android.libraries.sessionstorage.api.SessionStore @@ -35,9 +38,13 @@ import kotlinx.coroutines.CancellationException import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.Client +import org.matrix.rustcomponents.sdk.ClientBuilder import org.matrix.rustcomponents.sdk.HumanQrLoginException +import org.matrix.rustcomponents.sdk.OidcConfiguration +import org.matrix.rustcomponents.sdk.QrCodeData import org.matrix.rustcomponents.sdk.QrCodeDecodeException import org.matrix.rustcomponents.sdk.QrLoginProgress import org.matrix.rustcomponents.sdk.QrLoginProgressListener @@ -55,6 +62,7 @@ class RustMatrixAuthenticationService @Inject constructor( private val rustMatrixClientFactory: RustMatrixClientFactory, private val passphraseGenerator: PassphraseGenerator, private val oidcConfigurationProvider: OidcConfigurationProvider, + private val appPreferencesStore: AppPreferencesStore, ) : MatrixAuthenticationService { // Passphrase which will be used for new sessions. Existing sessions will use the passphrase // stored in the SessionData. @@ -117,9 +125,10 @@ class RustMatrixAuthenticationService @Inject constructor( withContext(coroutineDispatchers.io) { val emptySessionPath = rotateSessionPath() runCatching { - val client = getBaseClientBuilder(emptySessionPath) - .serverNameOrHomeserverUrl(homeserver) - .build() + val client = makeClient(sessionPaths = emptySessionPath) { + serverNameOrHomeserverUrl(homeserver) + } + currentClient = client val homeServerDetails = client.homeserverLoginDetails().map() currentHomeserver.value = homeServerDetails.copy(url = homeserver) @@ -207,23 +216,24 @@ class RustMatrixAuthenticationService @Inject constructor( override suspend fun loginWithQrCode(qrCodeData: MatrixQrCodeLoginData, progress: (QrCodeLoginStep) -> Unit) = withContext(coroutineDispatchers.io) { + val sdkQrCodeLoginData = (qrCodeData as SdkQrCodeLoginData).rustQrCodeData val emptySessionPaths = rotateSessionPath() + val oidcConfiguration = oidcConfigurationProvider.get() + val progressListener = object : QrLoginProgressListener { + override fun onUpdate(state: QrLoginProgress) { + Timber.d("QR Code login progress: $state") + progress(state.toStep()) + } + } runCatching { - val client = rustMatrixClientFactory.getBaseClientBuilder( + val client = makeQrCodeLoginClient( sessionPaths = emptySessionPaths, passphrase = pendingPassphrase, - restore = false, + qrCodeData = sdkQrCodeLoginData, + oidcConfiguration = oidcConfiguration, + progressListener = progressListener, ) - .buildWithQrCode( - qrCodeData = (qrCodeData as SdkQrCodeLoginData).rustQrCodeData, - oidcConfiguration = oidcConfigurationProvider.get(), - progressListener = object : QrLoginProgressListener { - override fun onUpdate(state: QrLoginProgress) { - Timber.d("QR Code login progress: $state") - progress(state.toStep()) - } - } - ) + client.use { rustClient -> val sessionData = rustClient.session() .toSessionData( @@ -249,14 +259,80 @@ class RustMatrixAuthenticationService @Inject constructor( } } - private suspend fun getBaseClientBuilder( + private suspend fun makeClient( + sessionPaths: SessionPaths, + config: suspend ClientBuilder.() -> ClientBuilder, + ): Client { + val slidingSyncType = getSlidingSyncType() + if (slidingSyncType is ClientBuilderSlidingSync.Simplified) { + Timber.d("Creating client with simplified sliding sync") + try { + return rustMatrixClientFactory + .getBaseClientBuilder( + sessionPaths = sessionPaths, + passphrase = pendingPassphrase, + slidingSyncType = slidingSyncType, + ) + .run { config() } + .build() + } catch (e: HumanQrLoginException.SlidingSyncNotAvailable) { + Timber.e(e, "Failed to create client with simplified sliding sync, trying with Proxy now") + } + } + Timber.d("Creating client with Proxy sliding sync") + return rustMatrixClientFactory + .getBaseClientBuilder( + sessionPaths = sessionPaths, + passphrase = pendingPassphrase, + slidingSyncType = getSlidingSyncProxy(), + ) + .run { config() } + .build() + } + + private suspend fun makeQrCodeLoginClient( sessionPaths: SessionPaths, - ) = rustMatrixClientFactory - .getBaseClientBuilder( - sessionPaths = sessionPaths, - passphrase = pendingPassphrase, - restore = false, - ) + passphrase: String?, + qrCodeData: QrCodeData, + oidcConfiguration: OidcConfiguration, + progressListener: QrLoginProgressListener, + ): Client { + val slidingSyncType = getSlidingSyncType() + if (slidingSyncType is ClientBuilderSlidingSync.Simplified) { + Timber.d("Creating client for QR Code login with simplified sliding sync") + try { + return rustMatrixClientFactory + .getBaseClientBuilder( + sessionPaths = sessionPaths, + passphrase = pendingPassphrase, + slidingSyncType = slidingSyncType, + ) + .passphrase(passphrase) + .buildWithQrCode(qrCodeData, oidcConfiguration, progressListener) + } catch (e: HumanQrLoginException.SlidingSyncNotAvailable) { + Timber.e(e, "Failed to create client with simplified sliding sync, trying with Proxy now") + } + } + Timber.d("Creating client for QR Code login with Proxy sliding sync") + return rustMatrixClientFactory + .getBaseClientBuilder( + sessionPaths = sessionPaths, + passphrase = pendingPassphrase, + slidingSyncType = getSlidingSyncProxy(), + ) + .passphrase(passphrase) + .buildWithQrCode(qrCodeData, oidcConfiguration, progressListener) + } + + private suspend fun getSlidingSyncType(nativeSlidingSyncFailed: Boolean = false) = when { + appPreferencesStore.isSimplifiedSlidingSyncEnabledFlow().first() && !nativeSlidingSyncFailed -> ClientBuilderSlidingSync.Simplified + else -> getSlidingSyncProxy() + } + + private fun getSlidingSyncProxy() = when { + AuthenticationConfig.SLIDING_SYNC_PROXY_URL != null -> ClientBuilderSlidingSync.CustomProxy(AuthenticationConfig.SLIDING_SYNC_PROXY_URL!!) + else -> ClientBuilderSlidingSync.Discovered + } private fun clear() { currentClient?.close() 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 ed484f4426..5db394f77d 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 @@ -79,6 +79,7 @@ class FakeMatrixClient( private val userIdServerNameLambda: () -> String = { lambdaError() }, private val getUrlLambda: (String) -> Result = { lambdaError() }, var isNativeSlidingSyncSupportedLambda: suspend () -> Boolean = { true }, + var isSlidingSyncProxySupportedLambda: suspend () -> Boolean = { true }, var isUsingNativeSlidingSyncLambda: () -> Boolean = { true }, ) : MatrixClient { var setDisplayNameCalled: Boolean = false @@ -324,6 +325,10 @@ class FakeMatrixClient( return isNativeSlidingSyncSupportedLambda() } + override suspend fun isSlidingSyncProxySupported(): Boolean { + return isSlidingSyncProxySupportedLambda() + } + override fun isUsingNativeSlidingSync(): Boolean { return isUsingNativeSlidingSyncLambda() } diff --git a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt index 8e09547fb4..ab985e798d 100644 --- a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt +++ b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt @@ -87,7 +87,7 @@ class DefaultAppPreferencesStore @Inject constructor( override fun isSimplifiedSlidingSyncEnabledFlow(): Flow { return store.data.map { prefs -> - prefs[simplifiedSlidingSyncKey] ?: false + prefs[simplifiedSlidingSyncKey] ?: true } } diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index f7c3213ba4..b4fec91a0c 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -36,6 +36,7 @@ "Back" "Call" "Cancel" + "Cancel for now" "Choose photo" "Clear" "Close" @@ -283,6 +284,12 @@ Reason: %1$s." "Pinned messages" "You\'re about to go to your %1$s account to reset your identity. Afterwards you\'ll be taken back to the app." "Can\'t confirm? Go to your account to reset your identity." + "Withdraw verification and send" + "You can withdraw your verification and send this message anyway, or you can cancel for now and try again later after reverifying %1$s." + "Your message was not sent because %1$s’s verified identity has changed" + "Send message anyway" + "%1$s is using one or more unverified devices. You can send the message anyway, or you can cancel for now and try again later after %2$s has verified all their devices." + "Your message was not sent because %1$s has not verified one or more devices" "Pinned messages" "Failed processing media to upload, please try again." "Could not retrieve user details" @@ -304,6 +311,8 @@ Reason: %1$s." "Open in Google Maps" "Open in OpenStreetMap" "Share this location" + "Message not sent because %1$s’s verified identity has changed." + "Message not sent because %1$s has not verified one or more devices." "Location" "Version: %1$s (%2$s)" "en" diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt index 5319baf10e..19e1390f47 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt @@ -55,11 +55,11 @@ class MainActivity : ComponentActivity() { proxyProvider = proxyProvider, clock = DefaultSystemClock(), utdTracker = UtdTracker(NoopAnalyticsService()), - appPreferencesStore = InMemoryAppPreferencesStore(), featureFlagService = AlwaysEnabledFeatureFlagService(), ), passphraseGenerator = NullPassphraseGenerator(), oidcConfigurationProvider = OidcConfigurationProvider(baseDirectory), + appPreferencesStore = InMemoryAppPreferencesStore(), ) } diff --git a/services/apperror/impl/src/main/kotlin/io/element/android/services/apperror/impl/AppErrorView.kt b/services/apperror/impl/src/main/kotlin/io/element/android/services/apperror/impl/AppErrorView.kt index 80d3de2dfe..2bd46eeb00 100644 --- a/services/apperror/impl/src/main/kotlin/io/element/android/services/apperror/impl/AppErrorView.kt +++ b/services/apperror/impl/src/main/kotlin/io/element/android/services/apperror/impl/AppErrorView.kt @@ -36,7 +36,7 @@ private fun AppErrorViewContent( ErrorDialog( title = title, content = body, - onDismiss = onDismiss, + onSubmit = onDismiss, ) } diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_3_en.png new file mode 100644 index 0000000000..e625c84b24 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Day_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:98f68bcb22f867add02028ec43cc9b609d8cd76ace450eec1f010899b3f29445 +size 24728 diff --git a/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_3_en.png new file mode 100644 index 0000000000..6d9414c34a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/appnav.loggedin_LoggedInView_Night_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:48e881658f3627275743a5f5cf172f312d26ea0633fa84243da4b277b664f66b +size 22753 diff --git a/tools/localazy/config.json b/tools/localazy/config.json index f736825725..6f41be8693 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -1,5 +1,12 @@ { "modules" : [ + { + "name" : ":appnav", + "includeRegex" : [ + "banner\\.migrate_to_native_sliding_sync\\.force_logout.title", + "banner\\.migrate_to_native_sliding_sync\\.action" + ] + }, { "name" : ":features:rageshake:impl", "includeRegex" : [ From d4922593129117b76bf17a9ab954aa4c2f070cf9 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 13 Sep 2024 11:44:08 +0200 Subject: [PATCH 023/106] Enable account creation and iterate on the Button design --- .../kotlin/io/element/android/appconfig/OnBoardingConfig.kt | 2 +- .../android/features/onboarding/impl/OnBoardingView.kt | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/appconfig/src/main/kotlin/io/element/android/appconfig/OnBoardingConfig.kt b/appconfig/src/main/kotlin/io/element/android/appconfig/OnBoardingConfig.kt index d70f831eaa..7c08b28ce3 100644 --- a/appconfig/src/main/kotlin/io/element/android/appconfig/OnBoardingConfig.kt +++ b/appconfig/src/main/kotlin/io/element/android/appconfig/OnBoardingConfig.kt @@ -12,5 +12,5 @@ object OnBoardingConfig { const val CAN_LOGIN_WITH_QR_CODE = true /** Whether the user can create an account using the app. */ - const val CAN_CREATE_ACCOUNT = false + const val CAN_CREATE_ACCOUNT = true } diff --git a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt index 8ba1679a5e..b63ca0a12f 100644 --- a/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt +++ b/features/onboarding/impl/src/main/kotlin/io/element/android/features/onboarding/impl/OnBoardingView.kt @@ -39,8 +39,8 @@ 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.OutlinedButton import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings @@ -171,10 +171,9 @@ private fun OnBoardingButtons( .testTag(TestTags.onBoardingSignIn) ) if (state.canCreateAccount) { - OutlinedButton( + TextButton( text = stringResource(id = R.string.screen_onboarding_sign_up), onClick = onCreateAccount, - enabled = true, modifier = Modifier .fillMaxWidth() ) From 39348d2e7e1451bbf9460a9626c94a1b0bfff51e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 16 Sep 2024 12:22:07 +0200 Subject: [PATCH 024/106] Account Creation using a WebView --- features/login/impl/build.gradle.kts | 1 + .../features/login/impl/LoginFlowNode.kt | 14 ++ .../impl/resolver/network/ElementWellKnown.kt | 26 +++ .../impl/resolver/network/WellknownAPI.kt | 3 + .../ConfirmAccountProviderNode.kt | 6 + .../ConfirmAccountProviderPresenter.kt | 16 +- .../ConfirmAccountProviderState.kt | 1 + .../ConfirmAccountProviderStateProvider.kt | 25 ++- .../ConfirmAccountProviderView.kt | 12 ++ .../AccountCreationNotSupported.kt | 10 ++ .../createaccount/CreateAccountEvents.kt | 13 ++ .../createaccount/CreateAccountNode.kt | 43 +++++ .../createaccount/CreateAccountPresenter.kt | 83 +++++++++ .../createaccount/CreateAccountState.kt | 19 ++ .../CreateAccountStateProvider.kt | 33 ++++ .../createaccount/CreateAccountView.kt | 166 ++++++++++++++++++ .../screens/createaccount/MessageParser.kt | 45 +++++ .../MobileRegistrationResponse.kt | 27 +++ .../WebViewMessageInterceptor.kt | 84 +++++++++ .../WebClientUrlForAuthenticationRetriever.kt | 50 ++++++ .../impl/src/main/res/values/localazy.xml | 1 + .../ConfirmAccountProviderPresenterTest.kt | 95 ++++++++++ .../CreateAccountPresenterTest.kt | 145 +++++++++++++++ .../createaccount/DefaultMessageParserTest.kt | 84 +++++++++ .../createaccount/FakeMessageParser.kt | 19 ++ ...eWebClientUrlForAuthenticationRetriever.kt | 18 ++ .../api/auth/MatrixAuthenticationService.kt | 6 + .../api/auth/external/ExternalSession.kt | 20 +++ .../auth/RustMatrixAuthenticationService.kt | 18 ++ .../libraries/matrix/impl/mapper/Session.kt | 22 +++ .../auth/FakeMatrixAuthenticationService.kt | 7 + .../src/main/res/values-el/translations.xml | 1 - .../src/main/res/values-et/translations.xml | 1 - .../src/main/res/values/localazy.xml | 1 - tools/localazy/config.json | 1 + 35 files changed, 1106 insertions(+), 10 deletions(-) create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/network/ElementWellKnown.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/AccountCreationNotSupported.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountEvents.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountNode.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountPresenter.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountState.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountStateProvider.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountView.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/MessageParser.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/MobileRegistrationResponse.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/WebViewMessageInterceptor.kt create mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/web/WebClientUrlForAuthenticationRetriever.kt create mode 100644 features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountPresenterTest.kt create mode 100644 features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/DefaultMessageParserTest.kt create mode 100644 features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/FakeMessageParser.kt create mode 100644 features/login/impl/src/test/kotlin/io/element/android/features/login/impl/web/FakeWebClientUrlForAuthenticationRetriever.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/external/ExternalSession.kt diff --git a/features/login/impl/build.gradle.kts b/features/login/impl/build.gradle.kts index 6ea1eb7936..fc783e8733 100644 --- a/features/login/impl/build.gradle.kts +++ b/features/login/impl/build.gradle.kts @@ -44,6 +44,7 @@ dependencies { implementation(projects.libraries.oidc.api) implementation(libs.androidx.browser) implementation(platform(libs.network.retrofit.bom)) + implementation(libs.androidx.webkit) implementation(libs.network.retrofit) implementation(libs.serialization.json) api(projects.features.login.api) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt index a118920ebd..c9e97e8995 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/LoginFlowNode.kt @@ -30,6 +30,7 @@ import io.element.android.features.login.impl.accountprovider.AccountProviderDat import io.element.android.features.login.impl.qrcode.QrCodeLoginFlowNode import io.element.android.features.login.impl.screens.changeaccountprovider.ChangeAccountProviderNode import io.element.android.features.login.impl.screens.confirmaccountprovider.ConfirmAccountProviderNode +import io.element.android.features.login.impl.screens.createaccount.CreateAccountNode import io.element.android.features.login.impl.screens.loginpassword.LoginPasswordNode import io.element.android.features.login.impl.screens.searchaccountprovider.SearchAccountProviderNode import io.element.android.libraries.architecture.BackstackView @@ -109,6 +110,9 @@ class LoginFlowNode @AssistedInject constructor( @Parcelize data object LoginPassword : NavTarget + @Parcelize + data class CreateAccount(val url: String) : NavTarget + @Parcelize data class OidcView(val oidcDetails: OidcDetails) : NavTarget } @@ -140,6 +144,10 @@ class LoginFlowNode @AssistedInject constructor( } } + override fun onCreateAccountContinue(url: String) { + backstack.push(NavTarget.CreateAccount(url)) + } + override fun onLoginPasswordNeeded() { backstack.push(NavTarget.LoginPassword) } @@ -180,6 +188,12 @@ class LoginFlowNode @AssistedInject constructor( is NavTarget.OidcView -> { oidcEntryPoint.createFallbackWebViewNode(this, buildContext, navTarget.oidcDetails.url) } + is NavTarget.CreateAccount -> { + val inputs = CreateAccountNode.Inputs( + url = navTarget.url, + ) + createNode(buildContext, listOf(inputs)) + } } } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/network/ElementWellKnown.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/network/ElementWellKnown.kt new file mode 100644 index 0000000000..d149957a55 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/network/ElementWellKnown.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2023, 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.resolver.network + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * Example: + *
+ * {
+ *     "registration_helper_url": "https://element.io"
+ * }
+ * 
+ * . + */ +@Serializable +data class ElementWellKnown( + @SerialName("registration_helper_url") + val registrationHelperUrl: String? = null, +) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/network/WellknownAPI.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/network/WellknownAPI.kt index 05658e9e7c..11f1621b03 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/network/WellknownAPI.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/resolver/network/WellknownAPI.kt @@ -12,4 +12,7 @@ import retrofit2.http.GET internal interface WellknownAPI { @GET(".well-known/matrix/client") suspend fun getWellKnown(): WellKnown + + @GET(".well-known/element/element.json") + suspend fun getElementWellKnown(): ElementWellKnown } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderNode.kt index 8e865d9e39..454da3f795 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderNode.kt @@ -43,6 +43,7 @@ class ConfirmAccountProviderNode @AssistedInject constructor( interface Callback : Plugin { fun onLoginPasswordNeeded() fun onOidcDetails(oidcDetails: OidcDetails) + fun onCreateAccountContinue(url: String) fun onChangeAccountProvider() } @@ -54,6 +55,10 @@ class ConfirmAccountProviderNode @AssistedInject constructor( plugins().forEach { it.onLoginPasswordNeeded() } } + private fun onCreateAccountContinue(url: String) { + plugins().forEach { it.onCreateAccountContinue(url) } + } + private fun onChangeAccountProvider() { plugins().forEach { it.onChangeAccountProvider() } } @@ -67,6 +72,7 @@ class ConfirmAccountProviderNode @AssistedInject constructor( modifier = modifier, onOidcDetails = ::onOidcDetails, onNeedLoginPassword = ::onLoginPasswordNeeded, + onCreateAccountContinue = ::onCreateAccountContinue, onChange = ::onChangeAccountProvider, onLearnMoreClick = { openLearnMorePage(context) }, ) 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 a51573f602..c15c84744f 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 @@ -21,6 +21,8 @@ import dagger.assisted.AssistedInject import io.element.android.features.login.impl.DefaultLoginUserStory 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.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 @@ -36,6 +38,7 @@ class ConfirmAccountProviderPresenter @AssistedInject constructor( private val authenticationService: MatrixAuthenticationService, private val oidcActionFlow: OidcActionFlow, private val defaultLoginUserStory: DefaultLoginUserStory, + private val webClientUrlForAuthenticationRetriever: WebClientUrlForAuthenticationRetriever, ) : Presenter { data class Params( val isAccountCreation: Boolean, @@ -90,13 +93,24 @@ class ConfirmAccountProviderPresenter @AssistedInject constructor( if (matrixHomeServerDetails.supportsOidcLogin) { // Retrieve the details right now LoginFlow.OidcFlow(authenticationService.getOidcUrl().getOrThrow()) + } else if (params.isAccountCreation) { + val url = webClientUrlForAuthenticationRetriever.retrieve(homeserverUrl) + LoginFlow.AccountCreationFlow(url) } else if (matrixHomeServerDetails.supportsPasswordLogin) { LoginFlow.PasswordLogin } else { error("Unsupported login flow") } }.getOrThrow() - }.runCatchingUpdatingState(loginFlowAction, errorTransform = ChangeServerError::from) + }.runCatchingUpdatingState( + state = loginFlowAction, + errorTransform = { + when (it) { + is AccountCreationNotSupported -> it + else -> ChangeServerError.from(it) + } + } + ) } private suspend fun onOidcAction( 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 b73acab4ec..3c80d76d08 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 @@ -24,4 +24,5 @@ data class ConfirmAccountProviderState( sealed interface LoginFlow { data object PasswordLogin : LoginFlow data class OidcFlow(val oidcDetails: OidcDetails) : LoginFlow + data class AccountCreationFlow(val url: String) : LoginFlow } 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 d643f0001a..5c95823ded 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 @@ -8,20 +8,33 @@ 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.screens.createaccount.AccountCreationNotSupported import io.element.android.libraries.architecture.AsyncData open class ConfirmAccountProviderStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( aConfirmAccountProviderState(), - // Add other state here + aConfirmAccountProviderState( + isAccountCreation = true, + ), + aConfirmAccountProviderState( + isAccountCreation = true, + loginFlow = AsyncData.Failure(AccountCreationNotSupported()) + ), ) } -fun aConfirmAccountProviderState() = ConfirmAccountProviderState( - accountProvider = anAccountProvider(), - isAccountCreation = false, - loginFlow = AsyncData.Uninitialized, - eventSink = {} +private fun aConfirmAccountProviderState( + accountProvider: AccountProvider = anAccountProvider(), + isAccountCreation: Boolean = false, + loginFlow: AsyncData = AsyncData.Uninitialized, + eventSink: (ConfirmAccountProviderEvents) -> Unit = {}, +) = ConfirmAccountProviderState( + accountProvider = accountProvider, + isAccountCreation = isAccountCreation, + loginFlow = loginFlow, + 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 da1106d463..ac34d70107 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 @@ -22,6 +22,7 @@ import androidx.compose.ui.unit.dp 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.screens.createaccount.AccountCreationNotSupported import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule @@ -42,6 +43,7 @@ fun ConfirmAccountProviderView( onOidcDetails: (OidcDetails) -> Unit, onNeedLoginPassword: () -> Unit, onLearnMoreClick: () -> Unit, + onCreateAccountContinue: (url: String) -> Unit, onChange: () -> Unit, modifier: Modifier = Modifier, ) { @@ -116,6 +118,14 @@ fun ConfirmAccountProviderView( eventSink(ConfirmAccountProviderEvents.ClearError) }) } + is AccountCreationNotSupported -> { + ErrorDialog( + content = stringResource(CommonStrings.error_account_creation_not_possible), + onDismiss = { + eventSink.invoke(ConfirmAccountProviderEvents.ClearError) + } + ) + } } } is AsyncData.Loading -> Unit // The Continue button shows the loading state @@ -123,6 +133,7 @@ fun ConfirmAccountProviderView( when (val loginFlowState = state.loginFlow.data) { is LoginFlow.OidcFlow -> onOidcDetails(loginFlowState.oidcDetails) LoginFlow.PasswordLogin -> onNeedLoginPassword() + is LoginFlow.AccountCreationFlow -> onCreateAccountContinue(loginFlowState.url) } } AsyncData.Uninitialized -> Unit @@ -139,6 +150,7 @@ internal fun ConfirmAccountProviderViewPreview( state = state, onOidcDetails = {}, onNeedLoginPassword = {}, + onCreateAccountContinue = {}, onLearnMoreClick = {}, onChange = {}, ) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/AccountCreationNotSupported.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/AccountCreationNotSupported.kt new file mode 100644 index 0000000000..8a299a6d54 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/AccountCreationNotSupported.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.createaccount + +class AccountCreationNotSupported : Exception() diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountEvents.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountEvents.kt new file mode 100644 index 0000000000..8647d71c43 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountEvents.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.createaccount + +sealed interface CreateAccountEvents { + data class SetPageProgress(val progress: Int) : CreateAccountEvents + data class OnMessageReceived(val message: String) : CreateAccountEvents +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountNode.kt new file mode 100644 index 0000000000..61b380815f --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountNode.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.createaccount + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.architecture.NodeInputs +import io.element.android.libraries.architecture.inputs +import io.element.android.libraries.di.AppScope + +@ContributesNode(AppScope::class) +class CreateAccountNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + presenterFactory: CreateAccountPresenter.Factory, +) : Node(buildContext, plugins = plugins) { + data class Inputs( + val url: String, + ) : NodeInputs + + private val presenter = presenterFactory.create(inputs().url) + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + CreateAccountView( + state = state, + modifier = modifier, + onBackClick = ::navigateUp, + ) + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountPresenter.kt new file mode 100644 index 0000000000..69ffb10883 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountPresenter.kt @@ -0,0 +1,83 @@ +/* + * Copyright 2023, 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.createaccount + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import io.element.android.features.login.impl.DefaultLoginUserStory +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.core.extensions.flatMap +import io.element.android.libraries.core.meta.BuildMeta +import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService +import io.element.android.libraries.matrix.api.core.SessionId +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +class CreateAccountPresenter @AssistedInject constructor( + @Assisted private val url: String, + private val authenticationService: MatrixAuthenticationService, + private val defaultLoginUserStory: DefaultLoginUserStory, + private val messageParser: MessageParser, + private val buildMeta: BuildMeta, +) : Presenter { + @AssistedFactory + interface Factory { + fun create(url: String): CreateAccountPresenter + } + + @Composable + override fun present(): CreateAccountState { + val coroutineScope = rememberCoroutineScope() + val pageProgress: MutableState = remember { mutableIntStateOf(0) } + val createAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } + + fun handleEvents(event: CreateAccountEvents) { + when (event) { + is CreateAccountEvents.SetPageProgress -> { + pageProgress.value = event.progress + } + is CreateAccountEvents.OnMessageReceived -> { + // Ignore unexpected message + if (event.message.contains("isTrusted")) return + coroutineScope.importSession(event.message, createAction) + } + } + } + + return CreateAccountState( + url = url, + pageProgress = pageProgress.value, + isDebugBuild = buildMeta.isDebuggable, + createAction = createAction.value, + eventSink = ::handleEvents + ) + } + + private fun CoroutineScope.importSession(message: String, loggedInState: MutableState>) = launch { + loggedInState.value = AsyncAction.Loading + runCatching { + messageParser.parse(message) + }.flatMap { externalSession -> + authenticationService.importCreatedSession(externalSession) + }.onSuccess { sessionId -> + // We will not navigate to the WaitList screen, so the login user story is done + defaultLoginUserStory.setLoginFlowIsDone(true) + loggedInState.value = AsyncAction.Success(sessionId) + }.onFailure { failure -> + loggedInState.value = AsyncAction.Failure(failure) + } + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountState.kt new file mode 100644 index 0000000000..de05825d69 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountState.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.createaccount + +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.matrix.api.core.SessionId + +data class CreateAccountState( + val url: String, + val pageProgress: Int, + val createAction: AsyncAction, + val isDebugBuild: Boolean, + val eventSink: (CreateAccountEvents) -> Unit +) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountStateProvider.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountStateProvider.kt new file mode 100644 index 0000000000..45b3b4d004 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountStateProvider.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2023, 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.createaccount + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.matrix.api.core.SessionId + +open class CreateAccountStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aCreateAccountState(), + aCreateAccountState(pageProgress = 33), + aCreateAccountState(createAction = AsyncAction.Loading), + aCreateAccountState(createAction = AsyncAction.Failure(Throwable("Failed to create account"))), + ) +} + +private fun aCreateAccountState( + pageProgress: Int = 100, + createAction: AsyncAction = AsyncAction.Uninitialized, +) = CreateAccountState( + url = "https://example.com", + isDebugBuild = true, + pageProgress = pageProgress, + createAction = createAction, + eventSink = {} +) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountView.kt new file mode 100644 index 0000000000..7074f935d3 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountView.kt @@ -0,0 +1,166 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.createaccount + +import android.annotation.SuppressLint +import android.view.ViewGroup +import android.webkit.WebChromeClient +import android.webkit.WebView +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.consumeWindowInsets +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.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +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 androidx.compose.ui.viewinterop.AndroidView +import io.element.android.compound.theme.ElementTheme +import io.element.android.features.login.impl.R +import io.element.android.libraries.designsystem.components.async.AsyncActionView +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.aliasScreenTitle +import io.element.android.libraries.designsystem.theme.components.LinearProgressIndicator +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.theme.progressIndicatorTrackColor + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun CreateAccountView( + state: CreateAccountState, + onBackClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Scaffold( + modifier = modifier, + topBar = { + TopAppBar( + title = { + Text( + stringResource(R.string.screen_create_account_title), + style = ElementTheme.typography.aliasScreenTitle, + ) + }, + navigationIcon = { + BackButton(onClick = onBackClick) + }, + ) + } + ) { contentPadding -> + Box( + modifier = Modifier + .padding(contentPadding) + .consumeWindowInsets(contentPadding) + .fillMaxSize() + ) { + CreateAccountWebView( + modifier = Modifier + .fillMaxSize(), + state = state, + onWebViewCreate = { webView -> + WebViewMessageInterceptor(webView, state.isDebugBuild) { + state.eventSink(CreateAccountEvents.OnMessageReceived(it)) + } + } + ) + AnimatedVisibility( + visible = state.pageProgress != 100, + // Disable enter animation + enter = fadeIn(initialAlpha = 1f), + exit = fadeOut(), + ) { + LinearProgressIndicator( + modifier = Modifier + .fillMaxWidth() + .height(2.dp), + progress = { state.pageProgress / 100f }, + trackColor = ElementTheme.colors.progressIndicatorTrackColor, + ) + } + } + } + + AsyncActionView( + async = state.createAction, + onSuccess = {}, + onErrorDismiss = onBackClick, + onRetry = null + ) +} + +@Composable +private fun CreateAccountWebView( + state: CreateAccountState, + onWebViewCreate: (WebView) -> Unit, + modifier: Modifier = Modifier, +) { + if (LocalInspectionMode.current) { + Box(modifier = modifier, contentAlignment = Alignment.Center) { + Text("WebView - can't be previewed") + } + } else { + AndroidView( + modifier = modifier, + factory = { context -> + WebView(context).apply { + onWebViewCreate(this) + setup(state) + } + }, + update = { webView -> + if (webView.url != state.url) { + webView.loadUrl(state.url) + } + }, + onRelease = { webView -> + webView.destroy() + } + ) + } +} + +@SuppressLint("SetJavaScriptEnabled") +private fun WebView.setup(state: CreateAccountState) { + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + with(settings) { + javaScriptEnabled = true + domStorageEnabled = true + } + + webChromeClient = object : WebChromeClient() { + override fun onProgressChanged(view: WebView?, newProgress: Int) { + super.onProgressChanged(view, newProgress) + state.eventSink(CreateAccountEvents.SetPageProgress(newProgress)) + } + } +} + +@PreviewsDayNight +@Composable +internal fun CreateAccountViewPreview(@PreviewParameter(CreateAccountStateProvider::class) state: CreateAccountState) = ElementPreview { + CreateAccountView( + state = state, + onBackClick = {}, + ) +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/MessageParser.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/MessageParser.kt new file mode 100644 index 0000000000..a47bd8a83c --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/MessageParser.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.createaccount + +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource +import io.element.android.libraries.di.AppScope +import io.element.android.libraries.matrix.api.auth.external.ExternalSession +import kotlinx.serialization.json.Json +import javax.inject.Inject + +interface MessageParser { + /** + * Parse the message and return the ExternalSession object, or + * throw an exception if the message is invalid. + */ + fun parse(message: String): ExternalSession +} + +@ContributesBinding(AppScope::class) +class DefaultMessageParser @Inject constructor( + private val accountProviderDataSource: AccountProviderDataSource, +) : MessageParser { + override fun parse(message: String): ExternalSession { + val parser = Json { ignoreUnknownKeys = true } + val response = parser.decodeFromString(MobileRegistrationResponse.serializer(), message) + val userId = response.userId ?: error("No user ID in response") + val homeServer = response.homeServer ?: accountProviderDataSource.flow().value.url + val accessToken = response.accessToken ?: error("No access token in response") + val deviceId = response.deviceId ?: error("No device ID in response") + return ExternalSession( + userId = userId, + homeserverUrl = homeServer, + accessToken = accessToken, + deviceId = deviceId, + refreshToken = null, + slidingSyncProxy = null + ) + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/MobileRegistrationResponse.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/MobileRegistrationResponse.kt new file mode 100644 index 0000000000..5db50e1804 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/MobileRegistrationResponse.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.createaccount + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * For ref: + * https://github.com/element-hq/matrix-react-sdk/pull/42/files#diff-2bbba5a742004fd4e924a639ded444279f66f7ad890cb669fbc91ac6b8638c64R56 + */ +@Serializable +data class MobileRegistrationResponse( + @SerialName("user_id") + val userId: String? = null, + @SerialName("home_server") + val homeServer: String? = null, + @SerialName("access_token") + val accessToken: String? = null, + @SerialName("device_id") + val deviceId: String? = null, +) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/WebViewMessageInterceptor.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/WebViewMessageInterceptor.kt new file mode 100644 index 0000000000..eb59ddb858 --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/WebViewMessageInterceptor.kt @@ -0,0 +1,84 @@ +/* + * Copyright 2023, 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.createaccount + +import android.graphics.Bitmap +import android.webkit.JavascriptInterface +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.webkit.WebViewCompat +import androidx.webkit.WebViewFeature + +class WebViewMessageInterceptor( + webView: WebView, + private val debugLog: Boolean, + private val onMessage: (String) -> Unit, +) { + companion object { + // We call both the WebMessageListener and the JavascriptInterface objects in JS with this + // 'listenerName' so they can both receive the data from the WebView when + // `${LISTENER_NAME}.postMessage(...)` is called + const val LISTENER_NAME = "elementX" + } + + init { + webView.webViewClient = object : WebViewClient() { + override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { + super.onPageStarted(view, url, favicon) + + // We inject this JS code when the page starts loading to attach a message listener to the window. + // This listener will receive both messages: + // - EC widget API -> Element X (message.data.api == "fromWidget") + // - Element X -> EC widget API (message.data.api == "toWidget"), we should ignore these + view?.evaluateJavascript( + """ + window.addEventListener( + "mobileregistrationresponse", + (event) => { + let json = JSON.stringify(event.detail) + ${"console.log('message sent: ' + json);".takeIf { debugLog }} + $LISTENER_NAME.postMessage(json); + }, + false, + ); + """.trimIndent(), + null + ) + } + } + + // Use WebMessageListener if supported, otherwise use JavascriptInterface + if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) { + // Create a WebMessageListener, which will receive messages from the WebView and reply to them + val webMessageListener = WebViewCompat.WebMessageListener { _, message, _, _, _ -> + onMessageReceived(message.data) + } + WebViewCompat.addWebMessageListener( + webView, + LISTENER_NAME, + setOf("*"), + webMessageListener + ) + } else { + webView.addJavascriptInterface( + object { + @JavascriptInterface + fun postMessage(json: String?) { + onMessageReceived(json) + } + }, + LISTENER_NAME, + ) + } + } + + private fun onMessageReceived(json: String?) { + // Here is where we would handle the messages from the WebView, passing them to the listener + json?.let { onMessage(it) } + } +} diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/web/WebClientUrlForAuthenticationRetriever.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/web/WebClientUrlForAuthenticationRetriever.kt new file mode 100644 index 0000000000..9955fe150d --- /dev/null +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/web/WebClientUrlForAuthenticationRetriever.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.web + +import android.net.Uri +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.login.impl.resolver.network.WellknownAPI +import io.element.android.features.login.impl.screens.createaccount.AccountCreationNotSupported +import io.element.android.libraries.di.AppScope +import io.element.android.libraries.network.RetrofitFactory +import java.net.HttpURLConnection +import javax.inject.Inject + +interface WebClientUrlForAuthenticationRetriever { + suspend fun retrieve(homeServerUrl: String): String +} + +@ContributesBinding(AppScope::class) +class DefaultWebClientUrlForAuthenticationRetriever @Inject constructor( + private val retrofitFactory: RetrofitFactory, +) : WebClientUrlForAuthenticationRetriever { + override suspend fun retrieve(homeServerUrl: String): String { + val wellknownApi = retrofitFactory.create(homeServerUrl) + .create(WellknownAPI::class.java) + val result = try { + wellknownApi.getElementWellKnown() + } catch (e: Exception) { + throw when { + e is retrofit2.HttpException && + e.code() == HttpURLConnection.HTTP_NOT_FOUND -> AccountCreationNotSupported() + else -> e + } + } + val registrationHelperUrl = result.registrationHelperUrl + return if (registrationHelperUrl != null) { + Uri.parse(registrationHelperUrl) + .buildUpon() + .appendQueryParameter("hs_url", homeServerUrl) + .build() + .toString() + } else { + throw AccountCreationNotSupported() + } + } +} diff --git a/features/login/impl/src/main/res/values/localazy.xml b/features/login/impl/src/main/res/values/localazy.xml index b0b6252d52..a46b083d63 100644 --- a/features/login/impl/src/main/res/values/localazy.xml +++ b/features/login/impl/src/main/res/values/localazy.xml @@ -21,6 +21,7 @@ "You can only connect to an existing server that supports sliding sync. Your homeserver admin will need to configure it. %1$s" "What is the address of your server?" "Select your server" + "Create account" "This account has been deactivated." "Incorrect username and/or password" "This is not a valid user identifier. Expected format: ‘@user:homeserver.org’" 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 1609ffef3c..1d70580e4d 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 @@ -13,7 +13,10 @@ import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.login.impl.DefaultLoginUserStory import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource +import io.element.android.features.login.impl.screens.createaccount.AccountCreationNotSupported import io.element.android.features.login.impl.util.defaultAccountProvider +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 import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.test.A_HOMESERVER @@ -255,17 +258,109 @@ class ConfirmAccountProviderPresenterTest { } } + @Test + fun `present - confirm account creation without oidc and without url generates an error`() = runTest { + val authenticationService = FakeMatrixAuthenticationService() + authenticationService.givenHomeserver(A_HOMESERVER) + val presenter = createConfirmAccountProviderPresenter( + params = ConfirmAccountProviderPresenter.Params(isAccountCreation = true), + matrixAuthenticationService = authenticationService, + webClientUrlForAuthenticationRetriever = FakeWebClientUrlForAuthenticationRetriever { + throw AccountCreationNotSupported() + }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(ConfirmAccountProviderEvents.Continue) + skipItems(1) // Loading + // Check an error was returned + val submittedState = awaitItem() + assertThat(submittedState.loginFlow.errorOrNull()).isInstanceOf(AccountCreationNotSupported::class.java) + // Assert the error is then cleared + submittedState.eventSink(ConfirmAccountProviderEvents.ClearError) + val clearedState = awaitItem() + assertThat(clearedState.loginFlow).isEqualTo(AsyncData.Uninitialized) + } + } + + @Test + fun `present - confirm account creation with oidc is successful`() = runTest { + val authenticationService = FakeMatrixAuthenticationService() + authenticationService.givenHomeserver(A_HOMESERVER_OIDC) + val presenter = createConfirmAccountProviderPresenter( + params = ConfirmAccountProviderPresenter.Params(isAccountCreation = true), + matrixAuthenticationService = authenticationService, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(ConfirmAccountProviderEvents.Continue) + skipItems(1) // Loading + val submittedState = awaitItem() + assertThat(submittedState.loginFlow).isInstanceOf(AsyncData.Success::class.java) + assertThat(submittedState.loginFlow.dataOrNull()).isInstanceOf(LoginFlow.OidcFlow::class.java) + } + } + + @Test + fun `present - confirm account creation with oidc and url continues with oidc`() = runTest { + val aUrl = "aUrl" + val authenticationService = FakeMatrixAuthenticationService() + authenticationService.givenHomeserver(A_HOMESERVER_OIDC) + val presenter = createConfirmAccountProviderPresenter( + params = ConfirmAccountProviderPresenter.Params(isAccountCreation = true), + matrixAuthenticationService = authenticationService, + webClientUrlForAuthenticationRetriever = FakeWebClientUrlForAuthenticationRetriever { aUrl }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(ConfirmAccountProviderEvents.Continue) + skipItems(1) // Loading + val submittedState = awaitItem() + assertThat(submittedState.loginFlow).isInstanceOf(AsyncData.Success::class.java) + assertThat(submittedState.loginFlow.dataOrNull()).isInstanceOf(LoginFlow.OidcFlow::class.java) + } + } + + @Test + fun `present - confirm account creation without oidc and with url continuing with url`() = runTest { + val aUrl = "aUrl" + val authenticationService = FakeMatrixAuthenticationService() + authenticationService.givenHomeserver(A_HOMESERVER) + val presenter = createConfirmAccountProviderPresenter( + params = ConfirmAccountProviderPresenter.Params(isAccountCreation = true), + matrixAuthenticationService = authenticationService, + webClientUrlForAuthenticationRetriever = FakeWebClientUrlForAuthenticationRetriever { aUrl }, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(ConfirmAccountProviderEvents.Continue) + skipItems(1) // Loading + val submittedState = awaitItem() + assertThat(submittedState.loginFlow.dataOrNull()).isEqualTo(LoginFlow.AccountCreationFlow(aUrl)) + } + } + private fun createConfirmAccountProviderPresenter( params: ConfirmAccountProviderPresenter.Params = ConfirmAccountProviderPresenter.Params(isAccountCreation = false), accountProviderDataSource: AccountProviderDataSource = AccountProviderDataSource(), matrixAuthenticationService: MatrixAuthenticationService = FakeMatrixAuthenticationService(), defaultOidcActionFlow: DefaultOidcActionFlow = DefaultOidcActionFlow(), defaultLoginUserStory: DefaultLoginUserStory = DefaultLoginUserStory(), + webClientUrlForAuthenticationRetriever: WebClientUrlForAuthenticationRetriever = FakeWebClientUrlForAuthenticationRetriever(), ) = ConfirmAccountProviderPresenter( params = params, accountProviderDataSource = accountProviderDataSource, authenticationService = matrixAuthenticationService, oidcActionFlow = defaultOidcActionFlow, defaultLoginUserStory = defaultLoginUserStory, + webClientUrlForAuthenticationRetriever = webClientUrlForAuthenticationRetriever ) } diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountPresenterTest.kt new file mode 100644 index 0000000000..eb89e80638 --- /dev/null +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountPresenterTest.kt @@ -0,0 +1,145 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.createaccount + +import app.cash.molecule.RecompositionMode +import app.cash.molecule.moleculeFlow +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.features.login.impl.DefaultLoginUserStory +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.core.meta.BuildMeta +import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService +import io.element.android.libraries.matrix.api.auth.external.ExternalSession +import io.element.android.libraries.matrix.test.AN_EXCEPTION +import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService +import io.element.android.libraries.matrix.test.core.aBuildMeta +import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.lambda.value +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test + +class CreateAccountPresenterTest { + @get:Rule + val warmUpRule = WarmUpRule() + + @Test + fun `present - initial state`() = runTest { + val presenter = createPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.url).isEqualTo("aUrl") + assertThat(initialState.pageProgress).isEqualTo(0) + assertThat(initialState.createAction).isEqualTo(AsyncAction.Uninitialized) + assertThat(initialState.isDebugBuild).isTrue() + } + } + + @Test + fun `present - set up progress update the state`() = runTest { + val presenter = createPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(CreateAccountEvents.SetPageProgress(33)) + assertThat(awaitItem().pageProgress).isEqualTo(33) + } + } + + @Test + fun `present - receiving a message not able to be parsed change the state to error`() = runTest { + val presenter = createPresenter( + messageParser = FakeMessageParser { error("An error") } + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(CreateAccountEvents.OnMessageReceived("")) + assertThat(awaitItem().createAction).isInstanceOf(AsyncAction.Failure::class.java) + } + } + + @Test + fun `present - receiving a message containing isTrusted is ignored`() = runTest { + val presenter = createPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(CreateAccountEvents.OnMessageReceived("isTrusted")) + } + } + + @Test + fun `present - receiving a message able to be parsed change the state to success`() = runTest { + val defaultLoginUserStory = DefaultLoginUserStory() + defaultLoginUserStory.setLoginFlowIsDone(false) + assertThat(defaultLoginUserStory.loginFlowIsDone.value).isFalse() + val lambda = lambdaRecorder { _ -> anExternalSession() } + val presenter = createPresenter( + authenticationService = FakeMatrixAuthenticationService( + importCreatedSessionLambda = { Result.success(A_SESSION_ID) } + ), + messageParser = FakeMessageParser(lambda), + defaultLoginUserStory = defaultLoginUserStory, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(CreateAccountEvents.OnMessageReceived("aMessage")) + assertThat(awaitItem().createAction.isLoading()).isTrue() + assertThat(awaitItem().createAction.dataOrNull()).isEqualTo(A_SESSION_ID) + } + lambda.assertions().isCalledOnce().with(value("aMessage")) + assertThat(defaultLoginUserStory.loginFlowIsDone.value).isTrue() + } + + @Test + fun `present - receiving a message able to be parsed but error in importing change the state to error`() = runTest { + val defaultLoginUserStory = DefaultLoginUserStory() + defaultLoginUserStory.setLoginFlowIsDone(false) + assertThat(defaultLoginUserStory.loginFlowIsDone.value).isFalse() + val presenter = createPresenter( + authenticationService = FakeMatrixAuthenticationService( + importCreatedSessionLambda = { Result.failure(AN_EXCEPTION) } + ), + messageParser = FakeMessageParser { anExternalSession() } + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(CreateAccountEvents.OnMessageReceived("")) + assertThat(awaitItem().createAction.isLoading()).isTrue() + assertThat(awaitItem().createAction.errorOrNull()).isNotNull() + } + assertThat(defaultLoginUserStory.loginFlowIsDone.value).isFalse() + } + + private fun createPresenter( + url: String = "aUrl", + authenticationService: MatrixAuthenticationService = FakeMatrixAuthenticationService(), + defaultLoginUserStory: DefaultLoginUserStory = DefaultLoginUserStory(), + messageParser: MessageParser = FakeMessageParser(), + buildMeta: BuildMeta = aBuildMeta(), + ) = CreateAccountPresenter( + url = url, + authenticationService = authenticationService, + defaultLoginUserStory = defaultLoginUserStory, + messageParser = messageParser, + buildMeta = buildMeta, + ) +} diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/DefaultMessageParserTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/DefaultMessageParserTest.kt new file mode 100644 index 0000000000..44ccb5f0fb --- /dev/null +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/DefaultMessageParserTest.kt @@ -0,0 +1,84 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.createaccount + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource +import io.element.android.features.login.impl.util.defaultAccountProvider +import io.element.android.libraries.matrix.api.auth.external.ExternalSession +import kotlinx.serialization.SerializationException +import org.junit.Assert.assertThrows +import org.junit.Test + +class DefaultMessageParserTest { + private val validMessage = """ + { + "user_id": "user_id", + "home_server": "home_server", + "access_token": "access_token", + "device_id": "device_id" + } + """.trimIndent() + + @Test + fun `DefaultMessageParser is able to parse correct message`() { + val sut = DefaultMessageParser( + AccountProviderDataSource() + ) + assertThat(sut.parse(validMessage)).isEqualTo( + anExternalSession( + homeserverUrl = "home_server", + ) + ) + } + + @Test + fun `DefaultMessageParser should throw Exception in case of error`() { + val sut = DefaultMessageParser( + AccountProviderDataSource() + ) + // kotlinx.serialization.json.internal.JsonDecodingException + assertThrows(SerializationException::class.java) { sut.parse("invalid json") } + // missing userId + assertThrows(IllegalStateException::class.java) { sut.parse(validMessage.replace(""""user_id": "user_id",""", "")) } + // missing accessToken + assertThrows(IllegalStateException::class.java) { sut.parse(validMessage.replace(""""access_token": "access_token",""", "")) } + // missing deviceId + assertThrows(IllegalStateException::class.java) { + sut.parse( + validMessage + .replace(""""access_token": "access_token",""", """"access_token": "access_token"""") + .replace(""""device_id": "device_id"""", "") + ) + } + } + + @Test + fun `DefaultMessageParser should be successful even is homeserver url is missing`() { + val sut = DefaultMessageParser( + AccountProviderDataSource() + ) + // missing homeServer + assertThat(sut.parse(validMessage.replace(""""home_server": "home_server",""", ""))).isEqualTo( + anExternalSession( + homeserverUrl = defaultAccountProvider.url, + ) + ) + } +} + +internal fun anExternalSession( + homeserverUrl: String = "home_server", +) = ExternalSession( + userId = "user_id", + homeserverUrl = homeserverUrl, + accessToken = "access_token", + deviceId = "device_id", + refreshToken = null, + slidingSyncProxy = null +) diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/FakeMessageParser.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/FakeMessageParser.kt new file mode 100644 index 0000000000..4207d6b102 --- /dev/null +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/FakeMessageParser.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.screens.createaccount + +import io.element.android.libraries.matrix.api.auth.external.ExternalSession +import io.element.android.tests.testutils.lambda.lambdaError + +class FakeMessageParser( + private val parseResult: (String) -> ExternalSession = { lambdaError() } +) : MessageParser { + override fun parse(message: String): ExternalSession { + return parseResult(message) + } +} diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/web/FakeWebClientUrlForAuthenticationRetriever.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/web/FakeWebClientUrlForAuthenticationRetriever.kt new file mode 100644 index 0000000000..c94d114be5 --- /dev/null +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/web/FakeWebClientUrlForAuthenticationRetriever.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.login.impl.web + +import io.element.android.tests.testutils.lambda.lambdaError + +class FakeWebClientUrlForAuthenticationRetriever( + private val retrieveLambda: suspend (homeServerUrl: String) -> String = { lambdaError() } +) : WebClientUrlForAuthenticationRetriever { + override suspend fun retrieve(homeServerUrl: String): String { + return retrieveLambda(homeServerUrl) + } +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt index bf0955098b..bb3d396202 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.api.auth import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClientProvider +import io.element.android.libraries.matrix.api.auth.external.ExternalSession import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep import io.element.android.libraries.matrix.api.core.SessionId @@ -30,6 +31,11 @@ interface MatrixAuthenticationService { suspend fun setHomeserver(homeserver: String): Result suspend fun login(username: String, password: String): Result + /** + * Import a session that was created using another client, for instance Element Web. + */ + suspend fun importCreatedSession(externalSession: ExternalSession): Result + /* * OIDC part. */ diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/external/ExternalSession.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/external/ExternalSession.kt new file mode 100644 index 0000000000..d85135b26e --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/external/ExternalSession.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.auth.external + +/*** + * Represents a session data of a session created by another client. + */ +data class ExternalSession( + val userId: String, + val deviceId: String, + val accessToken: String, + val refreshToken: String?, + val homeserverUrl: String, + val slidingSyncProxy: String? +) 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 47a010cf2d..d1f0d29295 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 @@ -17,6 +17,7 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.auth.external.ExternalSession import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep import io.element.android.libraries.matrix.api.core.SessionId @@ -160,6 +161,23 @@ class RustMatrixAuthenticationService @Inject constructor( } } + override suspend fun importCreatedSession(externalSession: ExternalSession): Result = + withContext(coroutineDispatchers.io) { + runCatching { + currentClient ?: error("You need to call `setHomeserver()` first") + val currentSessionPaths = sessionPaths ?: error("You need to call `setHomeserver()` first") + val sessionData = externalSession.toSessionData( + isTokenValid = true, + loginType = LoginType.PASSWORD, + passphrase = pendingPassphrase, + sessionPaths = currentSessionPaths, + ) + clear() + sessionStore.storeData(sessionData) + SessionId(sessionData.userId) + } + } + private var pendingOidcAuthorizationData: OidcAuthorizationData? = null override suspend fun getOidcUrl(): Result { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt index 95bf823872..0f9bd5c87d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/mapper/Session.kt @@ -7,6 +7,7 @@ package io.element.android.libraries.matrix.impl.mapper +import io.element.android.libraries.matrix.api.auth.external.ExternalSession import io.element.android.libraries.matrix.impl.paths.SessionPaths import io.element.android.libraries.sessionstorage.api.LoginType import io.element.android.libraries.sessionstorage.api.SessionData @@ -35,3 +36,24 @@ internal fun Session.toSessionData( sessionPath = sessionPaths.fileDirectory.absolutePath, cachePath = sessionPaths.cacheDirectory.absolutePath, ) + +internal fun ExternalSession.toSessionData( + isTokenValid: Boolean, + loginType: LoginType, + passphrase: String?, + sessionPaths: SessionPaths, +) = SessionData( + userId = userId, + deviceId = deviceId, + accessToken = accessToken, + refreshToken = refreshToken, + homeserverUrl = homeserverUrl, + oidcData = null, + slidingSyncProxy = slidingSyncProxy, + loginTimestamp = Date(), + isTokenValid = isTokenValid, + loginType = loginType, + passphrase = passphrase, + sessionPath = sessionPaths.fileDirectory.absolutePath, + cachePath = sessionPaths.cacheDirectory.absolutePath, +) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt index 6f5ffa3928..8c18629817 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeMatrixAuthenticationService.kt @@ -11,12 +11,14 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails import io.element.android.libraries.matrix.api.auth.OidcDetails +import io.element.android.libraries.matrix.api.auth.external.ExternalSession import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.sessionstorage.api.LoggedInState +import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.simulateLongTask import kotlinx.coroutines.flow.Flow @@ -30,6 +32,7 @@ class FakeMatrixAuthenticationService( var matrixClientResult: ((SessionId) -> Result)? = null, var loginWithQrCodeResult: (qrCodeData: MatrixQrCodeLoginData, progress: (QrCodeLoginStep) -> Unit) -> Result = lambdaRecorder Unit, Result> { _, _ -> Result.success(A_SESSION_ID) }, + private val importCreatedSessionLambda: (ExternalSession) -> Result = { lambdaError() } ) : MatrixAuthenticationService { private val homeserver = MutableStateFlow(null) private var oidcError: Throwable? = null @@ -73,6 +76,10 @@ class FakeMatrixAuthenticationService( loginError?.let { Result.failure(it) } ?: Result.success(A_USER_ID) } + override suspend fun importCreatedSession(externalSession: ExternalSession): Result = simulateLongTask { + return importCreatedSessionLambda(externalSession) + } + override suspend fun getOidcUrl(): Result = simulateLongTask { oidcError?.let { Result.failure(it) } ?: Result.success(A_OIDC_DATA) } 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 15d9c7244d..d0fd3cbdab 100644 --- a/libraries/ui-strings/src/main/res/values-el/translations.xml +++ b/libraries/ui-strings/src/main/res/values-el/translations.xml @@ -273,7 +273,6 @@ "Γεια, μίλα μου στην εφαρμογή %1$s :%2$s" "%1$s Android" "Κούνησε δυνατά τη συσκευή σου για να αναφέρεις κάποιο σφάλμα" - "Δημιουργία λογαριασμού" "Αποτυχία επιλογής πολυμέσου, δοκίμασε ξανά." "Αποτυχία μεταφόρτωσης μέσου, δοκίμασε ξανά." "Αποτυχία μεταφόρτωσης πολυμέσων, δοκίμασε ξανά." 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 74a646fb66..f6bcbf0fe4 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -273,7 +273,6 @@ Põhjus: %1$s." "Hei, suhtle minuga %1$s võrgus: %2$s" "%1$s Android" "Veast teatamiseks raputa nutiseadet ägedalt" - "Loo kasutajakonto" "Meediafaili valimine ei õnnestunud. Palun proovi uuesti." "Meediafaili töötlemine enne üleslaadimist ei õnnestunud. Palun proovi uuesti." "Meediafaili üleslaadimine ei õnnestunud. Palun proovi uuesti." diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 3b8ad9ec24..17da391831 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -273,7 +273,6 @@ Reason: %1$s." "Hey, talk to me on %1$s: %2$s" "%1$s Android" "Rageshake to report bug" - "Create account" "Failed selecting media, please try again." "Failed processing media to upload, please try again." "Failed uploading media, please try again." diff --git a/tools/localazy/config.json b/tools/localazy/config.json index 6f41be8693..f463b6d621 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -127,6 +127,7 @@ "screen_server_confirmation_.*", "screen_change_server_.*", "screen_change_account_provider_.*", + "screen_create_account_.*", "screen_account_provider_.*", "screen_waitlist_.*", "screen_qr_code_login_.*" From aab5a27a91144f9499f5d2190c71d1e2c4dc441b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 13 Sep 2024 22:03:06 +0200 Subject: [PATCH 025/106] Open external url (like terms and condition) in a Custom Chrome Tab, and disable to "Leave page" dialog. --- .../createaccount/CreateAccountNode.kt | 13 ++++++++++++ .../createaccount/CreateAccountView.kt | 21 ++++++++++++++++--- .../WebViewMessageInterceptor.kt | 9 ++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountNode.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountNode.kt index 61b380815f..b17699e6f8 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountNode.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountNode.kt @@ -7,14 +7,18 @@ package io.element.android.features.login.impl.screens.createaccount +import android.app.Activity import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode +import io.element.android.compound.theme.ElementTheme +import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.inputs import io.element.android.libraries.di.AppScope @@ -31,13 +35,22 @@ class CreateAccountNode @AssistedInject constructor( private val presenter = presenterFactory.create(inputs().url) + private fun onOpenExternalUrl(activity: Activity, darkTheme: Boolean, url: String) { + activity.openUrlInChromeCustomTab(null, darkTheme, url) + } + @Composable override fun View(modifier: Modifier) { + val activity = LocalContext.current as Activity + val isDark = ElementTheme.isLightTheme.not() val state = presenter.present() CreateAccountView( state = state, modifier = modifier, onBackClick = ::navigateUp, + onOpenExternalUrl = { + onOpenExternalUrl(activity, isDark, it) + }, ) } } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountView.kt index 7074f935d3..aaa67a80f9 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/CreateAccountView.kt @@ -9,6 +9,7 @@ package io.element.android.features.login.impl.screens.createaccount import android.annotation.SuppressLint import android.view.ViewGroup +import android.webkit.JsResult import android.webkit.WebChromeClient import android.webkit.WebView import androidx.compose.animation.AnimatedVisibility @@ -41,12 +42,14 @@ 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.theme.progressIndicatorTrackColor +import timber.log.Timber @OptIn(ExperimentalMaterial3Api::class) @Composable fun CreateAccountView( state: CreateAccountState, onBackClick: () -> Unit, + onOpenExternalUrl: (String) -> Unit, modifier: Modifier = Modifier, ) { Scaffold( @@ -76,9 +79,14 @@ fun CreateAccountView( .fillMaxSize(), state = state, onWebViewCreate = { webView -> - WebViewMessageInterceptor(webView, state.isDebugBuild) { - state.eventSink(CreateAccountEvents.OnMessageReceived(it)) - } + WebViewMessageInterceptor( + webView, + state.isDebugBuild, + onOpenExternalUrl = onOpenExternalUrl, + onMessage = { + state.eventSink(CreateAccountEvents.OnMessageReceived(it)) + }, + ) } ) AnimatedVisibility( @@ -153,6 +161,12 @@ private fun WebView.setup(state: CreateAccountState) { super.onProgressChanged(view, newProgress) state.eventSink(CreateAccountEvents.SetPageProgress(newProgress)) } + + override fun onJsBeforeUnload(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean { + Timber.w("onJsBeforeUnload, cancelling the dialog, we will open external links in a Custom Chrome Tab") + result?.confirm() + return true + } } } @@ -162,5 +176,6 @@ internal fun CreateAccountViewPreview(@PreviewParameter(CreateAccountStateProvid CreateAccountView( state = state, onBackClick = {}, + onOpenExternalUrl = {}, ) } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/WebViewMessageInterceptor.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/WebViewMessageInterceptor.kt index eb59ddb858..f07c466736 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/WebViewMessageInterceptor.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/WebViewMessageInterceptor.kt @@ -9,6 +9,7 @@ package io.element.android.features.login.impl.screens.createaccount import android.graphics.Bitmap import android.webkit.JavascriptInterface +import android.webkit.WebResourceRequest import android.webkit.WebView import android.webkit.WebViewClient import androidx.webkit.WebViewCompat @@ -17,6 +18,7 @@ import androidx.webkit.WebViewFeature class WebViewMessageInterceptor( webView: WebView, private val debugLog: Boolean, + private val onOpenExternalUrl: (String) -> Unit, private val onMessage: (String) -> Unit, ) { companion object { @@ -50,6 +52,13 @@ class WebViewMessageInterceptor( null ) } + + override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean { + request ?: return super.shouldOverrideUrlLoading(view, request) + // Load the URL in a Chrome Custom Tab, and return true to cancel the load + onOpenExternalUrl(request.url.toString()) + return true + } } // Use WebMessageListener if supported, otherwise use JavascriptInterface From a4e93ebe2710cfe35e178f28a22fd4be94ebddea Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 16 Sep 2024 10:46:51 +0200 Subject: [PATCH 026/106] Temporary account creation flow is only supported on matrix.org --- .../impl/web/WebClientUrlForAuthenticationRetriever.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/web/WebClientUrlForAuthenticationRetriever.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/web/WebClientUrlForAuthenticationRetriever.kt index 9955fe150d..0f5375bde4 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/web/WebClientUrlForAuthenticationRetriever.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/web/WebClientUrlForAuthenticationRetriever.kt @@ -9,11 +9,13 @@ package io.element.android.features.login.impl.web import android.net.Uri import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.appconfig.AuthenticationConfig import io.element.android.features.login.impl.resolver.network.WellknownAPI import io.element.android.features.login.impl.screens.createaccount.AccountCreationNotSupported import io.element.android.libraries.di.AppScope import io.element.android.libraries.network.RetrofitFactory import java.net.HttpURLConnection +import timber.log.Timber import javax.inject.Inject interface WebClientUrlForAuthenticationRetriever { @@ -25,6 +27,10 @@ class DefaultWebClientUrlForAuthenticationRetriever @Inject constructor( private val retrofitFactory: RetrofitFactory, ) : WebClientUrlForAuthenticationRetriever { override suspend fun retrieve(homeServerUrl: String): String { + if (homeServerUrl != AuthenticationConfig.MATRIX_ORG_URL) { + Timber.w("Temporary account creation flow is only supported on matrix.org") + throw AccountCreationNotSupported() + } val wellknownApi = retrofitFactory.create(homeServerUrl) .create(WellknownAPI::class.java) val result = try { From 10e95cbf28333e990b1ad5ba2ef15877c2c62968 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 16 Sep 2024 12:39:40 +0200 Subject: [PATCH 027/106] Fix compilation error --- .../ConfirmAccountProviderView.kt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) 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 ac34d70107..c6d47793af 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 @@ -111,17 +111,19 @@ fun ConfirmAccountProviderView( ) } is ChangeServerError.SlidingSyncAlert -> { - SlidingSyncNotSupportedDialog(onLearnMoreClick = { - onLearnMoreClick() - eventSink(ConfirmAccountProviderEvents.ClearError) - }, onDismiss = { - eventSink(ConfirmAccountProviderEvents.ClearError) - }) + SlidingSyncNotSupportedDialog( + onLearnMoreClick = { + onLearnMoreClick() + eventSink(ConfirmAccountProviderEvents.ClearError) + }, + onDismiss = { + eventSink(ConfirmAccountProviderEvents.ClearError) + }) } is AccountCreationNotSupported -> { ErrorDialog( content = stringResource(CommonStrings.error_account_creation_not_possible), - onDismiss = { + onSubmit = { eventSink.invoke(ConfirmAccountProviderEvents.ClearError) } ) From 7647414c685c619c003231b495ebeb08a70800d1 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 16 Sep 2024 10:50:01 +0000 Subject: [PATCH 028/106] Update screenshots --- ...irmaccountprovider_ConfirmAccountProviderView_Day_1_en.png | 3 +++ ...irmaccountprovider_ConfirmAccountProviderView_Day_2_en.png | 3 +++ ...maccountprovider_ConfirmAccountProviderView_Night_1_en.png | 3 +++ ...maccountprovider_ConfirmAccountProviderView_Night_2_en.png | 3 +++ ....impl.screens.createaccount_CreateAccountView_Day_0_en.png | 3 +++ ....impl.screens.createaccount_CreateAccountView_Day_1_en.png | 3 +++ ....impl.screens.createaccount_CreateAccountView_Day_2_en.png | 3 +++ ....impl.screens.createaccount_CreateAccountView_Day_3_en.png | 3 +++ ...mpl.screens.createaccount_CreateAccountView_Night_0_en.png | 3 +++ ...mpl.screens.createaccount_CreateAccountView_Night_1_en.png | 3 +++ ...mpl.screens.createaccount_CreateAccountView_Night_2_en.png | 3 +++ ...mpl.screens.createaccount_CreateAccountView_Night_3_en.png | 3 +++ .../features.onboarding.impl_OnBoardingView_Day_2_en.png | 4 ++-- .../features.onboarding.impl_OnBoardingView_Day_3_en.png | 4 ++-- .../features.onboarding.impl_OnBoardingView_Night_2_en.png | 4 ++-- .../features.onboarding.impl_OnBoardingView_Night_3_en.png | 4 ++-- 16 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_3_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en.png new file mode 100644 index 0000000000..f4a7f63530 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f2f3a79b578e2c4cb7f6c9cf48f2c94dd6889d57b82bd7454d9a0d7b76f58d8a +size 38689 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en.png new file mode 100644 index 0000000000..a348889301 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8df01760f694d1214e3d71582ee2e6ab3fe9a2319b8f1e3005d451764eb873f0 +size 39341 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en.png new file mode 100644 index 0000000000..f30b395104 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a6818bb540210582166ff6484dfca0ec45e88def508c9c5e3a0eb838514b591 +size 37634 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en.png new file mode 100644 index 0000000000..faf85fafa4 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f8a73d70b78289b7faf63a511f066fa3ee3fc89be512b1e69e143087c360fa2 +size 36847 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_0_en.png new file mode 100644 index 0000000000..d1ce609f52 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89344bcdfe8634d9d2e0ea701c7357e1744d18284a5374209e1903a100b5de47 +size 13651 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_1_en.png new file mode 100644 index 0000000000..7cf778987e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d47d8ae4144ac6a63cee3359fe7b6e0068069fc006fa99ff874b40ab38c3ef82 +size 13693 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_2_en.png new file mode 100644 index 0000000000..352466596f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c36947469bd91cb58d7d404feb22fe3257a648195d68d5594ef96d21f6a38da +size 13496 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_3_en.png new file mode 100644 index 0000000000..9d943f498f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Day_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6738e2c9b06b5f229b3b3d1d807e18e8d04661b664e61f5645a853329f11c23c +size 15423 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_0_en.png new file mode 100644 index 0000000000..beab9a1b1b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff4e3e6a8845b8cf2c81160d556c82ab1aa48e4f1912a63313b751ea0f83be08 +size 13252 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_1_en.png new file mode 100644 index 0000000000..f998350fcf --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e19e9c62760cc4cb0a5f4e2dd814c32c118233efd5714ab11f68520deb83d470 +size 13279 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_2_en.png new file mode 100644 index 0000000000..27d44ecd6a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bc1cbe1378c4cd1daf809d27d13f1221a443d683d9bfdcf3c0b2af1ada5bdf82 +size 12328 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_3_en.png new file mode 100644 index 0000000000..6740d1895e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.createaccount_CreateAccountView_Night_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8d8542941be6e786b2c33a4615eada254287bf61ca34536a9ec3f672f5b7613f +size 13753 diff --git a/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Day_2_en.png index 67d47d34d2..09dcffa934 100644 --- a/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:78cd46cb6a689088dda0ea79d7efcee4bbb41e956dd308820c369daa3e11582d -size 309346 +oid sha256:137ed2c613128525a2ee749c3f488cf8c2900dda49778dae420d72364a1d98d1 +size 307793 diff --git a/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Day_3_en.png index 17ed84c21e..e38bad3edb 100644 --- a/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:59d2f5f0f9ffc4f3ceca83626121d35e22482ee7f0be0626be2c922b64762cd9 -size 303240 +oid sha256:9a19a446abbcd7c4317dd6283df8de2fdf1829e905f353d4dd79132bdf1c4845 +size 301997 diff --git a/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Night_2_en.png index e15808ede5..d2dee86e6d 100644 --- a/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:01d8ce27c1f526f003003a643408216bf106d882c6f0275caf9bea78b8e05b92 -size 385522 +oid sha256:db259afbc02e4696b36101aa6ae6829d0ab8d23ee6c662b2ff63838894466b4f +size 384093 diff --git a/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Night_3_en.png index 1a58a5c612..fac9148917 100644 --- a/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.onboarding.impl_OnBoardingView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f5ab54696b3e60080df81b17c02804c81687c6b260c76408ffad6d0079d4bf86 -size 366816 +oid sha256:5b83da6855e10e0765619fb6557843b0b657526928ca94f2a565144f5b261c8e +size 365396 From 2d1cede6a8427cd770340e2bf7f4d72f6476e72d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 16 Sep 2024 14:23:56 +0200 Subject: [PATCH 029/106] Fix quality and failing test. --- .../confirmaccountprovider/ConfirmAccountProviderView.kt | 3 ++- .../impl/web/WebClientUrlForAuthenticationRetriever.kt | 7 +++---- .../features/onboarding/impl/OnBoardingPresenterTest.kt | 3 ++- 3 files changed, 7 insertions(+), 6 deletions(-) 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 c6d47793af..407ea9d88b 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 @@ -118,7 +118,8 @@ fun ConfirmAccountProviderView( }, onDismiss = { eventSink(ConfirmAccountProviderEvents.ClearError) - }) + } + ) } is AccountCreationNotSupported -> { ErrorDialog( diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/web/WebClientUrlForAuthenticationRetriever.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/web/WebClientUrlForAuthenticationRetriever.kt index 0f5375bde4..b7a30ee843 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/web/WebClientUrlForAuthenticationRetriever.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/web/WebClientUrlForAuthenticationRetriever.kt @@ -14,8 +14,8 @@ import io.element.android.features.login.impl.resolver.network.WellknownAPI import io.element.android.features.login.impl.screens.createaccount.AccountCreationNotSupported import io.element.android.libraries.di.AppScope import io.element.android.libraries.network.RetrofitFactory -import java.net.HttpURLConnection import timber.log.Timber +import java.net.HttpURLConnection import javax.inject.Inject interface WebClientUrlForAuthenticationRetriever { @@ -35,10 +35,9 @@ class DefaultWebClientUrlForAuthenticationRetriever @Inject constructor( .create(WellknownAPI::class.java) val result = try { wellknownApi.getElementWellKnown() - } catch (e: Exception) { + } catch (e: retrofit2.HttpException) { throw when { - e is retrofit2.HttpException && - e.code() == HttpURLConnection.HTTP_NOT_FOUND -> AccountCreationNotSupported() + e.code() == HttpURLConnection.HTTP_NOT_FOUND -> AccountCreationNotSupported() else -> e } } diff --git a/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt b/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt index fff5763221..8791992021 100644 --- a/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt +++ b/features/onboarding/impl/src/test/kotlin/io/element/android/features/onboarding/impl/OnBoardingPresenterTest.kt @@ -11,6 +11,7 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import io.element.android.appconfig.OnBoardingConfig import io.element.android.libraries.core.meta.BuildType import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService @@ -46,7 +47,7 @@ class OnBoardingPresenterTest { assertThat(initialState.isDebugBuild).isTrue() assertThat(initialState.canLoginWithQrCode).isFalse() assertThat(initialState.productionApplicationName).isEqualTo("B") - assertThat(initialState.canCreateAccount).isFalse() + assertThat(initialState.canCreateAccount).isEqualTo(OnBoardingConfig.CAN_CREATE_ACCOUNT) assertThat(awaitItem().canLoginWithQrCode).isTrue() } From 7238af7f7fdd64af2b9a180e19d4b4cfa96e5271 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 16 Sep 2024 15:02:20 +0200 Subject: [PATCH 030/106] Fix not being able to decline an invite from the room list (#3466) * Add `InvitedRoom` to wrap Rust SDK Rooms in 'invited' membership state. At the moment, this is a wrapper that allows us to call `Room.leave()` without having to initialise the room's timeline (which is impossible). * Add `MatrixRoom.getInvitedRoom(roomId)` to get one of these rooms. Also, `RustRoomFactory` now has a `createInvitedRoom` method for this. * Adapt `AcceptDeclineInvitePresenter` to use the new APIs. --- .../response/AcceptDeclineInvitePresenter.kt | 4 +-- .../AcceptDeclineInvitePresenterTest.kt | 16 ++-------- .../libraries/matrix/api/MatrixClient.kt | 2 ++ .../libraries/matrix/api/room/InvitedRoom.kt | 20 +++++++++++++ .../libraries/matrix/impl/RustMatrixClient.kt | 5 ++++ .../matrix/impl/room/RustInvitedRoom.kt | 28 ++++++++++++++++++ .../matrix/impl/room/RustRoomFactory.kt | 29 +++++++++++++++++++ .../libraries/matrix/test/FakeMatrixClient.kt | 6 ++++ .../matrix/test/room/FakeInvitedRoom.kt | 27 +++++++++++++++++ 9 files changed, 122 insertions(+), 15 deletions(-) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/InvitedRoom.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustInvitedRoom.kt create mode 100644 libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeInvitedRoom.kt diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt index 7d117dba5e..c44a6cfb4f 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt @@ -112,8 +112,8 @@ class AcceptDeclineInvitePresenter @Inject constructor( private fun CoroutineScope.declineInvite(roomId: RoomId, declinedAction: MutableState>) = launch { suspend { - client.getRoom(roomId)?.use { - it.leave().getOrThrow() + client.getInvitedRoom(roomId)?.use { + it.declineInvite().getOrThrow() notificationCleaner.clearMembershipNotificationForRoom(client.sessionId, roomId) } roomId diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt index f4dcb4f278..45fb2efc86 100644 --- a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt @@ -21,7 +21,7 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_NAME import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.FakeMatrixClient -import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import io.element.android.libraries.matrix.test.room.FakeInvitedRoom import io.element.android.libraries.matrix.test.room.join.FakeJoinRoom import io.element.android.libraries.push.api.notifications.NotificationCleaner import io.element.android.libraries.push.test.notifications.FakeNotificationCleaner @@ -83,12 +83,7 @@ class AcceptDeclineInvitePresenterTest { Result.failure(RuntimeException("Failed to leave room")) } val client = FakeMatrixClient().apply { - givenGetRoomResult( - roomId = A_ROOM_ID, - result = FakeMatrixRoom( - leaveRoomLambda = declineInviteFailure - ) - ) + getInvitedRoomResults[A_ROOM_ID] = FakeInvitedRoom(declineInviteResult = declineInviteFailure) } val presenter = createAcceptDeclineInvitePresenter(client = client) presenter.test { @@ -133,12 +128,7 @@ class AcceptDeclineInvitePresenterTest { Result.success(Unit) } val client = FakeMatrixClient().apply { - givenGetRoomResult( - roomId = A_ROOM_ID, - result = FakeMatrixRoom( - leaveRoomLambda = declineInviteSuccess - ) - ) + getInvitedRoomResults[A_ROOM_ID] = FakeInvitedRoom(declineInviteResult = declineInviteSuccess) } val presenter = createAcceptDeclineInvitePresenter( client = 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 3b7441395a..ca44838553 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 @@ -21,6 +21,7 @@ import io.element.android.libraries.matrix.api.notification.NotificationService import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.pusher.PushersService +import io.element.android.libraries.matrix.api.room.InvitedRoom import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.RoomMembershipObserver @@ -49,6 +50,7 @@ interface MatrixClient : Closeable { val sessionCoroutineScope: CoroutineScope val ignoredUsersFlow: StateFlow> suspend fun getRoom(roomId: RoomId): MatrixRoom? + suspend fun getInvitedRoom(roomId: RoomId): InvitedRoom? suspend fun findDM(userId: UserId): RoomId? suspend fun ignoreUser(userId: UserId): Result suspend fun unignoreUser(userId: UserId): Result diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/InvitedRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/InvitedRoom.kt new file mode 100644 index 0000000000..7e1dd5d10d --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/InvitedRoom.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.room + +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId + +/** A reference to a room the current user has been invited to, with the ability to decline the invite. */ +interface InvitedRoom : AutoCloseable { + val sessionId: SessionId + val roomId: RoomId + + /** Decline the invite to this room. */ + suspend fun declineInvite(): 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 c9989796e5..1112fde2f5 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 @@ -29,6 +29,7 @@ import io.element.android.libraries.matrix.api.notificationsettings.Notification import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.pusher.PushersService import io.element.android.libraries.matrix.api.room.CurrentUserMembership +import io.element.android.libraries.matrix.api.room.InvitedRoom import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.RoomMembershipObserver @@ -245,6 +246,10 @@ class RustMatrixClient( return roomFactory.create(roomId) } + override suspend fun getInvitedRoom(roomId: RoomId): InvitedRoom? { + return roomFactory.createInvitedRoom(roomId) + } + /** * Wait for the room to be available in the room list, with a membership for the current user of [CurrentUserMembership.JOINED]. * @param roomIdOrAlias the room id or alias to wait for diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustInvitedRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustInvitedRoom.kt new file mode 100644 index 0000000000..67e9e5e7a5 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustInvitedRoom.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.room + +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.room.InvitedRoom +import org.matrix.rustcomponents.sdk.Room + +class RustInvitedRoom( + override val sessionId: SessionId, + private val invitedRoom: Room, +) : InvitedRoom { + override val roomId = RoomId(invitedRoom.id()) + + override suspend fun declineInvite(): Result = runCatching { + invitedRoom.leave() + } + + override fun close() { + invitedRoom.destroy() + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt index 04210d6959..a440578513 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt @@ -14,6 +14,7 @@ import io.element.android.libraries.matrix.api.core.DeviceId import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService +import io.element.android.libraries.matrix.api.room.InvitedRoom import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.roomlist.awaitLoaded @@ -27,6 +28,7 @@ import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.FilterTimelineEventType +import org.matrix.rustcomponents.sdk.Membership import org.matrix.rustcomponents.sdk.Room import org.matrix.rustcomponents.sdk.RoomListException import org.matrix.rustcomponents.sdk.RoomListItem @@ -123,6 +125,33 @@ class RustRoomFactory( } } + suspend fun createInvitedRoom(roomId: RoomId): InvitedRoom? = withContext(dispatcher) { + if (isDestroyed) { + Timber.d("Room factory is destroyed, returning null for $roomId") + return@withContext null + } + val roomListItem = innerRoomListService.roomOrNull(roomId.value) + if (roomListItem == null) { + Timber.d("Room not found for $roomId") + return@withContext null + } + if (roomListItem.membership() != Membership.INVITED) { + Timber.d("Room $roomId is not in invited state") + return@withContext null + } + val invitedRoom = try { + roomListItem.invitedRoom() + } catch (e: RoomListException) { + Timber.e(e, "Failed to get invited room for $roomId") + return@withContext null + } + + RustInvitedRoom( + sessionId = sessionId, + invitedRoom = invitedRoom, + ) + } + private suspend fun getRoomReferences(roomId: RoomId): RustRoomReferences? { cache[roomId]?.let { Timber.d("Room found in cache for $roomId") 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 5db394f77d..908cb443ea 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 @@ -22,6 +22,7 @@ import io.element.android.libraries.matrix.api.notification.NotificationService import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.pusher.PushersService +import io.element.android.libraries.matrix.api.room.InvitedRoom import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.RoomMembershipObserver @@ -99,6 +100,7 @@ class FakeMatrixClient( private var createDmResult: Result = Result.success(A_ROOM_ID) private var findDmResult: RoomId? = A_ROOM_ID private val getRoomResults = mutableMapOf() + val getInvitedRoomResults = mutableMapOf() private val searchUserResults = mutableMapOf>() private val getProfileResults = mutableMapOf>() private var uploadMediaResult: Result = Result.success(AN_AVATAR_URL) @@ -125,6 +127,10 @@ class FakeMatrixClient( return getRoomResults[roomId] } + override suspend fun getInvitedRoom(roomId: RoomId): InvitedRoom? { + return getInvitedRoomResults[roomId] + } + override suspend fun findDM(userId: UserId): RoomId? { return findDmResult } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeInvitedRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeInvitedRoom.kt new file mode 100644 index 0000000000..3224d1fd2f --- /dev/null +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeInvitedRoom.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.test.room + +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.room.InvitedRoom +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.tests.testutils.lambda.lambdaError + +class FakeInvitedRoom( + override val sessionId: SessionId = A_SESSION_ID, + override val roomId: RoomId = A_ROOM_ID, + private val declineInviteResult: () -> Result = { lambdaError() } +) : InvitedRoom { + override suspend fun declineInvite(): Result { + return declineInviteResult() + } + + override fun close() = Unit +} From be3ead0db96934570d1ee0811607df0e5f0a133e Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 16 Sep 2024 15:22:40 +0200 Subject: [PATCH 031/106] Send failure verified user : add some comments and logs. --- .../ResolveVerifiedUserSendFailureView.kt | 6 +++--- .../resolve/VerifiedUserSendFailureIterator.kt | 13 +++++++++++++ .../resolve/VerifiedUserSendFailureResolver.kt | 6 ++++++ .../libraries/matrix/api/room/MatrixRoom.kt | 16 ++++++++++++++++ 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt index e0d964fa51..4c1d40cc87 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt @@ -118,7 +118,7 @@ private fun VerifiedUserSendFailure.title(): String { id = CommonStrings.screen_resolve_send_failure_changed_identity_title, userDisplayName ) - VerifiedUserSendFailure.None -> "" + VerifiedUserSendFailure.None -> error("This method should never be called for this state") } } @@ -134,7 +134,7 @@ private fun VerifiedUserSendFailure.subtitle(): String { id = CommonStrings.screen_resolve_send_failure_changed_identity_subtitle, userDisplayName ) - VerifiedUserSendFailure.None -> "" + VerifiedUserSendFailure.None -> error("This method should never be called for this state") } } @@ -143,7 +143,7 @@ private fun VerifiedUserSendFailure.resolveAction(): String { return when (this) { is VerifiedUserSendFailure.UnsignedDevice -> stringResource(id = CommonStrings.screen_resolve_send_failure_unsigned_device_primary_button_title) is VerifiedUserSendFailure.ChangedIdentity -> stringResource(id = CommonStrings.screen_resolve_send_failure_changed_identity_primary_button_title) - VerifiedUserSendFailure.None -> "" + VerifiedUserSendFailure.None -> error("This method should never be called for this state") } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureIterator.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureIterator.kt index ccdcfb509b..8b438808ff 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureIterator.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureIterator.kt @@ -8,6 +8,7 @@ package io.element.android.features.messages.impl.crypto.sendfailure.resolve import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState +import timber.log.Timber /** * Iterator for [LocalEventSendState.Failed.VerifiedUser] @@ -30,6 +31,12 @@ class UnsignedDeviceSendFailureIterator( ) : VerifiedUserSendFailureIterator { private val iterator = failure.devices.iterator() + init { + if (!hasNext()) { + Timber.w("Got $failure without any devices, shouldn't happen.") + } + } + override fun hasNext(): Boolean { return iterator.hasNext() } @@ -47,6 +54,12 @@ class ChangedIdentitySendFailureIterator( ) : VerifiedUserSendFailureIterator { private val iterator = failure.users.iterator() + init { + if (!hasNext()) { + Timber.w("Got $failure without any users, shouldn't happen.") + } + } + override fun hasNext(): Boolean { return iterator.hasNext() } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureResolver.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureResolver.kt index 0f6049b11f..be775ed122 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureResolver.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/VerifiedUserSendFailureResolver.kt @@ -13,6 +13,12 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import timber.log.Timber +/** + * This class is responsible for resolving and resending a failed message sent to a verified user. + * It also allow to resend the message without resolving the failure, for example if the user has in the meantime verified their device again. + * It's using the [VerifiedUserSendFailureIterator] to iterate over the different failures (ie. the different users concerned by the failure). + * This way, the user can resolve and resend the message for each user concerned, one by one. + */ class VerifiedUserSendFailureResolver( private val room: MatrixRoom, private val transactionId: TransactionId, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 1936b9f60c..d266b45d35 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -350,7 +350,23 @@ interface MatrixRoom : Closeable { */ suspend fun clearComposerDraft(): Result + /** + * Ignore the local trust for the given devices and resend messages that failed to send because said devices are unverified. + * + * @param devices The map of users identifiers to device identifiers received in the error + * @param transactionId The send queue transaction identifier of the local echo the send error applies to. + * + */ suspend fun ignoreDeviceTrustAndResend(devices: Map>, transactionId: TransactionId): Result + + /** + * Remove verification requirements for the given users and + * resend messages that failed to send because their identities were no longer verified. + * + * @param userIds The list of users identifiers received in the error. + * @param transactionId The send queue transaction identifier of the local echo the send error applies to. + * + */ suspend fun withdrawVerificationAndResend(userIds: List, transactionId: TransactionId): Result override fun close() = destroy() From 7f1d9bbc3f8419501e28546e38c50b7192414545 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 16 Sep 2024 15:59:31 +0200 Subject: [PATCH 032/106] Remove wrong comment --- .../impl/screens/createaccount/WebViewMessageInterceptor.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/WebViewMessageInterceptor.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/WebViewMessageInterceptor.kt index f07c466736..6dfe903b09 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/WebViewMessageInterceptor.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/createaccount/WebViewMessageInterceptor.kt @@ -34,9 +34,6 @@ class WebViewMessageInterceptor( super.onPageStarted(view, url, favicon) // We inject this JS code when the page starts loading to attach a message listener to the window. - // This listener will receive both messages: - // - EC widget API -> Element X (message.data.api == "fromWidget") - // - Element X -> EC widget API (message.data.api == "toWidget"), we should ignore these view?.evaluateJavascript( """ window.addEventListener( From bb0a281342192895222e588ed23b424369bc5f4e Mon Sep 17 00:00:00 2001 From: bmarty <3940906+bmarty@users.noreply.github.com> Date: Mon, 16 Sep 2024 18:40:24 +0000 Subject: [PATCH 033/106] Sync Strings from Localazy --- .../src/main/res/values-cs/translations.xml | 5 + .../src/main/res/values-de/translations.xml | 5 + .../src/main/res/values-el/translations.xml | 5 + .../src/main/res/values-et/translations.xml | 5 + .../src/main/res/values-fr/translations.xml | 5 + .../src/main/res/values-ru/translations.xml | 5 + .../src/main/res/values-sk/translations.xml | 5 + .../src/main/res/values-nl/translations.xml | 1 + .../src/main/res/values-nl/translations.xml | 11 + .../src/main/res/values-de/translations.xml | 4 +- .../src/main/res/values-de/translations.xml | 1 + .../src/main/res/values-el/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 1 + .../src/main/res/values-fr/translations.xml | 1 + .../src/main/res/values-nl/translations.xml | 36 + .../src/main/res/values-ru/translations.xml | 1 + .../src/main/res/values-sk/translations.xml | 1 + .../src/main/res/values-nl/translations.xml | 4 + .../src/main/res/values-nl/translations.xml | 4 + .../src/main/res/values-nl/translations.xml | 52 + .../src/main/res/values-nl/translations.xml | 5 + .../src/main/res/values-de/translations.xml | 5 + .../src/main/res/values-fr/translations.xml | 6 + .../src/main/res/values-nl/translations.xml | 12 + .../src/main/res/values-ru/translations.xml | 6 + .../src/main/res/values-de/translations.xml | 3 + .../src/main/res/values-fr/translations.xml | 1 + .../src/main/res/values-nl/translations.xml | 9 + .../src/main/res/values-ru/translations.xml | 1 + .../src/main/res/values-nl/translations.xml | 8 +- .../src/main/res/values-de/translations.xml | 6 + .../src/main/res/values-nl/translations.xml | 4 + .../src/main/res/values-nl/translations.xml | 5 + .../src/main/res/values-nl/translations.xml | 24 + .../src/main/res/values-nl/translations.xml | 11 + .../src/main/res/values-nl/translations.xml | 10 + .../src/main/res/values-nl/translations.xml | 11 + .../src/main/res/values-de/translations.xml | 17 +- .../src/main/res/values-fr/translations.xml | 12 + .../src/main/res/values-nl/translations.xml | 19 + .../src/main/res/values-ru/translations.xml | 10 + .../src/main/res/values-sk/translations.xml | 1 + .../src/main/res/values/localazy.xml | 2 +- .../appnav.loggedin_LoggedInView_Day_3_de.png | 3 + ...mpl.unlock_PinUnlockViewInApp_Day_2_de.png | 4 +- ...een.impl.unlock_PinUnlockView_Day_2_de.png | 4 +- ...er_ConfirmAccountProviderView_Day_1_de.png | 3 + ...er_ConfirmAccountProviderView_Day_2_de.png | 3 + ...eateaccount_CreateAccountView_Day_0_de.png | 3 + ...eateaccount_CreateAccountView_Day_1_de.png | 3 + ...eateaccount_CreateAccountView_Day_2_de.png | 3 + ...eateaccount_CreateAccountView_Day_3_de.png | 3 + ...impl.actionlist_SheetContent_Day_12_de.png | 3 + ...veVerifiedUserSendFailureView_Day_1_de.png | 3 + ...veVerifiedUserSendFailureView_Day_2_de.png | 3 + ...nner_PinnedMessagesBannerView_Day_1_de.png | 3 + ...nner_PinnedMessagesBannerView_Day_2_de.png | 4 +- ...d.list_PinnedMessagesListView_Day_0_de.png | 4 +- ...d.list_PinnedMessagesListView_Day_1_de.png | 3 + ...d.list_PinnedMessagesListView_Day_2_de.png | 3 + ...d.list_PinnedMessagesListView_Day_3_de.png | 3 + ....components_MessageShieldView_Day_0_de.png | 4 +- ...nboarding.impl_OnBoardingView_Day_2_de.png | 4 +- ...nboarding.impl_OnBoardingView_Day_3_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_1_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 +- ...ures.roomdetails.impl_RoomDetails_1_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 +- ...iveSlidingSyncMigrationBanner_Day_0_de.png | 3 + ...omponents_RoomListContentView_Day_4_de.png | 4 +- ...onents_SetUpRecoveryKeyBanner_Day_0_de.png | 4 +- ...s.roomlist.impl_RoomListView_Day_10_de.png | 4 +- ...ord_ResetIdentityPasswordView_Day_3_de.png | 4 +- screenshots/html/data.js | 1189 +++++++++-------- ...er_ConfirmAccountProviderView_Day_2_en.png | 4 +- ..._ConfirmAccountProviderView_Night_2_en.png | 4 +- 100 files changed, 1063 insertions(+), 676 deletions(-) create mode 100644 appnav/src/main/res/values-cs/translations.xml create mode 100644 appnav/src/main/res/values-de/translations.xml create mode 100644 appnav/src/main/res/values-el/translations.xml create mode 100644 appnav/src/main/res/values-et/translations.xml create mode 100644 appnav/src/main/res/values-fr/translations.xml create mode 100644 appnav/src/main/res/values-ru/translations.xml create mode 100644 appnav/src/main/res/values-sk/translations.xml create mode 100644 features/joinroom/impl/src/main/res/values-nl/translations.xml create mode 100644 features/roomaliasresolver/impl/src/main/res/values-nl/translations.xml create mode 100644 features/roomdirectory/impl/src/main/res/values-nl/translations.xml create mode 100644 libraries/permissions/impl/src/main/res/values-nl/translations.xml create mode 100644 libraries/pushproviders/firebase/src/main/res/values-nl/translations.xml create mode 100644 libraries/pushproviders/unifiedpush/src/main/res/values-nl/translations.xml create mode 100644 libraries/troubleshoot/impl/src/main/res/values-nl/translations.xml create mode 100644 screenshots/de/appnav.loggedin_LoggedInView_Day_3_de.png create mode 100644 screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_de.png create mode 100644 screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_de.png create mode 100644 screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_0_de.png create mode 100644 screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_1_de.png create mode 100644 screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_2_de.png create mode 100644 screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_3_de.png create mode 100644 screenshots/de/features.messages.impl.actionlist_SheetContent_Day_12_de.png create mode 100644 screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_de.png create mode 100644 screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_de.png create mode 100644 screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_de.png create mode 100644 screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_de.png create mode 100644 screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_de.png create mode 100644 screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_de.png create mode 100644 screenshots/de/features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Day_0_de.png diff --git a/appnav/src/main/res/values-cs/translations.xml b/appnav/src/main/res/values-cs/translations.xml new file mode 100644 index 0000000000..e749887bc4 --- /dev/null +++ b/appnav/src/main/res/values-cs/translations.xml @@ -0,0 +1,5 @@ + + + "Odhlásit se a upgradovat" + "Váš domovský server již nepodporuje starý protokol. Chcete-li pokračovat v používání aplikace, odhlaste se a znovu se přihlaste." + diff --git a/appnav/src/main/res/values-de/translations.xml b/appnav/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..2b33dacaca --- /dev/null +++ b/appnav/src/main/res/values-de/translations.xml @@ -0,0 +1,5 @@ + + + "Abmelden und aktualisieren" + "Dein Homeserver unterstützt das alte Protokoll nicht mehr. Bitte logge dich aus und melde dich wieder an, um die App weiter zu nutzen." + diff --git a/appnav/src/main/res/values-el/translations.xml b/appnav/src/main/res/values-el/translations.xml new file mode 100644 index 0000000000..42925c0b6f --- /dev/null +++ b/appnav/src/main/res/values-el/translations.xml @@ -0,0 +1,5 @@ + + + "Αποσύνδεση &amp; Αναβάθμιση" + "Ο οικιακός διακομιστής σου δεν υποστηρίζει πλέον το παλιό πρωτόκολλο. Αποσυνδέσου και συνδέσου ξανά για να συνεχίσεις να χρησιμοποιείς την εφαρμογή." + diff --git a/appnav/src/main/res/values-et/translations.xml b/appnav/src/main/res/values-et/translations.xml new file mode 100644 index 0000000000..1631134d60 --- /dev/null +++ b/appnav/src/main/res/values-et/translations.xml @@ -0,0 +1,5 @@ + + + "Logi välja ja uuenda" + "Sinu koduserver enam ei toeta vana protokolli. Jätkamaks rakenduse kasutamist palun logi välja ning seejärel tagasi." + diff --git a/appnav/src/main/res/values-fr/translations.xml b/appnav/src/main/res/values-fr/translations.xml new file mode 100644 index 0000000000..6295bc88df --- /dev/null +++ b/appnav/src/main/res/values-fr/translations.xml @@ -0,0 +1,5 @@ + + + "Déconnecter et mettre à niveau" + "Votre serveur d’accueil ne prend plus en charge l’ancien protocole. Veuillez vous déconnecter puis vous reconnecter pour continuer à utiliser l’application." + diff --git a/appnav/src/main/res/values-ru/translations.xml b/appnav/src/main/res/values-ru/translations.xml new file mode 100644 index 0000000000..df600ea045 --- /dev/null +++ b/appnav/src/main/res/values-ru/translations.xml @@ -0,0 +1,5 @@ + + + "Выйти и обновить" + "Ваш homeserver больше не поддерживает старый протокол. Пожалуйста, выйдите из системы и войдите снова, чтобы продолжить использование приложения." + diff --git a/appnav/src/main/res/values-sk/translations.xml b/appnav/src/main/res/values-sk/translations.xml new file mode 100644 index 0000000000..d1ac766f8c --- /dev/null +++ b/appnav/src/main/res/values-sk/translations.xml @@ -0,0 +1,5 @@ + + + "Odhlásiť sa a aktualizovať" + "Váš domovský server už nepodporuje starý protokol. Ak chcete pokračovať v používaní aplikácie, odhláste sa a znova sa prihláste." + diff --git a/features/analytics/api/src/main/res/values-nl/translations.xml b/features/analytics/api/src/main/res/values-nl/translations.xml index fcd05769c5..996fe846d5 100644 --- a/features/analytics/api/src/main/res/values-nl/translations.xml +++ b/features/analytics/api/src/main/res/values-nl/translations.xml @@ -3,4 +3,5 @@ "Deel anonieme gebruiksgegevens om ons te helpen problemen te identificeren." "Je kunt al onze voorwaarden %1$s lezen." "hier" + "Gebruiksgegevens delen"
diff --git a/features/joinroom/impl/src/main/res/values-nl/translations.xml b/features/joinroom/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..d778ef8640 --- /dev/null +++ b/features/joinroom/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,11 @@ + + + "Toetreden tot de kamer" + "Klop om deel te nemen" + "%1$s ondersteunt nog geen spaces. Je kunt spaces benaderen via de webbrowser." + "Spaces worden nog niet ondersteund" + "Klik op de knop hieronder en een kamerbeheerder wordt op de hoogte gebracht. Na goedkeuring kun je deelnemen aan het gesprek." + "Je moet lid zijn van deze kamer om de berichtgeschiedenis te bekijken." + "Wil je tot deze kamer toetreden?" + "Voorbeeld is niet beschikbaar" + diff --git a/features/lockscreen/impl/src/main/res/values-de/translations.xml b/features/lockscreen/impl/src/main/res/values-de/translations.xml index bf89b3f5e4..4042df3d1b 100644 --- a/features/lockscreen/impl/src/main/res/values-de/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-de/translations.xml @@ -28,8 +28,8 @@ Wähle etwas Einprägsames. Bei falscher Eingabe wirst du aus der App ausgeloggt "Du hast %1$d Versuche zum Entsperren" - "Falsche PIN. Du hast %1$d weitere Chance" - "Falsche PIN. Du hast %1$d weitere Chancen" + "Falsche PIN. Du hast %1$d weiteren Versuch" + "Falsche PIN. Du hast %1$d weitere Versuche" "Biometrie verwenden" "PIN verwenden" diff --git a/features/login/impl/src/main/res/values-de/translations.xml b/features/login/impl/src/main/res/values-de/translations.xml index c2bdf37ca7..0ead5a8147 100644 --- a/features/login/impl/src/main/res/values-de/translations.xml +++ b/features/login/impl/src/main/res/values-de/translations.xml @@ -21,6 +21,7 @@ "Du kannst nur eine Verbindung zu einem vorhandenen Server herstellen, der Sliding Sync unterstützt. Dein Homeserver-Administrator muss das konfigurieren. %1$s" "Wie lautet die Adresse deines Servers?" "Wähle deinen Server aus" + "Konto erstellen" "Dieses Konto wurde deaktiviert." "Falscher Benutzername und/oder Passwort" "Dies ist keine gültige Benutzerkennung. Erwartetes Format: \'@user:homeserver.org\'" diff --git a/features/login/impl/src/main/res/values-el/translations.xml b/features/login/impl/src/main/res/values-el/translations.xml index 24f26483fb..b0ad469732 100644 --- a/features/login/impl/src/main/res/values-el/translations.xml +++ b/features/login/impl/src/main/res/values-el/translations.xml @@ -21,6 +21,7 @@ "Μπορείτε να συνδεθείς μόνο σε υπάρχοντα διακομιστή που υποστηρίζει Sliding sync. Ο διαχειριστής του οικιακού διακομιστή σου θα πρέπει να το ρυθμίσει. %1$s" "Ποια είναι η διεύθυνση του διακομιστή σου;" "Επέλεξε το διακομιστή σου" + "Δημιουργία λογαριασμού" "Αυτός ο λογαριασμός έχει απενεργοποιηθεί." "Λανθασμένο όνομα χρήστη ή κωδικός πρόσβασης" "Αυτό δεν είναι έγκυρο αναγνωριστικό χρήστη. Αναμενόμενη μορφή: \'@χρήστης:homeserver.org\'" diff --git a/features/login/impl/src/main/res/values-et/translations.xml b/features/login/impl/src/main/res/values-et/translations.xml index f82ea50b91..36ce791bb2 100644 --- a/features/login/impl/src/main/res/values-et/translations.xml +++ b/features/login/impl/src/main/res/values-et/translations.xml @@ -21,6 +21,7 @@ "Sa saad luua ühendust vaid olemasoleva serveriga, mis toetab Sliding sync režiimi. Sinu koduserveri haldur peaks selle seadistama. %1$s" "Mis on sinu koduserveri aadress?" "Vali oma server" + "Loo kasutajakonto" "Konto on kasutusest eemaldatud." "Vigane kasutajanimi ja/või salasõna" "See ei ole korrektne kasutajanimi. Õige vorming on: „@kasutaja:koduserver.ee“" diff --git a/features/login/impl/src/main/res/values-fr/translations.xml b/features/login/impl/src/main/res/values-fr/translations.xml index a5928ffb3f..b075da9fda 100644 --- a/features/login/impl/src/main/res/values-fr/translations.xml +++ b/features/login/impl/src/main/res/values-fr/translations.xml @@ -21,6 +21,7 @@ "Vous ne pouvez vous connecter qu’à un serveur existant qui prend en charge le sliding sync. L’administrateur de votre serveur d’accueil devra le configurer. %1$s" "Quelle est l’adresse de votre serveur ?" "Choisissez votre serveur" + "Créer un compte" "Ce compte a été désactivé." "Nom d’utilisateur et/ou mot de passe incorrects" "Il ne s’agit pas d’un identifiant utilisateur valide. Format attendu : « @user:homeserver.org »" diff --git a/features/login/impl/src/main/res/values-nl/translations.xml b/features/login/impl/src/main/res/values-nl/translations.xml index 0e351f8498..627f5b873e 100644 --- a/features/login/impl/src/main/res/values-nl/translations.xml +++ b/features/login/impl/src/main/res/values-nl/translations.xml @@ -14,6 +14,8 @@ "Gebruik een andere accountprovider, zoals je eigen privéserver of een zakelijke account." "Wijzig accountprovider" "We konden deze homeserver niet bereiken. Controleer of je de homeserver-URL juist hebt ingevoerd. Als de URL juist is, neem dan contact op met de beheerder van je homeserver voor verdere hulp." + "Sliding sync is niet beschikbaar vanwege een probleem in het well-known bestand: +%1$s" "Deze server ondersteunt op dit moment geen sliding sync." "Homeserver-URL" "Je kunt alleen verbinding maken met een bestaande server die sliding sync ondersteunt. De beheerder van de homeserver moet dit configureren. %1$s" @@ -28,7 +30,41 @@ "Matrix is een open netwerk voor veilige, gedecentraliseerde communicatie." "Welkom terug!" "Inloggen bij %1$s" + "Een beveiligde verbinding tot stand brengen" + "Er kon geen beveiligde verbinding worden gemaakt met het nieuwe apparaat. Je bestaande apparaten zijn nog steeds veilig en je hoeft je daarover geen zorgen te maken." + "Wat nu?" + "Probeer opnieuw in te loggen met een QR-code voor het geval dit een netwerkprobleem was" + "Als je hetzelfde probleem ondervindt, probeer dan een ander wifi-netwerk of gebruik je mobiele data in plaats van wifi." + "Als dat niet werkt, log dan handmatig in" + "Verbinding niet veilig" + "Daar word je gevraagd om de twee cijfers in te voeren die op dit apparaat worden weergegeven." + "Voer het onderstaande nummer in op je andere apparaat" + "De aanmelding is geannuleerd op het andere apparaat." + "Login verzoek geannuleerd" + "De aanmelding is geweigerd op het andere apparaat." + "Aanmelden geweigerd" + "Aanmelden is verlopen. Probeer het opnieuw." + "De aanmelding was niet op tijd voltooid" + "QR-code wordt niet ondersteund" + "Klaar om te scannen" + "Open %1$s op een desktopapparaat" + "Klik op je afbeelding" + "Selecteer %1$s" + "“Nieuw apparaat koppelen”" + "Scan de QR-code met dit apparaat" + "Open %1$s op een ander apparaat om de QR-code te krijgen" + "Gebruik de QR-code die op het andere apparaat wordt weergegeven." "Probeer het opnieuw" + "Verkeerde QR-code" + "Ga naar camera-instellingen" + "Je moet %1$s toestemming geven om de camera van je apparaat te gebruiken om verder te gaan." + "Cameratoegang toestaan om de QR-code te scannen" + "Scan de QR-code" + "Opnieuw beginnen" + "Er is een onverwachte fout opgetreden. Probeer het opnieuw." + "Aan het wachten op je andere apparaat" + "Je accountprovider kan om de volgende code vragen om de aanmelding te verifiëren." + "Je verificatiecode" "Accountprovider wijzigen" "Een privéserver voor medewerkers van Element." "Matrix is een open netwerk voor veilige, gedecentraliseerde communicatie." diff --git a/features/login/impl/src/main/res/values-ru/translations.xml b/features/login/impl/src/main/res/values-ru/translations.xml index 71a2691b4c..40f3f9b5df 100644 --- a/features/login/impl/src/main/res/values-ru/translations.xml +++ b/features/login/impl/src/main/res/values-ru/translations.xml @@ -21,6 +21,7 @@ "Вы можете подключиться только к существующему серверу, поддерживающему sliding sync. Администратору домашнего сервера потребуется настроить его. %1$s" "Какой адрес у вашего сервера?" "Выберите свой сервер" + "Создать учетную запись" "Данная учетная запись была деактивирована." "Неверное имя пользователя и/или пароль" "Это не корректный идентификатор пользователя. Ожидаемый формат: \'@user:homeserver.org\'" diff --git a/features/login/impl/src/main/res/values-sk/translations.xml b/features/login/impl/src/main/res/values-sk/translations.xml index 8d862609b7..7cadc5ecb8 100644 --- a/features/login/impl/src/main/res/values-sk/translations.xml +++ b/features/login/impl/src/main/res/values-sk/translations.xml @@ -21,6 +21,7 @@ "Môžete sa pripojiť iba k existujúcemu serveru, ktorý podporuje kĺzavú synchronizáciu. Správca domovského servera ju bude musieť nakonfigurovať. %1$s" "Aká je adresa vášho servera?" "Vyberte svoj server" + "Vytvoriť účet" "Tento účet bol deaktivovaný." "Nesprávne používateľské meno a/alebo heslo" "Toto nie je platný identifikátor používateľa. Očakávaný formát: \'@pouzivatel:homeserver.sk\'" diff --git a/features/preferences/impl/src/main/res/values-nl/translations.xml b/features/preferences/impl/src/main/res/values-nl/translations.xml index 6296b409b2..06f4c6cd26 100644 --- a/features/preferences/impl/src/main/res/values-nl/translations.xml +++ b/features/preferences/impl/src/main/res/values-nl/translations.xml @@ -6,12 +6,14 @@ "Aangepaste basis-URL voor Element Call" "Stel een aangepaste basis-URL in voor Element Call." "Ongeldige URL, zorg ervoor dat je het protocol (http/https) en het juiste adres invult." + "Push-meldingen provider" "Schakel de uitgebreide tekstverwerker uit om Markdown handmatig te typen." "Leesbevestigingen" "Indien uitgeschakeld worden er geen leesbevestigingen verstuurd. Je ontvangt nog steeds leesbevestigingen van andere gebruikers." "Aanwezigheid delen" "Indien uitgeschakeld kun je geen leesbevestigingen en typmeldingen verzenden of ontvangen." "Schakel optie in om de berichtbron in de tijdlijn te bekijken." + "Je hebt geen geblokkeerde gebruikers." "Deblokkeren" "Je zult alle berichten van hen weer kunnen zien." "Gebruiker deblokkeren" @@ -49,4 +51,6 @@ Als je doorgaat, kunnen sommige van je instellingen veranderen." "systeeminstellingen" "Systeemmeldingen uitgeschakeld" "Meldingen" + "Problemen oplossen" + "Problemen met meldingen oplossen" diff --git a/features/roomaliasresolver/impl/src/main/res/values-nl/translations.xml b/features/roomaliasresolver/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..9bf0f7156b --- /dev/null +++ b/features/roomaliasresolver/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,4 @@ + + + "Kan het kameradres niet vinden." + diff --git a/features/roomdetails/impl/src/main/res/values-nl/translations.xml b/features/roomdetails/impl/src/main/res/values-nl/translations.xml index 117ef56b9f..a3a4dc965a 100644 --- a/features/roomdetails/impl/src/main/res/values-nl/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-nl/translations.xml @@ -3,14 +3,41 @@ "Er is een fout opgetreden bij het bijwerken van de meldingsinstelling." "Je homeserver ondersteunt deze optie niet in versleutelde kamers; in sommige kamers krijg je mogelijk geen meldingen." "Peilingen" + "Alleen beheerders" + "Personen verbannen" + "Berichten verwijderen" "Iedereen" + "Personen uitnodigen" + "Moderatie van leden" + "Berichten en inhoud" + "Beheerders en moderators" + "Personen verwijderen" + "Kamerafbeelding wijzigen" + "Kamergegevens" + "Kamernaam wijzigen" + "Kameronderwerp wijzigen" + "Berichten verzenden" + "Beheerders bewerken" "Je kunt deze actie niet ongedaan maken. Je bevordert deze gebruiker tot hetzelfde machtsniveau als jij." "Beheerder toevoegen?" + "Degraderen" + "Je kunt deze wijziging niet ongedaan maken omdat je jezelf degradeert. Als je de laatste gebruiker met bevoegdheden in de kamer bent, is het onmogelijk om deze bevoegdheden terug te krijgen." "Jezelf degraderen?" + "%1$s (In behandeling)" + "(In afwachting)" + "Beheerders hebben automatisch moderatorrechten" + "Moderators bewerken" + "Beheerders" + "Moderators" "Leden" + "Je hebt niet-opgeslagen wijzigingen" + "Wijzigingen opslaan?" "Onderwerp toevoegen" "Reeds lid" "Reeds uitgenodigd" + "Versleuteld" + "Niet versleuteld" + "Openbare kamer" "Kamer bewerken" "Er is een onbekende fout opgetreden en de informatie kon niet worden gewijzigd." "Kan kamer niet bijwerken" @@ -25,20 +52,30 @@ "Aangepast" "Standaard" "Meldingen" + "Rollen en rechten" "Naam van de kamer" "Beveiliging" "Kamer delen" + "Kamer info" "Onderwerp" "Kamer bijwerken…" + "Verbannen" + "Ze kunnen niet meer toetreden tot deze kamer als ze worden uitgenodigd." + "Weet je zeker dat je dit lid wilt verbannen?" + "Er zijn geen verbannen gebruikers in deze kamer." + "%1$s verbannen" "%1$d persoon" "%1$d personen" + "Lid verwijderen en verbannen" "Verwijderen uit kamer" "Lid verwijderen en verbannen" "Alleen lid verwijderen" "Lid verwijderen en toekomstige deelname verbieden?" "Ontbannen" + "Ze kunnen opnieuw tot de kamer toetreden als ze worden uitgenodigd." + "Ontban gebruiker" "Profiel bekijken" "Verbannen" "Leden" @@ -47,6 +84,7 @@ "Beheerder" "Moderator" "Kamerleden" + "%1$s ontbannen" "Aanpassen toestaan" "Als je dit inschakelt, wordt je standaardinstelling overschreven" "Stuur me een melding in deze chat voor" @@ -61,4 +99,18 @@ "Alle berichten" "Alleen vermeldingen en trefwoorden" "In deze kamer, stuur me een melding voor" + "Beheerders" + "Mijn rol wijzigen" + "Degraderen tot lid" + "Degraderen tot moderator" + "Moderatie van leden" + "Berichten en inhoud" + "Moderators" + "Rechten" + "Rechten opnieuw instellen" + "Als je de rechten opnieuw instelt, raak je de huidige instellingen kwijt." + "Rechten opnieuw instellen?" + "Rollen" + "Kamergegevens" + "Rollen en rechten" diff --git a/features/roomdirectory/impl/src/main/res/values-nl/translations.xml b/features/roomdirectory/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..a2c6da3d09 --- /dev/null +++ b/features/roomdirectory/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,5 @@ + + + "Laden mislukt" + "Kamergids" + diff --git a/features/roomlist/impl/src/main/res/values-de/translations.xml b/features/roomlist/impl/src/main/res/values-de/translations.xml index 6215b3d4e4..372e918e09 100644 --- a/features/roomlist/impl/src/main/res/values-de/translations.xml +++ b/features/roomlist/impl/src/main/res/values-de/translations.xml @@ -1,5 +1,10 @@ + "Abmelden und aktualisieren" + "Dein Server unterstützt jetzt ein neues, schnelleres Protokoll. Melde dich ab und melde dich wieder an, um zu aktualisieren. Wenn du das jetzt tust, vermeidest du eine erzwungene Abmeldung, wenn das alte Protokoll später entfernt wird." + "Dein Homeserver unterstützt das alte Protokoll nicht mehr. Bitte logge dich aus und melde dich wieder an, um die App weiter zu nutzen." + "Aktualisierung verfügbar" + "Wiederherstellung einrichten" "Dein Chat-Backup ist derzeit nicht synchronisiert. Du musst deinen Wiederherstellungsschlüssel bestätigen, um Zugriff auf dein Chat-Backup zu erhalten." "Wiederherstellungsschlüssel bestätigen." "Damit du keinen wichtigen Anruf verpasst, ändere bitte deine Einstellungen so, dass du bei gesperrtem Telefon Benachrichtigungen im Vollbildmodus erhältst." diff --git a/features/roomlist/impl/src/main/res/values-fr/translations.xml b/features/roomlist/impl/src/main/res/values-fr/translations.xml index e2f3b22fe1..fb2188a8a4 100644 --- a/features/roomlist/impl/src/main/res/values-fr/translations.xml +++ b/features/roomlist/impl/src/main/res/values-fr/translations.xml @@ -1,5 +1,11 @@ + "Déconnecter et mettre à niveau" + "Votre serveur prend désormais en charge un nouveau protocole plus rapide. Déconnectez-vous, puis reconnectez-vous pour effectuer la mise à niveau dès maintenant. En le faisant tout de suite, vous éviterez une déconnexion forcée lorsque l’ancien protocole sera supprimé." + "Votre serveur d’accueil ne prend plus en charge l’ancien protocole. Veuillez vous déconnecter puis vous reconnecter pour continuer à utiliser l’application." + "Mise à niveau disponible" + "Générez une nouvelle clé de récupération qui peut être utilisée pour restaurer l’historique de vos messages chiffrés au cas où vous perdriez l’accès à vos appareils." + "Configurer la récupération" "La sauvegarde des conversations est désynchronisée. Vous devez confirmer la clé de récupération pour accéder à votre historique." "Confirmer votre clé de récupération" "Afin de ne jamais manquer un appel important, veuillez modifier vos paramètres pour autoriser les notifications en plein écran lorsque votre appareil est verrouillé." diff --git a/features/roomlist/impl/src/main/res/values-nl/translations.xml b/features/roomlist/impl/src/main/res/values-nl/translations.xml index a20e0a695c..b20bad6cdd 100644 --- a/features/roomlist/impl/src/main/res/values-nl/translations.xml +++ b/features/roomlist/impl/src/main/res/values-nl/translations.xml @@ -14,13 +14,25 @@ "Ga aan de slag door iemand een bericht te sturen." "Nog geen chats." "Favorieten" + "Je kunt een chat toevoegen aan je favorieten in de chatinstellingen. +Voor nu kun je filters deselecteren om je andere chats te zien" + "Je hebt nog geen favoriete chats" + "Uitnodigingen" + "Je hebt geen openstaande uitnodigingen." "Lage prioriteit" + "Je kunt filters deselecteren om je andere chats te zien" + "Je hebt geen chats voor deze selectie" "Personen" + "Je hebt nog geen directe chats" "Kamers" + "Je zit nog niet in een kamer" "Ongelezen" + "Gefeliciteerd! +Je hebt geen ongelezen berichten!" "Chats" "Markeren als gelezen" "Markeren als ongelezen" + "Blader door alle kamers" "Het lijkt erop dat je een nieuw apparaat gebruikt. Verifieer met een ander apparaat om toegang te krijgen tot je versleutelde berichten." "Verifieer dat jij het bent" diff --git a/features/roomlist/impl/src/main/res/values-ru/translations.xml b/features/roomlist/impl/src/main/res/values-ru/translations.xml index c9ccc1f44f..a057f9284d 100644 --- a/features/roomlist/impl/src/main/res/values-ru/translations.xml +++ b/features/roomlist/impl/src/main/res/values-ru/translations.xml @@ -1,5 +1,11 @@ + "Выйти и обновить" + "Теперь ваш сервер поддерживает новый, более быстрый протокол. Выйдите из системы и снова войдите в систему для обновления прямо сейчас. Сделав это сейчас, вы сможете избежать принудительного выхода из системы при последующем удалении старого протокола." + "Ваш homeserver больше не поддерживает старый протокол. Пожалуйста, выйдите из системы и войдите снова, чтобы продолжить использование приложения." + "Доступно обновление" + "Создайте новый ключ восстановления, который можно использовать для восстановления зашифрованной истории сообщений в случае потери доступа к своим устройствам." + "Настроить восстановление" "В настоящее время резервная копия вашего чата не синхронизирована. Требуется подтвердить вашим ключом восстановления, чтобы сохранить доступ к резервной копии чата." "Введите " diff --git a/features/securebackup/impl/src/main/res/values-de/translations.xml b/features/securebackup/impl/src/main/res/values-de/translations.xml index 413ae1ea81..4be1de6ddd 100644 --- a/features/securebackup/impl/src/main/res/values-de/translations.xml +++ b/features/securebackup/impl/src/main/res/values-de/translations.xml @@ -29,6 +29,7 @@ "Wiederherstellungsschlüssel" " mit einem anderen Gerät" + "Zurücksetzen fortsetzen" "Ausschalten" "Du verlierst deine verschlüsselten Nachrichten, wenn du auf allen Geräten abgemeldet bist." "Bist du sicher, dass du das Backup deaktivieren willst?" @@ -68,4 +69,6 @@ Das bedeutet:" "Stelle sicher, dass du deinen Wiederherstellungsschlüssel an einem sicheren Ort aufbewahren kannst" "Einrichtung der Wiederherstellung erfolgreich" "Wiederherstellung einrichten" + "Es ist ein unbekannter Fehler aufgetreten. Bitte überprüfe das Passwort deines Kontos und versuche es erneut." + "Eingeben…" diff --git a/features/securebackup/impl/src/main/res/values-fr/translations.xml b/features/securebackup/impl/src/main/res/values-fr/translations.xml index 1b36266924..346ad49329 100644 --- a/features/securebackup/impl/src/main/res/values-fr/translations.xml +++ b/features/securebackup/impl/src/main/res/values-fr/translations.xml @@ -16,6 +16,7 @@ "Suivez les instructions pour créer une nouvelle clé de récupération" "Enregistrez votre nouvelle clé dans un gestionnaire de mots de passe ou dans une note chiffrée" "Réinitialisez le chiffrement de votre compte en utilisant un autre appareil" + "Continuer la réinitialisation" "Les détails de votre compte, vos contacts, vos préférences et votre liste de discussions seront conservés" "Vous perdrez l’historique de vos messages" "Vous devrez vérifier à nouveau tous vos appareils et tous vos contacts" diff --git a/features/securebackup/impl/src/main/res/values-nl/translations.xml b/features/securebackup/impl/src/main/res/values-nl/translations.xml index b4dbb23562..388230dd7d 100644 --- a/features/securebackup/impl/src/main/res/values-nl/translations.xml +++ b/features/securebackup/impl/src/main/res/values-nl/translations.xml @@ -9,6 +9,13 @@ "Je chatback-up is momenteel niet gesynchroniseerd." "Herstelmogelijkheid instellen" "Krijg toegang tot je versleutelde berichten als je al je apparaten kwijtraakt of overal uit %1$s bent uitgelogd." + "Open %1$s op een desktopapparaat" + "Log opnieuw in op je account" + "Wanneer je wordt gevraagd om je apparaat te verifiëren, selecteer %1$s" + "“Alles opnieuw instellen”" + "Volg de instructies om een nieuwe herstelsleutel te maken" + "Sla je nieuwe herstelsleutel op in een wachtwoordmanager of versleutelde notitie" + "Stel de versleuteling voor je account opnieuw in met een ander apparaat" "Uitschakelen" "Je verliest je versleutelde berichten als je bent uitgelogd op alle apparaten." "Weet je zeker dat je de back-up wilt uitschakelen?" @@ -21,11 +28,13 @@ "Zorg ervoor dat je je herstelsleutel op een veilige plek kunt bewaren" "Herstelsleutel gewijzigd" "Herstelsleutel wijzigen?" + "Maak een nieuwe herstelsleutel" "Zorg ervoor dat niemand dit scherm kan zien!" "Probeer het opnieuw om toegang tot je chatback-up te bevestigen." "Onjuiste herstelsleutel" "Als je een beveiligingssleutel of beveiligingszin hebt, werkt dit ook." "Voer in…" + "Herstelsleutel kwijt?" "Herstelsleutel bevestigd" "Voer je herstelsleutel in" "Herstelsleutel gekopieerd" 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 ae45ab45eb..52d239069d 100644 --- a/features/securebackup/impl/src/main/res/values-ru/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ru/translations.xml @@ -26,6 +26,7 @@ " в менеджере паролей или зашифрованной заметке" "Сбросьте шифрование вашей учетной записи с помощью другого устройства." + "Продолжить сброс" "Данные вашей учетной записи, контакты, настройки и список чатов будут сохранены" "Вы потеряете существующую историю сообщений" "Вам нужно будет заново подтвердить все существующие устройства и контакты." diff --git a/features/verifysession/impl/src/main/res/values-nl/translations.xml b/features/verifysession/impl/src/main/res/values-nl/translations.xml index 6330ad2fc6..bebac551e2 100644 --- a/features/verifysession/impl/src/main/res/values-nl/translations.xml +++ b/features/verifysession/impl/src/main/res/values-nl/translations.xml @@ -1,12 +1,18 @@ + "Maak een nieuwe herstelsleutel" + "Verifieer dit apparaat om beveiligde berichten in te stellen." + "Bevestig dat jij het bent" + "Nu kun je veilig berichten lezen of verzenden, en iedereen met wie je chat kan dit apparaat ook vertrouwen." + "Apparaat geverifieerd" + "Wachten op ander apparaat…" "Er lijkt iets niet goed te gaan. Of er is een time-out opgetreden of het verzoek is geweigerd." "Bevestig dat de emoji\'s hieronder overeenkomen met de emoji\'s in je andere sessie." "Vergelijk emoji\'s" "Bevestig dat de onderstaande cijfers overeenkomen met de cijfers die worden weergegeven in je andere sessie." "Vergelijk getallen" "Je nieuwe sessie is nu geverifieerd. Het heeft toegang tot je versleutelde berichten en andere gebruikers zullen het als vertrouwd beschouwen." - "Voer recovery key in" + "Voer herstelsleutel in" "Bewijs dat jij het bent om toegang te krijgen tot je versleutelde berichtgeschiedenis." "Open een bestaande sessie" "Verificatie opnieuw proberen" diff --git a/libraries/eventformatter/impl/src/main/res/values-de/translations.xml b/libraries/eventformatter/impl/src/main/res/values-de/translations.xml index 597632a1f6..1b99fd2e5d 100644 --- a/libraries/eventformatter/impl/src/main/res/values-de/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-de/translations.xml @@ -45,6 +45,12 @@ "Du hast den Raum-Namen entfernt" "%1$shat keine Änderungen vorgenommen" "Du hast keine Änderungen vorgenommen" + "%1$s hat die fixierten Nachrichten geändert" + "Du hast die fixierten Nachrichten geändert" + "%1$s fixierte eine Nachricht" + "Du hast eine Nachricht fixiert" + "%1$s löste eine Nachricht" + "Du hast eine Nachricht gelöst" "%1$s hat die Einladung abgelehnt" "Du hast die Einladung abgelehnt" "%1$s hat %2$s entfernt" diff --git a/libraries/eventformatter/impl/src/main/res/values-nl/translations.xml b/libraries/eventformatter/impl/src/main/res/values-nl/translations.xml index b10c806572..dba242a458 100644 --- a/libraries/eventformatter/impl/src/main/res/values-nl/translations.xml +++ b/libraries/eventformatter/impl/src/main/res/values-nl/translations.xml @@ -3,12 +3,16 @@ "(afbeelding is ook gewijzigd)" "%1$s wijzigde van afbeelding" "Je hebt je afbeelding gewijzigd" + "%1$s werd gedegradeerd tot lid" + "%1$s werd gedegradeerd tot moderator" "%1$s heeft de weergavenaam aangepast van %2$s naar %3$s" "Je hebt je weergavenaam aangepast van %1$s naar %2$s" "%1$s heeft de weergavenaam verwijderd (dit was %2$s)" "Je hebt je weergavenaam verwijderd (dit was %1$s)" "%1$s heeft de weergavenaam %2$s aangenomen" "Je hebt de weergavenaam %1$s aangenomen" + "%1$s werd bevorderd tot beheerder" + "%1$s werd bevorderd tot moderator" "%1$s heeft de kamerafbeelding gewijzigd" "Je hebt de kamerafbeelding gewijzigd" "%1$s heeft de kamerafbeelding verwijderd" diff --git a/libraries/permissions/impl/src/main/res/values-nl/translations.xml b/libraries/permissions/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..b23c075bae --- /dev/null +++ b/libraries/permissions/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,5 @@ + + + "Controleren of de applicatie meldingen kan weergeven." + "Controleer machtigingen" + diff --git a/libraries/push/impl/src/main/res/values-nl/translations.xml b/libraries/push/impl/src/main/res/values-nl/translations.xml index d9ed0161ed..425973551a 100644 --- a/libraries/push/impl/src/main/res/values-nl/translations.xml +++ b/libraries/push/impl/src/main/res/values-nl/translations.xml @@ -49,4 +49,28 @@ "Achtergrondsynchronisatie" "Google-services" "Geen geldige Google Play-services gevonden. Meldingen werken mogelijk niet goed." + "Naam van de huidige provider aan het ophalen." + "Er zijn geen push-providers geselecteerd." + "Huidige push-provider: %1$s." + "Huidige push-provider" + "Zorg ervoor dat de applicatie minimaal één push-provider heeft." + "Geen push-providers gevonden." + + "%1$d push-provider gevonden: %2$s" + "%1$d push-providers gevonden: %2$s" + + "Push-providers detecteren" + "Controleer of de applicatie een melding kan weergeven." + "Er is niet op de melding geklikt." + "Kan de melding niet weergeven." + "Er is op de melding geklikt!" + "Melding weergeven" + "Klik op de melding om verder te gaan met de test." + "Ervoor zorgen dat de applicatie pushberichten ontvangt." + "Fout: pusher heeft het verzoek afgewezen." + "Fout: %1$s." + "Fout, kan push niet testen." + "Fout, time-out tijdens het wachten op push." + "Push terugkoppeling duurde %1$d ms." + "Test Push terugkoppeling" diff --git a/libraries/pushproviders/firebase/src/main/res/values-nl/translations.xml b/libraries/pushproviders/firebase/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..d847c39901 --- /dev/null +++ b/libraries/pushproviders/firebase/src/main/res/values-nl/translations.xml @@ -0,0 +1,11 @@ + + + "Zorg ervoor dat Firebase beschikbaar is." + "Firebase is niet beschikbaar." + "Firebase is beschikbaar." + "Firebase controleren" + "Zorg ervoor dat de Firebase-token beschikbaar is." + "Firebase-token is niet bekend." + "Firebase-token: %1$s." + "Firebase-token controleren" + diff --git a/libraries/pushproviders/unifiedpush/src/main/res/values-nl/translations.xml b/libraries/pushproviders/unifiedpush/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..afe222b147 --- /dev/null +++ b/libraries/pushproviders/unifiedpush/src/main/res/values-nl/translations.xml @@ -0,0 +1,10 @@ + + + "Ervoor zorgen dat UnifiedPush verdelers beschikbaar zijn." + "Geen push-verdelers gevonden." + + "%1$d verdeler gevonden: %2$s." + "%1$d verdelers gevonden: %2$s." + + "UnifiedPush controleren" + diff --git a/libraries/troubleshoot/impl/src/main/res/values-nl/translations.xml b/libraries/troubleshoot/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..5ce2bd89ad --- /dev/null +++ b/libraries/troubleshoot/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,11 @@ + + + "Tests uitvoeren" + "Tests opnieuw uitvoeren" + "Sommige tests zijn mislukt. Controleer de details." + "Voer de tests uit om problemen in je configuratie op te sporen waardoor meldingen mogelijk niet naar verwachting werken." + "Probeer het op te lossen" + "Alle tests zijn geslaagd." + "Problemen met meldingen oplossen" + "Sommige tests vereisen je aandacht. Controleer de details." + 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 dcd41ca7a6..ee31b18978 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -36,6 +36,7 @@ "Zurück" "Anruf" "Abbrechen" + "Jetzt abbrechen" "Foto auswählen" "Löschen" "Schließen" @@ -80,6 +81,7 @@ "Ok" "Einstellungen öffnen" "Öffnen mit" + "Fixieren" "Schnelle Antwort" "Zitat" "Reagieren" @@ -109,7 +111,8 @@ "Foto aufnehmen" "Für Optionen tippen" "Erneut versuchen" - "Entpinnen" + "Lösen" + "Im Chatverlauf anzeigen" "Quellcode anzeigen" "Ja" "Über" @@ -175,6 +178,7 @@ Grund: %1$s." "Personen" "Permalink" "Erlaubnis" + "Fixiert" "Bitte warten …" "Bist du sicher, dass du diese Umfrage beenden möchtest?" "Umfrage: %1$s" @@ -258,6 +262,7 @@ Grund: %1$s." "Einige Nachrichten wurden nicht gesendet" "Entschuldigung, es ist ein Fehler aufgetreten" "Die Authentizität dieser verschlüsselten Nachricht kann auf diesem Gerät nicht garantiert werden." + "Unverschlüsselt." "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 Benutzer." @@ -268,6 +273,15 @@ Grund: %1$s." "Medienauswahl fehlgeschlagen, bitte versuche es erneut." "Fehler beim Verarbeiten des hochgeladenen Mediums. Bitte versuche es erneut." "Das Hochladen der Medien ist fehlgeschlagen. Bitte versuche es erneut." + "Drücke auf eine Nachricht und wähle “%1$s”, um sie hier einzufügen." + "Fixiere wichtige Nachrichten, so dass sie leicht gefunden werden können" + + "%1$d fixierte Nachricht" + "%1$d fixierte Nachrichten" + + "Fixierte Nachrichten" + "Nachricht trotzdem senden" + "Fixierte Nachrichten" "Fehler beim Verarbeiten des hochgeladenen Mediums. Bitte versuche es erneut." "Benutzerdetails konnten nicht abgerufen werden" "Blockieren" @@ -279,6 +293,7 @@ Grund: %1$s." "Blockierung aufheben" "%1$s von %2$s" "%1$s Angepinnte Nachrichten" + "Nachricht wird geladen…" "Alle anzeigen" "Chat" "Standort teilen" 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 258f386137..831c134f22 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -36,6 +36,7 @@ "Retour" "Appel" "Annuler" + "Annuler pour l’instant" "Choisir une photo" "Effacer" "Fermer" @@ -249,6 +250,7 @@ Raison: %1$s." "Attention" "Vos modifications n’ont pas été enregistrées. Êtes-vous certain de vouloir quitter?" "Enregistrer les changements?" + "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" "%1$s n’a pas pu charger la carte. Veuillez réessayer ultérieurement." "Échec du chargement des messages" @@ -280,6 +282,14 @@ Raison: %1$s." "%1$d messages épinglés" "Messages épinglés" + "Vous êtes sur le point d’accéder à votre compte %1$s pour réinitialiser votre identité. Vous serez ensuite redirigé vers l’application." + "Vous ne pouvez pas confirmer ? Accédez à votre compte pour réinitialiser votre identité." + "Révoquer la verification et envoyer" + "Vous pouvez révoquer la verification et envoyer ce message, ou vous pouvez annuler pour l’instant et réessayer plus tard après avoir vérifié à nouveau %1$s." + "Votre message n’a pas été envoyé car l’identité vérifiée de %1$s a changé" + "Envoyer le message quand même" + "%1$s utilise un ou plusieurs appareils non vérifiés. Vous pouvez quand même envoyer le message, ou vous pouvez annuler pour l’instant et réessayer plus tard après que %2$s vérifie tous ses appareils." + "Votre message n’a pas été envoyé car %1$s a un ou plusieurs appareils non vérifiés" "Messages épinglés" "Échec du traitement des médias à télécharger, veuillez réessayer." "Impossible de récupérer les détails de l’utilisateur" @@ -301,6 +311,8 @@ Raison: %1$s." "Ouvrir dans Google Maps" "Ouvrir dans OpenStreetMap" "Partager cette position" + "Le message n’a pas été envoyé car l’identité vérifiée de %1$s a changé." + "Le message n’a pas été envoyé car %1$s n’a pas vérifié un ou plusieurs appareils." "Position" "Version : %1$s ( %2$s )" "fr" 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 7b9034291f..a1d8c194a4 100644 --- a/libraries/ui-strings/src/main/res/values-nl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nl/translations.xml @@ -34,6 +34,7 @@ "Accepteren" "Toevoegen aan tijdlijn" "Terug" + "Bellen" "Annuleren" "Kies foto" "Wissen" @@ -49,6 +50,7 @@ "Weigeren" "Peiling verwijderen" "Uitschakelen" + "Verwerpen" "Gereed" "Bewerken" "Peiling wijzigen" @@ -57,6 +59,7 @@ "Voer pincode in" "Wachtwoord vergeten?" "Doorsturen" + "Terug" "Uitnodigen" "Mensen uitnodigen" "Nodig mensen uit voor %1$s" @@ -70,6 +73,7 @@ "Meer laden" "Account beheren" "Apparaten beheren" + "Bericht" "Volgende" "Nee" "Niet nu" @@ -84,6 +88,7 @@ "Antwoord in subchat" "Probleem melden" "Inhoud melden" + "Opnieuw instellen" "Opnieuw proberen" "Decryptie opnieuw proberen" "Opslaan" @@ -108,10 +113,13 @@ "Over" "Beleid inzake redelijk gebruik" "Geavanceerde instellingen" + "Gebruiksgegevens" "Weergave" "Geluid" "Geblokkeerde gebruikers" "Bubbels" + "Gesprek bezig (niet ondersteund)" + "Oproep gestart" "Chat back-up" "Copyright" "Kamer maken…" @@ -153,12 +161,14 @@ "Modern" "Dempen" "Geen resultaten" + "Geen kamernaam" "Offline" "of" "Wachtwoord" "Personen" "Permalink" "Toestemming" + "Even geduld…" "Weet je zeker dat je deze peiling wilt beëindigen?" "Peiling: %1$s" "Totaal aantal stemmen: %1$s" @@ -180,6 +190,8 @@ "Kamer" "Naam van de kamer" "bijv. de naam van je project" + "Wijzigingen opgeslagen" + "Opslaan" "Schermvergrendeling" "Iemand zoeken" "Zoekresultaten" @@ -193,6 +205,7 @@ "Instellingen" "Gedeelde locatie" "Uitloggen" + "Er is iets misgegaan" "Chat starten…" "Sticker" "Geslaagd" @@ -205,6 +218,7 @@ "Onderwerp" "Waar gaat deze kamer over?" "Kan niet ontsleutelen" + "Je hebt geen toegang tot dit bericht" "Uitnodigingen konden niet naar een of meerdere gebruikers worden verzonden." "Kan uitnodiging(en) niet verzenden" "Ontgrendelen" @@ -222,11 +236,14 @@ "Fout" "Geslaagd" "Waarschuwing" + "Je wijzigingen zijn niet opgeslagen. Weet je zeker dat je terug wilt gaan?" + "Wijzigingen opslaan?" "Het aanmaken van de permanente link is mislukt" "%1$s kon de kaart niet laden. Probeer het later opnieuw." "Het laden van berichten is mislukt" "%1$s had geen toegang tot je locatie. Probeer het later opnieuw." "Het uploaden van je spraakbericht is mislukt." + "Bericht niet gevonden" "%1$s heeft geen toegang tot je locatie. Je kunt dit inschakelen bij Instellingen." "%1$s heeft geen toegang tot je locatie. Schakel toegang hieronder in." "%1$s heeft geen toegang tot je microfoon. Schakel toegang in om een spraakbericht op te nemen." @@ -244,9 +261,11 @@ "Blokkeren" "Geblokkeerde gebruikers kunnen je geen berichten sturen en al hun berichten worden verborgen. Je kunt ze op elk moment deblokkeren." "Gebruiker blokkeren" + "Profiel" "Deblokkeren" "Je zult alle berichten van hen weer kunnen zien." "Gebruiker deblokkeren" + "Chat" "Locatie delen" "Deel mijn locatie" "Openen in Apple Maps" 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 6dd12d85df..407ce90c96 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -38,6 +38,7 @@ "Назад" "Позвонить" "Отмена" + "Отмените сейчас" "Выбрать фото" "Очистить" "Закрыть" @@ -256,6 +257,7 @@ "Предупреждение" "Изменения не сохранены. Вы действительно хотите вернуться?" "Сохранить изменения?" + "Ваш homeserver необходимо обновить, чтобы он поддерживал Matrix Authentication Service и создание учетной записи." "Не удалось создать постоянную ссылку" "Не удалось загрузить карту %1$s. Пожалуйста, повторите попытку позже." "Не удалось загрузить сообщения" @@ -290,6 +292,12 @@ "Закрепленные сообщения" "Вы собираетесь перейти в свою учетную запись %1$s, чтобы сбросить идентификацию. После этого вы вернетесь в приложение." "Не можете подтвердить? Перейдите в свою учетную запись, чтобы сбросить свою идентификацию." + "Отозвать верификацию и отправить" + "Вы можете отозвать свою верификацию и отправить это сообщение в любом случае или вы можете отменить ее сейчас и повторить попытку позже после повторной верификации %1$s." + "Ваше сообщение не было отправлено, потому что изменилась подтвержденная личность %1$s" + "Отправь сообщение в любом случае" + "%1$s использует одно или несколько непроверенных устройств. Вы все равно можете отправить сообщение или отменить его пока и повторить попытку позже %2$s, проверив все устройства пользователя." + "Ваше сообщение не было отправлено, потому что %1$s не проверил одно или несколько устройств" "Закрепленные сообщения" "Не удалось обработать медиафайл для загрузки, попробуйте еще раз." "Не удалось получить данные о пользователе" @@ -311,6 +319,8 @@ "Открыть в Google Maps" "Открыть в OpenStreetMap" "Поделиться этим местоположением" + "Сообщение не отправлено, потому что верифицированная личность %1$s изменилась." + "Сообщение не отправлено, потому что %1$s не проверил одно или несколько устройств." "Местоположение" "Версия: %1$s (%2$s)" "ru" 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 3486ebeb15..d184c35e0c 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -255,6 +255,7 @@ Dôvod: %1$s." "Upozornenie" "Vaše zmeny neboli uložené. Naozaj sa chcete vrátiť?" "Uložiť zmeny?" + "Váš domovský server musí byť aktualizovaný tak, aby podporoval Matrix Authentication Server a vytvorenie účtu." "Nepodarilo sa vytvoriť trvalý odkaz" "%1$s nedokázal načítať mapu. Skúste to prosím neskôr." "Načítanie správ zlyhalo" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 17da391831..d55f7dc41c 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -251,7 +251,7 @@ Reason: %1$s." "Warning" "Your changes have not been saved. Are you sure you want to go back?" "Save changes?" - "Your homeserver needs to be upgraded to support Matrix Authentication Server and account creation." + "Your homeserver needs to be upgraded to support Matrix Authentication Service and account creation." "Failed creating the permalink" "%1$s could not load the map. Please try again later." "Failed loading messages" diff --git a/screenshots/de/appnav.loggedin_LoggedInView_Day_3_de.png b/screenshots/de/appnav.loggedin_LoggedInView_Day_3_de.png new file mode 100644 index 0000000000..03db0d9f7d --- /dev/null +++ b/screenshots/de/appnav.loggedin_LoggedInView_Day_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f535f7d2913ec47e30a45b9734f1905844fb49b5f2e20915f308c7a3aaf0633a +size 28227 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_de.png index 08fa1da445..4d58cac782 100644 --- a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_de.png +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae53bc6a3d857c58ae51b28a954d07ea1b6532e11034a82203d30273071ff3ec -size 23562 +oid sha256:707e640a752ec0e320fb1a20debaf7ceddf2b36a76c0059d82b421a5baa49d20 +size 23784 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_2_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_2_de.png index a4d7e88514..f8ba109911 100644 --- a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_2_de.png +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82b87880816463b56ad04aa1453b6fb74b64d1fe2436e8ee8015f9e918dbc483 -size 39094 +oid sha256:a0626ba6f85dafa09da2d8df68086593aab5c6af87be82f0a38564ae5c2e2a02 +size 39176 diff --git a/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_de.png b/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_de.png new file mode 100644 index 0000000000..90bdfbd9d9 --- /dev/null +++ b/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c060f0778f1cc237cc6392e53acf5a6b543d3acd2bc17d0c3ce044d2dd9a028 +size 40383 diff --git a/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_de.png b/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_de.png new file mode 100644 index 0000000000..9dc59b6bc0 --- /dev/null +++ b/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1519e48ee816d293367b106b9c0fb864ca4e91c5bacf9f6d005dfcd720976d6 +size 39245 diff --git a/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_0_de.png b/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_0_de.png new file mode 100644 index 0000000000..1de44959ed --- /dev/null +++ b/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc44751070bfec3956fcd02393cbdf62436a1f065cb00f5407cf46b4b0eb3101 +size 13406 diff --git a/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_1_de.png b/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_1_de.png new file mode 100644 index 0000000000..db5f9573f6 --- /dev/null +++ b/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b345f6492eb7ecf24226050d3278e7b5fd78736c20173fb8d7a03d1bf71e2cae +size 13450 diff --git a/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_2_de.png b/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_2_de.png new file mode 100644 index 0000000000..e23afae05a --- /dev/null +++ b/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:69629592939063f0916ab2e77e69b98fa8e51f2ba5346f6be32ba2612054d441 +size 13372 diff --git a/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_3_de.png b/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_3_de.png new file mode 100644 index 0000000000..0f7d3b0478 --- /dev/null +++ b/screenshots/de/features.login.impl.screens.createaccount_CreateAccountView_Day_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd07fc9ba41cabd1894139517fe3b13a92e300bd5eee5d9e27f836489bbde9cb +size 15526 diff --git a/screenshots/de/features.messages.impl.actionlist_SheetContent_Day_12_de.png b/screenshots/de/features.messages.impl.actionlist_SheetContent_Day_12_de.png new file mode 100644 index 0000000000..667b224dc4 --- /dev/null +++ b/screenshots/de/features.messages.impl.actionlist_SheetContent_Day_12_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:147cc98d5d7fb08ba2d6954bd9474adfe2006ee866a3852ff7b2368b11907d63 +size 51528 diff --git a/screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_de.png b/screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_de.png new file mode 100644 index 0000000000..8c25a06e53 --- /dev/null +++ b/screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae27a8ec38ca3a8a6157b6065018e8fb76d6a943456b6f186594393ce2e1bd1c +size 60488 diff --git a/screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_de.png b/screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_de.png new file mode 100644 index 0000000000..939427e4d9 --- /dev/null +++ b/screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:70d9cbc012233cb9a0f538ae8634c24440afb92c5d7e38717215201ae62ada4a +size 56753 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 new file mode 100644 index 0000000000..6a9e2c93f8 --- /dev/null +++ b/screenshots/de/features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a970f4f1ce3cbbbfde86774d40f68cd35537586dd6c43c7de84ae422c813b91 +size 8529 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 96bc10b985..0911cafa8f 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:e615668e59a443185ea1151820f08951b37ea5bbe394e049262be04cc2a00cdb -size 12285 +oid sha256:e1790f4c2d4a6b54c4e20dd44b9d14f38b5bec555f65c5f30a17439fddab8842 +size 12768 diff --git a/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_de.png b/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_de.png index ac3a73d739..ed4e20aae2 100644 --- a/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_de.png +++ b/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1ccd86242d92f1a773f35ee6f4fabc44699fb4ed7744ef41282b880e671699f3 -size 24182 +oid sha256:68447035a33d0acad5d3055808b77bd30dc876c00a28ecd06546d592811625bd +size 24294 diff --git a/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_de.png b/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_de.png new file mode 100644 index 0000000000..2c5b8d4c12 --- /dev/null +++ b/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d0f5407369b9d57c271a432046b373e9e0a8177ec8931b8dcc4893e577d205f +size 9070 diff --git a/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_de.png b/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_de.png new file mode 100644 index 0000000000..7a27e388ea --- /dev/null +++ b/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b5c48945b82ddae5217f6b0bce3f74e81bfa7b2eb929deb697dc936ccbf2bac +size 35386 diff --git a/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_de.png b/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_de.png new file mode 100644 index 0000000000..541b33f5d3 --- /dev/null +++ b/screenshots/de/features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0927e2dece4cca09e69aea086f2b026ec6143a47d7ca34cd3d9edab22ecf3b31 +size 42816 diff --git a/screenshots/de/features.messages.impl.timeline.components_MessageShieldView_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components_MessageShieldView_Day_0_de.png index 04d3bf0665..b11f28b3dd 100644 --- a/screenshots/de/features.messages.impl.timeline.components_MessageShieldView_Day_0_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_MessageShieldView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0bdf88e9ea1157af338533be63f6df5845a40352babe56cba9c03ecfc7539a0a -size 47175 +oid sha256:13b03b0125a0d3f6b44330a7ae2a49ac4139951371d4992c9b308f09c1afdeed +size 47269 diff --git a/screenshots/de/features.onboarding.impl_OnBoardingView_Day_2_de.png b/screenshots/de/features.onboarding.impl_OnBoardingView_Day_2_de.png index fc2434d46c..6121562597 100644 --- a/screenshots/de/features.onboarding.impl_OnBoardingView_Day_2_de.png +++ b/screenshots/de/features.onboarding.impl_OnBoardingView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8856d920221c12eb15e4b539e9b13e0f692d1f7fd7184214efa7cc387179a851 -size 312746 +oid sha256:11eeb61c2d3ad494bb9b106ac1443df0c98f5f77d5b70ec4f0f617c1dcceb5fc +size 311194 diff --git a/screenshots/de/features.onboarding.impl_OnBoardingView_Day_3_de.png b/screenshots/de/features.onboarding.impl_OnBoardingView_Day_3_de.png index 70dfd4f2ec..e2bd3aa8f1 100644 --- a/screenshots/de/features.onboarding.impl_OnBoardingView_Day_3_de.png +++ b/screenshots/de/features.onboarding.impl_OnBoardingView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4b4a054a736fda19b44fb1aed86df28a63ce00704789a9828b6d7f933c7081a -size 306739 +oid sha256:1d4ebb057326ef42c95a77a46a3b5ab183a83b6fd734e11c598222f4cae4a07a +size 305270 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png index fa370d2d6c..355a348677 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:6121327494502b096c25dceece3e42e45eb3cf5b98578e8be7f7a96d006240be -size 44157 +oid sha256:8b7ff61b4b4281fdce700003fdaad4138b75075e10a66b9e4e0de8ae487d9d84 +size 44271 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png index 59bb9b9897..1a28f57540 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:23e0b1b6e830eba355a0b7b139aafc1be11b781e6ef03df01786f5d6aa0c1b21 -size 46343 +oid sha256:384654c739d25cfd314ecde1fedaa6c8c0beccdfabfb0b0f0faacf1f1d10f6e1 +size 46456 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png index 4d57857101..6a7dcf16e7 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:22beba9c2412749866f57de99ee180a78761d2c47c06784a5d161a0aa91a3328 -size 44832 +oid sha256:9ff26f20abce5bfa8e936057d70258bbac919cc47c7aa27b374176f7d618c7ba +size 44947 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png index 098b141519..53674500dd 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:2ade9b2a3b5f32e65876becaf64ba6fb4627b9e4e6f2f3075634c6db9589798f -size 48494 +oid sha256:9cc4178e91b11dd83bcfc07e291a989317e744fbfcfb802e913875988d7f1685 +size 48606 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png index 2be7ff6576..a0eb722a41 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:e93f96555973aa1c30fc5ce2ea981bb26203e129a8cee2255ae3acfc53225e55 -size 46831 +oid sha256:edb4fe7262c508c066c11cebbf578e2b4851a871d5c438085bb3caea1dfae14a +size 46936 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png index 1e435d5e0f..a8632d499b 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:31e5144d7d0e819a4979fb3747d1b33f7dd1a12e23316598b908ef1db3f970b0 -size 42706 +oid sha256:da8ed936f17cd7b016aa5c2e45fe1df9bfbe149c686ab04903fafb537cf322c0 +size 42808 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png index 5f9ee3c8ff..6b21e09888 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:73618da5786309a1c338f77d18e88b82a25e228256c336714b5dbbd039937adc -size 43723 +oid sha256:e65461ca9a5aa89268fdfe04759d4c0dd5918ca395470d58c95a9f50eefb4ee4 +size 43835 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png index 7d713991e5..667414400c 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:0cc61ea48b4ed1e8a31c46996afb5c547ba2c6f75b98c4af2fb00b9921896ba3 -size 41780 +oid sha256:bec0e6890c5da8790c3b787d05ea7dab0e1084e8c1f34e98fdf6a478adfeff95 +size 41892 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png index ceedaf8a5d..2a431ede3d 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:fca83c8ab2de5105cba3eb2884d9b73501f5d83c7d9c4764dbbc35b387646d5f -size 47170 +oid sha256:30dd58fbdb510dce6e75347fcf9cca171770f285aa4abe981624b49c7ea45ab0 +size 47282 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png index 1b784506e8..07c6683054 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:403b8193a9bac5094515c7911c4f58859d12c3491f52e1d942b132a3de7d0445 -size 44718 +oid sha256:1ad624a4ae1c20addec10174f60e2115649bb8440d9d1b742091a5a2a8b3e68b +size 44834 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png index 1b784506e8..07c6683054 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:403b8193a9bac5094515c7911c4f58859d12c3491f52e1d942b132a3de7d0445 -size 44718 +oid sha256:1ad624a4ae1c20addec10174f60e2115649bb8440d9d1b742091a5a2a8b3e68b +size 44834 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png index 746506a9bd..b7d93442f2 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:c18704beb6082319d63d176d7e1cc333ffe1b14e18aeb1326ed736afb0fc9eb5 -size 47737 +oid sha256:84a24a5c58ecfb144caf04c0e8652d290c0574ff6cb1dbed7b701df2fa9e195b +size 47850 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png index ea4ed4d191..4d9d503a0d 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:c016d05fc5dccf7e9d9e619c42279e677b92e74af8f4a72108e2117d402c99fd -size 46665 +oid sha256:8a20b95ef4d95bdc045505ed01199ec219d5698a8295f3301e4f260ad926a043 +size 46780 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png index 81d7577a9b..d0c7127489 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:c734cbce4733caaf9ba237fe9ce76a0e1d081ab9fcf348bdc69e27468fb677bc -size 45709 +oid sha256:0dfce3cff7725fc9e5778c813be51fc159817ecdecfd14fe62af7905213d3c4f +size 45824 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png index ef718f3558..31cc642e29 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:073ea237aede57bd96b74b154c845e06066131f608d228d74430922686b10002 -size 45170 +oid sha256:d5d7311a5e7fd9e5e950128960089555ac4d84341c2d9107e94d1396c9d1175a +size 45326 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png index 387d0fa600..fb144576a1 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:2e73c7eb3bea900153fc3ced3b3e0fdc7b8948934783b870394587500035c2c3 -size 47443 +oid sha256:b80349e217e0649d360502c881abdca61008ac0a52a9860cb223588174673850 +size 47606 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png index 5fd1221199..0ad7508787 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:c09c681362992445b2ba1a7f66ede83a1e934b6c58a63e29dad6a01d8fd91c09 -size 45899 +oid sha256:dac10588ea7f2d0909356bdd24ac789959ebbc52853c6d6904a7e3899eba3313 +size 46058 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png index 7d8aacdd38..ec420272df 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:d70a4c8e5f753f9f8564b74e780d40beecf46efd5127a80a947736f6ae104d04 -size 49565 +oid sha256:3f9797f47aea0f543849c333616a55b73cd5afcd236498f9e85129720c0246c9 +size 49720 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png index bd5263e590..05ce4083ee 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:a95e349b642b9d00db353dcef8544ae7953725c8b46372812fba3eeb652d0923 -size 47918 +oid sha256:c202ce10bcadc283985cdbc537db571b9cd3c452bc3f99bf0587c9beb354bd0f +size 48091 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png index b1395c8bb8..5691f770cd 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:f2ce330939fb18280697f35bef030723fb8658225e750eb46a4023c9cec0cc6e -size 43836 +oid sha256:9f17d568db0c791191fd171ff60a7f1f9dda733610a8cdc4fc13128625b45507 +size 43984 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png index a887b71d4c..019cc7168b 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:8ed6dea45912127b7eca3a89759241963915ed157f0b7722d8981bbfa1f748aa -size 44920 +oid sha256:1df92fa426acbbdfecb208e03cd98e0e699816cb7e9f4780479710dd0ac9a866 +size 45077 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png index 5091e52d62..28b88db2ae 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:3407b1e432f4d5a90ed0be8ee529364ad61e5d190d2a614530d5d929273bd712 -size 42655 +oid sha256:d43f43946824fa36994303c527ed6ac4396b1d3c71d3562ec456a7daecd6fec2 +size 42816 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png index af53a9d8ad..a731314fc9 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:864a597bb95aec9d8ba3a677617b9fd3cafe863ae5fe336c4db165fc7038fb0f -size 48284 +oid sha256:c6a6d1abea617ec460b96d70a2fb197926714a3b120cc7217e15031232438078 +size 48442 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png index 6a2d10d4b1..5f85ce08f7 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:c4ac057ad0587edc72bef380cc2446df7152588aa20c259fba76e255c7d05a53 -size 45627 +oid sha256:725c2b15c127b3b7e455f07de17d582d2b7aa04cfcb13cea1b56f6f6ab2ecdaa +size 45783 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png index 6a2d10d4b1..5f85ce08f7 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:c4ac057ad0587edc72bef380cc2446df7152588aa20c259fba76e255c7d05a53 -size 45627 +oid sha256:725c2b15c127b3b7e455f07de17d582d2b7aa04cfcb13cea1b56f6f6ab2ecdaa +size 45783 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png index ad016b5911..84fcc21085 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:81881ff88e285e6bf4f13e0dfe746842b6a7a33d4babb5f579a5be31ae0cca3b -size 48955 +oid sha256:633389d3bd3878fb2aa7e75359967fb72b168a769ee99bdf2581661915fad981 +size 49103 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png index 6669a44928..066b9b403b 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:facf28de76d249f99e5b4f32bfa46c932cc77bb4bebe5a496abdeaf1cabff1c4 -size 47823 +oid sha256:f47f49ff6c3aa8ba703b2ffdd6bc08d3c389f8bd79abb276a437571f78f08ee0 +size 47984 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png index 0b62a52c4c..c0c98b9a73 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:a054d80a79ca39138c830df9d3dde06ca8900e37989dabd4ef4af8a963a415eb -size 46763 +oid sha256:6542cfb73e64d5022a089872f80793e34244c530609d5c408872f249f53f8337 +size 46926 diff --git a/screenshots/de/features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Day_0_de.png b/screenshots/de/features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Day_0_de.png new file mode 100644 index 0000000000..3b132a6365 --- /dev/null +++ b/screenshots/de/features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Day_0_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4edb266d9c0e99cf4104509169407379d6bcf75889abd0b4ebfa9f800e23b5aa +size 45278 diff --git a/screenshots/de/features.roomlist.impl.components_RoomListContentView_Day_4_de.png b/screenshots/de/features.roomlist.impl.components_RoomListContentView_Day_4_de.png index 82bcfe7d5b..7f02a36973 100644 --- a/screenshots/de/features.roomlist.impl.components_RoomListContentView_Day_4_de.png +++ b/screenshots/de/features.roomlist.impl.components_RoomListContentView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:afa1fbbfeafb9c3265c005b919d1da8d09ff10cd0e8ec60d7a1f42587c57a1b7 -size 73911 +oid sha256:ca791ab27e69f4a84eecfe420aba93fd7aedbcca93914e8aceb8781dd0409981 +size 82377 diff --git a/screenshots/de/features.roomlist.impl.components_SetUpRecoveryKeyBanner_Day_0_de.png b/screenshots/de/features.roomlist.impl.components_SetUpRecoveryKeyBanner_Day_0_de.png index 193d5a5010..082adc23cb 100644 --- a/screenshots/de/features.roomlist.impl.components_SetUpRecoveryKeyBanner_Day_0_de.png +++ b/screenshots/de/features.roomlist.impl.components_SetUpRecoveryKeyBanner_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:284e0f25302bddb07a48154b1dedc5b651881901ef45c065f67ac9ba19523ee8 -size 28834 +oid sha256:75b3f513dcbf3a7fd948f20b7ed438669ae827111da49941de11f28a80bad250 +size 30064 diff --git a/screenshots/de/features.roomlist.impl_RoomListView_Day_10_de.png b/screenshots/de/features.roomlist.impl_RoomListView_Day_10_de.png index 71fb3198ec..0405427877 100644 --- a/screenshots/de/features.roomlist.impl_RoomListView_Day_10_de.png +++ b/screenshots/de/features.roomlist.impl_RoomListView_Day_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5592b558284e74ab31471943c4484efe60a373f8136b2af9493e853029cb5435 -size 102313 +oid sha256:04d51057429c916bda03e771ca7da818fe32f9766257eb4813fcba924e5dd5d4 +size 103878 diff --git a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png index c068c315bf..a8bc71740a 100644 --- a/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png +++ b/screenshots/de/features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:836d97a08320f602807201ac740eb417ba173ddfd4821455f9d85ca8945c0d64 -size 39351 +oid sha256:0f6d57c36c609cd6d810368df13f7bfb15b7366ffdbe17dfb4c6be64b8bd33b8 +size 41658 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 8ae51996f2..92f0a2a384 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,41 +1,41 @@ // Generated file, do not edit export const screenshots = [ ["en","en-dark","de",], -["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",19978,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",19982,], ["features.invite.impl.response_AcceptDeclineInviteView_Day_0_en","features.invite.impl.response_AcceptDeclineInviteView_Night_0_en",0,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19978,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19978,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19978,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19978,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19982,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19982,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19982,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19982,], ["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,], ["features.login.impl.accountprovider_AccountProviderView_Day_4_en","features.login.impl.accountprovider_AccountProviderView_Night_4_en",0,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19978,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19978,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19978,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19978,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19978,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19978,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19978,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19978,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",19978,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",19978,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19978,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19978,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19978,], -["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19978,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19982,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19982,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19982,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19982,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19982,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19982,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19982,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19982,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",19982,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",19982,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19982,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19982,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19982,], +["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19982,], ["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",19978,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",19982,], ["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",19978,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",19982,], ["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",19978,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",19982,], ["libraries.designsystem.components.async_AsyncIndicatorFailure_Day_0_en","libraries.designsystem.components.async_AsyncIndicatorFailure_Night_0_en",0,], ["libraries.designsystem.components.async_AsyncIndicatorLoading_Day_0_en","libraries.designsystem.components.async_AsyncIndicatorLoading_Night_0_en",0,], ["libraries.designsystem.components.async_AsyncLoading_Day_0_en","libraries.designsystem.components.async_AsyncLoading_Night_0_en",0,], -["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",19978,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",19982,], ["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,], @@ -45,11 +45,11 @@ 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_AttachmentsView_0_en","",19978,], -["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19978,], -["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19978,], -["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19978,], -["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19978,], +["features.messages.impl.attachments.preview_AttachmentsView_0_en","",19982,], +["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19982,], +["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19982,], +["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19982,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19982,], ["libraries.designsystem.components.avatar_Avatar_Avatars_0_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_10_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_11_en","",0,], @@ -129,13 +129,13 @@ export const screenshots = [ ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], ["libraries.designsystem.components_BigCheckmark_Day_0_en","libraries.designsystem.components_BigCheckmark_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",19978,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19978,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19978,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19978,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19978,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19978,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19978,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",19982,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19982,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19982,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19982,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19982,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19982,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19982,], ["libraries.designsystem.components_BloomInitials_Day_0_en","libraries.designsystem.components_BloomInitials_Night_0_en",0,], ["libraries.designsystem.components_BloomInitials_Day_1_en","libraries.designsystem.components_BloomInitials_Night_1_en",0,], ["libraries.designsystem.components_BloomInitials_Day_2_en","libraries.designsystem.components_BloomInitials_Night_2_en",0,], @@ -146,87 +146,93 @@ export const screenshots = [ ["libraries.designsystem.components_BloomInitials_Day_7_en","libraries.designsystem.components_BloomInitials_Night_7_en",0,], ["libraries.designsystem.components_Bloom_Day_0_en","libraries.designsystem.components_Bloom_Night_0_en",0,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19978,], -["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19978,], -["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19978,], -["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19978,], -["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19978,], +["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19982,], +["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19982,], +["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19982,], +["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19982,], +["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19982,], ["libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_ButtonRowMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonRowMolecule_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_0_en","features.call.impl.ui_CallScreenPipView_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_1_en","features.call.impl.ui_CallScreenPipView_Night_1_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",19978,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19978,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19978,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19978,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19978,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19978,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19978,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19978,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19978,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19978,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19978,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19978,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19978,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19978,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19978,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19978,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19978,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19978,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19978,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19978,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19978,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",19982,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19982,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19982,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19982,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19982,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19982,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19982,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19982,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19982,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19982,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19982,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19982,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19982,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19982,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19982,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19982,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19982,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19982,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19982,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19982,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19982,], ["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",19978,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19978,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",19982,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19982,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19978,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19982,], ["libraries.designsystem.theme.components_Checkboxes_Toggles_en","",0,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], ["libraries.designsystem.theme_ColorAliases_Day_0_en","libraries.designsystem.theme_ColorAliases_Night_0_en",0,], ["libraries.textcomposer.components_ComposerOptionsButton_Day_0_en","libraries.textcomposer.components_ComposerOptionsButton_Night_0_en",0,], ["libraries.designsystem.components.avatar_CompositeAvatar_Avatars_en","",0,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19978,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19978,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19982,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19982,], ["features.preferences.impl.developer.tracing_ConfigureTracingView_Day_0_en","features.preferences.impl.developer.tracing_ConfigureTracingView_Night_0_en",0,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19978,], -["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19978,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19982,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",19982,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",19982,], +["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19982,], ["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_ConnectivityIndicatorView_Day_0_en","features.networkmonitor.api.ui_ConnectivityIndicatorView_Night_0_en",0,], -["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19978,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19978,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19978,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19978,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19978,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19978,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19978,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19978,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19978,], -["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19978,], -["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19978,], -["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19978,], -["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19978,], -["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19978,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19978,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19982,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",19982,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",19982,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",19982,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",19982,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19982,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19982,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19982,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19982,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19982,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19982,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19982,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19982,], +["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19982,], +["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19982,], +["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19982,], +["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19982,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19982,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19982,], ["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",19978,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19978,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19978,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",19982,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19982,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19982,], ["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",19978,], -["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19978,], -["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19978,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",19982,], +["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19982,], +["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19982,], ["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",19978,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",19978,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",19978,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19978,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19978,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19978,], -["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19978,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",19982,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",19982,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",19982,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19982,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19982,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19982,], +["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19982,], ["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,], @@ -238,12 +244,12 @@ 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",19978,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19978,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19978,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19978,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19978,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19978,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",19982,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19982,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19982,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19982,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19982,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19982,], ["libraries.matrix.ui.components_EditableAvatarView_Day_0_en","libraries.matrix.ui.components_EditableAvatarView_Night_0_en",0,], ["libraries.matrix.ui.components_EditableAvatarView_Day_1_en","libraries.matrix.ui.components_EditableAvatarView_Night_1_en",0,], ["libraries.matrix.ui.components_EditableAvatarView_Day_2_en","libraries.matrix.ui.components_EditableAvatarView_Night_2_en",0,], @@ -253,9 +259,9 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiPicker_Night_0_en",0,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19978,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19978,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19978,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19982,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19982,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19982,], ["features.messages.impl.timeline.debug_EventDebugInfoView_Day_0_en","features.messages.impl.timeline.debug_EventDebugInfoView_Night_0_en",0,], ["libraries.featureflag.ui_FeatureListView_Day_0_en","libraries.featureflag.ui_FeatureListView_Night_0_en",0,], ["libraries.designsystem.theme.components_FilledButtonLargeLowPadding_Buttons_en","",0,], @@ -266,15 +272,15 @@ export const screenshots = [ ["libraries.designsystem.theme.components_FloatingActionButton_Floating Action Buttons_en","",0,], ["libraries.designsystem.atomic.pages_FlowStepPage_Day_0_en","libraries.designsystem.atomic.pages_FlowStepPage_Night_0_en",0,], ["features.messages.impl.timeline.focus_FocusRequestStateView_Day_0_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_0_en",0,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19978,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19978,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19978,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19982,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19982,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19982,], ["libraries.textcomposer.components_FormattingOption_Day_0_en","libraries.textcomposer.components_FormattingOption_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_0_en","features.messages.impl.forward_ForwardMessagesView_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_1_en","features.messages.impl.forward_ForwardMessagesView_Night_1_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_2_en","features.messages.impl.forward_ForwardMessagesView_Night_2_en",0,], -["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19978,], -["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19978,], +["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19982,], +["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19982,], ["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,], @@ -301,37 +307,37 @@ 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",19978,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",19982,], ["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",19978,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",19982,], ["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",19978,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",19982,], ["libraries.designsystem.atomic.molecules_InfoListItemMolecule_Day_0_en","libraries.designsystem.atomic.molecules_InfoListItemMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.organisms_InfoListOrganism_Day_0_en","libraries.designsystem.atomic.organisms_InfoListOrganism_Night_0_en",0,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19978,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19982,], ["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",0,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19978,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19978,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19978,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19978,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19978,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19978,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19978,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19978,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19978,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19982,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19982,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19982,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19982,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19982,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19982,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19982,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19982,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19982,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], ["libraries.designsystem.components_LabelledOutlinedTextField_Day_0_en","libraries.designsystem.components_LabelledOutlinedTextField_Night_0_en",0,], ["libraries.designsystem.components_LabelledTextField_Day_0_en","libraries.designsystem.components_LabelledTextField_Night_0_en",0,], ["features.leaveroom.api_LeaveRoomView_Day_0_en","features.leaveroom.api_LeaveRoomView_Night_0_en",0,], -["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19978,], -["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19978,], -["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19978,], -["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19978,], -["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19978,], -["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19978,], +["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19982,], +["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19982,], +["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19982,], +["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19982,], +["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19982,], +["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19982,], ["libraries.designsystem.background_LightGradientBackground_Day_0_en","libraries.designsystem.background_LightGradientBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_LinearProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components.dialogs_ListDialogContent_Dialogs_en","",0,], @@ -382,28 +388,29 @@ export const screenshots = [ ["libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List supporting text - small padding_List sections_en","",0,], ["libraries.textcomposer.components_LiveWaveformView_Day_0_en","libraries.textcomposer.components_LiveWaveformView_Night_0_en",0,], ["appnav.room.joined_LoadingRoomNodeView_Day_0_en","appnav.room.joined_LoadingRoomNodeView_Night_0_en",0,], -["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",19978,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19978,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19978,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19978,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",19982,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19982,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19982,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19982,], ["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",19978,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19978,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19978,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19978,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19978,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19978,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19978,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19978,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19978,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19978,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19978,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19978,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19978,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19978,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19978,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",19982,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19982,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",19982,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19982,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19982,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19982,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19982,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19982,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19982,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19982,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19982,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19982,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19982,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19982,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19982,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19982,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19978,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19982,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en","libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeader_Day_0_en","libraries.matrix.ui.components_MatrixUserHeader_Night_0_en",0,], @@ -413,7 +420,7 @@ export const screenshots = [ ["libraries.mediaviewer.api.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_10_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19978,], +["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19982,], ["libraries.mediaviewer.api.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_5_en","",0,], @@ -425,7 +432,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",19978,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",19982,], ["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_10_en","features.messages.impl.timeline.components_MessageEventBubble_Night_10_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_11_en","features.messages.impl.timeline.components_MessageEventBubble_Night_11_en",0,], @@ -442,7 +449,7 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessageEventBubble_Day_7_en","features.messages.impl.timeline.components_MessageEventBubble_Night_7_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_8_en","features.messages.impl.timeline.components_MessageEventBubble_Night_8_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_9_en","features.messages.impl.timeline.components_MessageEventBubble_Night_9_en",0,], -["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",19978,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",19982,], ["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,], @@ -450,25 +457,25 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessagesReactionButton_Day_1_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_1_en",0,], ["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.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19978,], -["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19978,], -["features.messages.impl.typing_MessagesViewWithTyping_Day_2_en","features.messages.impl.typing_MessagesViewWithTyping_Night_2_en",19978,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19978,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19978,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19978,], -["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19978,], -["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",19978,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",19978,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19978,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19978,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19978,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19978,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19978,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19978,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19978,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19978,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19982,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19982,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_2_en","features.messages.impl.typing_MessagesViewWithTyping_Night_2_en",19982,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19982,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19982,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19982,], +["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19982,], +["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",19982,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",19982,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19982,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19982,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19982,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19982,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19982,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19982,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19982,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19982,], ["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",19978,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",19982,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom Sheets_en","",0,], ["appicon.element_MonochromeIcon_en","",0,], @@ -477,29 +484,29 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelectedTrailingContent_Multiple selection List item - selection in trailing content_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple selection List item - selection in supporting text_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple selection List item - no selection_List items_en","",0,], -["features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Day_0_en","features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Night_0_en",0,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19978,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19978,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19978,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19978,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19978,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19978,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19978,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19978,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19978,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19978,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19978,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19978,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19978,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19978,], +["features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Day_0_en","features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Night_0_en",19982,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19982,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19982,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19982,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19982,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19982,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19982,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19982,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19982,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19982,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19982,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19982,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19982,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19982,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19982,], ["libraries.oidc.impl.webview_OidcView_Day_0_en","libraries.oidc.impl.webview_OidcView_Night_0_en",0,], ["libraries.oidc.impl.webview_OidcView_Day_1_en","libraries.oidc.impl.webview_OidcView_Night_1_en",0,], ["libraries.designsystem.atomic.pages_OnBoardingPage_Day_0_en","libraries.designsystem.atomic.pages_OnBoardingPage_Night_0_en",0,], -["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19978,], -["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19978,], -["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19978,], -["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19978,], -["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19978,], +["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19982,], +["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19982,], +["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19982,], +["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19982,], +["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19982,], ["libraries.designsystem.background_OnboardingBackground_Day_0_en","libraries.designsystem.background_OnboardingBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_OutlinedButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonLarge_Buttons_en","",0,], @@ -514,62 +521,62 @@ export const screenshots = [ ["libraries.designsystem.components_PageTitleWithIconFull_Day_3_en","libraries.designsystem.components_PageTitleWithIconFull_Night_3_en",0,], ["libraries.designsystem.components_PageTitleWithIconFull_Day_4_en","libraries.designsystem.components_PageTitleWithIconFull_Night_4_en",0,], ["libraries.designsystem.components_PageTitleWithIconMinimal_Day_0_en","libraries.designsystem.components_PageTitleWithIconMinimal_Night_0_en",0,], -["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19978,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19978,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19978,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19978,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19978,], +["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19982,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19982,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19982,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19982,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19982,], ["features.lockscreen.impl.components_PinEntryTextField_Day_0_en","features.lockscreen.impl.components_PinEntryTextField_Night_0_en",0,], ["libraries.designsystem.components_PinIcon_Day_0_en","libraries.designsystem.components_PinIcon_Night_0_en",0,], ["features.lockscreen.impl.unlock.keypad_PinKeypad_Day_0_en","features.lockscreen.impl.unlock.keypad_PinKeypad_Night_0_en",0,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",19978,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19978,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19978,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19978,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19978,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19978,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19978,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19978,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19978,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19978,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19978,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19978,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19978,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19978,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",19982,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19982,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19982,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19982,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19982,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19982,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19982,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19982,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19982,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19982,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19982,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19982,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19982,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19982,], ["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",19978,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",0,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",19978,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",19978,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",19978,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",19978,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",19978,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",19978,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",19978,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",19978,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",19978,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",0,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",0,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",0,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",19982,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",19982,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",19982,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",19982,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",19982,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",19982,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",19982,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",19982,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",19982,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",19982,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",19982,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",19982,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",19982,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",19982,], ["libraries.designsystem.atomic.atoms_PlaceholderAtom_Day_0_en","libraries.designsystem.atomic.atoms_PlaceholderAtom_Night_0_en",0,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",19978,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19978,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19978,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19978,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19978,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",19982,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19982,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19982,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19982,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19982,], ["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",19978,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19978,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19978,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19978,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19978,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19978,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19978,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19978,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19978,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19978,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19978,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",19982,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19982,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19982,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19982,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19982,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19982,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19982,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19982,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19982,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19982,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19982,], ["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,], @@ -586,192 +593,195 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceTextLight_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeDark_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeLight_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19978,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19978,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19978,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19978,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19982,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19982,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19982,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19982,], ["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","",19978,], -["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19978,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19978,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19978,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19978,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19978,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19978,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19978,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19978,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19978,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19978,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19978,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19978,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19978,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19978,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19978,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19978,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19978,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",19982,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19982,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19982,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19982,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19982,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19982,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19982,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19982,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19982,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19982,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19982,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19982,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19982,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19982,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19982,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19982,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19982,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19982,], ["libraries.designsystem.theme.components_RadioButton_Toggles_en","",0,], -["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19978,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19978,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19982,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19982,], ["features.rageshake.api.preferences_RageshakePreferencesView_Day_1_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_1_en",0,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19978,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19978,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19978,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19978,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19978,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19978,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19978,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19978,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19978,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",19978,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",19978,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19978,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19978,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19978,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19978,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19978,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19978,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19978,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19978,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19978,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19982,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19982,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19982,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19982,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19982,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19982,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19982,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19982,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19982,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",19982,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",19982,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19982,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19982,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19982,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19982,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19982,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19982,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19982,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19982,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19982,], ["libraries.designsystem.atomic.atoms_RedIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_RedIndicatorAtom_Night_0_en",0,], ["features.messages.impl.timeline.components_ReplySwipeIndicator_Day_0_en","features.messages.impl.timeline.components_ReplySwipeIndicator_Night_0_en",0,], -["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",19978,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19978,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19978,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19978,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19978,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19978,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",19978,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",19978,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",19978,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",19978,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",19982,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19982,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19982,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19982,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19982,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19982,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",19982,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",19982,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",19982,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",19982,], ["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",0,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",19978,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19978,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19978,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19978,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19978,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19978,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19978,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19978,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19978,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19978,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19978,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",19982,], +["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",19982,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",19982,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19982,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19982,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19982,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19982,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19982,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19982,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19982,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19982,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19982,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19982,], ["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",0,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19978,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19982,], ["features.roomdetails.impl.components_RoomBadgeNegative_Day_0_en","features.roomdetails.impl.components_RoomBadgeNegative_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgeNeutral_Day_0_en","features.roomdetails.impl.components_RoomBadgeNeutral_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgePositive_Day_0_en","features.roomdetails.impl.components_RoomBadgePositive_Night_0_en",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",19978,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",19978,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",19978,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",19978,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",19978,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",19978,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",19978,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",19978,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",19978,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",19978,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",19978,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",19978,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",19978,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",19978,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19978,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19978,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19978,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19978,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19978,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19978,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19978,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19978,], -["features.roomdetails.impl_RoomDetails_0_en","",19978,], -["features.roomdetails.impl_RoomDetails_10_en","",19978,], -["features.roomdetails.impl_RoomDetails_11_en","",19978,], -["features.roomdetails.impl_RoomDetails_12_en","",19978,], -["features.roomdetails.impl_RoomDetails_13_en","",19978,], -["features.roomdetails.impl_RoomDetails_1_en","",19978,], -["features.roomdetails.impl_RoomDetails_2_en","",19978,], -["features.roomdetails.impl_RoomDetails_3_en","",19978,], -["features.roomdetails.impl_RoomDetails_4_en","",19978,], -["features.roomdetails.impl_RoomDetails_5_en","",19978,], -["features.roomdetails.impl_RoomDetails_6_en","",19978,], -["features.roomdetails.impl_RoomDetails_7_en","",19978,], -["features.roomdetails.impl_RoomDetails_8_en","",19978,], -["features.roomdetails.impl_RoomDetails_9_en","",19978,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19978,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19978,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19978,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19978,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19978,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19978,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19978,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19978,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19978,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19978,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19978,], -["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19978,], -["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19978,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",19982,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",19982,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",19982,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",19982,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",19982,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",19982,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",19982,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",19982,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",19982,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",19982,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",19982,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",19982,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",19982,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",19982,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19982,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19982,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19982,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19982,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19982,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19982,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19982,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19982,], +["features.roomdetails.impl_RoomDetails_0_en","",19982,], +["features.roomdetails.impl_RoomDetails_10_en","",19982,], +["features.roomdetails.impl_RoomDetails_11_en","",19982,], +["features.roomdetails.impl_RoomDetails_12_en","",19982,], +["features.roomdetails.impl_RoomDetails_13_en","",19982,], +["features.roomdetails.impl_RoomDetails_1_en","",19982,], +["features.roomdetails.impl_RoomDetails_2_en","",19982,], +["features.roomdetails.impl_RoomDetails_3_en","",19982,], +["features.roomdetails.impl_RoomDetails_4_en","",19982,], +["features.roomdetails.impl_RoomDetails_5_en","",19982,], +["features.roomdetails.impl_RoomDetails_6_en","",19982,], +["features.roomdetails.impl_RoomDetails_7_en","",19982,], +["features.roomdetails.impl_RoomDetails_8_en","",19982,], +["features.roomdetails.impl_RoomDetails_9_en","",19982,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19982,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19982,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19982,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19982,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19982,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19982,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19982,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19982,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19982,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19982,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19982,], +["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19982,], +["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19982,], ["features.roomlist.impl.components_RoomListContentView_Day_2_en","features.roomlist.impl.components_RoomListContentView_Night_2_en",0,], -["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19978,], +["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19982,], ["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19982,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19978,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19978,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19978,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19978,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19978,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19982,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19982,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19982,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19982,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19982,], ["features.roomlist.impl.search_RoomListSearchContent_Day_0_en","features.roomlist.impl.search_RoomListSearchContent_Night_0_en",0,], -["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19978,], -["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19978,], -["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19978,], -["features.roomlist.impl_RoomListView_Day_10_en","features.roomlist.impl_RoomListView_Night_10_en",19978,], -["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19978,], -["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19978,], -["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19978,], -["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19978,], -["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19978,], -["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19978,], -["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19978,], +["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19982,], +["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19982,], +["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19982,], +["features.roomlist.impl_RoomListView_Day_10_en","features.roomlist.impl_RoomListView_Night_10_en",19982,], +["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19982,], +["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19982,], +["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19982,], +["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19982,], +["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19982,], +["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19982,], +["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19982,], ["features.roomlist.impl_RoomListView_Day_8_en","features.roomlist.impl_RoomListView_Night_8_en",0,], ["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",0,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19978,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19978,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19978,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19978,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19978,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19978,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19978,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19978,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19982,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19982,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19982,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19982,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19982,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19982,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19982,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19982,], ["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",0,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19978,], -["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19978,], -["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19978,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19982,], +["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19982,], +["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19982,], ["libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Day_0_en","libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Night_0_en",0,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19978,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19978,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19978,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19978,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19978,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19978,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19978,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19978,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19978,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19982,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19982,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19982,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19982,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19982,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19982,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19982,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19982,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19982,], ["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_9_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_9_en",0,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19978,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19978,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19978,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19978,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19978,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19978,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19978,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19978,], -["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19978,], -["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19978,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19978,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19978,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19978,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19978,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19978,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19982,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19982,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19982,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19982,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19982,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19982,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19982,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19982,], +["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19982,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19982,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19982,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19982,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19982,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19982,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19982,], ["features.roomlist.impl.components_RoomSummaryPlaceholderRow_Day_0_en","features.roomlist.impl.components_RoomSummaryPlaceholderRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_0_en","features.roomlist.impl.components_RoomSummaryRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_10_en","features.roomlist.impl.components_RoomSummaryRow_Night_10_en",0,], @@ -794,10 +804,10 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_26_en","features.roomlist.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_27_en","features.roomlist.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_28_en","features.roomlist.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19978,], -["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19978,], -["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19978,], -["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19978,], +["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19982,], +["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19982,], +["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19982,], +["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19982,], ["features.roomlist.impl.components_RoomSummaryRow_Day_3_en","features.roomlist.impl.components_RoomSummaryRow_Night_3_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_4_en","features.roomlist.impl.components_RoomSummaryRow_Night_4_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_5_en","features.roomlist.impl.components_RoomSummaryRow_Night_5_en",0,], @@ -805,64 +815,64 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_7_en","features.roomlist.impl.components_RoomSummaryRow_Night_7_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_8_en","features.roomlist.impl.components_RoomSummaryRow_Night_8_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_9_en","features.roomlist.impl.components_RoomSummaryRow_Night_9_en",0,], -["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19978,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19978,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19978,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19982,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19982,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19982,], ["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",19978,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19978,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19978,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",19982,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19982,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19982,], ["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","",19978,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search views_en","",19982,], ["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,], -["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19978,], -["features.createroom.impl.components_SearchSingleUserResultItem_en","",19978,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19978,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19978,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19978,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19978,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19978,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19978,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19978,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19978,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19978,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19978,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19978,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19978,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19978,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19978,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19978,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19978,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19978,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19978,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19978,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19978,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19978,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19978,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19978,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19978,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19978,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19978,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19978,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19978,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19978,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19978,], +["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19982,], +["features.createroom.impl.components_SearchSingleUserResultItem_en","",19982,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19982,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19982,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19982,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19982,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19982,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19982,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19982,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19982,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19982,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19982,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19982,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19982,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19982,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19982,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19982,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19982,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19982,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19982,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19982,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19982,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19982,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19982,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19982,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19982,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19982,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19982,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19982,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19982,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19982,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19982,], ["libraries.matrix.ui.components_SelectedRoom_Day_0_en","libraries.matrix.ui.components_SelectedRoom_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoom_Day_1_en","libraries.matrix.ui.components_SelectedRoom_Night_1_en",0,], ["libraries.matrix.ui.components_SelectedUserCannotRemove_Day_0_en","libraries.matrix.ui.components_SelectedUserCannotRemove_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUser_Day_0_en","libraries.matrix.ui.components_SelectedUser_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUsersRowList_Day_0_en","libraries.matrix.ui.components_SelectedUsersRowList_Night_0_en",0,], ["libraries.textcomposer.components_SendButton_Day_0_en","libraries.textcomposer.components_SendButton_Night_0_en",0,], -["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19978,], -["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19978,], -["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19978,], -["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19978,], -["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19978,], +["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19982,], +["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19982,], +["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19982,], +["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19982,], +["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19982,], ["libraries.matrix.ui.messages.sender_SenderName_Day_0_en","libraries.matrix.ui.messages.sender_SenderName_Night_0_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_1_en","libraries.matrix.ui.messages.sender_SenderName_Night_1_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_2_en","libraries.matrix.ui.messages.sender_SenderName_Night_2_en",0,], @@ -872,39 +882,40 @@ export const screenshots = [ ["libraries.matrix.ui.messages.sender_SenderName_Day_6_en","libraries.matrix.ui.messages.sender_SenderName_Night_6_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_7_en","libraries.matrix.ui.messages.sender_SenderName_Night_7_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_8_en","libraries.matrix.ui.messages.sender_SenderName_Night_8_en",0,], -["features.roomlist.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_SetUpRecoveryKeyBanner_Night_0_en",19978,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19978,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19978,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19978,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19978,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19978,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19978,], +["features.roomlist.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_SetUpRecoveryKeyBanner_Night_0_en",19982,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19982,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19982,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19982,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19982,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19982,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19982,], ["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",19978,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",19982,], ["features.messages.impl.actionlist_SheetContent_Day_0_en","features.messages.impl.actionlist_SheetContent_Night_0_en",0,], ["features.messages.impl.timeline.components.reactionsummary_SheetContent_Day_0_en","features.messages.impl.timeline.components.reactionsummary_SheetContent_Night_0_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19978,], -["features.messages.impl.actionlist_SheetContent_Day_11_en","features.messages.impl.actionlist_SheetContent_Night_11_en",19978,], +["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19982,], +["features.messages.impl.actionlist_SheetContent_Day_11_en","features.messages.impl.actionlist_SheetContent_Night_11_en",19982,], +["features.messages.impl.actionlist_SheetContent_Day_12_en","features.messages.impl.actionlist_SheetContent_Night_12_en",19982,], ["features.messages.impl.actionlist_SheetContent_Day_1_en","features.messages.impl.actionlist_SheetContent_Night_1_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19978,], -["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19978,], -["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19978,], -["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19978,], -["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19978,], -["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19978,], -["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19978,], -["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19978,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19978,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19978,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19978,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19978,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19978,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19978,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19978,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19978,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19978,], +["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19982,], +["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19982,], +["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19982,], +["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19982,], +["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19982,], +["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19982,], +["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19982,], +["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19982,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19982,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19982,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19982,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19982,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19982,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19982,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19982,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19982,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19982,], ["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,], ["libraries.designsystem.components.list_SingleSelectionListItemCustomFormattert_Single selection List item - custom formatter_List items_en","",0,], @@ -913,7 +924,7 @@ export const screenshots = [ ["libraries.designsystem.components.list_SingleSelectionListItemUnselectedWithSupportingText_Single selection List item - no selection, supporting text_List items_en","",0,], ["libraries.designsystem.components.list_SingleSelectionListItem_Single selection List item - no selection_List items_en","",0,], ["libraries.designsystem.theme.components_Sliders_Sliders_en","",0,], -["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19978,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19982,], ["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,], @@ -923,37 +934,37 @@ export const screenshots = [ ["libraries.designsystem.modifiers_SquareSizeModifierLargeHeight_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeWidth_en","",0,], ["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",0,], -["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19978,], +["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19982,], ["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",19978,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",19982,], ["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",19978,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",19982,], ["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_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19978,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19978,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19978,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19978,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19978,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19978,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19978,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19978,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19978,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19978,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19978,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19978,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19978,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19978,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19978,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19978,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19978,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19978,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19982,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19982,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19982,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19982,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19982,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19982,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19982,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19982,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19982,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19982,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19982,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19982,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19982,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19982,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19982,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19982,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19982,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19982,], ["libraries.textcomposer_TextComposerVoice_Day_0_en","libraries.textcomposer_TextComposerVoice_Night_0_en",0,], ["libraries.designsystem.theme.components_TextDark_Text_en","",0,], ["libraries.designsystem.theme.components_TextFieldDark_TextFields_en","",0,], @@ -965,26 +976,26 @@ export const screenshots = [ ["libraries.designsystem.theme.components_TextFieldValueTextFieldDark_TextFields_en","",0,], ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19978,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19978,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19978,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19982,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19982,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19982,], ["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",19978,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19978,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",19982,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19982,], ["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.event_TimelineImageWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_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_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19978,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19982,], ["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",19978,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19978,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19978,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",19982,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19982,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19982,], ["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,], @@ -992,16 +1003,16 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",19978,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19978,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",19982,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19982,], ["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_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19978,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19982,], ["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",19978,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19978,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",19982,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19982,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en",0,], @@ -1010,36 +1021,36 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",19978,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",19982,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",19978,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",19982,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",0,], ["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","",19978,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",19982,], ["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_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19978,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19978,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19982,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19982,], ["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_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",19978,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",19982,], ["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",19978,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19978,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19978,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19978,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19978,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",19982,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19982,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19982,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19982,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19982,], ["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",19978,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19978,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",19982,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19982,], ["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",19978,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",19982,], ["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,], @@ -1048,8 +1059,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",19978,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19978,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",19982,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19982,], ["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,], @@ -1061,7 +1072,7 @@ 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",19978,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",19982,], ["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,], @@ -1083,84 +1094,84 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemVoiceView_Day_9_en","features.messages.impl.timeline.components.event_TimelineItemVoiceView_Night_9_en",0,], ["features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en",0,], -["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",19978,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19978,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",19982,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19982,], ["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",0,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",19978,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19978,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19978,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19978,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19978,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19978,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",19978,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19978,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",19982,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19982,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19982,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19982,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19982,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19982,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",19982,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19982,], ["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",19978,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",19982,], ["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",19978,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",19982,], ["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",19978,], +["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",19982,], ["features.messages.impl.timeline_TimelineView_Day_9_en","features.messages.impl.timeline_TimelineView_Night_9_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",19978,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19978,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19978,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19978,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19978,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19978,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19978,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19978,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",19982,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19982,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19982,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19982,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19982,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19982,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19982,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19982,], ["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",19978,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19978,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19978,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19978,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19978,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19978,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",19982,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19982,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19982,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19982,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19982,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19982,], ["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","",19978,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",19982,], ["libraries.matrix.ui.components_UnsavedAvatar_Day_0_en","libraries.matrix.ui.components_UnsavedAvatar_Night_0_en",0,], ["libraries.designsystem.components.avatar_UserAvatarColors_Day_0_en","libraries.designsystem.components.avatar_UserAvatarColors_Night_0_en",0,], -["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19978,], -["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19978,], -["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19978,], -["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19978,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19982,], +["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19982,], +["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19982,], +["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19982,], ["features.createroom.impl.components_UserListView_Day_3_en","features.createroom.impl.components_UserListView_Night_3_en",0,], ["features.createroom.impl.components_UserListView_Day_4_en","features.createroom.impl.components_UserListView_Night_4_en",0,], ["features.createroom.impl.components_UserListView_Day_5_en","features.createroom.impl.components_UserListView_Night_5_en",0,], ["features.createroom.impl.components_UserListView_Day_6_en","features.createroom.impl.components_UserListView_Night_6_en",0,], -["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19978,], +["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19982,], ["features.createroom.impl.components_UserListView_Day_8_en","features.createroom.impl.components_UserListView_Night_8_en",0,], -["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19978,], +["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19982,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], ["features.preferences.impl.user_UserPreferences_Day_2_en","features.preferences.impl.user_UserPreferences_Night_2_en",0,], ["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",0,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19978,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19978,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19978,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19978,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19978,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19978,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19978,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19978,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19978,], -["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19978,], -["features.verifysession.impl_VerifySelfSessionView_Day_10_en","features.verifysession.impl_VerifySelfSessionView_Night_10_en",19978,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19982,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19982,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19982,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19982,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19982,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19982,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19982,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19982,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19982,], +["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19982,], +["features.verifysession.impl_VerifySelfSessionView_Day_10_en","features.verifysession.impl_VerifySelfSessionView_Night_10_en",19982,], ["features.verifysession.impl_VerifySelfSessionView_Day_11_en","features.verifysession.impl_VerifySelfSessionView_Night_11_en",0,], ["features.verifysession.impl_VerifySelfSessionView_Day_12_en","features.verifysession.impl_VerifySelfSessionView_Night_12_en",0,], -["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19978,], -["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19978,], -["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19978,], -["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19978,], -["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19978,], -["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19978,], -["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19978,], -["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19978,], -["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19978,], +["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19982,], +["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19982,], +["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19982,], +["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19982,], +["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19982,], +["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19982,], +["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19982,], +["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19982,], +["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19982,], ["libraries.designsystem.ruler_VerticalRuler_Day_0_en","libraries.designsystem.ruler_VerticalRuler_Night_0_en",0,], ["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,], @@ -1175,6 +1186,6 @@ export const screenshots = [ ["libraries.textcomposer.components_VoiceMessageRecording_Day_0_en","libraries.textcomposer.components_VoiceMessageRecording_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessage_Day_0_en","libraries.textcomposer.components_VoiceMessage_Night_0_en",0,], ["libraries.designsystem.components.media_WaveformPlaybackView_Day_0_en","libraries.designsystem.components.media_WaveformPlaybackView_Night_0_en",0,], -["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19978,], +["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19982,], ["libraries.designsystem.ruler_WithRulers_Day_0_en","libraries.designsystem.ruler_WithRulers_Night_0_en",0,], ]; diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en.png index a348889301..d880280de2 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8df01760f694d1214e3d71582ee2e6ab3fe9a2319b8f1e3005d451764eb873f0 -size 39341 +oid sha256:f45332a3b2a62939aff408aa9537f9b71c4bb85bbe26b43c61a6400441830483 +size 39482 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en.png index faf85fafa4..5c49aa51c3 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f8a73d70b78289b7faf63a511f066fa3ee3fc89be512b1e69e143087c360fa2 -size 36847 +oid sha256:ea7772eb8d6f825dc5d8a5823e8452e4e4aec1db0b460a189715b843d8f7ae7c +size 37021 From 62a9d8ce29910bad4d53122db2b3ae041404e3c5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 10:04:28 +0200 Subject: [PATCH 034/106] SDK 0.2.45 abbe2ec52316c998c3894989b9c48b3781967d26 --- 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 07898a0950..d536ed5c68 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -162,7 +162,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.44" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.45" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } From beb0bff3cca91f56890c770dda09ecbb411bc799 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 10:21:27 +0200 Subject: [PATCH 035/106] Use new API `awaitRoomRemoteEcho` to wait for the created room to be available. --- .../android/libraries/matrix/impl/RustMatrixClient.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 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 1112fde2f5..ff43659b40 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 @@ -311,14 +311,16 @@ class RustMatrixClient( avatar = createRoomParams.avatar, powerLevelContentOverride = defaultRoomCreationPowerLevels, ) - val roomId = RoomId(client.createRoom(rustParams)) + val roomId = client.createRoom(rustParams) // Wait to receive the room back from the sync but do not returns failure if it fails. try { - awaitJoinedRoom(roomId.toRoomIdOrAlias(), 30.seconds) + withTimeout(30.seconds) { + client.awaitRoomRemoteEcho(roomId) + } } catch (e: Exception) { Timber.e(e, "Timeout waiting for the room to be available in the room list") } - roomId + RoomId(roomId) } } From 3a0e182ba9f2412e5eba45bc62fa283c6e6b9d3c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 10:59:26 +0200 Subject: [PATCH 036/106] Use new API `awaitRoomRemoteEcho` to ensure that the room is ready SDK side. --- .../android/libraries/matrix/impl/RustMatrixClient.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 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 ff43659b40..9e77dcff4c 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 @@ -272,6 +272,8 @@ class RustMatrixClient( .filter(predicate) .first() .first() + // Ensure that the room is ready + .also { client.awaitRoomRemoteEcho(it.roomId.value) } } } @@ -311,16 +313,14 @@ class RustMatrixClient( avatar = createRoomParams.avatar, powerLevelContentOverride = defaultRoomCreationPowerLevels, ) - val roomId = client.createRoom(rustParams) + val roomId = RoomId(client.createRoom(rustParams)) // Wait to receive the room back from the sync but do not returns failure if it fails. try { - withTimeout(30.seconds) { - client.awaitRoomRemoteEcho(roomId) - } + awaitJoinedRoom(roomId.toRoomIdOrAlias(), 30.seconds) } catch (e: Exception) { Timber.e(e, "Timeout waiting for the room to be available in the room list") } - RoomId(roomId) + roomId } } From 265c60a05615685272c9d9e086c2703028887613 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 11:01:28 +0200 Subject: [PATCH 037/106] Fix test compilation issue. --- .../impl/call/DefaultElementCallBaseUrlProviderTest.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/call/DefaultElementCallBaseUrlProviderTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/call/DefaultElementCallBaseUrlProviderTest.kt index 03174d5359..a5333d3c1f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/call/DefaultElementCallBaseUrlProviderTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/call/DefaultElementCallBaseUrlProviderTest.kt @@ -91,8 +91,9 @@ class DefaultElementCallBaseUrlProviderTest { private fun createElementWellKnown(widgetUrl: String): ElementWellKnown { return ElementWellKnown( call = ElementCallWellKnown( - widgetUrl = widgetUrl - ) + widgetUrl = widgetUrl, + ), + registrationHelperUrl = null, ) } } From 340d08e328eca57d8e767e6a075ad3ad3de33de8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 11:50:11 +0200 Subject: [PATCH 038/106] SDK 0.2.46 f576c72ef8cf4d735e3f91e9ec52aba0278c643f --- 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 d536ed5c68..14d38d3a2c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -162,7 +162,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.45" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.46" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } From 4583ffeaf94c9dbed08b15052fc27a7bb484dfc4 Mon Sep 17 00:00:00 2001 From: bmarty <3940906+bmarty@users.noreply.github.com> Date: Tue, 17 Sep 2024 11:05:35 +0000 Subject: [PATCH 039/106] Sync Strings from Localazy --- .../src/main/res/values-hu/translations.xml | 5 + .../src/main/res/values-hu/translations.xml | 1 + .../src/main/res/values-hu/translations.xml | 4 + .../src/main/res/values-de/translations.xml | 2 +- .../src/main/res/values-de/translations.xml | 1 + .../src/main/res/values-de/translations.xml | 1 + .../src/main/res/values-de/translations.xml | 11 + .../src/main/res/values-et/translations.xml | 2 +- .../src/main/res/values-fr/translations.xml | 4 +- .../src/main/res/values-hu/translations.xml | 10 + .../src/main/res/values/localazy.xml | 4 +- ...er_ConfirmAccountProviderView_Day_2_de.png | 4 +- ...impl.actionlist_SheetContent_Day_12_de.png | 4 +- ...veVerifiedUserSendFailureView_Day_1_de.png | 4 +- ...veVerifiedUserSendFailureView_Day_2_de.png | 4 +- ....components_MessageShieldView_Day_0_de.png | 4 +- ...sable_SecureBackupDisableView_Day_0_de.png | 4 +- ...sable_SecureBackupDisableView_Day_1_de.png | 4 +- ...sable_SecureBackupDisableView_Day_2_de.png | 4 +- ...sable_SecureBackupDisableView_Day_3_de.png | 4 +- screenshots/html/data.js | 1200 ++++++++--------- ...impl.actionlist_SheetContent_Day_12_en.png | 4 +- ...pl.actionlist_SheetContent_Night_12_en.png | 4 +- ...veVerifiedUserSendFailureView_Day_1_en.png | 4 +- ...VerifiedUserSendFailureView_Night_1_en.png | 4 +- 25 files changed, 665 insertions(+), 632 deletions(-) create mode 100644 appnav/src/main/res/values-hu/translations.xml diff --git a/appnav/src/main/res/values-hu/translations.xml b/appnav/src/main/res/values-hu/translations.xml new file mode 100644 index 0000000000..e4b24f811b --- /dev/null +++ b/appnav/src/main/res/values-hu/translations.xml @@ -0,0 +1,5 @@ + + + "Kijelentkezés és frissítés" + "A Matrix-kiszolgáló már nem támogatja a régi protokollt. Az alkalmazás további használatához jelentkezzen ki és be." + diff --git a/features/login/impl/src/main/res/values-hu/translations.xml b/features/login/impl/src/main/res/values-hu/translations.xml index a37288fd6f..1fb7f12d0c 100644 --- a/features/login/impl/src/main/res/values-hu/translations.xml +++ b/features/login/impl/src/main/res/values-hu/translations.xml @@ -21,6 +21,7 @@ "Csak olyan meglévő kiszolgálóhoz csatlakozhat, amely támogatja a Sliding sync protokollt. Ezt a Matrix-kiszolgáló adminisztrátorának kell beállítania. %1$s" "Mi a kiszolgálója címe?" "Válassza ki a kiszolgálóját" + "Fiók létrehozása" "Ez a fiók deaktiválva lett." "Helytelen felhasználónév vagy jelszó" "Ez nem érvényes felhasználóazonosító. A várt formátum: „@user:homeserver.org”" diff --git a/features/roomlist/impl/src/main/res/values-hu/translations.xml b/features/roomlist/impl/src/main/res/values-hu/translations.xml index 2325b7ae21..20006fd466 100644 --- a/features/roomlist/impl/src/main/res/values-hu/translations.xml +++ b/features/roomlist/impl/src/main/res/values-hu/translations.xml @@ -1,5 +1,9 @@ + "Kijelentkezés és frissíté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." + "A Matrix-kiszolgáló már nem támogatja a régi protokollt. Az alkalmazás további használatához jelentkezzen ki és be." + "Frissítés érhető el" "Hozzon létre egy új helyreállítási kulcsot, amellyel visszaállíthatja a titkosított üzenetek előzményeit, ha elveszíti az eszközökhöz való hozzáférést." "Helyreállítás beállítása" "A csevegés biztonsági mentése nincs szinkronban. Meg kell erősítenie a helyreállítási kulcsát, hogy továbbra is hozzáférjen a csevegés biztonsági mentéséhez." diff --git a/features/securebackup/impl/src/main/res/values-de/translations.xml b/features/securebackup/impl/src/main/res/values-de/translations.xml index 4be1de6ddd..9589aa0534 100644 --- a/features/securebackup/impl/src/main/res/values-de/translations.xml +++ b/features/securebackup/impl/src/main/res/values-de/translations.xml @@ -36,7 +36,7 @@ "Wenn du das Backup deaktivierst, wird dein aktuelles Backup des Verschlüsselungsschlüssels entfernt und andere Sicherheitsfunktionen werden deaktiviert. Das bedeutet:" "Keine Historie für verschlüsselte Nachrichten auf neuen Geräten ." - "Du verlierst den Zugriff auf deine verschlüsselten Nachrichten, wenn du dich überall von %1$s abmeldest" + "Zugriff auf deine verschlüsselten Nachrichten verlieren, wenn du dich überall von %1$s abmeldest" "Bist du sicher, dass du das Backup deaktivieren willst?" "Hier kannst Du einen neuen Wiederherstellungsschlüssel erstellen. Nachdem Du einen neuen Wiederherstellungsschlüssel erstellt hast, funktioniert dein alter Schlüssel nicht mehr." "Wiederherstellungsschlüssel erstellen" diff --git a/features/verifysession/impl/src/main/res/values-de/translations.xml b/features/verifysession/impl/src/main/res/values-de/translations.xml index 5f0d9504f4..1ddda0126b 100644 --- a/features/verifysession/impl/src/main/res/values-de/translations.xml +++ b/features/verifysession/impl/src/main/res/values-de/translations.xml @@ -4,6 +4,7 @@ "Verifiziere dieses Gerät, um sicheres Messaging einzurichten." "Bestätige, dass du es bist" "Ein anderes Gerät verwenden" + "Wiederherstellungsschlüssel verwenden" "Du kannst nun verschlüsselte Nachrichten lesen oder versenden." "Gerät verifiziert" "Ein anderes Gerät verwenden" diff --git a/libraries/push/impl/src/main/res/values-de/translations.xml b/libraries/push/impl/src/main/res/values-de/translations.xml index 35924e6247..fc5edbf1d9 100644 --- a/libraries/push/impl/src/main/res/values-de/translations.xml +++ b/libraries/push/impl/src/main/res/values-de/translations.xml @@ -34,6 +34,7 @@ "Schnelle Antwort" "Du wurdest eingeladen, den Raum zu betreten" "Ich" + "%1$s hat Dich erwähnt oder geantwortet" "Du siehst dir die Benachrichtigung an! Klicke hier!" "%1$s: %2$s" "%1$s: %2$s %3$s" 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 ee31b18978..13bd0b7d93 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -250,6 +250,7 @@ Grund: %1$s." "Warnung" "Deine Änderungen wurden nicht gespeichert. Bist du sicher, dass du zurückgehen willst?" "Änderungen speichern?" + "Dein Homeserver muss aktualisiert werden, um den Matrix Authentication Services und die Erstellung von Konten zu unterstützen." "Fehler beim Erstellen des Permalinks" "%1$s konnte die Karte nicht laden. Bitte versuche es später erneut." "Fehler beim Laden der Nachrichten" @@ -262,6 +263,7 @@ Grund: %1$s." "Einige Nachrichten wurden nicht gesendet" "Entschuldigung, es ist ein Fehler aufgetreten" "Die Authentizität dieser verschlüsselten Nachricht kann auf diesem Gerät nicht garantiert werden." + "Verschlüsselt von einem zuvor verifizierten Nutzer." "Unverschlüsselt." "Verschlüsselt von einem unbekannten oder gelöschten Gerät." "Verschlüsselt durch ein Gerät, das nicht von seinem Besitzer verifiziert wurde." @@ -280,7 +282,14 @@ Grund: %1$s." "%1$d fixierte Nachrichten" "Fixierte Nachrichten" + "Du wirst jetzt zu deinem %1$s Konto geleitet, um deine Identität zurückzusetzen. Danach wirst du zur App zurückgebracht." + "Kannst du das nicht bestätigen? Gehe zu deinem Konto, um deine Identität zurückzusetzen." + "Verifizierung zurückziehen und senden" + "Du kannst deine Verifizierung zurückziehen und diese Nachricht trotzdem senden, oder du kannst sie vorerst abbrechen und es später noch einmal versuchen, nachdem du %1$s erneut verifiziert hast." + "Deine Nachricht wurde nicht gesendet, da sich die verifizierte Identität von %1$s geändert hat" "Nachricht trotzdem senden" + "%1$s verwendet wenigstens ein nicht verifiziertes Gerät. Du kannst die Nachricht trotzdem verschicken, oder vorerst abbrechen und später erneut versuchen, nachdem %2$s alle Geräte verifiziert hat." + "Deine Nachricht wurde nicht gesendet, weil %1$s nicht alle Geräte verifiziert hat" "Fixierte Nachrichten" "Fehler beim Verarbeiten des hochgeladenen Mediums. Bitte versuche es erneut." "Benutzerdetails konnten nicht abgerufen werden" @@ -302,6 +311,8 @@ Grund: %1$s." "In Google Maps öffnen" "In OpenStreetMap öffnen" "Diesen Standort teilen" + "Nachricht nicht gesendet, weil sich die verifizierte Identität von %1$s geändert hat." + "Nachricht wurde nicht gesendet, weil %1$s nicht alle Geräte verifiziert hat" "Standort" "Version: %1$s (%2$s)" "en" 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 f6bcbf0fe4..1de14e5f1f 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -251,7 +251,7 @@ Põhjus: %1$s." "Hoiatus" "Sinu tehtud muudatused pole veel salvestatud. Kas sa oled kindel, et soovid minna tagasi?" "Kas salvestame muudatused?" - "Selleks et koos kasutajakonto loomisega toimiks Matrix Authentication Serveri tugi, vajab sinu koduserver uuendamist." + "Selleks et koos kasutajakonto loomisega toimiks Matrix Authentication Service\'i tugi, vajab sinu koduserver uuendamist." "Püsilingi loomine ei õnnestumud" "%1$s kaardi laadimine ei õnnestunud. Palun proovi hiljem uuesti." "Sõnumite laadimine ei õnnestunud" 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 831c134f22..8c41675598 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -289,7 +289,7 @@ Raison: %1$s." "Votre message n’a pas été envoyé car l’identité vérifiée de %1$s a changé" "Envoyer le message quand même" "%1$s utilise un ou plusieurs appareils non vérifiés. Vous pouvez quand même envoyer le message, ou vous pouvez annuler pour l’instant et réessayer plus tard après que %2$s vérifie tous ses appareils." - "Votre message n’a pas été envoyé car %1$s a un ou plusieurs appareils non vérifiés" + "Votre message n’a pas été envoyé car %1$s n’a pas vérifié tous ses appareils" "Messages épinglés" "Échec du traitement des médias à télécharger, veuillez réessayer." "Impossible de récupérer les détails de l’utilisateur" @@ -312,7 +312,7 @@ Raison: %1$s." "Ouvrir dans OpenStreetMap" "Partager cette position" "Le message n’a pas été envoyé car l’identité vérifiée de %1$s a changé." - "Le message n’a pas été envoyé car %1$s n’a pas vérifié un ou plusieurs appareils." + "Le message n’a pas été envoyé car %1$s n’a pas vérifié tous ses appareils." "Position" "Version : %1$s ( %2$s )" "fr" 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 fff7fcbe20..977c6c8928 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -36,6 +36,7 @@ "Vissza" "Hívás" "Mégse" + "Egyelőre nem" "Fénykép kiválasztása" "Törlés" "Bezárás" @@ -250,6 +251,7 @@ Ok: %1$s." "Figyelmeztetés" "A módosítások nem lettek mentve. Biztos, hogy visszalép?" "Menti a módosításokat?" + "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" "Az %1$s nem tudta betölteni a térképet. Próbálja meg újra később." "Nem sikerült betölteni az üzeneteket" @@ -283,6 +285,12 @@ Ok: %1$s." "Kitűzött üzenetek" "Arra készül, hogy belépjen a(z) %1$s fiókjába, hogy visszaállítsa a személyazonosságát. Ezután vissza fog térni az alkalmazásba." "Nem tudja megerősíteni? Ugorjon a fiókjához, és állítsa vissza a személyazonosságát." + "Ellenőrzés visszavonása és elküldés" + "Visszavonhatja az ellenőrzést, és ennek ellenére elküldheti ezt az üzenetet, vagy egyelőre törölheti, és %1$s újbóli ellenőrzése után újra megpróbálhatja." + "Az üzenete nem lett elküldve, mert %1$s ellenőrzött személyazonossága megváltozott." + "Üzenet elküldése mindenképp" + "%1$s egy vagy több ellenőrizetlen eszközt használ. Így is elküldheti az üzenetet, vagy megszakíthatja most, és megpróbálhatja újra, miután %2$s ellenőrizte az összes eszközét." + "Az üzenet nem lett elküldve, mert %1$s nem ellenőrizte az összes eszközét" "Kitűzött üzenetek" "Nem sikerült feldolgozni a feltöltendő médiát, próbálja újra." "Nem sikerült letölteni a felhasználói adatokat" @@ -304,6 +312,8 @@ Ok: %1$s." "Megnyitás a Google Mapsben" "Megnyitás az OpenStreetMapen" "E hely megosztása" + "Az üzenet nem lett elküldve, mert %1$s ellenőrzött személyazonossága megváltozott." + "Az üzenet nem lett elküldve, mert %1$s nem ellenőrizte az összes eszközét." "Hely" "Verzió: %1$s (%2$s)" "hu" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index d55f7dc41c..8e2e7822bf 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -290,7 +290,7 @@ Reason: %1$s." "Your message was not sent because %1$s’s verified identity has changed" "Send message anyway" "%1$s is using one or more unverified devices. You can send the message anyway, or you can cancel for now and try again later after %2$s has verified all their devices." - "Your message was not sent because %1$s has not verified one or more devices" + "Your message was not sent because %1$s has not verified all devices" "Pinned messages" "Failed processing media to upload, please try again." "Could not retrieve user details" @@ -313,7 +313,7 @@ Reason: %1$s." "Open in OpenStreetMap" "Share this location" "Message not sent because %1$s’s verified identity has changed." - "Message not sent because %1$s has not verified one or more devices." + "Message not sent because %1$s has not verified all devices." "Location" "Version: %1$s (%2$s)" "en" diff --git a/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_de.png b/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_de.png index 9dc59b6bc0..6b5271c39f 100644 --- a/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_de.png +++ b/screenshots/de/features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1519e48ee816d293367b106b9c0fb864ca4e91c5bacf9f6d005dfcd720976d6 -size 39245 +oid sha256:dbc451dbdbf48cbcf5851863970cfb2d5728d6ad1f0fbf8207b26cb9e8ace861 +size 39645 diff --git a/screenshots/de/features.messages.impl.actionlist_SheetContent_Day_12_de.png b/screenshots/de/features.messages.impl.actionlist_SheetContent_Day_12_de.png index 667b224dc4..2fd9274774 100644 --- a/screenshots/de/features.messages.impl.actionlist_SheetContent_Day_12_de.png +++ b/screenshots/de/features.messages.impl.actionlist_SheetContent_Day_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:147cc98d5d7fb08ba2d6954bd9474adfe2006ee866a3852ff7b2368b11907d63 -size 51528 +oid sha256:dcd09b6f69e80f03ea6e81c64a7da582dc732a6288fb0660bddb6a2b4fe41a07 +size 51531 diff --git a/screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_de.png b/screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_de.png index 8c25a06e53..937f0b8b00 100644 --- a/screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_de.png +++ b/screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae27a8ec38ca3a8a6157b6065018e8fb76d6a943456b6f186594393ce2e1bd1c -size 60488 +oid sha256:5b73f8ee5792e95bb189e3dfdb615e30d2089afb879ed05958245ddba0251aae +size 63856 diff --git a/screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_de.png b/screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_de.png index 939427e4d9..9d990d6e19 100644 --- a/screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_de.png +++ b/screenshots/de/features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:70d9cbc012233cb9a0f538ae8634c24440afb92c5d7e38717215201ae62ada4a -size 56753 +oid sha256:54ad73d4aa324d71a5a6f718b8fb508b6a90aaf3f433f0e35ac621ca713ca0a1 +size 67574 diff --git a/screenshots/de/features.messages.impl.timeline.components_MessageShieldView_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components_MessageShieldView_Day_0_de.png index b11f28b3dd..6b3a059bf1 100644 --- a/screenshots/de/features.messages.impl.timeline.components_MessageShieldView_Day_0_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_MessageShieldView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:13b03b0125a0d3f6b44330a7ae2a49ac4139951371d4992c9b308f09c1afdeed -size 47269 +oid sha256:282e9afb40069c21fce9c8df11e9d1f98d07184fa0600ec8488b1a667ee0d1e0 +size 48184 diff --git a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_0_de.png b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_0_de.png index 46a6198a48..c262e144cb 100644 --- a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_0_de.png +++ b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:42ceb0bf684dcb97456ee904342afa81e966de5e595fbf741f26a25536f2700d -size 71135 +oid sha256:9fb3f15ba65c5bcc785dfbac0a51202a517cd04e38526d2ff7fcc41e63f80f68 +size 70437 diff --git a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_1_de.png b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_1_de.png index ac3fdcdf6d..dd41236040 100644 --- a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_1_de.png +++ b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:be22cf2ce23200a147bffc00d7bb7879957c046d44f97f46237783eeacfd6802 -size 54437 +oid sha256:8ba76ed706efff9b4dd95dac0cdd8c6034fa6265cbf18cc8a52bca3d10111e49 +size 53634 diff --git a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_2_de.png b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_2_de.png index a39ca0c09d..87bd3bbed3 100644 --- a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_2_de.png +++ b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8334e9951e681fc87b1713ad9f2dee7b1bf288f479c9b77f026a7779ff3ad8d0 -size 71639 +oid sha256:7ff2ad4d9b49356877cf58160ffdca4867fe4aeaab74ac768760461649badd40 +size 70938 diff --git a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png index d5a14dcbe8..33662ae687 100644 --- a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png +++ b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6c730cf5ceebede7f6a9a02edad610ae9c7ec42e77a37cec222bda261b48cacc -size 42017 +oid sha256:57f314de86936d227316399b4d873b6d0cf72aa763b8eea3048c7580777301aa +size 41346 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 92f0a2a384..6ac9ca9bfe 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,41 +1,41 @@ // Generated file, do not edit export const screenshots = [ ["en","en-dark","de",], -["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",19982,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",19983,], ["features.invite.impl.response_AcceptDeclineInviteView_Day_0_en","features.invite.impl.response_AcceptDeclineInviteView_Night_0_en",0,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19982,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19982,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19982,], -["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19982,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_1_en","features.invite.impl.response_AcceptDeclineInviteView_Night_1_en",19983,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_2_en","features.invite.impl.response_AcceptDeclineInviteView_Night_2_en",19983,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_3_en","features.invite.impl.response_AcceptDeclineInviteView_Night_3_en",19983,], +["features.invite.impl.response_AcceptDeclineInviteView_Day_4_en","features.invite.impl.response_AcceptDeclineInviteView_Night_4_en",19983,], ["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,], ["features.login.impl.accountprovider_AccountProviderView_Day_4_en","features.login.impl.accountprovider_AccountProviderView_Night_4_en",0,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19982,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19982,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19982,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19982,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19982,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19982,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19982,], -["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19982,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",19982,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",19982,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19982,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19982,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19982,], -["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19982,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",19983,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",19983,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",19983,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",19983,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_0_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_0_en",19983,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_1_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_1_en",19983,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_2_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_2_en",19983,], +["features.preferences.impl.advanced_AdvancedSettingsView_Day_3_en","features.preferences.impl.advanced_AdvancedSettingsView_Night_3_en",19983,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",19983,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",19983,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",19983,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",19983,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",19983,], +["services.apperror.impl_AppErrorView_Day_0_en","services.apperror.impl_AppErrorView_Night_0_en",19983,], ["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",19982,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",19983,], ["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",19982,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",19983,], ["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",19982,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",19983,], ["libraries.designsystem.components.async_AsyncIndicatorFailure_Day_0_en","libraries.designsystem.components.async_AsyncIndicatorFailure_Night_0_en",0,], ["libraries.designsystem.components.async_AsyncIndicatorLoading_Day_0_en","libraries.designsystem.components.async_AsyncIndicatorLoading_Night_0_en",0,], ["libraries.designsystem.components.async_AsyncLoading_Day_0_en","libraries.designsystem.components.async_AsyncLoading_Night_0_en",0,], -["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",19982,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",19983,], ["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,], @@ -45,11 +45,11 @@ 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_AttachmentsView_0_en","",19982,], -["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19982,], -["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19982,], -["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19982,], -["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19982,], +["features.messages.impl.attachments.preview_AttachmentsView_0_en","",19983,], +["features.messages.impl.attachments.preview_AttachmentsView_1_en","",19983,], +["features.messages.impl.attachments.preview_AttachmentsView_2_en","",19983,], +["features.messages.impl.attachments.preview_AttachmentsView_3_en","",19983,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",19983,], ["libraries.designsystem.components.avatar_Avatar_Avatars_0_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_10_en","",0,], ["libraries.designsystem.components.avatar_Avatar_Avatars_11_en","",0,], @@ -129,13 +129,13 @@ export const screenshots = [ ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], ["libraries.designsystem.components_BigCheckmark_Day_0_en","libraries.designsystem.components_BigCheckmark_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",19982,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19982,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19982,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19982,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19982,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19982,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19982,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",19983,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",19983,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",19983,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",19983,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",19983,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",19983,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",19983,], ["libraries.designsystem.components_BloomInitials_Day_0_en","libraries.designsystem.components_BloomInitials_Night_0_en",0,], ["libraries.designsystem.components_BloomInitials_Day_1_en","libraries.designsystem.components_BloomInitials_Night_1_en",0,], ["libraries.designsystem.components_BloomInitials_Day_2_en","libraries.designsystem.components_BloomInitials_Night_2_en",0,], @@ -146,93 +146,93 @@ export const screenshots = [ ["libraries.designsystem.components_BloomInitials_Day_7_en","libraries.designsystem.components_BloomInitials_Night_7_en",0,], ["libraries.designsystem.components_Bloom_Day_0_en","libraries.designsystem.components_Bloom_Night_0_en",0,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19982,], -["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19982,], -["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19982,], -["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19982,], -["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19982,], +["features.rageshake.impl.bugreport_BugReportView_Day_0_en","features.rageshake.impl.bugreport_BugReportView_Night_0_en",19983,], +["features.rageshake.impl.bugreport_BugReportView_Day_1_en","features.rageshake.impl.bugreport_BugReportView_Night_1_en",19983,], +["features.rageshake.impl.bugreport_BugReportView_Day_2_en","features.rageshake.impl.bugreport_BugReportView_Night_2_en",19983,], +["features.rageshake.impl.bugreport_BugReportView_Day_3_en","features.rageshake.impl.bugreport_BugReportView_Night_3_en",19983,], +["features.rageshake.impl.bugreport_BugReportView_Day_4_en","features.rageshake.impl.bugreport_BugReportView_Night_4_en",19983,], ["libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonColumnMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.molecules_ButtonRowMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ButtonRowMolecule_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_0_en","features.call.impl.ui_CallScreenPipView_Night_0_en",0,], ["features.call.impl.ui_CallScreenPipView_Day_1_en","features.call.impl.ui_CallScreenPipView_Night_1_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",19982,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19982,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19982,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19982,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19982,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19982,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19982,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19982,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19982,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19982,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19982,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19982,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19982,], -["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19982,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19982,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19982,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19982,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19982,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19982,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19982,], -["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19982,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",19983,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",19983,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",19983,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_0_en",19983,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_10_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_10_en",19983,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_1_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_1_en",19983,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_2_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_2_en",19983,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_3_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_3_en",19983,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_4_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_4_en",19983,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_5_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_5_en",19983,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_6_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_6_en",19983,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_7_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_7_en",19983,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_8_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_8_en",19983,], +["features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Day_9_en","features.roomdetails.impl.rolesandpermissions.changeroles_ChangeRolesView_Night_9_en",19983,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_0_en",19983,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_1_en",19983,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_2_en",19983,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_3_en",19983,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_4_en",19983,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_5_en",19983,], +["features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions.permissions_ChangeRoomPermissionsView_Night_6_en",19983,], ["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",19982,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19982,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",19983,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",19983,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19982,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",19983,], ["libraries.designsystem.theme.components_Checkboxes_Toggles_en","",0,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], ["libraries.designsystem.theme_ColorAliases_Day_0_en","libraries.designsystem.theme_ColorAliases_Night_0_en",0,], ["libraries.textcomposer.components_ComposerOptionsButton_Day_0_en","libraries.textcomposer.components_ComposerOptionsButton_Night_0_en",0,], ["libraries.designsystem.components.avatar_CompositeAvatar_Avatars_en","",0,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19982,], -["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19982,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_0_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_0_en",19983,], +["features.createroom.impl.configureroom_ConfigureRoomView_Day_1_en","features.createroom.impl.configureroom_ConfigureRoomView_Night_1_en",19983,], ["features.preferences.impl.developer.tracing_ConfigureTracingView_Day_0_en","features.preferences.impl.developer.tracing_ConfigureTracingView_Night_0_en",0,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19982,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",19982,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",19982,], -["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19982,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",19983,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",19983,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",19983,], +["features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",19983,], ["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_ConnectivityIndicatorView_Day_0_en","features.networkmonitor.api.ui_ConnectivityIndicatorView_Night_0_en",0,], -["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19982,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",19982,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",19982,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",19982,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",19982,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19982,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19982,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19982,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19982,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19982,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19982,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19982,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19982,], -["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19982,], -["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19982,], -["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19982,], -["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19982,], -["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19982,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19982,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",19983,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",19983,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",19983,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",19983,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",19983,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",19983,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",19983,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",19983,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",19983,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",19983,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",19983,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",19983,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",19983,], +["features.createroom.impl.root_CreateRoomRootView_Day_0_en","features.createroom.impl.root_CreateRoomRootView_Night_0_en",19983,], +["features.createroom.impl.root_CreateRoomRootView_Day_1_en","features.createroom.impl.root_CreateRoomRootView_Night_1_en",19983,], +["features.createroom.impl.root_CreateRoomRootView_Day_2_en","features.createroom.impl.root_CreateRoomRootView_Night_2_en",19983,], +["features.createroom.impl.root_CreateRoomRootView_Day_3_en","features.createroom.impl.root_CreateRoomRootView_Night_3_en",19983,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime pickers_en","",19983,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime pickers_en","",19983,], ["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",19982,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19982,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19982,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",19983,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",19983,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",19983,], ["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",19982,], -["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19982,], -["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19982,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",19983,], +["features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_Night_0_en",19983,], +["features.roomlist.impl.components_DefaultRoomListTopBar_Day_0_en","features.roomlist.impl.components_DefaultRoomListTopBar_Night_0_en",19983,], ["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",19982,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",19982,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",19982,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19982,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19982,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19982,], -["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19982,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",19983,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",19983,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",19983,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",19983,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",19983,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",19983,], +["libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Day_0_en","libraries.designsystem.atomic.molecules_DialogLikeBannerMolecule_Night_0_en",19983,], ["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,], @@ -244,12 +244,12 @@ 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",19982,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19982,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19982,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19982,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19982,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19982,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",19983,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",19983,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",19983,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",19983,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",19983,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",19983,], ["libraries.matrix.ui.components_EditableAvatarView_Day_0_en","libraries.matrix.ui.components_EditableAvatarView_Night_0_en",0,], ["libraries.matrix.ui.components_EditableAvatarView_Day_1_en","libraries.matrix.ui.components_EditableAvatarView_Night_1_en",0,], ["libraries.matrix.ui.components_EditableAvatarView_Day_2_en","libraries.matrix.ui.components_EditableAvatarView_Night_2_en",0,], @@ -259,9 +259,9 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiPicker_Night_0_en",0,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19982,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19982,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19982,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",19983,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",19983,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",19983,], ["features.messages.impl.timeline.debug_EventDebugInfoView_Day_0_en","features.messages.impl.timeline.debug_EventDebugInfoView_Night_0_en",0,], ["libraries.featureflag.ui_FeatureListView_Day_0_en","libraries.featureflag.ui_FeatureListView_Night_0_en",0,], ["libraries.designsystem.theme.components_FilledButtonLargeLowPadding_Buttons_en","",0,], @@ -272,15 +272,15 @@ export const screenshots = [ ["libraries.designsystem.theme.components_FloatingActionButton_Floating Action Buttons_en","",0,], ["libraries.designsystem.atomic.pages_FlowStepPage_Day_0_en","libraries.designsystem.atomic.pages_FlowStepPage_Night_0_en",0,], ["features.messages.impl.timeline.focus_FocusRequestStateView_Day_0_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_0_en",0,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19982,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19982,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19982,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",19983,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",19983,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",19983,], ["libraries.textcomposer.components_FormattingOption_Day_0_en","libraries.textcomposer.components_FormattingOption_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_0_en","features.messages.impl.forward_ForwardMessagesView_Night_0_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_1_en","features.messages.impl.forward_ForwardMessagesView_Night_1_en",0,], ["features.messages.impl.forward_ForwardMessagesView_Day_2_en","features.messages.impl.forward_ForwardMessagesView_Night_2_en",0,], -["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19982,], -["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19982,], +["features.messages.impl.forward_ForwardMessagesView_Day_3_en","features.messages.impl.forward_ForwardMessagesView_Night_3_en",19983,], +["features.roomlist.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.roomlist.impl.components_FullScreenIntentPermissionBanner_Night_0_en",19983,], ["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,], @@ -307,37 +307,37 @@ 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",19982,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",19983,], ["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",19982,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",19983,], ["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",19982,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",19983,], ["libraries.designsystem.atomic.molecules_InfoListItemMolecule_Day_0_en","libraries.designsystem.atomic.molecules_InfoListItemMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.organisms_InfoListOrganism_Day_0_en","libraries.designsystem.atomic.organisms_InfoListOrganism_Night_0_en",0,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19982,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",19983,], ["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",0,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19982,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19982,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19982,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19982,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19982,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19982,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19982,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19982,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19982,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",19983,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",19983,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",19983,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",19983,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",19983,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",19983,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",19983,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",19983,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",19983,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], ["libraries.designsystem.components_LabelledOutlinedTextField_Day_0_en","libraries.designsystem.components_LabelledOutlinedTextField_Night_0_en",0,], ["libraries.designsystem.components_LabelledTextField_Day_0_en","libraries.designsystem.components_LabelledTextField_Night_0_en",0,], ["features.leaveroom.api_LeaveRoomView_Day_0_en","features.leaveroom.api_LeaveRoomView_Night_0_en",0,], -["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19982,], -["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19982,], -["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19982,], -["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19982,], -["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19982,], -["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19982,], +["features.leaveroom.api_LeaveRoomView_Day_1_en","features.leaveroom.api_LeaveRoomView_Night_1_en",19983,], +["features.leaveroom.api_LeaveRoomView_Day_2_en","features.leaveroom.api_LeaveRoomView_Night_2_en",19983,], +["features.leaveroom.api_LeaveRoomView_Day_3_en","features.leaveroom.api_LeaveRoomView_Night_3_en",19983,], +["features.leaveroom.api_LeaveRoomView_Day_4_en","features.leaveroom.api_LeaveRoomView_Night_4_en",19983,], +["features.leaveroom.api_LeaveRoomView_Day_5_en","features.leaveroom.api_LeaveRoomView_Night_5_en",19983,], +["features.leaveroom.api_LeaveRoomView_Day_6_en","features.leaveroom.api_LeaveRoomView_Night_6_en",19983,], ["libraries.designsystem.background_LightGradientBackground_Day_0_en","libraries.designsystem.background_LightGradientBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_LinearProgressIndicator_Progress Indicators_en","",0,], ["libraries.designsystem.components.dialogs_ListDialogContent_Dialogs_en","",0,], @@ -388,29 +388,29 @@ export const screenshots = [ ["libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List supporting text - small padding_List sections_en","",0,], ["libraries.textcomposer.components_LiveWaveformView_Day_0_en","libraries.textcomposer.components_LiveWaveformView_Night_0_en",0,], ["appnav.room.joined_LoadingRoomNodeView_Day_0_en","appnav.room.joined_LoadingRoomNodeView_Night_0_en",0,], -["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",19982,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19982,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19982,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19982,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",19983,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",19983,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",19983,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",19983,], ["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",19982,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19982,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",19982,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19982,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19982,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19982,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19982,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19982,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19982,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19982,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19982,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19982,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19982,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19982,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19982,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19982,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",19983,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",19983,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",19983,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",19983,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",19983,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",19983,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",19983,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",19983,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",19983,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",19983,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",19983,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",19983,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",19983,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",19983,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",19983,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",19983,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19982,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",19983,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en","libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeader_Day_0_en","libraries.matrix.ui.components_MatrixUserHeader_Night_0_en",0,], @@ -420,7 +420,7 @@ export const screenshots = [ ["libraries.mediaviewer.api.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_10_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19982,], +["libraries.mediaviewer.api.viewer_MediaViewerView_2_en","",19983,], ["libraries.mediaviewer.api.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.api.viewer_MediaViewerView_5_en","",0,], @@ -432,7 +432,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",19982,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",19983,], ["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_10_en","features.messages.impl.timeline.components_MessageEventBubble_Night_10_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_11_en","features.messages.impl.timeline.components_MessageEventBubble_Night_11_en",0,], @@ -449,7 +449,7 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessageEventBubble_Day_7_en","features.messages.impl.timeline.components_MessageEventBubble_Night_7_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_8_en","features.messages.impl.timeline.components_MessageEventBubble_Night_8_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_9_en","features.messages.impl.timeline.components_MessageEventBubble_Night_9_en",0,], -["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",19982,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",19983,], ["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,], @@ -457,25 +457,25 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessagesReactionButton_Day_1_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_1_en",0,], ["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.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19982,], -["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19982,], -["features.messages.impl.typing_MessagesViewWithTyping_Day_2_en","features.messages.impl.typing_MessagesViewWithTyping_Night_2_en",19982,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19982,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19982,], -["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19982,], -["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19982,], -["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",19982,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",19982,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19982,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19982,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19982,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19982,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19982,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19982,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19982,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19982,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_0_en","features.messages.impl.typing_MessagesViewWithTyping_Night_0_en",19983,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_1_en","features.messages.impl.typing_MessagesViewWithTyping_Night_1_en",19983,], +["features.messages.impl.typing_MessagesViewWithTyping_Day_2_en","features.messages.impl.typing_MessagesViewWithTyping_Night_2_en",19983,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",19983,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",19983,], +["features.messages.impl_MessagesView_Day_11_en","features.messages.impl_MessagesView_Night_11_en",19983,], +["features.messages.impl_MessagesView_Day_12_en","features.messages.impl_MessagesView_Night_12_en",19983,], +["features.messages.impl_MessagesView_Day_13_en","features.messages.impl_MessagesView_Night_13_en",19983,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",19983,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",19983,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",19983,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",19983,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",19983,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",19983,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",19983,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",19983,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",19983,], ["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",19982,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",19983,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom Sheets_en","",0,], ["appicon.element_MonochromeIcon_en","",0,], @@ -484,29 +484,29 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelectedTrailingContent_Multiple selection List item - selection in trailing content_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple selection List item - selection in supporting text_List items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple selection List item - no selection_List items_en","",0,], -["features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Day_0_en","features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Night_0_en",19982,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19982,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19982,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19982,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19982,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19982,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19982,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19982,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19982,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19982,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19982,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19982,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19982,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19982,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19982,], +["features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Day_0_en","features.roomlist.impl.components_NativeSlidingSyncMigrationBanner_Night_0_en",19983,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",19983,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",19983,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",19983,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",19983,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",19983,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",19983,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",19983,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",19983,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",19983,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",19983,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",19983,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",19983,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",19983,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",19983,], ["libraries.oidc.impl.webview_OidcView_Day_0_en","libraries.oidc.impl.webview_OidcView_Night_0_en",0,], ["libraries.oidc.impl.webview_OidcView_Day_1_en","libraries.oidc.impl.webview_OidcView_Night_1_en",0,], ["libraries.designsystem.atomic.pages_OnBoardingPage_Day_0_en","libraries.designsystem.atomic.pages_OnBoardingPage_Night_0_en",0,], -["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19982,], -["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19982,], -["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19982,], -["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19982,], -["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19982,], +["features.onboarding.impl_OnBoardingView_Day_0_en","features.onboarding.impl_OnBoardingView_Night_0_en",19983,], +["features.onboarding.impl_OnBoardingView_Day_1_en","features.onboarding.impl_OnBoardingView_Night_1_en",19983,], +["features.onboarding.impl_OnBoardingView_Day_2_en","features.onboarding.impl_OnBoardingView_Night_2_en",19983,], +["features.onboarding.impl_OnBoardingView_Day_3_en","features.onboarding.impl_OnBoardingView_Night_3_en",19983,], +["features.onboarding.impl_OnBoardingView_Day_4_en","features.onboarding.impl_OnBoardingView_Night_4_en",19983,], ["libraries.designsystem.background_OnboardingBackground_Day_0_en","libraries.designsystem.background_OnboardingBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_OutlinedButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonLarge_Buttons_en","",0,], @@ -521,62 +521,62 @@ export const screenshots = [ ["libraries.designsystem.components_PageTitleWithIconFull_Day_3_en","libraries.designsystem.components_PageTitleWithIconFull_Night_3_en",0,], ["libraries.designsystem.components_PageTitleWithIconFull_Day_4_en","libraries.designsystem.components_PageTitleWithIconFull_Night_4_en",0,], ["libraries.designsystem.components_PageTitleWithIconMinimal_Day_0_en","libraries.designsystem.components_PageTitleWithIconMinimal_Night_0_en",0,], -["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19982,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19982,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19982,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19982,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19982,], +["features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Day_0_en","features.roomdetails.impl.rolesandpermissions.changeroles_PendingMemberRowWithLongName_Night_0_en",19983,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",19983,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",19983,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",19983,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",19983,], ["features.lockscreen.impl.components_PinEntryTextField_Day_0_en","features.lockscreen.impl.components_PinEntryTextField_Night_0_en",0,], ["libraries.designsystem.components_PinIcon_Day_0_en","libraries.designsystem.components_PinIcon_Night_0_en",0,], ["features.lockscreen.impl.unlock.keypad_PinKeypad_Day_0_en","features.lockscreen.impl.unlock.keypad_PinKeypad_Night_0_en",0,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",19982,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19982,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19982,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19982,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19982,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19982,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19982,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19982,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19982,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19982,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19982,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19982,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19982,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19982,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",19983,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",19983,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",19983,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",19983,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",19983,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",19983,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",19983,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",19983,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",19983,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",19983,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",19983,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",19983,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",19983,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",19983,], ["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",19982,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",19982,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",19982,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",19982,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",19982,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",19982,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",19982,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",19982,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",19982,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",19982,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",19982,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",19982,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",19982,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",19982,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",19983,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",19983,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",19983,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",19983,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",19983,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",19983,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",19983,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",19983,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",19983,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",19983,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",19983,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",19983,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",19983,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",19983,], ["libraries.designsystem.atomic.atoms_PlaceholderAtom_Day_0_en","libraries.designsystem.atomic.atoms_PlaceholderAtom_Night_0_en",0,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",19982,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19982,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19982,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19982,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19982,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",19983,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",19983,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",19983,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",19983,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",19983,], ["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",19982,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19982,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19982,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19982,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19982,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19982,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19982,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19982,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19982,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19982,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19982,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",19983,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",19983,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",19983,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",19983,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",19983,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",19983,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",19983,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",19983,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",19983,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",19983,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",19983,], ["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,], @@ -593,195 +593,195 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceTextLight_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeDark_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceTextWithEndBadgeLight_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19982,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19982,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19982,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19982,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",19983,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",19983,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",19983,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",19983,], ["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","",19982,], -["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19982,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19982,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19982,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19982,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19982,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19982,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19982,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19982,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19982,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19982,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19982,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19982,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19982,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19982,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19982,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19982,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19982,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",19983,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",19983,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",19983,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",19983,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",19983,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",19983,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",19983,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",19983,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",19983,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",19983,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",19983,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",19983,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",19983,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",19983,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",19983,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",19983,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",19983,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",19983,], ["libraries.designsystem.theme.components_RadioButton_Toggles_en","",0,], -["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19982,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19982,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",19983,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",19983,], ["features.rageshake.api.preferences_RageshakePreferencesView_Day_1_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_1_en",0,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19982,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19982,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19982,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19982,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19982,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19982,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19982,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19982,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19982,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",19982,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",19982,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19982,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19982,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19982,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19982,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19982,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19982,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19982,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19982,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19982,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",19983,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",19983,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",19983,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",19983,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",19983,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",19983,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",19983,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",19983,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",19983,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",19983,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",19983,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",19983,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",19983,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",19983,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",19983,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",19983,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",19983,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",19983,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",19983,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",19983,], ["libraries.designsystem.atomic.atoms_RedIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_RedIndicatorAtom_Night_0_en",0,], ["features.messages.impl.timeline.components_ReplySwipeIndicator_Day_0_en","features.messages.impl.timeline.components_ReplySwipeIndicator_Night_0_en",0,], -["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",19982,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19982,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19982,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19982,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19982,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19982,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",19982,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",19982,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",19982,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",19982,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",19983,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",19983,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",19983,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",19983,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",19983,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",19983,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",19983,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",19983,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",19983,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",19983,], ["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",0,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",19982,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",19983,], ["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",19982,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",19982,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19982,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19982,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19982,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19982,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19982,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19982,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19982,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19982,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19982,], -["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19982,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",19983,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",19983,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",19983,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",19983,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_0_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_0_en",19983,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_1_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_1_en",19983,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_2_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_2_en",19983,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_3_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_3_en",19983,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_4_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_4_en",19983,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_5_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_5_en",19983,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_6_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_6_en",19983,], +["features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Day_7_en","features.roomdetails.impl.rolesandpermissions_RolesAndPermissionsView_Night_7_en",19983,], ["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",0,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19982,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",19983,], ["features.roomdetails.impl.components_RoomBadgeNegative_Day_0_en","features.roomdetails.impl.components_RoomBadgeNegative_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgeNeutral_Day_0_en","features.roomdetails.impl.components_RoomBadgeNeutral_Night_0_en",0,], ["features.roomdetails.impl.components_RoomBadgePositive_Day_0_en","features.roomdetails.impl.components_RoomBadgePositive_Night_0_en",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",19982,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",19982,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",19982,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",19982,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",19982,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",19982,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",19982,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",19982,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",19982,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",19982,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",19982,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",19982,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",19982,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",19982,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19982,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19982,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19982,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19982,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19982,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19982,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19982,], -["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19982,], -["features.roomdetails.impl_RoomDetails_0_en","",19982,], -["features.roomdetails.impl_RoomDetails_10_en","",19982,], -["features.roomdetails.impl_RoomDetails_11_en","",19982,], -["features.roomdetails.impl_RoomDetails_12_en","",19982,], -["features.roomdetails.impl_RoomDetails_13_en","",19982,], -["features.roomdetails.impl_RoomDetails_1_en","",19982,], -["features.roomdetails.impl_RoomDetails_2_en","",19982,], -["features.roomdetails.impl_RoomDetails_3_en","",19982,], -["features.roomdetails.impl_RoomDetails_4_en","",19982,], -["features.roomdetails.impl_RoomDetails_5_en","",19982,], -["features.roomdetails.impl_RoomDetails_6_en","",19982,], -["features.roomdetails.impl_RoomDetails_7_en","",19982,], -["features.roomdetails.impl_RoomDetails_8_en","",19982,], -["features.roomdetails.impl_RoomDetails_9_en","",19982,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19982,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19982,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19982,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19982,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19982,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19982,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19982,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19982,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19982,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19982,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19982,], -["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19982,], -["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19982,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",19983,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",19983,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",19983,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",19983,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",19983,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",19983,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",19983,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",19983,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",19983,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",19983,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",19983,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",19983,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",19983,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",19983,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_0_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_0_en",19983,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_1_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_1_en",19983,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_2_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_2_en",19983,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_3_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_3_en",19983,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_4_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_4_en",19983,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_5_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_5_en",19983,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_6_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_6_en",19983,], +["features.roomdetails.impl.edit_RoomDetailsEditView_Day_7_en","features.roomdetails.impl.edit_RoomDetailsEditView_Night_7_en",19983,], +["features.roomdetails.impl_RoomDetails_0_en","",19983,], +["features.roomdetails.impl_RoomDetails_10_en","",19983,], +["features.roomdetails.impl_RoomDetails_11_en","",19983,], +["features.roomdetails.impl_RoomDetails_12_en","",19983,], +["features.roomdetails.impl_RoomDetails_13_en","",19983,], +["features.roomdetails.impl_RoomDetails_1_en","",19983,], +["features.roomdetails.impl_RoomDetails_2_en","",19983,], +["features.roomdetails.impl_RoomDetails_3_en","",19983,], +["features.roomdetails.impl_RoomDetails_4_en","",19983,], +["features.roomdetails.impl_RoomDetails_5_en","",19983,], +["features.roomdetails.impl_RoomDetails_6_en","",19983,], +["features.roomdetails.impl_RoomDetails_7_en","",19983,], +["features.roomdetails.impl_RoomDetails_8_en","",19983,], +["features.roomdetails.impl_RoomDetails_9_en","",19983,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",19983,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",19983,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",19983,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",19983,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",19983,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",19983,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",19983,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_4_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_4_en",19983,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_5_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_5_en",19983,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_6_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_6_en",19983,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_7_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_7_en",19983,], +["features.roomlist.impl.components_RoomListContentView_Day_0_en","features.roomlist.impl.components_RoomListContentView_Night_0_en",19983,], +["features.roomlist.impl.components_RoomListContentView_Day_1_en","features.roomlist.impl.components_RoomListContentView_Night_1_en",19983,], ["features.roomlist.impl.components_RoomListContentView_Day_2_en","features.roomlist.impl.components_RoomListContentView_Night_2_en",0,], -["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19982,], -["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19982,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19982,], -["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19982,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19982,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19982,], -["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19982,], +["features.roomlist.impl.components_RoomListContentView_Day_3_en","features.roomlist.impl.components_RoomListContentView_Night_3_en",19983,], +["features.roomlist.impl.components_RoomListContentView_Day_4_en","features.roomlist.impl.components_RoomListContentView_Night_4_en",19983,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_0_en","features.roomlist.impl.filters_RoomListFiltersView_Night_0_en",19983,], +["features.roomlist.impl.filters_RoomListFiltersView_Day_1_en","features.roomlist.impl.filters_RoomListFiltersView_Night_1_en",19983,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_0_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_0_en",19983,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_1_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_1_en",19983,], +["features.roomlist.impl_RoomListModalBottomSheetContent_Day_2_en","features.roomlist.impl_RoomListModalBottomSheetContent_Night_2_en",19983,], ["features.roomlist.impl.search_RoomListSearchContent_Day_0_en","features.roomlist.impl.search_RoomListSearchContent_Night_0_en",0,], -["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19982,], -["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19982,], -["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19982,], -["features.roomlist.impl_RoomListView_Day_10_en","features.roomlist.impl_RoomListView_Night_10_en",19982,], -["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19982,], -["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19982,], -["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19982,], -["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19982,], -["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19982,], -["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19982,], -["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19982,], +["features.roomlist.impl.search_RoomListSearchContent_Day_1_en","features.roomlist.impl.search_RoomListSearchContent_Night_1_en",19983,], +["features.roomlist.impl.search_RoomListSearchContent_Day_2_en","features.roomlist.impl.search_RoomListSearchContent_Night_2_en",19983,], +["features.roomlist.impl_RoomListView_Day_0_en","features.roomlist.impl_RoomListView_Night_0_en",19983,], +["features.roomlist.impl_RoomListView_Day_10_en","features.roomlist.impl_RoomListView_Night_10_en",19983,], +["features.roomlist.impl_RoomListView_Day_1_en","features.roomlist.impl_RoomListView_Night_1_en",19983,], +["features.roomlist.impl_RoomListView_Day_2_en","features.roomlist.impl_RoomListView_Night_2_en",19983,], +["features.roomlist.impl_RoomListView_Day_3_en","features.roomlist.impl_RoomListView_Night_3_en",19983,], +["features.roomlist.impl_RoomListView_Day_4_en","features.roomlist.impl_RoomListView_Night_4_en",19983,], +["features.roomlist.impl_RoomListView_Day_5_en","features.roomlist.impl_RoomListView_Night_5_en",19983,], +["features.roomlist.impl_RoomListView_Day_6_en","features.roomlist.impl_RoomListView_Night_6_en",19983,], +["features.roomlist.impl_RoomListView_Day_7_en","features.roomlist.impl_RoomListView_Night_7_en",19983,], ["features.roomlist.impl_RoomListView_Day_8_en","features.roomlist.impl_RoomListView_Night_8_en",0,], ["features.roomlist.impl_RoomListView_Day_9_en","features.roomlist.impl_RoomListView_Night_9_en",0,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19982,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19982,], -["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19982,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19982,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19982,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19982,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19982,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19982,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_0_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_0_en",19983,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_1_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_1_en",19983,], +["features.roomdetails.impl.members_RoomMemberListViewBanned_Day_2_en","features.roomdetails.impl.members_RoomMemberListViewBanned_Night_2_en",19983,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",19983,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",19983,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",19983,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",19983,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",19983,], ["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",0,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19982,], -["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19982,], -["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19982,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",19983,], +["features.roomdetails.impl.members_RoomMemberListView_Day_7_en","features.roomdetails.impl.members_RoomMemberListView_Night_7_en",19983,], +["features.roomdetails.impl.members_RoomMemberListView_Day_8_en","features.roomdetails.impl.members_RoomMemberListView_Night_8_en",19983,], ["libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Day_0_en","libraries.designsystem.atomic.molecules_RoomMembersCountMolecule_Night_0_en",0,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19982,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19982,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19982,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19982,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19982,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19982,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19982,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19982,], -["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19982,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_0_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_0_en",19983,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_1_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_1_en",19983,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_2_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_2_en",19983,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_3_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_3_en",19983,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_4_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_4_en",19983,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_5_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_5_en",19983,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_6_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_6_en",19983,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_7_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_7_en",19983,], +["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_8_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_8_en",19983,], ["features.roomdetails.impl.members.moderation_RoomMembersModerationView_Day_9_en","features.roomdetails.impl.members.moderation_RoomMembersModerationView_Night_9_en",0,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19982,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19982,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19982,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19982,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19982,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19982,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19982,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19982,], -["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19982,], -["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19982,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19982,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19982,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19982,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19982,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19982,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",19983,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",19983,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",19983,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",19983,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",19983,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",19983,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",19983,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",19983,], +["features.createroom.impl.components_RoomPrivacyOption_Day_0_en","features.createroom.impl.components_RoomPrivacyOption_Night_0_en",19983,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",19983,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",19983,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",19983,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",19983,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",19983,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",19983,], ["features.roomlist.impl.components_RoomSummaryPlaceholderRow_Day_0_en","features.roomlist.impl.components_RoomSummaryPlaceholderRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_0_en","features.roomlist.impl.components_RoomSummaryRow_Night_0_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_10_en","features.roomlist.impl.components_RoomSummaryRow_Night_10_en",0,], @@ -804,10 +804,10 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_26_en","features.roomlist.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_27_en","features.roomlist.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_28_en","features.roomlist.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19982,], -["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19982,], -["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19982,], -["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19982,], +["features.roomlist.impl.components_RoomSummaryRow_Day_29_en","features.roomlist.impl.components_RoomSummaryRow_Night_29_en",19983,], +["features.roomlist.impl.components_RoomSummaryRow_Day_2_en","features.roomlist.impl.components_RoomSummaryRow_Night_2_en",19983,], +["features.roomlist.impl.components_RoomSummaryRow_Day_30_en","features.roomlist.impl.components_RoomSummaryRow_Night_30_en",19983,], +["features.roomlist.impl.components_RoomSummaryRow_Day_31_en","features.roomlist.impl.components_RoomSummaryRow_Night_31_en",19983,], ["features.roomlist.impl.components_RoomSummaryRow_Day_3_en","features.roomlist.impl.components_RoomSummaryRow_Night_3_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_4_en","features.roomlist.impl.components_RoomSummaryRow_Night_4_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_5_en","features.roomlist.impl.components_RoomSummaryRow_Night_5_en",0,], @@ -815,64 +815,64 @@ export const screenshots = [ ["features.roomlist.impl.components_RoomSummaryRow_Day_7_en","features.roomlist.impl.components_RoomSummaryRow_Night_7_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_8_en","features.roomlist.impl.components_RoomSummaryRow_Night_8_en",0,], ["features.roomlist.impl.components_RoomSummaryRow_Day_9_en","features.roomlist.impl.components_RoomSummaryRow_Night_9_en",0,], -["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19982,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19982,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19982,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",19983,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",19983,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",19983,], ["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",19982,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19982,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19982,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",19983,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",19983,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",19983,], ["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","",19982,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search views_en","",19983,], ["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,], -["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19982,], -["features.createroom.impl.components_SearchSingleUserResultItem_en","",19982,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19982,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19982,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19982,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19982,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19982,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19982,], -["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19982,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19982,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19982,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19982,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19982,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19982,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19982,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19982,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19982,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19982,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19982,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19982,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19982,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19982,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19982,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19982,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19982,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19982,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19982,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19982,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19982,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19982,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19982,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19982,], +["features.createroom.impl.components_SearchMultipleUsersResultItem_en","",19983,], +["features.createroom.impl.components_SearchSingleUserResultItem_en","",19983,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",19983,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",19983,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",19983,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",19983,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_0_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_0_en",19983,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_1_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_1_en",19983,], +["features.securebackup.impl.enable_SecureBackupEnableView_Day_2_en","features.securebackup.impl.enable_SecureBackupEnableView_Night_2_en",19983,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",19983,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",19983,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",19983,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",19983,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",19983,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",19983,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",19983,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",19983,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",19983,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",19983,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",19983,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",19983,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",19983,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",19983,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",19983,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",19983,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",19983,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",19983,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",19983,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",19983,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",19983,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",19983,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",19983,], ["libraries.matrix.ui.components_SelectedRoom_Day_0_en","libraries.matrix.ui.components_SelectedRoom_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoom_Day_1_en","libraries.matrix.ui.components_SelectedRoom_Night_1_en",0,], ["libraries.matrix.ui.components_SelectedUserCannotRemove_Day_0_en","libraries.matrix.ui.components_SelectedUserCannotRemove_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUser_Day_0_en","libraries.matrix.ui.components_SelectedUser_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedUsersRowList_Day_0_en","libraries.matrix.ui.components_SelectedUsersRowList_Night_0_en",0,], ["libraries.textcomposer.components_SendButton_Day_0_en","libraries.textcomposer.components_SendButton_Night_0_en",0,], -["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19982,], -["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19982,], -["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19982,], -["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19982,], -["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19982,], +["features.location.impl.send_SendLocationView_Day_0_en","features.location.impl.send_SendLocationView_Night_0_en",19983,], +["features.location.impl.send_SendLocationView_Day_1_en","features.location.impl.send_SendLocationView_Night_1_en",19983,], +["features.location.impl.send_SendLocationView_Day_2_en","features.location.impl.send_SendLocationView_Night_2_en",19983,], +["features.location.impl.send_SendLocationView_Day_3_en","features.location.impl.send_SendLocationView_Night_3_en",19983,], +["features.location.impl.send_SendLocationView_Day_4_en","features.location.impl.send_SendLocationView_Night_4_en",19983,], ["libraries.matrix.ui.messages.sender_SenderName_Day_0_en","libraries.matrix.ui.messages.sender_SenderName_Night_0_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_1_en","libraries.matrix.ui.messages.sender_SenderName_Night_1_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_2_en","libraries.matrix.ui.messages.sender_SenderName_Night_2_en",0,], @@ -882,40 +882,40 @@ export const screenshots = [ ["libraries.matrix.ui.messages.sender_SenderName_Day_6_en","libraries.matrix.ui.messages.sender_SenderName_Night_6_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_7_en","libraries.matrix.ui.messages.sender_SenderName_Night_7_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_8_en","libraries.matrix.ui.messages.sender_SenderName_Night_8_en",0,], -["features.roomlist.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_SetUpRecoveryKeyBanner_Night_0_en",19982,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19982,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19982,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19982,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19982,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19982,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19982,], +["features.roomlist.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.roomlist.impl.components_SetUpRecoveryKeyBanner_Night_0_en",19983,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",19983,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",19983,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",19983,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",19983,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",19983,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",19983,], ["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",19982,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",19983,], ["features.messages.impl.actionlist_SheetContent_Day_0_en","features.messages.impl.actionlist_SheetContent_Night_0_en",0,], ["features.messages.impl.timeline.components.reactionsummary_SheetContent_Day_0_en","features.messages.impl.timeline.components.reactionsummary_SheetContent_Night_0_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19982,], -["features.messages.impl.actionlist_SheetContent_Day_11_en","features.messages.impl.actionlist_SheetContent_Night_11_en",19982,], -["features.messages.impl.actionlist_SheetContent_Day_12_en","features.messages.impl.actionlist_SheetContent_Night_12_en",19982,], +["features.messages.impl.actionlist_SheetContent_Day_10_en","features.messages.impl.actionlist_SheetContent_Night_10_en",19983,], +["features.messages.impl.actionlist_SheetContent_Day_11_en","features.messages.impl.actionlist_SheetContent_Night_11_en",19983,], +["features.messages.impl.actionlist_SheetContent_Day_12_en","features.messages.impl.actionlist_SheetContent_Night_12_en",19983,], ["features.messages.impl.actionlist_SheetContent_Day_1_en","features.messages.impl.actionlist_SheetContent_Night_1_en",0,], -["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19982,], -["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19982,], -["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19982,], -["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19982,], -["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19982,], -["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19982,], -["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19982,], -["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19982,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19982,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19982,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19982,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19982,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19982,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19982,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19982,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19982,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19982,], +["features.messages.impl.actionlist_SheetContent_Day_2_en","features.messages.impl.actionlist_SheetContent_Night_2_en",19983,], +["features.messages.impl.actionlist_SheetContent_Day_3_en","features.messages.impl.actionlist_SheetContent_Night_3_en",19983,], +["features.messages.impl.actionlist_SheetContent_Day_4_en","features.messages.impl.actionlist_SheetContent_Night_4_en",19983,], +["features.messages.impl.actionlist_SheetContent_Day_5_en","features.messages.impl.actionlist_SheetContent_Night_5_en",19983,], +["features.messages.impl.actionlist_SheetContent_Day_6_en","features.messages.impl.actionlist_SheetContent_Night_6_en",19983,], +["features.messages.impl.actionlist_SheetContent_Day_7_en","features.messages.impl.actionlist_SheetContent_Night_7_en",19983,], +["features.messages.impl.actionlist_SheetContent_Day_8_en","features.messages.impl.actionlist_SheetContent_Night_8_en",19983,], +["features.messages.impl.actionlist_SheetContent_Day_9_en","features.messages.impl.actionlist_SheetContent_Night_9_en",19983,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",19983,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",19983,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",19983,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",19983,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",19983,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",19983,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",19983,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",19983,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",19983,], ["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,], ["libraries.designsystem.components.list_SingleSelectionListItemCustomFormattert_Single selection List item - custom formatter_List items_en","",0,], @@ -924,7 +924,7 @@ export const screenshots = [ ["libraries.designsystem.components.list_SingleSelectionListItemUnselectedWithSupportingText_Single selection List item - no selection, supporting text_List items_en","",0,], ["libraries.designsystem.components.list_SingleSelectionListItem_Single selection List item - no selection_List items_en","",0,], ["libraries.designsystem.theme.components_Sliders_Sliders_en","",0,], -["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19982,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",19983,], ["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,], @@ -934,37 +934,37 @@ export const screenshots = [ ["libraries.designsystem.modifiers_SquareSizeModifierLargeHeight_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeWidth_en","",0,], ["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",0,], -["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19982,], +["features.location.api.internal_StaticMapPlaceholder_Day_1_en","features.location.api.internal_StaticMapPlaceholder_Night_1_en",19983,], ["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",19982,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",19983,], ["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",19982,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",19983,], ["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_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19982,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19982,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19982,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19982,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19982,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19982,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19982,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19982,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19982,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19982,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19982,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19982,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19982,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19982,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19982,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19982,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19982,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19982,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",19983,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",19983,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",19983,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",19983,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",19983,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",19983,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",19983,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",19983,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",19983,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",19983,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",19983,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",19983,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",19983,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",19983,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",19983,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",19983,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",19983,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",19983,], ["libraries.textcomposer_TextComposerVoice_Day_0_en","libraries.textcomposer_TextComposerVoice_Night_0_en",0,], ["libraries.designsystem.theme.components_TextDark_Text_en","",0,], ["libraries.designsystem.theme.components_TextFieldDark_TextFields_en","",0,], @@ -976,26 +976,26 @@ export const screenshots = [ ["libraries.designsystem.theme.components_TextFieldValueTextFieldDark_TextFields_en","",0,], ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19982,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19982,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19982,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime pickers_en","",19983,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime pickers_en","",19983,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime pickers_en","",19983,], ["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",19982,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19982,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",19983,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",19983,], ["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.event_TimelineImageWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineImageWithCaptionRow_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_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19982,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",19983,], ["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",19982,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19982,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19982,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",19983,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",19983,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",19983,], ["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,], @@ -1003,16 +1003,16 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",19982,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19982,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",19983,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",19983,], ["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_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19982,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",19983,], ["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",19982,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19982,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",19983,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",19983,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en",0,], @@ -1021,36 +1021,36 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",19982,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",19983,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",19982,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",19983,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",0,], ["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","",19982,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",19983,], ["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_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19982,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19982,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",19983,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",19983,], ["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_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",19982,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",19983,], ["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",19982,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19982,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19982,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19982,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19982,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",19983,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",19983,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",19983,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",19983,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",19983,], ["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",19982,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19982,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",19983,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",19983,], ["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",19982,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",19983,], ["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,], @@ -1059,8 +1059,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",19982,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19982,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",19983,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",19983,], ["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,], @@ -1072,7 +1072,7 @@ 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",19982,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",19983,], ["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,], @@ -1094,84 +1094,84 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemVoiceView_Day_9_en","features.messages.impl.timeline.components.event_TimelineItemVoiceView_Night_9_en",0,], ["features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en",0,], -["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",19982,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19982,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",19983,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",19983,], ["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",0,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",19982,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19982,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19982,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19982,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19982,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19982,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",19982,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19982,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",19983,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",19983,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",19983,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",19983,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",19983,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",19983,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",19983,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",19983,], ["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",19982,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",19983,], ["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",19982,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",19983,], ["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",19982,], +["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",19983,], ["features.messages.impl.timeline_TimelineView_Day_9_en","features.messages.impl.timeline_TimelineView_Night_9_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",19982,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19982,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19982,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19982,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19982,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19982,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19982,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19982,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",19983,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",19983,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",19983,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",19983,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",19983,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",19983,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",19983,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",19983,], ["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",19982,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19982,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19982,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19982,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19982,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19982,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",19983,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",19983,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",19983,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",19983,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",19983,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",19983,], ["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","",19982,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",19983,], ["libraries.matrix.ui.components_UnsavedAvatar_Day_0_en","libraries.matrix.ui.components_UnsavedAvatar_Night_0_en",0,], ["libraries.designsystem.components.avatar_UserAvatarColors_Day_0_en","libraries.designsystem.components.avatar_UserAvatarColors_Night_0_en",0,], -["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19982,], -["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19982,], -["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19982,], -["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19982,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",19983,], +["features.createroom.impl.components_UserListView_Day_0_en","features.createroom.impl.components_UserListView_Night_0_en",19983,], +["features.createroom.impl.components_UserListView_Day_1_en","features.createroom.impl.components_UserListView_Night_1_en",19983,], +["features.createroom.impl.components_UserListView_Day_2_en","features.createroom.impl.components_UserListView_Night_2_en",19983,], ["features.createroom.impl.components_UserListView_Day_3_en","features.createroom.impl.components_UserListView_Night_3_en",0,], ["features.createroom.impl.components_UserListView_Day_4_en","features.createroom.impl.components_UserListView_Night_4_en",0,], ["features.createroom.impl.components_UserListView_Day_5_en","features.createroom.impl.components_UserListView_Night_5_en",0,], ["features.createroom.impl.components_UserListView_Day_6_en","features.createroom.impl.components_UserListView_Night_6_en",0,], -["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19982,], +["features.createroom.impl.components_UserListView_Day_7_en","features.createroom.impl.components_UserListView_Night_7_en",19983,], ["features.createroom.impl.components_UserListView_Day_8_en","features.createroom.impl.components_UserListView_Night_8_en",0,], -["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19982,], +["features.createroom.impl.components_UserListView_Day_9_en","features.createroom.impl.components_UserListView_Night_9_en",19983,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], ["features.preferences.impl.user_UserPreferences_Day_2_en","features.preferences.impl.user_UserPreferences_Night_2_en",0,], ["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",0,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19982,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19982,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19982,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19982,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19982,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19982,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19982,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19982,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19982,], -["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19982,], -["features.verifysession.impl_VerifySelfSessionView_Day_10_en","features.verifysession.impl_VerifySelfSessionView_Night_10_en",19982,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",19983,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",19983,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",19983,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",19983,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",19983,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",19983,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",19983,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",19983,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",19983,], +["features.verifysession.impl_VerifySelfSessionView_Day_0_en","features.verifysession.impl_VerifySelfSessionView_Night_0_en",19983,], +["features.verifysession.impl_VerifySelfSessionView_Day_10_en","features.verifysession.impl_VerifySelfSessionView_Night_10_en",19983,], ["features.verifysession.impl_VerifySelfSessionView_Day_11_en","features.verifysession.impl_VerifySelfSessionView_Night_11_en",0,], ["features.verifysession.impl_VerifySelfSessionView_Day_12_en","features.verifysession.impl_VerifySelfSessionView_Night_12_en",0,], -["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19982,], -["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19982,], -["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19982,], -["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19982,], -["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19982,], -["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19982,], -["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19982,], -["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19982,], -["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19982,], +["features.verifysession.impl_VerifySelfSessionView_Day_1_en","features.verifysession.impl_VerifySelfSessionView_Night_1_en",19983,], +["features.verifysession.impl_VerifySelfSessionView_Day_2_en","features.verifysession.impl_VerifySelfSessionView_Night_2_en",19983,], +["features.verifysession.impl_VerifySelfSessionView_Day_3_en","features.verifysession.impl_VerifySelfSessionView_Night_3_en",19983,], +["features.verifysession.impl_VerifySelfSessionView_Day_4_en","features.verifysession.impl_VerifySelfSessionView_Night_4_en",19983,], +["features.verifysession.impl_VerifySelfSessionView_Day_5_en","features.verifysession.impl_VerifySelfSessionView_Night_5_en",19983,], +["features.verifysession.impl_VerifySelfSessionView_Day_6_en","features.verifysession.impl_VerifySelfSessionView_Night_6_en",19983,], +["features.verifysession.impl_VerifySelfSessionView_Day_7_en","features.verifysession.impl_VerifySelfSessionView_Night_7_en",19983,], +["features.verifysession.impl_VerifySelfSessionView_Day_8_en","features.verifysession.impl_VerifySelfSessionView_Night_8_en",19983,], +["features.verifysession.impl_VerifySelfSessionView_Day_9_en","features.verifysession.impl_VerifySelfSessionView_Night_9_en",19983,], ["libraries.designsystem.ruler_VerticalRuler_Day_0_en","libraries.designsystem.ruler_VerticalRuler_Night_0_en",0,], ["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,], @@ -1186,6 +1186,6 @@ export const screenshots = [ ["libraries.textcomposer.components_VoiceMessageRecording_Day_0_en","libraries.textcomposer.components_VoiceMessageRecording_Night_0_en",0,], ["libraries.textcomposer.components_VoiceMessage_Day_0_en","libraries.textcomposer.components_VoiceMessage_Night_0_en",0,], ["libraries.designsystem.components.media_WaveformPlaybackView_Day_0_en","libraries.designsystem.components.media_WaveformPlaybackView_Night_0_en",0,], -["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19982,], +["features.ftue.impl.welcome_WelcomeView_Day_0_en","features.ftue.impl.welcome_WelcomeView_Night_0_en",19983,], ["libraries.designsystem.ruler_WithRulers_Day_0_en","libraries.designsystem.ruler_WithRulers_Night_0_en",0,], ]; diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Day_12_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Day_12_en.png index 362a9d5f95..aad99c4b83 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Day_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Day_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dccf918b02e10cc95f48de10ed7fbbf1d09fed2629d73ec09308a6604c02c0e3 -size 47777 +oid sha256:67210d5b8bba63c7c18013967fba0ffe92b1263733f66f26f864c6b52d73783a +size 46864 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Night_12_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Night_12_en.png index b028117445..3ec416c537 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Night_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.actionlist_SheetContent_Night_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa076d0959c240108d948841358a5f485f3ab53d470de58c9c81e6d0b32cbd43 -size 46843 +oid sha256:f3dea9d5bd54cd6342a6d243760e383e39db8998a0caa25fb3dfb0547789efbe +size 45864 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 8b48d2c346..b10cbcbcac 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:ad9fa358acfb3257129c6ad0966af876cb469bab06969bef1e56b286ce99fe8b -size 58822 +oid sha256:91368f180f0dc431efed5f4a628a700a87aa3571bd5b49747171b6cfbc6fd464 +size 56981 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 7056928a24..42a57b0ba4 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:5704cb8201901bcb0a4a3a28a21390133fe1010fb928cae94530a2900f01e336 -size 57172 +oid sha256:6d632744706c96f51c14171b74f34e1be8f97aaefcd9f8173e7b03b7b458430d +size 55532 From d700bcf71ff5603ae2bb8b4485249ca623095903 Mon Sep 17 00:00:00 2001 From: bmarty <3940906+bmarty@users.noreply.github.com> Date: Tue, 17 Sep 2024 11:44:31 +0000 Subject: [PATCH 040/106] Sync Strings from Localazy --- .../impl/src/main/res/values-de/translations.xml | 7 +++---- ...ackup.impl.disable_SecureBackupDisableView_Day_0_de.png | 4 ++-- ...ackup.impl.disable_SecureBackupDisableView_Day_1_de.png | 4 ++-- ...ackup.impl.disable_SecureBackupDisableView_Day_2_de.png | 4 ++-- ...ackup.impl.disable_SecureBackupDisableView_Day_3_de.png | 4 ++-- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/features/securebackup/impl/src/main/res/values-de/translations.xml b/features/securebackup/impl/src/main/res/values-de/translations.xml index 9589aa0534..3b95814763 100644 --- a/features/securebackup/impl/src/main/res/values-de/translations.xml +++ b/features/securebackup/impl/src/main/res/values-de/translations.xml @@ -33,10 +33,9 @@ "Ausschalten" "Du verlierst deine verschlüsselten Nachrichten, wenn du auf allen Geräten abgemeldet bist." "Bist du sicher, dass du das Backup deaktivieren willst?" - "Wenn du das Backup deaktivierst, wird dein aktuelles Backup des Verschlüsselungsschlüssels entfernt und andere Sicherheitsfunktionen werden deaktiviert. -Das bedeutet:" - "Keine Historie für verschlüsselte Nachrichten auf neuen Geräten ." - "Zugriff auf deine verschlüsselten Nachrichten verlieren, wenn du dich überall von %1$s abmeldest" + "Wenn du das Backup deaktivierst, wird dein aktuelles Schlüssel Backup für die Verschlüsselung entfernt und andere Sicherheitsfunktionen werden deaktiviert. Das bedeutet:" + "Keinen Nachrichtenverlauf für verschlüsselte Nachrichten auf neuen Geräten ." + "Verlust des Zugriffs auf Deine verschlüsselten Nachrichten, wenn Du Dich überall von %1$s abmeldest" "Bist du sicher, dass du das Backup deaktivieren willst?" "Hier kannst Du einen neuen Wiederherstellungsschlüssel erstellen. Nachdem Du einen neuen Wiederherstellungsschlüssel erstellt hast, funktioniert dein alter Schlüssel nicht mehr." "Wiederherstellungsschlüssel erstellen" diff --git a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_0_de.png b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_0_de.png index c262e144cb..e2838bdd57 100644 --- a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_0_de.png +++ b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9fb3f15ba65c5bcc785dfbac0a51202a517cd04e38526d2ff7fcc41e63f80f68 -size 70437 +oid sha256:5108d337185d1cd70063fbf34a5510a5e3d441f001f164f61042bbd2fbe93e1f +size 72102 diff --git a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_1_de.png b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_1_de.png index dd41236040..dfb1308cdd 100644 --- a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_1_de.png +++ b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ba76ed706efff9b4dd95dac0cdd8c6034fa6265cbf18cc8a52bca3d10111e49 -size 53634 +oid sha256:857e94824a054038e372ddfc47b64e3132f1ea9d35da6de8f371c7a5ce67fef5 +size 54421 diff --git a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_2_de.png b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_2_de.png index 87bd3bbed3..e64607ce87 100644 --- a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_2_de.png +++ b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ff2ad4d9b49356877cf58160ffdca4867fe4aeaab74ac768760461649badd40 -size 70938 +oid sha256:7fa5a407d658c99463e30074041a643d6e826427b5171061e345af5419f9bbbf +size 72612 diff --git a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png index 33662ae687..69f9af3f5c 100644 --- a/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png +++ b/screenshots/de/features.securebackup.impl.disable_SecureBackupDisableView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57f314de86936d227316399b4d873b6d0cf72aa763b8eea3048c7580777301aa -size 41346 +oid sha256:770cb9396ba855398d65d18e7794c771b8cfc26aa73a7dcb04b49ac3bacd63ac +size 41944 From 8a655de6913bda8b3c76cb3a7f332a51e15d8061 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 14:00:36 +0200 Subject: [PATCH 041/106] Adding fastlane file for version 0.6.1 --- fastlane/metadata/android/en-US/changelogs/40006010.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/40006010.txt diff --git a/fastlane/metadata/android/en-US/changelogs/40006010.txt b/fastlane/metadata/android/en-US/changelogs/40006010.txt new file mode 100644 index 0000000000..0574894881 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40006010.txt @@ -0,0 +1,2 @@ +Element X is the new generation of Element for professional and personal use on mobile. It’s the fastest Matrix client with a seamless & intuitive user interface. +Full changelog: https://github.com/element-hq/element-x-android/releases From fe5c08108e68121bee2025f833f5f715de8078a7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 14:02:39 +0200 Subject: [PATCH 042/106] version++ --- plugins/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index 0ea95396de..c2e6f2d5c3 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -47,7 +47,7 @@ private const val versionMinor = 6 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -private const val versionPatch = 1 +private const val versionPatch = 2 object Versions { val versionCode = 4_000_000 + versionMajor * 1_00_00 + versionMinor * 1_00 + versionPatch From b94a5c9c516ebd952b836064650e5c953d76f083 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 14:36:12 +0200 Subject: [PATCH 043/106] Changelog for version 0.6.1 --- CHANGES.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 0cd6932883..e4215c9fda 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,29 @@ +Changes in Element X v0.6.1 (2024-09-17) +======================================== + +### ✨ Features +* Add forced logout flow when the proxy is no longer available by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3458 +* Temporary account creation using Element Web. by @bmarty in https://github.com/element-hq/element-x-android/pull/3467 + +### 🙌 Improvements +* Feature/valere/invisible crypto feature flag by @BillCarsonFr in https://github.com/element-hq/element-x-android/pull/3451 +* Require acknowledgement to send to a verified user if their identity changed or if a device is unverified. by @ganfra in https://github.com/element-hq/element-x-android/pull/3461 +* Update pinned message actions by @ganfra in https://github.com/element-hq/element-x-android/pull/3438 + +### 🐛 Bugfixes +* Fix events blinking at the beginning of DM by @bmarty in https://github.com/element-hq/element-x-android/pull/3449 +* Fix not being able to decline an invite from the room list by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3466 + +### 🗣 Translations +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/3464 +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/3469 +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/3476 +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/3477 + +### Others +* Upgrade Rust sdk to 0.2.45 by @bmarty in https://github.com/element-hq/element-x-android/pull/3472 +* SDK 0.2.46 by @bmarty in https://github.com/element-hq/element-x-android/pull/3475 + Changes in Element X v0.6.0 (2024-09-12) ======================================== From cbb5e0ffed3be44d5b6047ca4a2e92779979fc8c Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 17 Sep 2024 16:17:08 +0200 Subject: [PATCH 044/106] Resolve send failure verification : fix crash when dismissing. --- .../resolve/ResolveVerifiedUserSendFailureView.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt index 4c1d40cc87..e0d964fa51 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt @@ -118,7 +118,7 @@ private fun VerifiedUserSendFailure.title(): String { id = CommonStrings.screen_resolve_send_failure_changed_identity_title, userDisplayName ) - VerifiedUserSendFailure.None -> error("This method should never be called for this state") + VerifiedUserSendFailure.None -> "" } } @@ -134,7 +134,7 @@ private fun VerifiedUserSendFailure.subtitle(): String { id = CommonStrings.screen_resolve_send_failure_changed_identity_subtitle, userDisplayName ) - VerifiedUserSendFailure.None -> error("This method should never be called for this state") + VerifiedUserSendFailure.None -> "" } } @@ -143,7 +143,7 @@ private fun VerifiedUserSendFailure.resolveAction(): String { return when (this) { is VerifiedUserSendFailure.UnsignedDevice -> stringResource(id = CommonStrings.screen_resolve_send_failure_unsigned_device_primary_button_title) is VerifiedUserSendFailure.ChangedIdentity -> stringResource(id = CommonStrings.screen_resolve_send_failure_changed_identity_primary_button_title) - VerifiedUserSendFailure.None -> error("This method should never be called for this state") + VerifiedUserSendFailure.None -> "" } } From b87bec622894f7c02438e17a595eb9e82ae2348c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 13:19:46 +0200 Subject: [PATCH 045/106] Account deactivation. --- features/deactivation/api/build.gradle.kts | 17 + .../api/AccountDeactivationEntryPoint.kt | 12 + features/deactivation/impl/build.gradle.kts | 49 +++ .../logout/impl/AccountDeactivationEvents.kt | 15 + .../logout/impl/AccountDeactivationNode.kt | 35 ++ .../impl/AccountDeactivationPresenter.kt | 84 +++++ .../logout/impl/AccountDeactivationState.kt | 32 ++ .../impl/AccountDeactivationStateProvider.kt | 52 +++ .../logout/impl/AccountDeactivationView.kt | 324 ++++++++++++++++++ .../DefaultAccountDeactivationEntryPoint.kt | 23 ++ .../ui/AccountDeactivationActionDialog.kt | 43 +++ .../AccountDeactivationConfirmationDialog.kt | 29 ++ .../impl/src/main/res/values/localazy.xml | 12 + .../impl/AccountDeactivationPresenterTest.kt | 157 +++++++++ .../impl/AccountDeactivationViewTest.kt | 52 +++ features/preferences/impl/build.gradle.kts | 1 + .../preferences/impl/PreferencesFlowNode.kt | 12 + .../impl/root/PreferencesRootNode.kt | 6 + .../impl/root/PreferencesRootPresenter.kt | 8 + .../impl/root/PreferencesRootState.kt | 1 + .../impl/root/PreferencesRootStateProvider.kt | 1 + .../impl/root/PreferencesRootView.kt | 12 + .../impl/root/PreferencesRootPresenterTest.kt | 34 +- .../atomic/organisms/InfoListOrganism.kt | 3 +- .../libraries/matrix/api/MatrixClient.kt | 3 + .../libraries/matrix/impl/RustMatrixClient.kt | 43 +++ .../libraries/matrix/test/FakeMatrixClient.kt | 8 + .../src/main/res/values/localazy.xml | 6 + tools/localazy/config.json | 6 + 29 files changed, 1071 insertions(+), 9 deletions(-) create mode 100644 features/deactivation/api/build.gradle.kts create mode 100644 features/deactivation/api/src/main/kotlin/io/element/android/features/deactivation/api/AccountDeactivationEntryPoint.kt create mode 100644 features/deactivation/impl/build.gradle.kts create mode 100644 features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationEvents.kt create mode 100644 features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationNode.kt create mode 100644 features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenter.kt create mode 100644 features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationState.kt create mode 100644 features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationStateProvider.kt create mode 100644 features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt create mode 100644 features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPoint.kt create mode 100644 features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/AccountDeactivationActionDialog.kt create mode 100644 features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/AccountDeactivationConfirmationDialog.kt create mode 100644 features/deactivation/impl/src/main/res/values/localazy.xml create mode 100644 features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt create mode 100644 features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt diff --git a/features/deactivation/api/build.gradle.kts b/features/deactivation/api/build.gradle.kts new file mode 100644 index 0000000000..25d59790e5 --- /dev/null +++ b/features/deactivation/api/build.gradle.kts @@ -0,0 +1,17 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ +plugins { + id("io.element.android-compose-library") +} + +android { + namespace = "io.element.android.features.deactivation.api" +} + +dependencies { + implementation(projects.libraries.architecture) +} diff --git a/features/deactivation/api/src/main/kotlin/io/element/android/features/deactivation/api/AccountDeactivationEntryPoint.kt b/features/deactivation/api/src/main/kotlin/io/element/android/features/deactivation/api/AccountDeactivationEntryPoint.kt new file mode 100644 index 0000000000..5865f1a2b8 --- /dev/null +++ b/features/deactivation/api/src/main/kotlin/io/element/android/features/deactivation/api/AccountDeactivationEntryPoint.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.deactivation.api + +import io.element.android.libraries.architecture.SimpleFeatureEntryPoint + +interface AccountDeactivationEntryPoint : SimpleFeatureEntryPoint diff --git a/features/deactivation/impl/build.gradle.kts b/features/deactivation/impl/build.gradle.kts new file mode 100644 index 0000000000..6e19a485d4 --- /dev/null +++ b/features/deactivation/impl/build.gradle.kts @@ -0,0 +1,49 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +plugins { + id("io.element.android-compose-library") + alias(libs.plugins.anvil) + id("kotlin-parcelize") +} + +android { + namespace = "io.element.android.features.deactivation.impl" + + testOptions { + unitTests { + isIncludeAndroidResources = true + } + } +} + +anvil { + generateDaggerFactories.set(true) +} + +dependencies { + implementation(projects.anvilannotations) + anvil(projects.anvilcodegen) + implementation(projects.libraries.androidutils) + implementation(projects.libraries.core) + implementation(projects.libraries.architecture) + implementation(projects.libraries.matrix.api) + implementation(projects.libraries.designsystem) + implementation(projects.libraries.uiStrings) + api(projects.features.deactivation.api) + + testImplementation(libs.test.junit) + testImplementation(libs.coroutines.test) + testImplementation(libs.molecule.runtime) + testImplementation(libs.test.truth) + testImplementation(libs.test.turbine) + testImplementation(libs.test.robolectric) + testImplementation(libs.androidx.compose.ui.test.junit) + testReleaseImplementation(libs.androidx.compose.ui.test.manifest) + testImplementation(projects.libraries.matrix.test) + testImplementation(projects.tests.testutils) +} diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationEvents.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationEvents.kt new file mode 100644 index 0000000000..35be3f4bf2 --- /dev/null +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationEvents.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.logout.impl + +sealed interface AccountDeactivationEvents { + data class SetEraseData(val eraseData: Boolean) : AccountDeactivationEvents + data class SetPassword(val password: String) : AccountDeactivationEvents + data class DeactivateAccount(val isRetry: Boolean) : AccountDeactivationEvents + data object CloseDialogs : AccountDeactivationEvents +} diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationNode.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationNode.kt new file mode 100644 index 0000000000..0faad3ad20 --- /dev/null +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationNode.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.logout.impl + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.di.SessionScope + +@ContributesNode(SessionScope::class) +class AccountDeactivationNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenter: AccountDeactivationPresenter, +) : Node(buildContext, plugins = plugins) { + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + AccountDeactivationView( + state = state, + onBackClick = ::navigateUp, + modifier = modifier, + ) + } +} diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenter.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenter.kt new file mode 100644 index 0000000000..8f0e895524 --- /dev/null +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenter.kt @@ -0,0 +1,84 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.logout.impl + +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 io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.architecture.runCatchingUpdatingState +import io.element.android.libraries.matrix.api.MatrixClient +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import javax.inject.Inject + +class AccountDeactivationPresenter @Inject constructor( + private val matrixClient: MatrixClient, +) : Presenter { + @Composable + override fun present(): AccountDeactivationState { + val localCoroutineScope = rememberCoroutineScope() + val action: MutableState> = remember { + mutableStateOf(AsyncAction.Uninitialized) + } + + val formState = remember { mutableStateOf(DeactivateFormState.Default) } + + fun handleEvents(event: AccountDeactivationEvents) { + when (event) { + is AccountDeactivationEvents.SetEraseData -> { + updateFormState(formState) { + copy(eraseData = event.eraseData) + } + } + is AccountDeactivationEvents.SetPassword -> { + updateFormState(formState) { + copy(password = event.password) + } + } + is AccountDeactivationEvents.DeactivateAccount -> + if (action.value.isConfirming() || event.isRetry) { + localCoroutineScope.deactivateAccount( + formState = formState.value, + action + ) + } else { + action.value = AsyncAction.Confirming + } + AccountDeactivationEvents.CloseDialogs -> { + action.value = AsyncAction.Uninitialized + } + } + } + + return AccountDeactivationState( + deactivateFormState = formState.value, + accountDeactivationAction = action.value, + eventSink = ::handleEvents + ) + } + + private fun updateFormState(formState: MutableState, updateLambda: DeactivateFormState.() -> DeactivateFormState) { + formState.value = updateLambda(formState.value) + } + + private fun CoroutineScope.deactivateAccount( + formState: DeactivateFormState, + action: MutableState>, + ) = launch { + suspend { + matrixClient.deactivateAccount( + password = formState.password, + eraseData = formState.eraseData, + ).getOrThrow() + }.runCatchingUpdatingState(action) + } +} diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationState.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationState.kt new file mode 100644 index 0000000000..5504c3b0bf --- /dev/null +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationState.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.logout.impl + +import android.os.Parcelable +import io.element.android.libraries.architecture.AsyncAction +import kotlinx.parcelize.Parcelize + +data class AccountDeactivationState( + val deactivateFormState: DeactivateFormState, + val accountDeactivationAction: AsyncAction, + val eventSink: (AccountDeactivationEvents) -> Unit, +) { + val submitEnabled: Boolean + get() = accountDeactivationAction is AsyncAction.Uninitialized && + deactivateFormState.password.isNotEmpty() +} + +@Parcelize +data class DeactivateFormState( + val eraseData: Boolean, + val password: String +) : Parcelable { + companion object { + val Default = DeactivateFormState(false, "") + } +} diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationStateProvider.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationStateProvider.kt new file mode 100644 index 0000000000..07ef6590bb --- /dev/null +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationStateProvider.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.logout.impl + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.architecture.AsyncAction + +open class AccountDeactivationStateProvider : PreviewParameterProvider { + private val filledForm = aDeactivateFormState(eraseData = true, password = "password") + override val values: Sequence + get() = sequenceOf( + anAccountDeactivationState(), + anAccountDeactivationState( + deactivateFormState = filledForm + ), + anAccountDeactivationState( + deactivateFormState = filledForm, + accountDeactivationAction = AsyncAction.Confirming, + ), + anAccountDeactivationState( + deactivateFormState = filledForm, + accountDeactivationAction = AsyncAction.Loading + ), + anAccountDeactivationState( + deactivateFormState = filledForm, + accountDeactivationAction = AsyncAction.Failure(Exception("Failed to deactivate account")) + ), + ) +} + +internal fun aDeactivateFormState( + eraseData: Boolean = false, + password: String = "", +) = DeactivateFormState( + eraseData = eraseData, + password = password, +) + +internal fun anAccountDeactivationState( + deactivateFormState: DeactivateFormState = aDeactivateFormState(), + accountDeactivationAction: AsyncAction = AsyncAction.Uninitialized, + eventSink: (AccountDeactivationEvents) -> Unit = {}, +) = AccountDeactivationState( + deactivateFormState = deactivateFormState, + accountDeactivationAction = accountDeactivationAction, + eventSink = eventSink, +) diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt new file mode 100644 index 0000000000..c46461580b --- /dev/null +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt @@ -0,0 +1,324 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +@file:OptIn(ExperimentalComposeUiApi::class) + +package io.element.android.features.logout.impl + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.autofill.AutofillType +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.VisualTransformation +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.deactivation.impl.R +import io.element.android.features.logout.impl.ui.AccountDeactivationActionDialog +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.designsystem.atomic.organisms.InfoListItem +import io.element.android.libraries.designsystem.atomic.organisms.InfoListOrganism +import io.element.android.libraries.designsystem.components.button.BackButton +import io.element.android.libraries.designsystem.components.form.textFieldState +import io.element.android.libraries.designsystem.components.list.SwitchListItem +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.aliasScreenTitle +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.OutlinedTextField +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.theme.components.autofill +import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext +import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.persistentListOf + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AccountDeactivationView( + state: AccountDeactivationState, + onBackClick: () -> Unit, + modifier: Modifier = Modifier, +) { + val eventSink = state.eventSink + + Scaffold( + modifier = modifier, + topBar = { + TopAppBar( + navigationIcon = { + BackButton(onClick = onBackClick) + }, + title = { + Text( + text = stringResource(R.string.screen_deactivate_account_title), + style = ElementTheme.typography.aliasScreenTitle, + ) + }, + ) + }, + ) { padding -> + val scrollState = rememberScrollState() + Column( + modifier = Modifier + .imePadding() + .padding(padding) + .consumeWindowInsets(padding) + .verticalScroll(state = scrollState) + .padding(vertical = 16.dp, horizontal = 20.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { + Content( + state = state, + onSubmitClick = { + eventSink(AccountDeactivationEvents.DeactivateAccount(isRetry = false)) + } + ) + Spacer(modifier = Modifier.height(32.dp)) + Buttons( + state = state, + onSubmitClick = { + eventSink(AccountDeactivationEvents.DeactivateAccount(isRetry = false)) + } + ) + } + } + AccountDeactivationActionDialog( + state.accountDeactivationAction, + onConfirmClick = { + eventSink(AccountDeactivationEvents.DeactivateAccount(isRetry = false)) + }, + onRetryClick = { + eventSink(AccountDeactivationEvents.DeactivateAccount(isRetry = true)) + }, + onDismissDialog = { + eventSink(AccountDeactivationEvents.CloseDialogs) + }, + ) +} + +@Composable +private fun ColumnScope.Buttons( + state: AccountDeactivationState, + onSubmitClick: () -> Unit, +) { + val logoutAction = state.accountDeactivationAction + Button( + text = stringResource(CommonStrings.action_deactivate), + showProgress = logoutAction is AsyncAction.Loading, + destructive = true, + enabled = state.submitEnabled, + modifier = Modifier.fillMaxWidth(), + onClick = onSubmitClick, + ) +} + +@Composable +private fun Content( + state: AccountDeactivationState, + onSubmitClick: () -> Unit, +) { + val isLoading by remember(state.deactivateFormState) { + derivedStateOf { + state.accountDeactivationAction is AsyncAction.Loading + } + } + val eraseData = state.deactivateFormState.eraseData + var passwordFieldState by textFieldState(stateValue = state.deactivateFormState.password) + + val focusManager = LocalFocusManager.current + val eventSink = state.eventSink + + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { + Text( + text = stringResource(R.string.screen_deactivate_account_description), + style = ElementTheme.typography.fontBodyMdRegular, + color = ElementTheme.colors.textSecondary, + ) + InfoListOrganism( + items = persistentListOf( + InfoListItem( + message = stringResource(R.string.screen_deactivate_account_list_item_1), + iconComposable = { + Icon( + modifier = Modifier.size(20.dp), + imageVector = CompoundIcons.Close(), + contentDescription = null, + tint = ElementTheme.colors.iconCriticalPrimary, + ) + }, + iconVector = CompoundIcons.Close(), + ), + InfoListItem( + message = stringResource(R.string.screen_deactivate_account_list_item_2), + iconComposable = { + Icon( + modifier = Modifier.size(20.dp), + imageVector = CompoundIcons.Close(), + contentDescription = null, + tint = ElementTheme.colors.iconCriticalPrimary, + ) + }, + ), + InfoListItem( + message = stringResource(R.string.screen_deactivate_account_list_item_3), + iconComposable = { + Icon( + modifier = Modifier.size(20.dp), + imageVector = CompoundIcons.Close(), + contentDescription = null, + tint = ElementTheme.colors.iconCriticalPrimary, + ) + }, + ), + InfoListItem( + message = stringResource(R.string.screen_deactivate_account_list_item_4), + iconComposable = { + Icon( + modifier = Modifier.size(20.dp), + imageVector = CompoundIcons.Check(), + contentDescription = null, + tint = ElementTheme.colors.iconSuccessPrimary, + ) + }, + ), + ), + textStyle = ElementTheme.typography.fontBodyMdRegular, + textColor = ElementTheme.colors.textSecondary, + iconTint = ElementTheme.colors.iconSuccessPrimary, + backgroundColor = Color.Transparent, + ) + + Column { + SwitchListItem( + headline = stringResource(R.string.screen_deactivate_account_delete_all_messages), + value = eraseData, + onChange = { + eventSink(AccountDeactivationEvents.SetEraseData(it)) + }, + enabled = !isLoading, + ) + Text( + modifier = Modifier.padding(start = 16.dp), + text = stringResource(R.string.screen_deactivate_account_delete_all_messages_notice), + style = ElementTheme.typography.fontBodySmRegular, + color = ElementTheme.colors.textSecondary, + ) + } + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp), + ) { + Text( + text = stringResource(CommonStrings.action_confirm_password), + style = ElementTheme.typography.fontBodySmMedium, + color = ElementTheme.colors.textSecondary, + ) + var passwordVisible by remember { mutableStateOf(false) } + if (isLoading) { + // Ensure password is hidden when user submits the form + passwordVisible = false + } + OutlinedTextField( + value = passwordFieldState, + readOnly = isLoading, + modifier = Modifier + .padding(top = 8.dp) + .fillMaxWidth() + .onTabOrEnterKeyFocusNext(focusManager) + .autofill( + autofillTypes = listOf(AutofillType.Password), + onFill = { + val sanitized = it.sanitize() + passwordFieldState = sanitized + eventSink(AccountDeactivationEvents.SetPassword(sanitized)) + } + ), + onValueChange = { + val sanitized = it.sanitize() + passwordFieldState = sanitized + eventSink(AccountDeactivationEvents.SetPassword(sanitized)) + }, + placeholder = { + Text(text = stringResource(CommonStrings.common_password)) + }, + visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), + trailingIcon = { + val image = + if (passwordVisible) CompoundIcons.VisibilityOn() else CompoundIcons.VisibilityOff() + val description = + if (passwordVisible) stringResource(CommonStrings.a11y_hide_password) else stringResource(CommonStrings.a11y_show_password) + + IconButton(onClick = { passwordVisible = !passwordVisible }) { + Icon(imageVector = image, description) + } + }, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Password, + imeAction = ImeAction.Done, + ), + keyboardActions = KeyboardActions( + onDone = { onSubmitClick() } + ), + singleLine = true, + ) + } + } +} + +/** + * Ensure that the string does not contain any new line characters, which can happen when pasting values. + */ +private fun String.sanitize(): String { + return replace("\n", "") +} + +@PreviewsDayNight +@Composable +internal fun AccountDeactivationViewPreview( + @PreviewParameter(AccountDeactivationStateProvider::class) state: AccountDeactivationState, +) = ElementPreview { + AccountDeactivationView( + state, + onBackClick = {}, + ) +} diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPoint.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPoint.kt new file mode 100644 index 0000000000..dd9197684c --- /dev/null +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPoint.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.logout.impl + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.deactivation.api.AccountDeactivationEntryPoint +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.AppScope +import javax.inject.Inject + +@ContributesBinding(AppScope::class) +class DefaultAccountDeactivationEntryPoint @Inject constructor() : AccountDeactivationEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext): Node { + return parentNode.createNode(buildContext) + } +} diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/AccountDeactivationActionDialog.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/AccountDeactivationActionDialog.kt new file mode 100644 index 0000000000..8fcd9557cf --- /dev/null +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/AccountDeactivationActionDialog.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.logout.impl.ui + +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.designsystem.components.ProgressDialog +import io.element.android.libraries.designsystem.components.dialogs.RetryDialog +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun AccountDeactivationActionDialog( + state: AsyncAction, + onConfirmClick: () -> Unit, + onRetryClick: () -> Unit, + onDismissDialog: () -> Unit, +) { + when (state) { + AsyncAction.Uninitialized -> + Unit + AsyncAction.Confirming -> + AccountDeactivationConfirmationDialog( + onSubmitClick = onConfirmClick, + onDismiss = onDismissDialog + ) + is AsyncAction.Loading -> + ProgressDialog(text = stringResource(CommonStrings.common_please_wait)) + is AsyncAction.Failure -> + RetryDialog( + title = stringResource(id = CommonStrings.dialog_title_error), + content = stringResource(id = CommonStrings.error_unknown), + onRetry = onRetryClick, + onDismiss = onDismissDialog, + ) + is AsyncAction.Success -> Unit + } +} diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/AccountDeactivationConfirmationDialog.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/AccountDeactivationConfirmationDialog.kt new file mode 100644 index 0000000000..18a79c8ed5 --- /dev/null +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/ui/AccountDeactivationConfirmationDialog.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.logout.impl.ui + +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import io.element.android.features.deactivation.impl.R +import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun AccountDeactivationConfirmationDialog( + onSubmitClick: () -> Unit, + onDismiss: () -> Unit, +) { + ConfirmationDialog( + title = stringResource(id = R.string.screen_deactivate_account_title), + content = stringResource(R.string.screen_deactivate_account_confirmation_dialog_content), + submitText = stringResource(id = CommonStrings.action_deactivate), + onSubmitClick = onSubmitClick, + onDismiss = onDismiss, + destructiveSubmit = true, + ) +} diff --git a/features/deactivation/impl/src/main/res/values/localazy.xml b/features/deactivation/impl/src/main/res/values/localazy.xml new file mode 100644 index 0000000000..5088a41c61 --- /dev/null +++ b/features/deactivation/impl/src/main/res/values/localazy.xml @@ -0,0 +1,12 @@ + + + "Please confirm that you want to deactivate your account. This action cannot be undone." + "Delete all my messages" + "Warning: Future users may see incomplete conversations." + "Deactivating your account is irreversible, it will:" + "Permanently disable your account (you can\'t log back in, and your ID can\'t be reused)." + "Remove you from all chat rooms." + "Delete your account information from our identity server." + "Your messages will still be visible to registered users but won’t be available to new or unregistered users if you choose to delete them." + "Account deactivation" + diff --git a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt new file mode 100644 index 0000000000..b34ac2f391 --- /dev/null +++ b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt @@ -0,0 +1,157 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.logout.impl + +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.matrix.api.MatrixClient +import io.element.android.libraries.matrix.test.AN_EXCEPTION +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.lambda.value +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test + +class AccountDeactivationPresenterTest { + @get:Rule + val warmUpRule = WarmUpRule() + + @Test + fun `present - initial state`() = runTest { + val presenter = createPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.accountDeactivationAction).isEqualTo(AsyncAction.Uninitialized) + assertThat(initialState.deactivateFormState).isEqualTo(DeactivateFormState.Default) + } + } + + @Test + fun `present - form update`() = runTest { + val presenter = createPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + assertThat(initialState.deactivateFormState).isEqualTo(DeactivateFormState.Default) + initialState.eventSink(AccountDeactivationEvents.SetEraseData(true)) + val updatedState = awaitItem() + assertThat(updatedState.deactivateFormState).isEqualTo(DeactivateFormState.Default.copy(eraseData = true)) + assertThat(updatedState.submitEnabled).isFalse() + updatedState.eventSink(AccountDeactivationEvents.SetPassword("password")) + val updatedState2 = awaitItem() + assertThat(updatedState2.deactivateFormState).isEqualTo(DeactivateFormState(password = "password", eraseData = true)) + assertThat(updatedState2.submitEnabled).isTrue() + } + } + + @Test + fun `present - submit`() = runTest { + val recorder = lambdaRecorder> { _, _ -> + Result.success(Unit) + } + val matrixClient = FakeMatrixClient( + deactivateAccountResult = recorder + ) + val presenter = createPresenter(matrixClient) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(AccountDeactivationEvents.SetPassword("password")) + skipItems(1) + initialState.eventSink(AccountDeactivationEvents.DeactivateAccount(isRetry = false)) + val updatedState = awaitItem() + assertThat(updatedState.accountDeactivationAction).isEqualTo(AsyncAction.Confirming) + updatedState.eventSink(AccountDeactivationEvents.DeactivateAccount(isRetry = false)) + val updatedState2 = awaitItem() + assertThat(updatedState2.accountDeactivationAction).isEqualTo(AsyncAction.Loading) + val finalState = awaitItem() + assertThat(finalState.accountDeactivationAction).isEqualTo(AsyncAction.Success(Unit)) + recorder.assertions().isCalledOnce().with(value("password"), value(false)) + } + } + + @Test + fun `present - submit with error and retry`() = runTest { + val recorder = lambdaRecorder> { _, _ -> + Result.failure(AN_EXCEPTION) + } + val matrixClient = FakeMatrixClient( + deactivateAccountResult = recorder + ) + val presenter = createPresenter(matrixClient) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(AccountDeactivationEvents.SetPassword("password")) + initialState.eventSink(AccountDeactivationEvents.SetEraseData(true)) + skipItems(2) + initialState.eventSink(AccountDeactivationEvents.DeactivateAccount(isRetry = false)) + val updatedState = awaitItem() + assertThat(updatedState.accountDeactivationAction).isEqualTo(AsyncAction.Confirming) + updatedState.eventSink(AccountDeactivationEvents.DeactivateAccount(isRetry = false)) + val updatedState2 = awaitItem() + assertThat(updatedState2.accountDeactivationAction).isEqualTo(AsyncAction.Loading) + val finalState = awaitItem() + assertThat(finalState.accountDeactivationAction).isEqualTo(AsyncAction.Failure(AN_EXCEPTION)) + recorder.assertions().isCalledOnce().with(value("password"), value(true)) + // Retry + finalState.eventSink(AccountDeactivationEvents.DeactivateAccount(isRetry = true)) + val finalState2 = awaitItem() + assertThat(finalState2.accountDeactivationAction).isEqualTo(AsyncAction.Loading) + assertThat(awaitItem().accountDeactivationAction).isEqualTo(AsyncAction.Failure(AN_EXCEPTION)) + } + } + + @Test + fun `present - submit with error and cancel`() = runTest { + val recorder = lambdaRecorder> { _, _ -> + Result.failure(AN_EXCEPTION) + } + val matrixClient = FakeMatrixClient( + deactivateAccountResult = recorder + ) + val presenter = createPresenter(matrixClient) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val initialState = awaitItem() + initialState.eventSink(AccountDeactivationEvents.SetPassword("password")) + initialState.eventSink(AccountDeactivationEvents.SetEraseData(true)) + skipItems(2) + initialState.eventSink(AccountDeactivationEvents.DeactivateAccount(isRetry = false)) + val updatedState = awaitItem() + assertThat(updatedState.accountDeactivationAction).isEqualTo(AsyncAction.Confirming) + updatedState.eventSink(AccountDeactivationEvents.DeactivateAccount(isRetry = false)) + val updatedState2 = awaitItem() + assertThat(updatedState2.accountDeactivationAction).isEqualTo(AsyncAction.Loading) + val finalState = awaitItem() + assertThat(finalState.accountDeactivationAction).isEqualTo(AsyncAction.Failure(AN_EXCEPTION)) + recorder.assertions().isCalledOnce().with(value("password"), value(true)) + // Cancel + finalState.eventSink(AccountDeactivationEvents.CloseDialogs) + val finalState2 = awaitItem() + assertThat(finalState2.accountDeactivationAction).isEqualTo(AsyncAction.Uninitialized) + } + } + + private fun createPresenter( + matrixClient: MatrixClient = FakeMatrixClient(), + ) = AccountDeactivationPresenter( + matrixClient = matrixClient, + ) +} diff --git a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt new file mode 100644 index 0000000000..97a1b34751 --- /dev/null +++ b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.features.logout.impl + +import androidx.activity.ComponentActivity +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.tests.testutils.EnsureNeverCalled +import io.element.android.tests.testutils.EventsRecorder +import io.element.android.tests.testutils.ensureCalledOnce +import io.element.android.tests.testutils.pressBack +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TestRule +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class AccountDeactivationViewTest { + @get:Rule val rule = createAndroidComposeRule() + + @Test + fun `clicking on back invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { + rule.setAccountDeactivationView( + state = anAccountDeactivationState(eventSink = eventsRecorder), + onBackClick = it, + ) + rule.pressBack() + } + } + + // TODO Add more tests +} + +private fun AndroidComposeTestRule.setAccountDeactivationView( + state: AccountDeactivationState, + onBackClick: () -> Unit = EnsureNeverCalled(), +) { + setContent { + AccountDeactivationView( + state = state, + onBackClick = onBackClick, + ) + } +} diff --git a/features/preferences/impl/build.gradle.kts b/features/preferences/impl/build.gradle.kts index a75b920b16..44a792a625 100644 --- a/features/preferences/impl/build.gradle.kts +++ b/features/preferences/impl/build.gradle.kts @@ -55,6 +55,7 @@ dependencies { implementation(projects.features.ftue.api) implementation(projects.features.licenses.api) implementation(projects.features.logout.api) + implementation(projects.features.deactivation.api) implementation(projects.features.roomlist.api) implementation(projects.services.analytics.api) implementation(projects.services.toolbox.api) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt index ad3673bc0e..9a4c5d490e 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt @@ -20,6 +20,7 @@ import com.bumble.appyx.navmodel.backstack.operation.push import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode +import io.element.android.features.deactivation.api.AccountDeactivationEntryPoint import io.element.android.features.licenses.api.OpenSourceLicensesEntryPoint import io.element.android.features.lockscreen.api.LockScreenEntryPoint import io.element.android.features.logout.api.LogoutEntryPoint @@ -52,6 +53,7 @@ class PreferencesFlowNode @AssistedInject constructor( private val notificationTroubleShootEntryPoint: NotificationTroubleShootEntryPoint, private val logoutEntryPoint: LogoutEntryPoint, private val openSourceLicensesEntryPoint: OpenSourceLicensesEntryPoint, + private val accountDeactivationEntryPoint: AccountDeactivationEntryPoint, ) : BaseFlowNode( backstack = BackStack( initialElement = plugins.filterIsInstance().first().initialElement.toNavTarget(), @@ -100,6 +102,9 @@ class PreferencesFlowNode @AssistedInject constructor( @Parcelize data object SignOut : NavTarget + @Parcelize + data object AccountDeactivation : NavTarget + @Parcelize data object OssLicenses : NavTarget } @@ -151,6 +156,10 @@ class PreferencesFlowNode @AssistedInject constructor( override fun onSignOutClick() { backstack.push(NavTarget.SignOut) } + + override fun onOpenAccountDeactivation() { + backstack.push(NavTarget.AccountDeactivation) + } } createNode(buildContext, plugins = listOf(callback)) } @@ -236,6 +245,9 @@ class PreferencesFlowNode @AssistedInject constructor( is NavTarget.OssLicenses -> { openSourceLicensesEntryPoint.getNode(this, buildContext) } + NavTarget.AccountDeactivation -> { + accountDeactivationEntryPoint.createNode(this, buildContext) + } } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt index 266fddbca0..9dfa53f4e6 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootNode.kt @@ -45,6 +45,7 @@ class PreferencesRootNode @AssistedInject constructor( fun onOpenUserProfile(matrixUser: MatrixUser) fun onOpenBlockedUsers() fun onSignOutClick() + fun onOpenAccountDeactivation() } private fun onOpenBugReport() { @@ -105,6 +106,10 @@ class PreferencesRootNode @AssistedInject constructor( plugins().forEach { it.onSignOutClick() } } + private fun onOpenAccountDeactivation() { + plugins().forEach { it.onOpenAccountDeactivation() } + } + @Composable override fun View(modifier: Modifier) { val state = presenter.present() @@ -132,6 +137,7 @@ class PreferencesRootNode @AssistedInject constructor( onSignOutClick() } }, + onDeactivateClick = this::onOpenAccountDeactivation ) directLogoutView.Render( 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 500570412d..f1507c45f4 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 @@ -15,6 +15,7 @@ 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 io.element.android.features.logout.api.direct.DirectLogoutPresenter import io.element.android.features.preferences.impl.utils.ShowDeveloperSettingsProvider import io.element.android.libraries.architecture.Presenter @@ -75,6 +76,12 @@ class PreferencesRootPresenter @Inject constructor( val devicesManagementUrl: MutableState = remember { mutableStateOf(null) } + var canDeactivateAccount by remember { + mutableStateOf(false) + } + LaunchedEffect(Unit) { + canDeactivateAccount = matrixClient.canDeactivateAccount() + } val showBlockedUsersItem by produceState(initialValue = false) { matrixClient.ignoredUsersFlow @@ -108,6 +115,7 @@ class PreferencesRootPresenter @Inject constructor( devicesManagementUrl = devicesManagementUrl.value, showAnalyticsSettings = hasAnalyticsProviders, showDeveloperSettings = showDeveloperSettings, + canDeactivateAccount = canDeactivateAccount, showNotificationSettings = showNotificationSettings.value, showLockScreenSettings = showLockScreenSettings.value, showBlockedUsersItem = showBlockedUsersItem, 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 f6db1cbec1..4ece77a55c 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 @@ -22,6 +22,7 @@ data class PreferencesRootState( val devicesManagementUrl: String?, val showAnalyticsSettings: Boolean, val showDeveloperSettings: Boolean, + val canDeactivateAccount: Boolean, val showLockScreenSettings: Boolean, val showNotificationSettings: Boolean, val showBlockedUsersItem: 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 464288fd9b..c91a7e1adc 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 @@ -29,6 +29,7 @@ fun aPreferencesRootState( showNotificationSettings = true, showLockScreenSettings = true, showBlockedUsersItem = true, + canDeactivateAccount = true, snackbarMessage = SnackbarMessage(CommonStrings.common_verification_complete), directLogoutState = aDirectLogoutState(), 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 4f47c7eab9..10e59bf334 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 @@ -57,6 +57,7 @@ fun PreferencesRootView( onOpenUserProfile: (MatrixUser) -> Unit, onOpenBlockedUsers: () -> Unit, onSignOutClick: () -> Unit, + onDeactivateClick: () -> Unit, modifier: Modifier = Modifier, ) { val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage) @@ -99,6 +100,7 @@ fun PreferencesRootView( onOpenAdvancedSettings = onOpenAdvancedSettings, onOpenDeveloperSettings = onOpenDeveloperSettings, onSignOutClick = onSignOutClick, + onDeactivateClick = onDeactivateClick, ) Footer( @@ -193,6 +195,7 @@ private fun ColumnScope.GeneralSection( onOpenAdvancedSettings: () -> Unit, onOpenDeveloperSettings: () -> Unit, onSignOutClick: () -> Unit, + onDeactivateClick: () -> Unit, ) { ListItem( headlineContent = { Text(stringResource(id = CommonStrings.common_about)) }, @@ -225,6 +228,14 @@ private fun ColumnScope.GeneralSection( style = ListItemStyle.Destructive, onClick = onSignOutClick, ) + if (state.canDeactivateAccount) { + ListItem( + headlineContent = { Text(stringResource(id = CommonStrings.action_deactivate_account)) }, + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Warning())), + style = ListItemStyle.Destructive, + onClick = onDeactivateClick, + ) + } } @Composable @@ -292,5 +303,6 @@ private fun ContentToPreview(matrixUser: MatrixUser) { onOpenUserProfile = {}, onOpenBlockedUsers = {}, onSignOutClick = {}, + onDeactivateClick = {}, ) } 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 4e276701f4..774d52076a 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 @@ -10,6 +10,7 @@ package io.element.android.features.preferences.impl.root import androidx.compose.runtime.Composable import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow +import app.cash.turbine.ReceiveTurbine import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.logout.api.direct.DirectLogoutPresenter @@ -45,7 +46,7 @@ class PreferencesRootPresenterTest { @Test fun `present - initial state`() = runTest { - val matrixClient = FakeMatrixClient() + val matrixClient = FakeMatrixClient(canDeactivateAccountResult = { true }) val presenter = createPresenter(matrixClient = matrixClient) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -76,11 +77,27 @@ class PreferencesRootPresenterTest { assertThat(loadedState.showDeveloperSettings).isTrue() assertThat(loadedState.showLockScreenSettings).isTrue() assertThat(loadedState.showNotificationSettings).isTrue() + assertThat(loadedState.canDeactivateAccount).isTrue() assertThat(loadedState.directLogoutState).isEqualTo(aDirectLogoutState) assertThat(loadedState.snackbarMessage).isNull() } } + @Test + fun `present - can deactivate account is false if the Matrix client say so`() = runTest { + val presenter = createPresenter( + matrixClient = FakeMatrixClient( + canDeactivateAccountResult = { false } + ) + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + val loadedState = awaitFirstItem() + assertThat(loadedState.canDeactivateAccount).isFalse() + } + } + @Test fun `present - developer settings is hidden by default in release builds`() = runTest { val presenter = createPresenter( @@ -89,8 +106,7 @@ class PreferencesRootPresenterTest { moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { - skipItems(1) - val loadedState = awaitItem() + val loadedState = awaitFirstItem() assertThat(loadedState.showDeveloperSettings).isFalse() } } @@ -103,20 +119,22 @@ class PreferencesRootPresenterTest { moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { - skipItems(1) - val loadedState = awaitItem() - + val loadedState = awaitFirstItem() repeat(times = ShowDeveloperSettingsProvider.DEVELOPER_SETTINGS_COUNTER) { assertThat(loadedState.showDeveloperSettings).isFalse() loadedState.eventSink(PreferencesRootEvents.OnVersionInfoClick) } - assertThat(awaitItem().showDeveloperSettings).isTrue() } } + private suspend fun ReceiveTurbine.awaitFirstItem(): T { + skipItems(1) + return awaitItem() + } + private fun createPresenter( - matrixClient: FakeMatrixClient = FakeMatrixClient(), + matrixClient: FakeMatrixClient = FakeMatrixClient(canDeactivateAccountResult = { true }), sessionVerificationService: FakeSessionVerificationService = FakeSessionVerificationService(), showDeveloperSettingsProvider: ShowDeveloperSettingsProvider = ShowDeveloperSettingsProvider(aBuildMeta(BuildType.DEBUG)), ) = PreferencesRootPresenter( diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/InfoListOrganism.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/InfoListOrganism.kt index fec66c6f96..dedcd75af0 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/InfoListOrganism.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/InfoListOrganism.kt @@ -38,6 +38,7 @@ fun InfoListOrganism( iconTint: Color = LocalContentColor.current, iconSize: Dp = 20.dp, textStyle: TextStyle = LocalTextStyle.current, + textColor: Color = ElementTheme.colors.textPrimary, verticalArrangement: Arrangement.Vertical = Arrangement.spacedBy(4.dp), ) { Column( @@ -56,7 +57,7 @@ fun InfoListOrganism( Text( text = item.message, style = textStyle, - color = ElementTheme.colors.textPrimary, + color = textColor, ) }, icon = { 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 ca44838553..6dacb03dfb 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 @@ -138,4 +138,7 @@ interface MatrixClient : Closeable { /** Returns `true` if the current session is using native sliding sync, `false` if it's using a proxy. */ fun isUsingNativeSlidingSync(): Boolean + + fun canDeactivateAccount(): Boolean + suspend fun deactivateAccount(password: String, eraseData: Boolean): 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 9e77dcff4c..a5c5f1f442 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 @@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl import io.element.android.libraries.androidutils.file.getSizeOfFiles import io.element.android.libraries.androidutils.file.safeDelete +import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.childScope import io.element.android.libraries.matrix.api.MatrixClient @@ -89,6 +90,8 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeout +import org.matrix.rustcomponents.sdk.AuthData +import org.matrix.rustcomponents.sdk.AuthDataPasswordDetails import org.matrix.rustcomponents.sdk.Client import org.matrix.rustcomponents.sdk.ClientException import org.matrix.rustcomponents.sdk.IgnoredUsersListener @@ -493,6 +496,46 @@ class RustMatrixClient( return result } + override fun canDeactivateAccount(): Boolean { + return runCatching { + client.canDeactivateAccount() + } + .getOrNull() + .orFalse() + } + + override suspend fun deactivateAccount(password: String, eraseData: Boolean): Result = withContext(sessionDispatcher) { + Timber.w("Deactivating account") + syncService.stop() + runCatching { + // First call without AuthData, should fail + val firstAttempt = runCatching { + client.deactivateAccount( + authData = null, + eraseData = eraseData, + ) + } + if (firstAttempt.isFailure) { + Timber.w(firstAttempt.exceptionOrNull(), "Expected failure, try again") + // This is expected, try again with the password + client.deactivateAccount( + authData = AuthData.Password( + passwordDetails = AuthDataPasswordDetails( + identifier = sessionId.value, + password = password, + ), + ), + eraseData = eraseData, + ) + } + close() + deleteSessionDirectory(deleteCryptoDb = true) + sessionStore.removeSession(sessionId.value) + }.onFailure { + Timber.e(it, "Failed to deactivate account") + } + } + override suspend fun getAccountManagementUrl(action: AccountManagementAction?): Result = withContext(sessionDispatcher) { val rustAction = action?.toRustAction() runCatching { 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 908cb443ea..2d5e29f064 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 @@ -79,6 +79,8 @@ class FakeMatrixClient( private val clearCacheLambda: () -> Unit = { lambdaError() }, private val userIdServerNameLambda: () -> String = { lambdaError() }, private val getUrlLambda: (String) -> Result = { lambdaError() }, + private val canDeactivateAccountResult: () -> Boolean = { lambdaError() }, + private val deactivateAccountResult: (String, Boolean) -> Result = { _, _ -> lambdaError() }, var isNativeSlidingSyncSupportedLambda: suspend () -> Boolean = { true }, var isSlidingSyncProxySupportedLambda: suspend () -> Boolean = { true }, var isUsingNativeSlidingSyncLambda: () -> Boolean = { true }, @@ -175,6 +177,12 @@ class FakeMatrixClient( return logoutLambda(ignoreSdkError, userInitiated) } + override fun canDeactivateAccount() = canDeactivateAccountResult() + + override suspend fun deactivateAccount(password: String, eraseData: Boolean): Result = simulateLongTask { + deactivateAccountResult(password, eraseData) + } + override fun close() = Unit override suspend fun getUserProfile(): Result = simulateLongTask { diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 8e2e7822bf..4ef598a33b 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -42,12 +42,15 @@ "Close" "Complete verification" "Confirm" + "Confirm password" "Continue" "Copy" "Copy link" "Copy link to message" "Create" "Create a room" + "Deactivate" + "Deactivate account" "Decline" "Delete Poll" "Disable" @@ -291,6 +294,8 @@ Reason: %1$s." "Send message anyway" "%1$s is using one or more unverified devices. You can send the message anyway, or you can cancel for now and try again later after %2$s has verified all their devices." "Your message was not sent because %1$s has not verified all devices" + "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices." + "Your message was not sent because you have not verified one or more of your devices" "Pinned messages" "Failed processing media to upload, please try again." "Could not retrieve user details" @@ -314,6 +319,7 @@ Reason: %1$s." "Share this location" "Message not sent because %1$s’s verified identity has changed." "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." "Location" "Version: %1$s (%2$s)" "en" diff --git a/tools/localazy/config.json b/tools/localazy/config.json index f463b6d621..f7555ea393 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -27,6 +27,12 @@ "screen_signout_.*" ] }, + { + "name" : ":features:deactivation:impl", + "includeRegex" : [ + "screen_deactivate_account_.*" + ] + }, { "name" : ":features:roomaliasresolver:impl", "includeRegex" : [ From 6154b08ba757dd343af1214d051bafaf8ad789b7 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 17 Sep 2024 15:13:22 +0000 Subject: [PATCH 046/106] Update screenshots --- .../features.logout.impl_AccountDeactivationView_Day_0_en.png | 3 +++ .../features.logout.impl_AccountDeactivationView_Day_1_en.png | 3 +++ .../features.logout.impl_AccountDeactivationView_Day_2_en.png | 3 +++ .../features.logout.impl_AccountDeactivationView_Day_3_en.png | 3 +++ .../features.logout.impl_AccountDeactivationView_Day_4_en.png | 3 +++ ...eatures.logout.impl_AccountDeactivationView_Night_0_en.png | 3 +++ ...eatures.logout.impl_AccountDeactivationView_Night_1_en.png | 3 +++ ...eatures.logout.impl_AccountDeactivationView_Night_2_en.png | 3 +++ ...eatures.logout.impl_AccountDeactivationView_Night_3_en.png | 3 +++ ...eatures.logout.impl_AccountDeactivationView_Night_4_en.png | 3 +++ ...res.preferences.impl.root_PreferencesRootViewDark_0_en.png | 4 ++-- ...res.preferences.impl.root_PreferencesRootViewDark_1_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_0_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_1_en.png | 4 ++-- 14 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_4_en.png 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 new file mode 100644 index 0000000000..44150a9cdc --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ee6b7ffa3bb58fb9124960bc7ef91b496888f1d2e4e00b6f073422e5598baeec +size 76791 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 new file mode 100644 index 0000000000..ae77faeecc --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:930cabf63ba6ea12db0b3339202df7553f03dd51eeadab3bf9c0cad2ae0b716d +size 75151 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 new file mode 100644 index 0000000000..0a50ec8c06 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e230e408e90da51876f4e416d65e3a1f0bc01572df95789aac4a81c0b81d85e4 +size 60970 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 new file mode 100644 index 0000000000..1d46dd4c3e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8f2ab416d3ec72b7033e9b930d50eb19c4ae8c21fbfae77c1ec91adca67b42f +size 55109 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 new file mode 100644 index 0000000000..9d17632802 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d060436e3171c6b8d2059067c568965b872ec8ddaff4ef53005e594069cef3f +size 51983 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 new file mode 100644 index 0000000000..5aebe11211 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa880b0b3f74fb3ec557645c02b5c932b7793520206568f88832aac4be466ec8 +size 74806 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 new file mode 100644 index 0000000000..38dca4e570 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3acc8da7da5ac077b35e3ea321ab527a68f1cd193a0a609cc738080dae6eedd2 +size 73250 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 new file mode 100644 index 0000000000..494d79db03 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e3171efff5e2aa90ac148bfa9a46686bdbb8c4ba52270575d905e5ce9e9da45 +size 57661 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 new file mode 100644 index 0000000000..e6a8e0d1b1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d86d686303683355f6c3b0f621828311242aebac20893407f9fd4f9bbdd4a3a1 +size 52115 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 new file mode 100644 index 0000000000..71ab4e1742 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Night_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:389c15a481d2ac06f283dddbda46e3032276c635e7ecca3446b81b435a63dd3b +size 48815 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 acddf62ed1..6e91a26672 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:297b638c5314b3ac97c164739799e299206f5c13c9b889b088f3db3ef5e0117f -size 35695 +oid sha256:f99630ffa68c56bcfa9f20b0c895869ccf285f9dca4b9f4d60518ab7f09944fa +size 37993 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 d95315c26a..a8fa281a84 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:58f464863c5294262427d3fb4b2e682140aa8805a43d12ea4dc9d41d3b976062 -size 35449 +oid sha256:7fc7114af573847a08d1d331a34f13ea2ee6d1b02e52995c3657b493eb2cb9fd +size 37747 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 449d1ada38..ac15df98a7 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:a14903e0fdc50efba1617758babec6a8ef3281b74a5eba7b8f17f41f6ae304a6 -size 36584 +oid sha256:32996754db75d663e65844ac5bcdfce45407154dce88afa5e6a6914d4717ad81 +size 39033 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 a33eaa62d5..1d6aa51b79 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:bed3564666198684c099e4be89ff919a1e1820ff5f91d39080f547e05cbeea2c -size 36539 +oid sha256:14d283a64fe6070713fcc0fdac0435da664f4644143db758eeacf18fd9d5ed07 +size 38987 From 8f2aecd42b67bb2a42eadd331f801cfc669af6cd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 17:30:38 +0200 Subject: [PATCH 047/106] Fix icon tint issue. --- .../android/features/logout/impl/AccountDeactivationView.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt index c46461580b..596bbb8412 100644 --- a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt @@ -184,7 +184,6 @@ private fun Content( tint = ElementTheme.colors.iconCriticalPrimary, ) }, - iconVector = CompoundIcons.Close(), ), InfoListItem( message = stringResource(R.string.screen_deactivate_account_list_item_2), From 5a6859b2517a7d46f1bfac2f3e695fe9d07f8e95 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 17:39:23 +0200 Subject: [PATCH 048/106] Make text parts in bold. --- .../logout/impl/AccountDeactivationView.kt | 17 +++++++++++++-- .../impl/src/main/res/values/localazy.xml | 6 ++++-- .../atomic/organisms/InfoListOrganism.kt | 21 +++++++++++++------ 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt index 596bbb8412..ec397393bb 100644 --- a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt @@ -54,6 +54,7 @@ import io.element.android.libraries.designsystem.components.form.textFieldState import io.element.android.libraries.designsystem.components.list.SwitchListItem import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Icon @@ -168,14 +169,26 @@ private fun Content( verticalArrangement = Arrangement.spacedBy(16.dp), ) { Text( - text = stringResource(R.string.screen_deactivate_account_description), + text = buildAnnotatedStringWithStyledPart( + R.string.screen_deactivate_account_description, + R.string.screen_deactivate_account_description_bold_part, + color = ElementTheme.colors.textSecondary, + bold = true, + underline = false, + ), style = ElementTheme.typography.fontBodyMdRegular, color = ElementTheme.colors.textSecondary, ) InfoListOrganism( items = persistentListOf( InfoListItem( - message = stringResource(R.string.screen_deactivate_account_list_item_1), + message = buildAnnotatedStringWithStyledPart( + R.string.screen_deactivate_account_list_item_1, + R.string.screen_deactivate_account_list_item_1_bold_part, + color = ElementTheme.colors.textSecondary, + bold = true, + underline = false, + ), iconComposable = { Icon( modifier = Modifier.size(20.dp), diff --git a/features/deactivation/impl/src/main/res/values/localazy.xml b/features/deactivation/impl/src/main/res/values/localazy.xml index 5088a41c61..4a648996be 100644 --- a/features/deactivation/impl/src/main/res/values/localazy.xml +++ b/features/deactivation/impl/src/main/res/values/localazy.xml @@ -3,8 +3,10 @@ "Please confirm that you want to deactivate your account. This action cannot be undone." "Delete all my messages" "Warning: Future users may see incomplete conversations." - "Deactivating your account is irreversible, it will:" - "Permanently disable your account (you can\'t log back in, and your ID can\'t be reused)." + "Deactivating your account is %1$s, it will:" + "irreversible" + "%1$s your account (you can\'t log back in, and your ID can\'t be reused)." + "Permanently disable" "Remove you from all chat rooms." "Delete your account information from our identity server." "Your messages will still be visible to registered users but won’t be available to new or unregistered users if you choose to delete them." diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/InfoListOrganism.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/InfoListOrganism.kt index dedcd75af0..f3ff74909c 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/InfoListOrganism.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/organisms/InfoListOrganism.kt @@ -17,6 +17,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @@ -54,11 +55,19 @@ fun InfoListOrganism( } InfoListItemMolecule( message = { - Text( - text = item.message, - style = textStyle, - color = textColor, - ) + if (item.message is AnnotatedString) { + Text( + text = item.message, + style = textStyle, + color = textColor, + ) + } else { + Text( + text = item.message.toString(), + style = textStyle, + color = textColor, + ) + } }, icon = { if (item.iconId != null) { @@ -87,7 +96,7 @@ fun InfoListOrganism( } data class InfoListItem( - val message: String, + val message: CharSequence, @DrawableRes val iconId: Int? = null, val iconVector: ImageVector? = null, val iconComposable: @Composable () -> Unit = {}, From 61bca4ff055feeb2428047abc428ffcdc0bac7dd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 17:42:52 +0200 Subject: [PATCH 049/106] Fix screen title --- features/deactivation/impl/src/main/res/values/localazy.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/deactivation/impl/src/main/res/values/localazy.xml b/features/deactivation/impl/src/main/res/values/localazy.xml index 4a648996be..0380cf1c94 100644 --- a/features/deactivation/impl/src/main/res/values/localazy.xml +++ b/features/deactivation/impl/src/main/res/values/localazy.xml @@ -10,5 +10,5 @@ "Remove you from all chat rooms." "Delete your account information from our identity server." "Your messages will still be visible to registered users but won’t be available to new or unregistered users if you choose to delete them." - "Account deactivation" + "Deactivate account" From 782e1e392e290a9dffc671bf4c7993168fa2c1c6 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 17 Sep 2024 15:54:22 +0000 Subject: [PATCH 050/106] Update screenshots --- .../features.logout.impl_AccountDeactivationView_Day_0_en.png | 4 ++-- .../features.logout.impl_AccountDeactivationView_Day_1_en.png | 4 ++-- .../features.logout.impl_AccountDeactivationView_Day_2_en.png | 4 ++-- .../features.logout.impl_AccountDeactivationView_Day_3_en.png | 4 ++-- .../features.logout.impl_AccountDeactivationView_Day_4_en.png | 4 ++-- ...eatures.logout.impl_AccountDeactivationView_Night_0_en.png | 4 ++-- ...eatures.logout.impl_AccountDeactivationView_Night_1_en.png | 4 ++-- ...eatures.logout.impl_AccountDeactivationView_Night_2_en.png | 4 ++-- ...eatures.logout.impl_AccountDeactivationView_Night_3_en.png | 4 ++-- ...eatures.logout.impl_AccountDeactivationView_Night_4_en.png | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.logout.impl_AccountDeactivationView_Day_0_en.png index 44150a9cdc..d935111fb9 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:ee6b7ffa3bb58fb9124960bc7ef91b496888f1d2e4e00b6f073422e5598baeec -size 76791 +oid sha256:4c39aa8d3c17480057e87f5fbe1a490f2c287726b8223b28fdb3a199670e664a +size 76627 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 ae77faeecc..6e683cf2df 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:930cabf63ba6ea12db0b3339202df7553f03dd51eeadab3bf9c0cad2ae0b716d -size 75151 +oid sha256:5676526f71b0e743ae5a9fa174186f07514fcd367a6d1dbd00f6e2c0ca8e3558 +size 74986 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 0a50ec8c06..80534b9551 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:e230e408e90da51876f4e416d65e3a1f0bc01572df95789aac4a81c0b81d85e4 -size 60970 +oid sha256:db84da9b296e66a1968359da1c80ac546f4851d1f581e5e4d9100f16df4e80fc +size 60534 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 1d46dd4c3e..0c830753d5 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:b8f2ab416d3ec72b7033e9b930d50eb19c4ae8c21fbfae77c1ec91adca67b42f -size 55109 +oid sha256:621f75bd069d08bf2ae1c6a51bc3022a32ba4c6eaf829b0731d294d462ce0bd7 +size 55043 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 9d17632802..d97957903f 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:1d060436e3171c6b8d2059067c568965b872ec8ddaff4ef53005e594069cef3f -size 51983 +oid sha256:f83cd277b65f86c7f5ad85d92454be4ab8df730078a7fc3f030f17b0b61b10a1 +size 51928 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 5aebe11211..8e57779361 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:fa880b0b3f74fb3ec557645c02b5c932b7793520206568f88832aac4be466ec8 -size 74806 +oid sha256:6b1b12d2b3f79c0c941b9b2d376d2d0e8e7684bdcba8b1fffe2d7f025b738678 +size 74846 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 38dca4e570..89f4f18a30 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:3acc8da7da5ac077b35e3ea321ab527a68f1cd193a0a609cc738080dae6eedd2 -size 73250 +oid sha256:90ada7991629e3f1888aa187425bb90bc525f75aedb5f368c589fbb2fbfe897d +size 73288 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 494d79db03..4cef2b643d 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:8e3171efff5e2aa90ac148bfa9a46686bdbb8c4ba52270575d905e5ce9e9da45 -size 57661 +oid sha256:685a1e99238808e83a4774bd139c14049f4dfc19dd8bac757207d1e697d9c716 +size 57240 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 e6a8e0d1b1..005c79045b 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:d86d686303683355f6c3b0f621828311242aebac20893407f9fd4f9bbdd4a3a1 -size 52115 +oid sha256:a6992f4794f325cbd35dae667f8cb7973bcc9470e61f8bedb600917bc15af44c +size 52087 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 71ab4e1742..b25188b298 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:389c15a481d2ac06f283dddbda46e3032276c635e7ecca3446b81b435a63dd3b -size 48815 +oid sha256:8594136f07338d981c1e9e395eb52cd7088af03565397ae416169388d721dca2 +size 48791 From 3ec38a15299ca2d0122babb9af6f908a70eba30b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 20:05:14 +0200 Subject: [PATCH 051/106] Adding fastlane file for version 0.6.2 --- fastlane/metadata/android/en-US/changelogs/40006020.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/40006020.txt diff --git a/fastlane/metadata/android/en-US/changelogs/40006020.txt b/fastlane/metadata/android/en-US/changelogs/40006020.txt new file mode 100644 index 0000000000..0574894881 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40006020.txt @@ -0,0 +1,2 @@ +Element X is the new generation of Element for professional and personal use on mobile. It’s the fastest Matrix client with a seamless & intuitive user interface. +Full changelog: https://github.com/element-hq/element-x-android/releases From 4bd7fbe2b004e6b637830fc571c70d7c1373a0c7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 20:06:10 +0200 Subject: [PATCH 052/106] version++ --- plugins/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index c2e6f2d5c3..54afab0525 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -47,7 +47,7 @@ private const val versionMinor = 6 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -private const val versionPatch = 2 +private const val versionPatch = 3 object Versions { val versionCode = 4_000_000 + versionMajor * 1_00_00 + versionMinor * 1_00 + versionPatch From dbc4c8f56ed5a6f31b9f5d70742e3dc7082a40d1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 20:33:16 +0200 Subject: [PATCH 053/106] Changelog for version 0.6.2 --- CHANGES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index e4215c9fda..a3b77c6ec6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +Changes in Element X v0.6.2 (2024-09-17) +======================================== + +### ✨ Features +* Account deactivation. by @bmarty in https://github.com/element-hq/element-x-android/pull/3479 + Changes in Element X v0.6.1 (2024-09-17) ======================================== From 5e3def8185157943f3395f74c90cec6cfbacba86 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 21:17:04 +0200 Subject: [PATCH 054/106] Add tests on AccountDeactivationView --- features/deactivation/impl/build.gradle.kts | 1 + .../logout/impl/AccountDeactivationView.kt | 3 + .../impl/AccountDeactivationViewTest.kt | 102 +++++++++++++++++- 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/features/deactivation/impl/build.gradle.kts b/features/deactivation/impl/build.gradle.kts index 6e19a485d4..25a71098ac 100644 --- a/features/deactivation/impl/build.gradle.kts +++ b/features/deactivation/impl/build.gradle.kts @@ -33,6 +33,7 @@ dependencies { implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) implementation(projects.libraries.designsystem) + implementation(projects.libraries.testtags) implementation(projects.libraries.uiStrings) api(projects.features.deactivation.api) diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt index ec397393bb..7df20acb96 100644 --- a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt @@ -65,6 +65,8 @@ import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.autofill import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext +import io.element.android.libraries.testtags.TestTags +import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.persistentListOf @@ -277,6 +279,7 @@ private fun Content( .padding(top = 8.dp) .fillMaxWidth() .onTabOrEnterKeyFocusNext(focusManager) + .testTag(TestTags.loginPassword) .autofill( autofillTypes = listOf(AutofillType.Password), onFill = { diff --git a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt index 97a1b34751..06d27e463b 100644 --- a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt +++ b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt @@ -10,15 +10,26 @@ package io.element.android.features.logout.impl import androidx.activity.ComponentActivity import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.performTextInput import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.features.deactivation.impl.R +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.matrix.test.AN_EXCEPTION +import io.element.android.libraries.matrix.test.A_PASSWORD +import io.element.android.libraries.testtags.TestTags +import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EventsRecorder +import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBack +import io.element.android.tests.testutils.pressTag import org.junit.Rule import org.junit.Test import org.junit.rules.TestRule import org.junit.runner.RunWith +import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class AccountDeactivationViewTest { @@ -36,7 +47,96 @@ class AccountDeactivationViewTest { } } - // TODO Add more tests + @Config(qualifiers = "h1024dp") + @Test + fun `clicking on Deactivate emits the expected Event`() { + val eventsRecorder = EventsRecorder() + rule.setAccountDeactivationView( + state = anAccountDeactivationState( + deactivateFormState = aDeactivateFormState( + password = A_PASSWORD, + ), + eventSink = eventsRecorder, + ), + ) + rule.clickOn(CommonStrings.action_deactivate) + eventsRecorder.assertSingle(AccountDeactivationEvents.DeactivateAccount(false)) + } + + @Test + fun `clicking on Deactivate on the confirmation dialog emits the expected Event`() { + val eventsRecorder = EventsRecorder() + rule.setAccountDeactivationView( + state = anAccountDeactivationState( + deactivateFormState = aDeactivateFormState( + password = A_PASSWORD, + ), + accountDeactivationAction = AsyncAction.Confirming, + eventSink = eventsRecorder, + ), + ) + rule.pressTag(TestTags.dialogPositive.value) + eventsRecorder.assertSingle(AccountDeactivationEvents.DeactivateAccount(false)) + } + + @Test + fun `clicking on retry on the confirmation dialog emits the expected Event`() { + val eventsRecorder = EventsRecorder() + rule.setAccountDeactivationView( + state = anAccountDeactivationState( + deactivateFormState = aDeactivateFormState( + password = A_PASSWORD, + ), + accountDeactivationAction = AsyncAction.Failure(AN_EXCEPTION), + eventSink = eventsRecorder, + ), + ) + rule.clickOn(CommonStrings.action_retry) + eventsRecorder.assertSingle(AccountDeactivationEvents.DeactivateAccount(true)) + } + + @Test + fun `switching on the erase all switch emits the expected Event`() { + val eventsRecorder = EventsRecorder() + rule.setAccountDeactivationView( + state = anAccountDeactivationState( + eventSink = eventsRecorder, + ), + ) + rule.clickOn(R.string.screen_deactivate_account_delete_all_messages) + eventsRecorder.assertSingle(AccountDeactivationEvents.SetEraseData(true)) + } + + @Test + fun `switching off the erase all switch emits the expected Event`() { + val eventsRecorder = EventsRecorder() + rule.setAccountDeactivationView( + state = anAccountDeactivationState( + deactivateFormState = aDeactivateFormState( + eraseData = true, + ), + eventSink = eventsRecorder, + ), + ) + rule.clickOn(R.string.screen_deactivate_account_delete_all_messages) + eventsRecorder.assertSingle(AccountDeactivationEvents.SetEraseData(false)) + } + + @Config(qualifiers = "h1024dp") + @Test + fun `typing text in the password field emits the expected Event`() { + val eventsRecorder = EventsRecorder() + rule.setAccountDeactivationView( + state = anAccountDeactivationState( + deactivateFormState = aDeactivateFormState( + password = A_PASSWORD, + ), + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithTag(TestTags.loginPassword.value).performTextInput("A") + eventsRecorder.assertSingle(AccountDeactivationEvents.SetPassword("A$A_PASSWORD")) + } } private fun AndroidComposeTestRule.setAccountDeactivationView( From 52405553293bf1b67a9efb848936a0e5e44d085a Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 18 Sep 2024 11:07:07 +0200 Subject: [PATCH 055/106] Resolve send failure verification : clearer message when unsigned device is from you --- .../messages/impl/actionlist/ActionListView.kt | 3 ++- .../crypto/sendfailure/VerifiedUserSendFailure.kt | 7 ++++--- .../sendfailure/VerifiedUserSendFailureFactory.kt | 8 ++++++-- .../ResolveVerifiedUserSendFailureStateProvider.kt | 2 +- .../resolve/ResolveVerifiedUserSendFailureView.kt | 9 +++++++-- .../ResolveVerifiedUserSendFailurePresenterTest.kt | 12 ++++++------ .../ui-strings/src/main/res/values/localazy.xml | 3 +++ 7 files changed, 29 insertions(+), 15 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt index 8c950012db..a81975bf46 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 @@ -374,7 +374,8 @@ private fun VerifiedUserSendFailureView( fun VerifiedUserSendFailure.headline(): String { return when (this) { is None -> "" - is UnsignedDevice -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_unsigned_device, userDisplayName) + is UnsignedDevice.FromOther -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_unsigned_device, userDisplayName) + is UnsignedDevice.FromYou -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_you_unsigned_device) is ChangedIdentity -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_changed_identity, userDisplayName) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt index e3c798f7df..13a26a8bdb 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt @@ -13,9 +13,10 @@ import androidx.compose.runtime.Immutable sealed interface VerifiedUserSendFailure { data object None : VerifiedUserSendFailure - data class UnsignedDevice( - val userDisplayName: String, - ) : VerifiedUserSendFailure + sealed interface UnsignedDevice : VerifiedUserSendFailure { + data object FromYou : UnsignedDevice + data class FromOther(val userDisplayName: String) : UnsignedDevice + } data class ChangedIdentity( val userDisplayName: String, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt index de5817c909..b96baed27d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt @@ -23,8 +23,12 @@ class VerifiedUserSendFailureFactory @Inject constructor( if (userId == null) { VerifiedUserSendFailure.None } else { - val displayName = room.userDisplayName(userId).getOrNull() ?: userId.value - VerifiedUserSendFailure.UnsignedDevice(displayName) + if (userId == room.sessionId) { + VerifiedUserSendFailure.UnsignedDevice.FromYou + } else { + val displayName = room.userDisplayName(userId).getOrNull() ?: userId.value + VerifiedUserSendFailure.UnsignedDevice.FromOther(displayName) + } } } is LocalEventSendState.Failed.VerifiedUserChangedIdentity -> { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt index 1f8335b648..cdbdf6fcb0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt @@ -36,7 +36,7 @@ fun aResolveVerifiedUserSendFailureState( eventSink = eventSink ) -fun anUnsignedDeviceSendFailure(userDisplayName: String = "Alice") = VerifiedUserSendFailure.UnsignedDevice( +fun anUnsignedDeviceSendFailure(userDisplayName: String = "Alice") = VerifiedUserSendFailure.UnsignedDevice.FromOther( userDisplayName = userDisplayName, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt index e0d964fa51..fb602fa943 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt @@ -113,7 +113,11 @@ fun ResolveVerifiedUserSendFailureView( @Composable private fun VerifiedUserSendFailure.title(): String { return when (this) { - is VerifiedUserSendFailure.UnsignedDevice -> stringResource(id = CommonStrings.screen_resolve_send_failure_unsigned_device_title, userDisplayName) + is VerifiedUserSendFailure.UnsignedDevice.FromOther -> stringResource( + id = CommonStrings.screen_resolve_send_failure_unsigned_device_title, + userDisplayName + ) + VerifiedUserSendFailure.UnsignedDevice.FromYou -> stringResource(id = CommonStrings.screen_resolve_send_failure_you_unsigned_device_title) is VerifiedUserSendFailure.ChangedIdentity -> stringResource( id = CommonStrings.screen_resolve_send_failure_changed_identity_title, userDisplayName @@ -125,11 +129,12 @@ private fun VerifiedUserSendFailure.title(): String { @Composable private fun VerifiedUserSendFailure.subtitle(): String { return when (this) { - is VerifiedUserSendFailure.UnsignedDevice -> stringResource( + is VerifiedUserSendFailure.UnsignedDevice.FromOther -> stringResource( id = CommonStrings.screen_resolve_send_failure_unsigned_device_subtitle, userDisplayName, userDisplayName, ) + VerifiedUserSendFailure.UnsignedDevice.FromYou -> stringResource(id = CommonStrings.screen_resolve_send_failure_you_unsigned_device_subtitle) is VerifiedUserSendFailure.ChangedIdentity -> stringResource( id = CommonStrings.screen_resolve_send_failure_changed_identity_subtitle, userDisplayName diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt index 8d5884cf08..e74ae89b4f 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt @@ -94,7 +94,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) skipItems(1) awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) state.eventSink(ResolveVerifiedUserSendFailureEvents.Dismiss) } skipItems(1) @@ -124,7 +124,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { skipItems(1) awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) state.eventSink(ResolveVerifiedUserSendFailureEvents.Retry) } awaitItem().also { state -> @@ -158,7 +158,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { skipItems(1) awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) } awaitItem().also { state -> @@ -167,7 +167,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { // This should move to the next user skipItems(2) awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID_2.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromOther(A_USER_ID_2.value)) assertThat(state.resolveAction).isEqualTo(AsyncAction.Success(Unit)) state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) } @@ -199,14 +199,14 @@ class ResolveVerifiedUserSendFailurePresenterTest { skipItems(1) awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) } awaitItem().also { state -> assertThat(state.resolveAction).isEqualTo(AsyncAction.Loading) } awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) assertThat(state.resolveAction).isInstanceOf(AsyncAction.Failure::class.java) } ensureAllEventsConsumed() diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 8e2e7822bf..c71dd4d505 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -291,6 +291,8 @@ Reason: %1$s." "Send message anyway" "%1$s is using one or more unverified devices. You can send the message anyway, or you can cancel for now and try again later after %2$s has verified all their devices." "Your message was not sent because %1$s has not verified all devices" + "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices." + "Your message was not sent because you have not verified one or more of your devices" "Pinned messages" "Failed processing media to upload, please try again." "Could not retrieve user details" @@ -314,6 +316,7 @@ Reason: %1$s." "Share this location" "Message not sent because %1$s’s verified identity has changed." "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." "Location" "Version: %1$s (%2$s)" "en" From 1a049832ab41ba6150641d468adb0255f2eb2d6a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 Sep 2024 11:41:15 +0200 Subject: [PATCH 056/106] Distinguish between roomId and roomAlias. --- .../android/libraries/matrix/api/core/MatrixPatterns.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt index 851dd44e3e..454dfba462 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt @@ -149,7 +149,12 @@ object MatrixPatterns { add(MatrixPatternResult(MatrixPatternType.USER_ID, permalink.userId.toString(), match.range.first, match.range.last + 1)) } is PermalinkData.RoomLink -> { - add(MatrixPatternResult(MatrixPatternType.ROOM_ALIAS, permalink.roomIdOrAlias.identifier, match.range.first, match.range.last + 1)) + when (permalink.roomIdOrAlias) { + is RoomIdOrAlias.Alias -> MatrixPatternType.ROOM_ALIAS + is RoomIdOrAlias.Id -> if (permalink.eventId == null) MatrixPatternType.ROOM_ID else null + }?.let { type -> + add(MatrixPatternResult(type, permalink.roomIdOrAlias.identifier, match.range.first, match.range.last + 1)) + } } else -> Unit } From c08b8c04169a58c772f43e320a49d2f35ad595f3 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 18 Sep 2024 13:54:54 +0200 Subject: [PATCH 057/106] Make sure the logout action doesn't cause a crash (#3480) * Make sure the logout doesn't cause a crash Some reasons why this could happen: 1. The `ClientDelegate` could receive a `didReceiveAuthError` callback call on a logout, which could trigger another logout when every Rust object had already been destroyed. 2. Even though we stop the sync before logging out, `LoggedInFlowNode` will try to start it again automatically when it detects we still have internet connection. Making sure to unregister the delegate should fix the first part of the issue. For the other one, adding `RustSyncService.isServiceReady` to check if we should start/stop the service, which is enabled by default and set to false on destroy should help. * Apply the same patch on account deactivation. --------- Co-authored-by: Benoit Marty --- .../matrix/impl/RustClientSessionDelegate.kt | 1 - .../libraries/matrix/impl/RustMatrixClient.kt | 44 ++++++++++++------- .../matrix/impl/sync/RustSyncService.kt | 23 +++++++++- 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt index 03a59203e5..dcdb719511 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt @@ -50,7 +50,6 @@ class RustClientSessionDelegate( */ fun bindClient(client: RustMatrixClient) { this.client = client - client.setDelegate(this) } override fun saveSessionInKeychain(session: Session) { 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 a5c5f1f442..a49db1ccd2 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 @@ -122,7 +122,7 @@ class RustMatrixClient( private val baseDirectory: File, baseCacheDirectory: File, private val clock: SystemClock, - sessionDelegate: RustClientSessionDelegate, + private val sessionDelegate: RustClientSessionDelegate, ) : MatrixClient { override val sessionId: UserId = UserId(client.userId()) override val deviceId: DeviceId = DeviceId(client.deviceId()) @@ -195,7 +195,7 @@ class RustMatrixClient( private val roomMembershipObserver = RoomMembershipObserver() - private val clientDelegateTaskHandle: TaskHandle? = client.setDelegate(sessionDelegate) + private var clientDelegateTaskHandle: TaskHandle? = client.setDelegate(sessionDelegate) private val _userProfile: MutableStateFlow = MutableStateFlow( MatrixUser( @@ -449,12 +449,12 @@ class RustMatrixClient( override fun close() { appCoroutineScope.launch { roomFactory.destroy() + rustSyncService.destroy() } sessionCoroutineScope.cancel() clientDelegateTaskHandle?.cancelAndDestroy() notificationSettingsService.destroy() verificationService.destroy() - syncService.destroy() innerRoomListService.destroy() notificationClient.destroy() notificationProcessSetup.destroy() @@ -473,7 +473,9 @@ class RustMatrixClient( override suspend fun logout(userInitiated: Boolean, ignoreSdkError: Boolean): String? { var result: String? = null - syncService.stop() + // Remove current delegate so we don't receive an auth error + clientDelegateTaskHandle?.cancelAndDestroy() + clientDelegateTaskHandle = null withContext(sessionDispatcher) { if (userInitiated) { try { @@ -482,12 +484,15 @@ class RustMatrixClient( if (ignoreSdkError) { Timber.e(failure, "Fail to call logout on HS. Still delete local files.") } else { + // If the logout failed we need to restore the delegate + clientDelegateTaskHandle = client.setDelegate(sessionDelegate) Timber.e(failure, "Fail to call logout on HS.") throw failure } } } close() + deleteSessionDirectory(deleteCryptoDb = true) if (userInitiated) { sessionStore.removeSession(sessionId.value) @@ -506,7 +511,9 @@ class RustMatrixClient( override suspend fun deactivateAccount(password: String, eraseData: Boolean): Result = withContext(sessionDispatcher) { Timber.w("Deactivating account") - syncService.stop() + // Remove current delegate so we don't receive an auth error + clientDelegateTaskHandle?.cancelAndDestroy() + clientDelegateTaskHandle = null runCatching { // First call without AuthData, should fail val firstAttempt = runCatching { @@ -518,15 +525,22 @@ class RustMatrixClient( if (firstAttempt.isFailure) { Timber.w(firstAttempt.exceptionOrNull(), "Expected failure, try again") // This is expected, try again with the password - client.deactivateAccount( - authData = AuthData.Password( - passwordDetails = AuthDataPasswordDetails( - identifier = sessionId.value, - password = password, + runCatching { + client.deactivateAccount( + authData = AuthData.Password( + passwordDetails = AuthDataPasswordDetails( + identifier = sessionId.value, + password = password, + ), ), - ), - eraseData = eraseData, - ) + eraseData = eraseData, + ) + }.onFailure { + Timber.e(it, "Failed to deactivate account") + // If the deactivation failed we need to restore the delegate + clientDelegateTaskHandle = client.setDelegate(sessionDelegate) + throw it + } } close() deleteSessionDirectory(deleteCryptoDb = true) @@ -592,10 +606,6 @@ class RustMatrixClient( return client.session().slidingSyncVersion == SlidingSyncVersion.Native } - internal fun setDelegate(delegate: RustClientSessionDelegate) { - client.setDelegate(delegate) - } - private suspend fun File.getCacheSize( includeCryptoDb: Boolean = false, ): Long = withContext(sessionDispatcher) { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt index cf52609fa0..0a859ee146 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt @@ -16,15 +16,22 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn -import org.matrix.rustcomponents.sdk.SyncServiceInterface import org.matrix.rustcomponents.sdk.SyncServiceState import timber.log.Timber +import java.util.concurrent.atomic.AtomicBoolean +import org.matrix.rustcomponents.sdk.SyncService as InnerSyncService class RustSyncService( - private val innerSyncService: SyncServiceInterface, + private val innerSyncService: InnerSyncService, sessionCoroutineScope: CoroutineScope ) : SyncService { + private val isServiceReady = AtomicBoolean(true) + override suspend fun startSync() = runCatching { + if (!isServiceReady.get()) { + Timber.d("Can't start sync: service is not ready") + return@runCatching + } Timber.i("Start sync") innerSyncService.start() }.onFailure { @@ -32,12 +39,24 @@ class RustSyncService( } override suspend fun stopSync() = runCatching { + if (!isServiceReady.get()) { + Timber.d("Can't stop sync: service is not ready") + return@runCatching + } Timber.i("Stop sync") innerSyncService.stop() }.onFailure { Timber.d("Stop sync failed: $it") } + suspend fun destroy() { + // If the service was still running, stop it + stopSync() + Timber.d("Destroying sync service") + isServiceReady.set(false) + innerSyncService.destroy() + } + override val syncState: StateFlow = innerSyncService.stateFlow() .map(SyncServiceState::toSyncState) From 05f2c71745428e47316713f51416385868c1c0f8 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 18 Sep 2024 14:01:05 +0200 Subject: [PATCH 058/106] Pinned messages : remove debounce now it's properly handled by sdk. --- .../impl/pinned/banner/PinnedMessagesBannerPresenter.kt | 3 --- .../messages/impl/pinned/list/PinnedMessagesListPresenter.kt | 4 +--- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt index 81405c8f38..457e96c5b8 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt @@ -25,14 +25,12 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.FlowPreview -import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import javax.inject.Inject -import kotlin.time.Duration.Companion.milliseconds class PinnedMessagesBannerPresenter @Inject constructor( private val room: MatrixRoom, @@ -123,7 +121,6 @@ class PinnedMessagesBannerPresenter @Inject constructor( is AsyncData.Loading -> flowOf(AsyncData.Loading()) is AsyncData.Success -> { asyncTimeline.data.timelineItems - .debounce(300.milliseconds) .map { timelineItems -> val pinnedItems = timelineItems.mapNotNull { timelineItem -> itemFactory.create(timelineItem) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt index 6c8c52a443..1525a8a5e1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt @@ -43,14 +43,12 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import timber.log.Timber -import kotlin.time.Duration.Companion.milliseconds class PinnedMessagesListPresenter @AssistedInject constructor( @Assisted private val navigator: PinnedMessagesListNavigator, @@ -174,7 +172,7 @@ class PinnedMessagesListPresenter @AssistedInject constructor( is AsyncData.Failure -> flowOf(AsyncData.Failure(asyncTimeline.error)) is AsyncData.Loading -> flowOf(AsyncData.Loading()) is AsyncData.Success -> { - val timelineItemsFlow = asyncTimeline.data.timelineItems.debounce(300.milliseconds) + val timelineItemsFlow = asyncTimeline.data.timelineItems combine(timelineItemsFlow, room.membersStateFlow) { items, membersState -> timelineItemsFactory.replaceWith( timelineItems = items, From 6b4cce7de342f8e60f0e823254f6ac79abd9e1b8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 Sep 2024 14:14:10 +0200 Subject: [PATCH 059/106] Code cleanup --- .../auth/RustMatrixAuthenticationService.kt | 27 +++++++++---------- .../RustSessionVerificationService.kt | 1 + 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index d1f0d29295..b63e307888 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 @@ -251,18 +251,17 @@ class RustMatrixAuthenticationService @Inject constructor( oidcConfiguration = oidcConfiguration, progressListener = progressListener, ) - - client.use { rustClient -> - val sessionData = rustClient.session() + val sessionData = client.use { rustClient -> + rustClient.session() .toSessionData( isTokenValid = true, loginType = LoginType.QR, passphrase = pendingPassphrase, sessionPaths = emptySessionPaths, ) - sessionStore.storeData(sessionData) - SessionId(sessionData.userId) } + sessionStore.storeData(sessionData) + SessionId(sessionData.userId) }.mapFailure { when (it) { is QrCodeDecodeException -> QrErrorMapper.map(it) @@ -285,14 +284,14 @@ class RustMatrixAuthenticationService @Inject constructor( if (slidingSyncType is ClientBuilderSlidingSync.Simplified) { Timber.d("Creating client with simplified sliding sync") try { - return rustMatrixClientFactory - .getBaseClientBuilder( - sessionPaths = sessionPaths, - passphrase = pendingPassphrase, - slidingSyncType = slidingSyncType, - ) - .run { config() } - .build() + return rustMatrixClientFactory + .getBaseClientBuilder( + sessionPaths = sessionPaths, + passphrase = pendingPassphrase, + slidingSyncType = slidingSyncType, + ) + .config() + .build() } catch (e: HumanQrLoginException.SlidingSyncNotAvailable) { Timber.e(e, "Failed to create client with simplified sliding sync, trying with Proxy now") } @@ -304,7 +303,7 @@ class RustMatrixAuthenticationService @Inject constructor( passphrase = pendingPassphrase, slidingSyncType = getSlidingSyncProxy(), ) - .run { config() } + .config() .build() } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt index 9d55d3402c..71004a74d7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt @@ -206,6 +206,7 @@ class RustSessionVerificationService( } } } + private suspend fun updateVerificationStatus() { if (verificationFlowState.value == VerificationFlowState.Finished) { // Calling `encryptionService.verificationState()` performs a network call and it will deadlock if there is no network From 7c56bc4c6bb6ff61da5a74b1213deb57234f711c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 Sep 2024 14:14:44 +0200 Subject: [PATCH 060/106] Move FakeRust classes and factories to a fixtures package --- .../matrix/impl/fixtures/FakeRustRoom.kt | 39 ++++++ .../impl/fixtures/FakeRustRoomListItem.kt | 32 +++++ .../fixtures/FakeRustRoomMembersIterator.kt | 31 +++++ .../matrix/impl/fixtures/RustRoomInfo.kt | 81 +++++++++++++ .../matrix/impl/fixtures/RustRoomMember.kt | 34 ++++++ .../room/member/RoomMemberListFetcherTest.kt | 113 ++++-------------- .../roomlist/RoomSummaryListProcessorTest.kt | 103 +--------------- 7 files changed, 244 insertions(+), 189 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomListItem.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomMembersIterator.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomMember.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt new file mode 100644 index 0000000000..f8f8b88a98 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.fixtures + +import io.element.android.libraries.matrix.test.A_ROOM_ID +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.Room +import org.matrix.rustcomponents.sdk.RoomMembersIterator + +class FakeRustRoom( + private val getMembers: () -> RoomMembersIterator = { FakeRustRoomMembersIterator() }, + private val getMembersNoSync: () -> RoomMembersIterator = { FakeRustRoomMembersIterator() }, +) : Room(NoPointer) { + var membersCallCount = 0 + var membersNoSyncCallCount = 0 + + override fun id(): String { + return A_ROOM_ID.value + } + + override suspend fun members(): RoomMembersIterator { + membersCallCount++ + return getMembers() + } + + override suspend fun membersNoSync(): RoomMembersIterator { + membersNoSyncCallCount++ + return getMembersNoSync() + } + + override fun close() { + // No-op + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomListItem.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomListItem.kt new file mode 100644 index 0000000000..1b9adee435 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomListItem.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.fixtures + +import io.element.android.libraries.matrix.api.core.RoomId +import org.matrix.rustcomponents.sdk.EventTimelineItem +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.RoomInfo +import org.matrix.rustcomponents.sdk.RoomListItem + +class FakeRustRoomListItem( + private val roomId: RoomId, + private val roomInfo: RoomInfo = aRustRoomInfo(id = roomId.value), + private val latestEvent: EventTimelineItem? = null, +) : RoomListItem(NoPointer) { + override fun id(): String { + return roomId.value + } + + override suspend fun roomInfo(): RoomInfo { + return roomInfo + } + + override suspend fun latestEvent(): EventTimelineItem? { + return latestEvent + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomMembersIterator.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomMembersIterator.kt new file mode 100644 index 0000000000..e5a0646303 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomMembersIterator.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.fixtures + +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.RoomMember +import org.matrix.rustcomponents.sdk.RoomMembersIterator + +class FakeRustRoomMembersIterator( + private var members: List? = null +) : RoomMembersIterator(NoPointer) { + override fun len(): UInt { + return members?.size?.toUInt() ?: 0u + } + + override fun nextChunk(chunkSize: UInt): List? { + if (members?.isEmpty() == true) { + return null + } + return members?.let { + val result = it.take(chunkSize.toInt()) + members = it.subList(result.size, it.size) + result + } + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt new file mode 100644 index 0000000000..e64dabf27a --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt @@ -0,0 +1,81 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.fixtures + +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_ROOM_NAME +import org.matrix.rustcomponents.sdk.Membership +import org.matrix.rustcomponents.sdk.RoomHero +import org.matrix.rustcomponents.sdk.RoomInfo +import org.matrix.rustcomponents.sdk.RoomMember +import org.matrix.rustcomponents.sdk.RoomNotificationMode + +fun aRustRoomInfo( + id: String = A_ROOM_ID.value, + displayName: String = A_ROOM_NAME, + rawName: String = A_ROOM_NAME, + topic: String? = null, + avatarUrl: String? = null, + isDirect: Boolean = false, + isPublic: Boolean = false, + isSpace: Boolean = false, + isTombstoned: Boolean = false, + isFavourite: Boolean = false, + canonicalAlias: String? = null, + alternativeAliases: List = listOf(), + membership: Membership = Membership.JOINED, + inviter: RoomMember? = null, + heroes: List = listOf(), + activeMembersCount: ULong = 0uL, + invitedMembersCount: ULong = 0uL, + joinedMembersCount: ULong = 0uL, + userPowerLevels: Map = mapOf(), + highlightCount: ULong = 0uL, + notificationCount: ULong = 0uL, + userDefinedNotificationMode: RoomNotificationMode? = null, + hasRoomCall: Boolean = false, + activeRoomCallParticipants: List = listOf(), + isMarkedUnread: Boolean = false, + numUnreadMessages: ULong = 0uL, + numUnreadNotifications: ULong = 0uL, + numUnreadMentions: ULong = 0uL, + pinnedEventIds: List = listOf(), + roomCreator: UserId? = null, +) = RoomInfo( + id = id, + displayName = displayName, + rawName = rawName, + topic = topic, + avatarUrl = avatarUrl, + isDirect = isDirect, + isPublic = isPublic, + isSpace = isSpace, + isTombstoned = isTombstoned, + isFavourite = isFavourite, + canonicalAlias = canonicalAlias, + alternativeAliases = alternativeAliases, + membership = membership, + inviter = inviter, + heroes = heroes, + activeMembersCount = activeMembersCount, + invitedMembersCount = invitedMembersCount, + joinedMembersCount = joinedMembersCount, + userPowerLevels = userPowerLevels, + highlightCount = highlightCount, + notificationCount = notificationCount, + cachedUserDefinedNotificationMode = userDefinedNotificationMode, + hasRoomCall = hasRoomCall, + activeRoomCallParticipants = activeRoomCallParticipants, + isMarkedUnread = isMarkedUnread, + numUnreadMessages = numUnreadMessages, + numUnreadNotifications = numUnreadNotifications, + numUnreadMentions = numUnreadMentions, + pinnedEventIds = pinnedEventIds, + creator = roomCreator?.value, +) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomMember.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomMember.kt new file mode 100644 index 0000000000..918ae1fe12 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomMember.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.fixtures + +import io.element.android.libraries.matrix.api.core.UserId +import org.matrix.rustcomponents.sdk.MembershipState +import org.matrix.rustcomponents.sdk.RoomMember +import uniffi.matrix_sdk.RoomMemberRole + +fun aRustRoomMember( + userId: UserId, + displayName: String? = null, + avatarUrl: String? = null, + membership: MembershipState = MembershipState.JOIN, + isNameAmbiguous: Boolean = false, + powerLevel: Long = 0L, + isIgnored: Boolean = false, + role: RoomMemberRole = RoomMemberRole.USER, +) = RoomMember( + userId = userId.value, + displayName = displayName, + avatarUrl = avatarUrl, + membership = membership, + isNameAmbiguous = isNameAmbiguous, + powerLevel = powerLevel, + normalizedPowerLevel = powerLevel, + isIgnored = isIgnored, + suggestedRoleForPowerLevel = role, +) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt index 2411b67c61..87e2f5a0b7 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt @@ -9,13 +9,14 @@ package io.element.android.libraries.matrix.impl.room.member import app.cash.turbine.test import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.roomMembers +import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoom +import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoomMembersIterator +import io.element.android.libraries.matrix.impl.fixtures.aRustRoomMember import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.CACHE import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.CACHE_AND_SERVER import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.SERVER -import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.A_USER_ID_2 import io.element.android.libraries.matrix.test.A_USER_ID_3 @@ -23,22 +24,16 @@ import io.element.android.libraries.matrix.test.A_USER_ID_4 import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.test.runTest import org.junit.Test -import org.matrix.rustcomponents.sdk.MembershipState -import org.matrix.rustcomponents.sdk.NoPointer -import org.matrix.rustcomponents.sdk.Room -import org.matrix.rustcomponents.sdk.RoomMember -import org.matrix.rustcomponents.sdk.RoomMembersIterator -import uniffi.matrix_sdk.RoomMemberRole class RoomMemberListFetcherTest { @Test fun `fetchRoomMembers with CACHE source - emits cached members, if any`() = runTest { val room = FakeRustRoom(getMembersNoSync = { - FakeRoomMembersIterator( + FakeRustRoomMembersIterator( listOf( - fakeRustRoomMember(A_USER_ID), - fakeRustRoomMember(A_USER_ID_2), - fakeRustRoomMember(A_USER_ID_3), + aRustRoomMember(A_USER_ID), + aRustRoomMember(A_USER_ID_2), + aRustRoomMember(A_USER_ID_3), ) ) }) @@ -65,7 +60,7 @@ class RoomMemberListFetcherTest { @Test fun `fetchRoomMembers with CACHE source - emits empty list, if no members exist`() = runTest { val room = FakeRustRoom(getMembersNoSync = { - FakeRoomMembersIterator(emptyList()) + FakeRustRoomMembersIterator(emptyList()) }) val fetcher = RoomMemberListFetcher(room, Dispatchers.Default) @@ -95,11 +90,11 @@ class RoomMemberListFetcherTest { @Test fun `fetchRoomMembers with CACHE source - emits all items at once`() = runTest { val room = FakeRustRoom(getMembersNoSync = { - FakeRoomMembersIterator( + FakeRustRoomMembersIterator( listOf( - fakeRustRoomMember(A_USER_ID), - fakeRustRoomMember(A_USER_ID_2), - fakeRustRoomMember(A_USER_ID_3), + aRustRoomMember(A_USER_ID), + aRustRoomMember(A_USER_ID_2), + aRustRoomMember(A_USER_ID_3), ) ) }) @@ -122,11 +117,11 @@ class RoomMemberListFetcherTest { @Test fun `fetchRoomMembers with SERVER source - emits only new members, if any`() = runTest { val room = FakeRustRoom(getMembers = { - FakeRoomMembersIterator( + FakeRustRoomMembersIterator( listOf( - fakeRustRoomMember(A_USER_ID), - fakeRustRoomMember(A_USER_ID_2), - fakeRustRoomMember(A_USER_ID_3), + aRustRoomMember(A_USER_ID), + aRustRoomMember(A_USER_ID_2), + aRustRoomMember(A_USER_ID_3), ) ) }) @@ -163,14 +158,14 @@ class RoomMemberListFetcherTest { fun `fetchRoomMembers with CACHE_AND_SERVER source - returns cached items first, then new ones`() = runTest { val room = FakeRustRoom( getMembersNoSync = { - FakeRoomMembersIterator(listOf(fakeRustRoomMember(A_USER_ID_4))) + FakeRustRoomMembersIterator(listOf(aRustRoomMember(A_USER_ID_4))) }, getMembers = { - FakeRoomMembersIterator( + FakeRustRoomMembersIterator( listOf( - fakeRustRoomMember(A_USER_ID), - fakeRustRoomMember(A_USER_ID_2), - fakeRustRoomMember(A_USER_ID_3), + aRustRoomMember(A_USER_ID), + aRustRoomMember(A_USER_ID_2), + aRustRoomMember(A_USER_ID_3), ) ) } @@ -203,69 +198,3 @@ class RoomMemberListFetcherTest { } } } - -class FakeRustRoom( - private val getMembers: () -> RoomMembersIterator = { FakeRoomMembersIterator() }, - private val getMembersNoSync: () -> RoomMembersIterator = { FakeRoomMembersIterator() }, -) : Room(NoPointer) { - var membersCallCount = 0 - var membersNoSyncCallCount = 0 - - override fun id(): String { - return A_ROOM_ID.value - } - - override suspend fun members(): RoomMembersIterator { - membersCallCount++ - return getMembers() - } - - override suspend fun membersNoSync(): RoomMembersIterator { - membersNoSyncCallCount++ - return getMembersNoSync() - } - - override fun close() { - // No-op - } -} - -class FakeRoomMembersIterator( - private var members: List? = null -) : RoomMembersIterator(NoPointer) { - override fun len(): UInt { - return members?.size?.toUInt() ?: 0u - } - - override fun nextChunk(chunkSize: UInt): List? { - if (members?.isEmpty() == true) { - return null - } - return members?.let { - val result = it.take(chunkSize.toInt()) - members = it.subList(result.size, it.size) - result - } - } -} - -private fun fakeRustRoomMember( - userId: UserId, - displayName: String? = null, - avatarUrl: String? = null, - membership: MembershipState = MembershipState.JOIN, - isNameAmbiguous: Boolean = false, - powerLevel: Long = 0L, - isIgnored: Boolean = false, - role: RoomMemberRole = RoomMemberRole.USER, -) = RoomMember( - userId = userId.value, - displayName = displayName, - avatarUrl = avatarUrl, - membership = membership, - isNameAmbiguous = isNameAmbiguous, - powerLevel = powerLevel, - normalizedPowerLevel = powerLevel, - isIgnored = isIgnored, - suggestedRoleForPowerLevel = role, -) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt index faa8a1102e..93096ee227 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt @@ -9,12 +9,10 @@ package io.element.android.libraries.matrix.impl.roomlist import com.google.common.truth.Truth.assertThat import com.sun.jna.Pointer -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.roomlist.RoomSummary +import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoomListItem import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID_2 -import io.element.android.libraries.matrix.test.A_ROOM_NAME import io.element.android.libraries.matrix.test.room.aRoomSummary import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled import kotlinx.coroutines.flow.MutableStateFlow @@ -22,19 +20,12 @@ import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test -import org.matrix.rustcomponents.sdk.EventTimelineItem -import org.matrix.rustcomponents.sdk.Membership -import org.matrix.rustcomponents.sdk.NoPointer -import org.matrix.rustcomponents.sdk.RoomHero -import org.matrix.rustcomponents.sdk.RoomInfo import org.matrix.rustcomponents.sdk.RoomList import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate import org.matrix.rustcomponents.sdk.RoomListItem import org.matrix.rustcomponents.sdk.RoomListServiceInterface import org.matrix.rustcomponents.sdk.RoomListServiceStateListener import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicatorListener -import org.matrix.rustcomponents.sdk.RoomMember -import org.matrix.rustcomponents.sdk.RoomNotificationMode import org.matrix.rustcomponents.sdk.RoomSubscription import org.matrix.rustcomponents.sdk.TaskHandle @@ -48,7 +39,7 @@ class RoomSummaryListProcessorTest { summaries.value = listOf(aRoomSummary()) val processor = createProcessor() - val newEntry = FakeRoomListItem(A_ROOM_ID_2) + val newEntry = FakeRustRoomListItem(A_ROOM_ID_2) processor.postUpdate(listOf(RoomListEntriesUpdate.Append(listOf(newEntry, newEntry, newEntry)))) assertThat(summaries.value.count()).isEqualTo(4) @@ -59,7 +50,7 @@ class RoomSummaryListProcessorTest { fun `PushBack adds a new entry at the end of the list`() = runTest { summaries.value = listOf(aRoomSummaryFilled()) val processor = createProcessor() - processor.postUpdate(listOf(RoomListEntriesUpdate.PushBack(FakeRoomListItem(A_ROOM_ID_2)))) + processor.postUpdate(listOf(RoomListEntriesUpdate.PushBack(FakeRustRoomListItem(A_ROOM_ID_2)))) assertThat(summaries.value.count()).isEqualTo(2) assertThat(summaries.value.last().roomId).isEqualTo(A_ROOM_ID_2) @@ -69,7 +60,7 @@ class RoomSummaryListProcessorTest { fun `PushFront inserts a new entry at the start of the list`() = runTest { summaries.value = listOf(aRoomSummaryFilled()) val processor = createProcessor() - processor.postUpdate(listOf(RoomListEntriesUpdate.PushFront(FakeRoomListItem(A_ROOM_ID_2)))) + processor.postUpdate(listOf(RoomListEntriesUpdate.PushFront(FakeRustRoomListItem(A_ROOM_ID_2)))) assertThat(summaries.value.count()).isEqualTo(2) assertThat(summaries.value.first().roomId).isEqualTo(A_ROOM_ID_2) @@ -81,7 +72,7 @@ class RoomSummaryListProcessorTest { val processor = createProcessor() val index = 0 - processor.postUpdate(listOf(RoomListEntriesUpdate.Set(index.toUInt(), FakeRoomListItem(A_ROOM_ID_2)))) + processor.postUpdate(listOf(RoomListEntriesUpdate.Set(index.toUInt(), FakeRustRoomListItem(A_ROOM_ID_2)))) assertThat(summaries.value.count()).isEqualTo(1) assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2) @@ -93,7 +84,7 @@ class RoomSummaryListProcessorTest { val processor = createProcessor() val index = 0 - processor.postUpdate(listOf(RoomListEntriesUpdate.Insert(index.toUInt(), FakeRoomListItem(A_ROOM_ID_2)))) + processor.postUpdate(listOf(RoomListEntriesUpdate.Insert(index.toUInt(), FakeRustRoomListItem(A_ROOM_ID_2)))) assertThat(summaries.value.count()).isEqualTo(2) assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2) @@ -185,85 +176,3 @@ class RoomSummaryListProcessorTest { override fun subscribeToRooms(roomIds: List, settings: RoomSubscription?) = Unit } } - -private fun aRustRoomInfo( - id: String = A_ROOM_ID.value, - displayName: String = A_ROOM_NAME, - rawName: String = A_ROOM_NAME, - topic: String? = null, - avatarUrl: String? = null, - isDirect: Boolean = false, - isPublic: Boolean = false, - isSpace: Boolean = false, - isTombstoned: Boolean = false, - isFavourite: Boolean = false, - canonicalAlias: String? = null, - alternativeAliases: List = listOf(), - membership: Membership = Membership.JOINED, - inviter: RoomMember? = null, - heroes: List = listOf(), - activeMembersCount: ULong = 0uL, - invitedMembersCount: ULong = 0uL, - joinedMembersCount: ULong = 0uL, - userPowerLevels: Map = mapOf(), - highlightCount: ULong = 0uL, - notificationCount: ULong = 0uL, - userDefinedNotificationMode: RoomNotificationMode? = null, - hasRoomCall: Boolean = false, - activeRoomCallParticipants: List = listOf(), - isMarkedUnread: Boolean = false, - numUnreadMessages: ULong = 0uL, - numUnreadNotifications: ULong = 0uL, - numUnreadMentions: ULong = 0uL, - pinnedEventIds: List = listOf(), - roomCreator: UserId? = null, -) = RoomInfo( - id = id, - displayName = displayName, - rawName = rawName, - topic = topic, - avatarUrl = avatarUrl, - isDirect = isDirect, - isPublic = isPublic, - isSpace = isSpace, - isTombstoned = isTombstoned, - isFavourite = isFavourite, - canonicalAlias = canonicalAlias, - alternativeAliases = alternativeAliases, - membership = membership, - inviter = inviter, - heroes = heroes, - activeMembersCount = activeMembersCount, - invitedMembersCount = invitedMembersCount, - joinedMembersCount = joinedMembersCount, - userPowerLevels = userPowerLevels, - highlightCount = highlightCount, - notificationCount = notificationCount, - cachedUserDefinedNotificationMode = userDefinedNotificationMode, - hasRoomCall = hasRoomCall, - activeRoomCallParticipants = activeRoomCallParticipants, - isMarkedUnread = isMarkedUnread, - numUnreadMessages = numUnreadMessages, - numUnreadNotifications = numUnreadNotifications, - numUnreadMentions = numUnreadMentions, - pinnedEventIds = pinnedEventIds, - creator = roomCreator?.value, -) - -class FakeRoomListItem( - private val roomId: RoomId, - private val roomInfo: RoomInfo = aRustRoomInfo(id = roomId.value), - private val latestEvent: EventTimelineItem? = null, -) : RoomListItem(NoPointer) { - override fun id(): String { - return roomId.value - } - - override suspend fun roomInfo(): RoomInfo { - return roomInfo - } - - override suspend fun latestEvent(): EventTimelineItem? { - return latestEvent - } -} From 352dbdb9cbb63950aa824b1f77bd130e7d79adce Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 Sep 2024 14:26:45 +0200 Subject: [PATCH 061/106] Cleanup tests. --- .../libraries/matrix/impl/fixtures/FakeRustRoom.kt | 14 ++++++-------- .../impl/room/member/RoomMemberListFetcherTest.kt | 12 ------------ 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt index f8f8b88a98..a9321bf347 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt @@ -7,29 +7,27 @@ package io.element.android.libraries.matrix.impl.fixtures +import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.tests.testutils.lambda.lambdaError import org.matrix.rustcomponents.sdk.NoPointer import org.matrix.rustcomponents.sdk.Room import org.matrix.rustcomponents.sdk.RoomMembersIterator class FakeRustRoom( - private val getMembers: () -> RoomMembersIterator = { FakeRustRoomMembersIterator() }, - private val getMembersNoSync: () -> RoomMembersIterator = { FakeRustRoomMembersIterator() }, + private val roomId: RoomId = A_ROOM_ID, + private val getMembers: () -> RoomMembersIterator = { lambdaError() }, + private val getMembersNoSync: () -> RoomMembersIterator = { lambdaError() }, ) : Room(NoPointer) { - var membersCallCount = 0 - var membersNoSyncCallCount = 0 - override fun id(): String { - return A_ROOM_ID.value + return roomId.value } override suspend fun members(): RoomMembersIterator { - membersCallCount++ return getMembers() } override suspend fun membersNoSync(): RoomMembersIterator { - membersNoSyncCallCount++ return getMembersNoSync() } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt index 87e2f5a0b7..dc8489e48f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt @@ -50,10 +50,6 @@ class RoomMemberListFetcherTest { val cachedItemsState = awaitItem() assertThat(cachedItemsState).isInstanceOf(MatrixRoomMembersState.Ready::class.java) assertThat((cachedItemsState as? MatrixRoomMembersState.Ready)?.roomMembers).hasSize(3) - - // Assert only the 'no sync' method was called, so no new member sync happened - assertThat(room.membersNoSyncCallCount).isEqualTo(1) - assertThat(room.membersCallCount).isEqualTo(0) } } @@ -133,10 +129,6 @@ class RoomMemberListFetcherTest { assertThat(awaitItem()).isInstanceOf(MatrixRoomMembersState.Unknown::class.java) assertThat(awaitItem()).isInstanceOf(MatrixRoomMembersState.Pending::class.java) assertThat((awaitItem() as? MatrixRoomMembersState.Ready)?.roomMembers?.size).isEqualTo(3) - - // Assert only the 'sync' method was called, so a new member sync happened - assertThat(room.membersNoSyncCallCount).isEqualTo(0) - assertThat(room.membersCallCount).isEqualTo(1) } } @@ -191,10 +183,6 @@ class RoomMemberListFetcherTest { assertThat(ready).isInstanceOf(MatrixRoomMembersState.Ready::class.java) assertThat(ready.roomMembers()).hasSize(3) } - - // Assert both member methods were called, so both the cache was hit and a new member sync happened - assertThat(room.membersNoSyncCallCount).isEqualTo(1) - assertThat(room.membersCallCount).isEqualTo(1) } } } From 1242316c05de68c78e42b18e943a9f40469c6aaf Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 18 Sep 2024 14:01:24 +0200 Subject: [PATCH 062/106] Timeline : makes sure we don't emit empty list when navigating back to timeline. --- .../features/messages/impl/timeline/TimelinePresenter.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt index 088354f245..29a2786bc0 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 @@ -17,6 +17,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -81,6 +82,7 @@ class TimelinePresenter @AssistedInject constructor( computeReactions = true, ) ) + private var timelineItems by mutableStateOf>(persistentListOf()) @Composable override fun present(): TimelineState { @@ -89,9 +91,12 @@ class TimelinePresenter @AssistedInject constructor( mutableStateOf(FocusRequestState.None) } + LaunchedEffect(Unit) { + timelineItemsFactory.timelineItems.collect { timelineItems = it } + } + val lastReadReceiptId = rememberSaveable { mutableStateOf(null) } - val timelineItems by timelineItemsFactory.timelineItems.collectAsState(initial = persistentListOf()) val roomInfo by room.roomInfoFlow.collectAsState(initial = null) val syncUpdateFlow = room.syncUpdateFlow.collectAsState() From d5ac6dabdf303c78ac346a4ed3917d4403a3a81c Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 18 Sep 2024 17:02:49 +0200 Subject: [PATCH 063/106] Fix sliding sync proxy login not working after native SS failure (#3489) --- .../matrix/impl/auth/RustMatrixAuthenticationService.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index b63e307888..47a81e9f65 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 @@ -42,6 +42,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.first import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.Client +import org.matrix.rustcomponents.sdk.ClientBuildException import org.matrix.rustcomponents.sdk.ClientBuilder import org.matrix.rustcomponents.sdk.HumanQrLoginException import org.matrix.rustcomponents.sdk.OidcConfiguration @@ -292,7 +293,7 @@ class RustMatrixAuthenticationService @Inject constructor( ) .config() .build() - } catch (e: HumanQrLoginException.SlidingSyncNotAvailable) { + } catch (e: ClientBuildException.SlidingSyncVersion) { Timber.e(e, "Failed to create client with simplified sliding sync, trying with Proxy now") } } From 30847e9e1f95e215a520f0448c256c6158a5d90a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 12:09:02 +0200 Subject: [PATCH 064/106] Add unit test on toAnalyticsJoinedRoom and fix a mapping issue. --- .../matrix/impl/analytics/JoinedRoomExt.kt | 5 +- .../impl/analytics/JoinedRoomExtKtTest.kt | 91 +++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExtKtTest.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt index a454c1b58f..81ef1672e3 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt @@ -10,9 +10,10 @@ package io.element.android.libraries.matrix.impl.analytics import im.vector.app.features.analytics.plan.JoinedRoom import io.element.android.libraries.matrix.api.room.MatrixRoom -private fun Long?.toAnalyticsRoomSize(): JoinedRoom.RoomSize { +private fun Long.toAnalyticsRoomSize(): JoinedRoom.RoomSize { return when (this) { - null, + 0L, + 1L -> JoinedRoom.RoomSize.One 2L -> JoinedRoom.RoomSize.Two in 3..10 -> JoinedRoom.RoomSize.ThreeToTen in 11..100 -> JoinedRoom.RoomSize.ElevenToOneHundred diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExtKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExtKtTest.kt new file mode 100644 index 0000000000..6140f32b2e --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExtKtTest.kt @@ -0,0 +1,91 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.analytics + +import com.google.common.truth.Truth.assertThat +import im.vector.app.features.analytics.plan.JoinedRoom +import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import org.junit.Test + +class JoinedRoomExtKtTest { + @Test + fun `test room size mapping`() { + mapOf( + listOf(0L, 1L) to JoinedRoom.RoomSize.One, + listOf(2L, 2L) to JoinedRoom.RoomSize.Two, + listOf(3L, 10L) to JoinedRoom.RoomSize.ThreeToTen, + listOf(11L, 100L) to JoinedRoom.RoomSize.ElevenToOneHundred, + listOf(101L, 1000L) to JoinedRoom.RoomSize.OneHundredAndOneToAThousand, + listOf(1001L, 2000L) to JoinedRoom.RoomSize.MoreThanAThousand + ).forEach { (joinedMemberCounts, expectedRoomSize) -> + joinedMemberCounts.forEach { joinedMemberCount -> + assertThat(aMatrixRoom(joinedMemberCount = joinedMemberCount).toAnalyticsJoinedRoom(null)) + .isEqualTo( + JoinedRoom( + isDM = false, + isSpace = false, + roomSize = expectedRoomSize, + trigger = null + ) + ) + } + } + } + + @Test + fun `test isDirect parameter mapping`() { + assertThat(aMatrixRoom(isDirect = true).toAnalyticsJoinedRoom(null)) + .isEqualTo( + JoinedRoom( + isDM = true, + isSpace = false, + roomSize = JoinedRoom.RoomSize.One, + trigger = null + ) + ) + } + + @Test + fun `test isSpace parameter mapping`() { + assertThat(aMatrixRoom(isSpace = true).toAnalyticsJoinedRoom(null)) + .isEqualTo( + JoinedRoom( + isDM = false, + isSpace = true, + roomSize = JoinedRoom.RoomSize.One, + trigger = null + ) + ) + } + + @Test + fun `test trigger parameter mapping`() { + assertThat(aMatrixRoom().toAnalyticsJoinedRoom(JoinedRoom.Trigger.Invite)) + .isEqualTo( + JoinedRoom( + isDM = false, + isSpace = false, + roomSize = JoinedRoom.RoomSize.One, + trigger = JoinedRoom.Trigger.Invite + ) + ) + } + + private fun aMatrixRoom( + isDirect: Boolean = false, + isSpace: Boolean = false, + joinedMemberCount: Long = 0 + ): MatrixRoom { + return FakeMatrixRoom( + isDirect = isDirect, + isSpace = isSpace, + joinedMemberCount = joinedMemberCount + ) + } +} From e43491ac5a6324f2195f4e532855704d018b74c5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 12:19:38 +0200 Subject: [PATCH 065/106] Add unit test on QrErrorMapper --- .../impl/auth/qrlogin/QrErrorMapperTest.kt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.kt new file mode 100644 index 0000000000..3bbb98fb34 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.auth.qrlogin + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeDecodeException +import io.element.android.libraries.matrix.api.auth.qrlogin.QrLoginException +import org.junit.Test +import org.matrix.rustcomponents.sdk.HumanQrLoginException as RustHumanQrLoginException +import org.matrix.rustcomponents.sdk.QrCodeDecodeException as RustQrCodeDecodeException + +class QrErrorMapperTest { + @Test + fun `test map QrCodeDecodeException`() { + val result = QrErrorMapper.map(RustQrCodeDecodeException.Crypto("test")) + assertThat(result).isInstanceOf(QrCodeDecodeException.Crypto::class.java) + assertThat(result.message).isEqualTo("test") + } + + @Test + fun `test map HumanQrLoginException`() { + assertThat(QrErrorMapper.map(RustHumanQrLoginException.Cancelled())).isEqualTo(QrLoginException.Cancelled) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.ConnectionInsecure())).isEqualTo(QrLoginException.ConnectionInsecure) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.Declined())).isEqualTo(QrLoginException.Declined) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.Expired())).isEqualTo(QrLoginException.Expired) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.OtherDeviceNotSignedIn())).isEqualTo(QrLoginException.OtherDeviceNotSignedIn) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.LinkingNotSupported())).isEqualTo(QrLoginException.LinkingNotSupported) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.Unknown())).isEqualTo(QrLoginException.Unknown) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.OidcMetadataInvalid())).isEqualTo(QrLoginException.OidcMetadataInvalid) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.SlidingSyncNotAvailable())).isEqualTo(QrLoginException.SlidingSyncNotAvailable) + } +} From 18461fa1f175ab2423562c7db4d8a23b4f3d7820 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 12:24:42 +0200 Subject: [PATCH 066/106] Add unit test on QrLoginProgress.toStep() --- .../QrLoginProgressExtensionsKtTest.kt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt new file mode 100644 index 0000000000..0de3d15e57 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.auth.qrlogin + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep +import org.junit.Test +import org.matrix.rustcomponents.sdk.QrLoginProgress + +class QrLoginProgressExtensionsKtTest { + @Test + fun `mapping QrLoginProgress should return expected result`() { + assertThat(QrLoginProgress.Starting.toStep()) + .isEqualTo(QrCodeLoginStep.Starting) + assertThat(QrLoginProgress.EstablishingSecureChannel(1u, "01").toStep()) + .isEqualTo(QrCodeLoginStep.EstablishingSecureChannel("01")) + assertThat(QrLoginProgress.WaitingForToken("userCode").toStep()) + .isEqualTo(QrCodeLoginStep.WaitingForToken("userCode")) + assertThat(QrLoginProgress.Done.toStep()) + .isEqualTo(QrCodeLoginStep.Finished) + } +} + + From 25fd71cb2c3517768a33ccde4d4ba6d7e10db1b4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 12:40:26 +0200 Subject: [PATCH 067/106] Make sure Throwable.mapAuthenticationException() is exhaustive on mapping ClientBuildException and add test for full coverage. --- .../matrix/impl/auth/AuthenticationException.kt | 15 +++++++++++---- .../auth/AuthenticationExceptionMappingTest.kt | 17 ++++++++++++++--- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt index 278b814fe2..cf48d68c70 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt @@ -8,14 +8,21 @@ package io.element.android.libraries.matrix.impl.auth import io.element.android.libraries.matrix.api.auth.AuthenticationException -import org.matrix.rustcomponents.sdk.ClientBuildException as RustAuthenticationException +import org.matrix.rustcomponents.sdk.ClientBuildException fun Throwable.mapAuthenticationException(): AuthenticationException { val message = this.message ?: "Unknown error" return when (this) { - is RustAuthenticationException.Generic -> AuthenticationException.Generic(message) - is RustAuthenticationException.InvalidServerName -> AuthenticationException.InvalidServerName(message) - is RustAuthenticationException.SlidingSyncVersion -> AuthenticationException.SlidingSyncVersion(message) + is ClientBuildException -> when (this) { + is ClientBuildException.Generic -> AuthenticationException.Generic(message) + is ClientBuildException.InvalidServerName -> AuthenticationException.InvalidServerName(message) + is ClientBuildException.SlidingSyncVersion -> AuthenticationException.SlidingSyncVersion(message) + is ClientBuildException.Sdk -> AuthenticationException.Generic(message) + is ClientBuildException.ServerUnreachable -> AuthenticationException.Generic(message) + is ClientBuildException.SlidingSync -> AuthenticationException.Generic(message) + is ClientBuildException.WellKnownDeserializationException -> AuthenticationException.Generic(message) + is ClientBuildException.WellKnownLookupFailed -> AuthenticationException.Generic(message) + } else -> AuthenticationException.Generic(message) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt index fd007151c8..81a1667f4e 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt @@ -36,13 +36,24 @@ class AuthenticationExceptionMappingTest { assertThat(ClientBuildException.InvalidServerName("Invalid server name").mapAuthenticationException()) .isException("Invalid server name") - assertThat(ClientBuildException.Sdk("SDK issue").mapAuthenticationException()) - .isException("SDK issue") - assertThat(ClientBuildException.SlidingSyncVersion("Sliding sync not available").mapAuthenticationException()) .isException("Sliding sync not available") } + @Test + fun `mapping other exceptions map to the Generic Kotlin`() { + assertThat(ClientBuildException.Sdk("SDK issue").mapAuthenticationException()) + .isException("SDK issue") + assertThat(ClientBuildException.ServerUnreachable("Server unreachable").mapAuthenticationException()) + .isException("Server unreachable") + assertThat(ClientBuildException.SlidingSync("Sliding Sync").mapAuthenticationException()) + .isException("Sliding Sync") + assertThat(ClientBuildException.WellKnownDeserializationException("WellKnown Deserialization").mapAuthenticationException()) + .isException("WellKnown Deserialization") + assertThat(ClientBuildException.WellKnownLookupFailed("WellKnown Lookup Failed").mapAuthenticationException()) + .isException("WellKnown Lookup Failed") + } + private inline fun ThrowableSubject.isException(message: String) { isInstanceOf(T::class.java) hasMessageThat().isEqualTo(message) From 021d7297e57a809a426598730da45267b10502da Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 12:47:55 +0200 Subject: [PATCH 068/106] Add unit test on ProgressWatcherWrapper --- .../impl/core/ProgressWatcherWrapperKtTest.kt | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/core/ProgressWatcherWrapperKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/core/ProgressWatcherWrapperKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/core/ProgressWatcherWrapperKtTest.kt new file mode 100644 index 0000000000..316c69ebb7 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/core/ProgressWatcherWrapperKtTest.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.core + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.ProgressCallback +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.matrix.rustcomponents.sdk.TransmissionProgress +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine + +class ProgressWatcherWrapperKtTest { + @Test + fun testToProgressWatcher() = runTest { + suspendCoroutine { continuation -> + val callback = object : ProgressCallback { + override fun onProgress(current: Long, total: Long) { + assertThat(current).isEqualTo(1) + assertThat(total).isEqualTo(2) + continuation.resume(Unit) + } + } + val result = callback.toProgressWatcher() + result.transmissionProgress(TransmissionProgress(1.toULong(), 2.toULong())) + } + } +} From eca112fcc0c4c161ee1d175778eea8b71e194a43 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 12:52:46 +0200 Subject: [PATCH 069/106] Add unit test on providesTracingFilterConfiguration --- .../matrix/impl/di/TracingMatrixModuleTest.kt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/di/TracingMatrixModuleTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/di/TracingMatrixModuleTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/di/TracingMatrixModuleTest.kt new file mode 100644 index 0000000000..687ca3d56c --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/di/TracingMatrixModuleTest.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.di + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.core.meta.BuildType +import io.element.android.libraries.matrix.api.tracing.TracingFilterConfigurations +import io.element.android.libraries.matrix.test.core.aBuildMeta +import org.junit.Test + +class TracingMatrixModuleTest { + @Test + fun `providesTracingFilterConfiguration returns debug config for debug build`() { + assertThat(TracingMatrixModule.providesTracingFilterConfiguration(aBuildMeta(BuildType.DEBUG))) + .isEqualTo(TracingFilterConfigurations.debug) + } + + @Test + fun `providesTracingFilterConfiguration returns nightly config for nightly build`() { + assertThat(TracingMatrixModule.providesTracingFilterConfiguration(aBuildMeta(BuildType.NIGHTLY))) + .isEqualTo(TracingFilterConfigurations.nightly) + } + + @Test + fun `providesTracingFilterConfiguration returns release config for release build`() { + assertThat(TracingMatrixModule.providesTracingFilterConfiguration(aBuildMeta(BuildType.RELEASE))) + .isEqualTo(TracingFilterConfigurations.release) + } +} From 5b8e99149a7c283c0d7b1ec79e70a83f5494c71a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 12:58:00 +0200 Subject: [PATCH 070/106] Add unit test on crypto mappers --- .../impl/encryption/BackupStateMapperTest.kt | 26 +++++++++++++++ .../encryption/BackupUploadStateMapperTest.kt | 33 +++++++++++++++++++ .../EnableRecoveryProgressMapperTest.kt | 31 +++++++++++++++++ .../encryption/RecoveryStateMapperTest.kt | 23 +++++++++++++ 4 files changed, 113 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt new file mode 100644 index 0000000000..fc804b0978 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE 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.BackupState +import org.junit.Test +import org.matrix.rustcomponents.sdk.BackupState as RustBackupState + +class BackupStateMapperTest { + @Test + fun `Ensure that mapping is correct`() { + assertThat(BackupStateMapper().map(RustBackupState.UNKNOWN)).isEqualTo(BackupState.UNKNOWN) + assertThat(BackupStateMapper().map(RustBackupState.CREATING)).isEqualTo(BackupState.CREATING) + assertThat(BackupStateMapper().map(RustBackupState.ENABLING)).isEqualTo(BackupState.ENABLING) + assertThat(BackupStateMapper().map(RustBackupState.RESUMING)).isEqualTo(BackupState.RESUMING) + assertThat(BackupStateMapper().map(RustBackupState.ENABLED)).isEqualTo(BackupState.ENABLED) + assertThat(BackupStateMapper().map(RustBackupState.DOWNLOADING)).isEqualTo(BackupState.DOWNLOADING) + assertThat(BackupStateMapper().map(RustBackupState.DISABLING)).isEqualTo(BackupState.DISABLING) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt new file mode 100644 index 0000000000..7c1ad1d7c5 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE 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.BackupUploadState +import org.junit.Test +import org.matrix.rustcomponents.sdk.BackupUploadState as RustBackupUploadState + +class BackupUploadStateMapperTest { + @Test + fun `Ensure that mapping is correct`() { + assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Waiting)) + .isEqualTo(BackupUploadState.Waiting) + assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Error)) + .isEqualTo(BackupUploadState.Error) + assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Done)) + .isEqualTo(BackupUploadState.Done) + assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Uploading(1.toUInt(), 2.toUInt()))) + .isEqualTo(BackupUploadState.Uploading(1, 2)) + } + + @Test + fun `Ensure that full uploading is mapper to Done`() { + assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Uploading(2.toUInt(), 2.toUInt()))) + .isEqualTo(BackupUploadState.Done) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt new file mode 100644 index 0000000000..191a7f3964 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE 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.EnableRecoveryProgress +import org.junit.Test +import org.matrix.rustcomponents.sdk.EnableRecoveryProgress as RustEnableRecoveryProgress + +class EnableRecoveryProgressMapperTest { + @Test + fun `Ensure that mapping is correct`() { + assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.CreatingRecoveryKey)) + .isEqualTo(EnableRecoveryProgress.CreatingRecoveryKey) + assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.CreatingBackup)) + .isEqualTo(EnableRecoveryProgress.CreatingBackup) + assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.Starting)) + .isEqualTo(EnableRecoveryProgress.Starting) + assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.BackingUp(1.toUInt(), 2.toUInt()))) + .isEqualTo(EnableRecoveryProgress.BackingUp(1, 2)) + assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.RoomKeyUploadError)) + .isEqualTo(EnableRecoveryProgress.RoomKeyUploadError) + assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.Done("recoveryKey"))) + .isEqualTo(EnableRecoveryProgress.Done("recoveryKey")) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.kt new file mode 100644 index 0000000000..9d7c2d0c04 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE 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.RecoveryState +import org.junit.Test +import org.matrix.rustcomponents.sdk.RecoveryState as RustRecoveryState + +class RecoveryStateMapperTest { + @Test + fun `Ensure that mapping is correct`() { + assertThat(RecoveryStateMapper().map(RustRecoveryState.UNKNOWN)).isEqualTo(RecoveryState.UNKNOWN) + assertThat(RecoveryStateMapper().map(RustRecoveryState.ENABLED)).isEqualTo(RecoveryState.ENABLED) + assertThat(RecoveryStateMapper().map(RustRecoveryState.DISABLED)).isEqualTo(RecoveryState.DISABLED) + assertThat(RecoveryStateMapper().map(RustRecoveryState.INCOMPLETE)).isEqualTo(RecoveryState.INCOMPLETE) + } +} From 5b44eab444b25934cab23ca5495b2316ca1be28a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 13:05:45 +0200 Subject: [PATCH 071/106] Ensure mapping of Rust exceptions cover all cases. --- .../impl/encryption/RecoveryExceptionMapper.kt | 18 +++++++++++------- .../matrix/impl/exception/ClientException.kt | 6 +++++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt index e200ca5434..b33d59375b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt @@ -14,13 +14,17 @@ import org.matrix.rustcomponents.sdk.RecoveryException as RustRecoveryException fun Throwable.mapRecoveryException(): RecoveryException { return when (this) { - is RustRecoveryException.SecretStorage -> RecoveryException.SecretStorage( - message = errorMessage - ) - is RustRecoveryException.BackupExistsOnServer -> RecoveryException.BackupExistsOnServer - is RustRecoveryException.Client -> RecoveryException.Client( - source.mapClientException() - ) + is RustRecoveryException -> { + when (this) { + is RustRecoveryException.SecretStorage -> RecoveryException.SecretStorage( + message = errorMessage + ) + is RustRecoveryException.BackupExistsOnServer -> RecoveryException.BackupExistsOnServer + is RustRecoveryException.Client -> RecoveryException.Client( + source.mapClientException() + ) + } + } else -> RecoveryException.Client( ClientException.Other("Unknown error") ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/exception/ClientException.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/exception/ClientException.kt index c15b873d73..87364930ce 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/exception/ClientException.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/exception/ClientException.kt @@ -12,7 +12,11 @@ import org.matrix.rustcomponents.sdk.ClientException as RustClientException fun Throwable.mapClientException(): ClientException { return when (this) { - is RustClientException.Generic -> ClientException.Generic(msg) + is RustClientException -> { + when (this) { + is RustClientException.Generic -> ClientException.Generic(msg) + } + } else -> ClientException.Other(message ?: "Unknown error") } } From 03b9a0f3137d63c5a40f49ba2e6935bb72309c37 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 13:26:29 +0200 Subject: [PATCH 072/106] Add unit test on mappers --- .../matrix/impl/room/StateEventTypeTest.kt | 68 +++++++++++++++++++ .../powerlevels/RoomPowerLevelsMapperTest.kt | 46 +++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt new file mode 100644 index 0000000000..3772ae780d --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt @@ -0,0 +1,68 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.room + +import com.google.common.truth.Truth.assertThat +import org.junit.Test + +import io.element.android.libraries.matrix.api.room.StateEventType +import org.matrix.rustcomponents.sdk.StateEventType as RustStateEventType + +class StateEventTypeTest { + @Test + fun `mapping Rust type should work`() { + assertThat(RustStateEventType.CALL_MEMBER.map()).isEqualTo(StateEventType.CALL_MEMBER) + assertThat(RustStateEventType.POLICY_RULE_ROOM.map()).isEqualTo(StateEventType.POLICY_RULE_ROOM) + assertThat(RustStateEventType.POLICY_RULE_SERVER.map()).isEqualTo(StateEventType.POLICY_RULE_SERVER) + assertThat(RustStateEventType.POLICY_RULE_USER.map()).isEqualTo(StateEventType.POLICY_RULE_USER) + assertThat(RustStateEventType.ROOM_ALIASES.map()).isEqualTo(StateEventType.ROOM_ALIASES) + assertThat(RustStateEventType.ROOM_AVATAR.map()).isEqualTo(StateEventType.ROOM_AVATAR) + assertThat(RustStateEventType.ROOM_CANONICAL_ALIAS.map()).isEqualTo(StateEventType.ROOM_CANONICAL_ALIAS) + assertThat(RustStateEventType.ROOM_CREATE.map()).isEqualTo(StateEventType.ROOM_CREATE) + assertThat(RustStateEventType.ROOM_ENCRYPTION.map()).isEqualTo(StateEventType.ROOM_ENCRYPTION) + assertThat(RustStateEventType.ROOM_GUEST_ACCESS.map()).isEqualTo(StateEventType.ROOM_GUEST_ACCESS) + assertThat(RustStateEventType.ROOM_HISTORY_VISIBILITY.map()).isEqualTo(StateEventType.ROOM_HISTORY_VISIBILITY) + assertThat(RustStateEventType.ROOM_JOIN_RULES.map()).isEqualTo(StateEventType.ROOM_JOIN_RULES) + assertThat(RustStateEventType.ROOM_MEMBER_EVENT.map()).isEqualTo(StateEventType.ROOM_MEMBER_EVENT) + assertThat(RustStateEventType.ROOM_NAME.map()).isEqualTo(StateEventType.ROOM_NAME) + assertThat(RustStateEventType.ROOM_PINNED_EVENTS.map()).isEqualTo(StateEventType.ROOM_PINNED_EVENTS) + assertThat(RustStateEventType.ROOM_POWER_LEVELS.map()).isEqualTo(StateEventType.ROOM_POWER_LEVELS) + assertThat(RustStateEventType.ROOM_SERVER_ACL.map()).isEqualTo(StateEventType.ROOM_SERVER_ACL) + assertThat(RustStateEventType.ROOM_THIRD_PARTY_INVITE.map()).isEqualTo(StateEventType.ROOM_THIRD_PARTY_INVITE) + assertThat(RustStateEventType.ROOM_TOMBSTONE.map()).isEqualTo(StateEventType.ROOM_TOMBSTONE) + assertThat(RustStateEventType.ROOM_TOPIC.map()).isEqualTo(StateEventType.ROOM_TOPIC) + assertThat(RustStateEventType.SPACE_CHILD.map()).isEqualTo(StateEventType.SPACE_CHILD) + assertThat(RustStateEventType.SPACE_PARENT.map()).isEqualTo(StateEventType.SPACE_PARENT) + } + + @Test + fun `mapping Kotlin type should work`() { + assertThat(StateEventType.CALL_MEMBER.map()).isEqualTo(RustStateEventType.CALL_MEMBER) + assertThat(StateEventType.POLICY_RULE_ROOM.map()).isEqualTo(RustStateEventType.POLICY_RULE_ROOM) + assertThat(StateEventType.POLICY_RULE_SERVER.map()).isEqualTo(RustStateEventType.POLICY_RULE_SERVER) + assertThat(StateEventType.POLICY_RULE_USER.map()).isEqualTo(RustStateEventType.POLICY_RULE_USER) + assertThat(StateEventType.ROOM_ALIASES.map()).isEqualTo(RustStateEventType.ROOM_ALIASES) + assertThat(StateEventType.ROOM_AVATAR.map()).isEqualTo(RustStateEventType.ROOM_AVATAR) + assertThat(StateEventType.ROOM_CANONICAL_ALIAS.map()).isEqualTo(RustStateEventType.ROOM_CANONICAL_ALIAS) + assertThat(StateEventType.ROOM_CREATE.map()).isEqualTo(RustStateEventType.ROOM_CREATE) + assertThat(StateEventType.ROOM_ENCRYPTION.map()).isEqualTo(RustStateEventType.ROOM_ENCRYPTION) + assertThat(StateEventType.ROOM_GUEST_ACCESS.map()).isEqualTo(RustStateEventType.ROOM_GUEST_ACCESS) + assertThat(StateEventType.ROOM_HISTORY_VISIBILITY.map()).isEqualTo(RustStateEventType.ROOM_HISTORY_VISIBILITY) + assertThat(StateEventType.ROOM_JOIN_RULES.map()).isEqualTo(RustStateEventType.ROOM_JOIN_RULES) + assertThat(StateEventType.ROOM_MEMBER_EVENT.map()).isEqualTo(RustStateEventType.ROOM_MEMBER_EVENT) + assertThat(StateEventType.ROOM_NAME.map()).isEqualTo(RustStateEventType.ROOM_NAME) + assertThat(StateEventType.ROOM_PINNED_EVENTS.map()).isEqualTo(RustStateEventType.ROOM_PINNED_EVENTS) + assertThat(StateEventType.ROOM_POWER_LEVELS.map()).isEqualTo(RustStateEventType.ROOM_POWER_LEVELS) + assertThat(StateEventType.ROOM_SERVER_ACL.map()).isEqualTo(RustStateEventType.ROOM_SERVER_ACL) + assertThat(StateEventType.ROOM_THIRD_PARTY_INVITE.map()).isEqualTo(RustStateEventType.ROOM_THIRD_PARTY_INVITE) + assertThat(StateEventType.ROOM_TOMBSTONE.map()).isEqualTo(RustStateEventType.ROOM_TOMBSTONE) + assertThat(StateEventType.ROOM_TOPIC.map()).isEqualTo(RustStateEventType.ROOM_TOPIC) + assertThat(StateEventType.SPACE_CHILD.map()).isEqualTo(RustStateEventType.SPACE_CHILD) + assertThat(StateEventType.SPACE_PARENT.map()).isEqualTo(RustStateEventType.SPACE_PARENT) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt new file mode 100644 index 0000000000..2a8a89004d --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.room.powerlevels + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.room.powerlevels.MatrixRoomPowerLevels +import org.junit.Test +import org.matrix.rustcomponents.sdk.RoomPowerLevels as RustRoomPowerLevels + +class RoomPowerLevelsMapperTest { + @Test + fun `test that mapping of RoomPowerLevels is correct`() { + assertThat( + RoomPowerLevelsMapper.map( + RustRoomPowerLevels( + ban = 1, + invite = 2, + kick = 3, + redact = 4, + eventsDefault = 5, + stateDefault = 6, + usersDefault = 7, + roomName = 8, + roomAvatar = 9, + roomTopic = 10, + ) + ) + ).isEqualTo( + MatrixRoomPowerLevels( + ban = 1, + invite = 2, + kick = 3, + sendEvents = 5, + redactEvents = 4, + roomName = 8, + roomAvatar = 9, + roomTopic = 10, + ) + ) + } +} From 764b0cf8d3194c4d0b1810f605e2374477fcaa70 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 13:39:17 +0200 Subject: [PATCH 073/106] Add unit test on elementHeroes() --- .../matrix/impl/room/RoomInfoExtTest.kt | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt new file mode 100644 index 0000000000..7c5c873155 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt @@ -0,0 +1,76 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.room + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.impl.fixtures.aRustRoomInfo +import io.element.android.libraries.matrix.test.A_USER_ID +import org.junit.Test +import org.matrix.rustcomponents.sdk.RoomHero + +class RoomInfoExtTest { + @Test + fun `get non empty element Heroes`() { + val result = aRustRoomInfo( + isDirect = true, + activeMembersCount = 2uL, + heroes = listOf(aRoomHero()) + ).elementHeroes() + assertThat(result).isEqualTo( + listOf( + MatrixUser( + userId = UserId(A_USER_ID.value), + displayName = "displayName", + avatarUrl = "avatarUrl", + ) + ) + ) + } + + @Test + fun `too many heroes and element Heroes is empty`() { + val result = aRustRoomInfo( + isDirect = true, + activeMembersCount = 2uL, + heroes = listOf(aRoomHero(), aRoomHero()) + ).elementHeroes() + assertThat(result).isEmpty() + } + + @Test + fun `not direct and element Heroes is empty`() { + val result = aRustRoomInfo( + isDirect = false, + activeMembersCount = 2uL, + heroes = listOf(aRoomHero()) + ).elementHeroes() + assertThat(result).isEmpty() + } + + @Test + fun `too many members and element Heroes is empty`() { + val result = aRustRoomInfo( + isDirect = true, + activeMembersCount = 3uL, + heroes = listOf(aRoomHero()) + ).elementHeroes() + assertThat(result).isEmpty() + } +} + +private fun aRoomHero( + userId: UserId = A_USER_ID, +): RoomHero { + return RoomHero( + userId = userId.value, + displayName = "displayName", + avatarUrl = "avatarUrl", + ) +} From 56ac755b62e0bc9aa0403a7bd6f83a75c5721e5a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 13:42:23 +0200 Subject: [PATCH 074/106] Add unit test on MessageEventType mappers --- .../impl/room/MessageEventTypeKtTest.kt | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt new file mode 100644 index 0000000000..847c41e89a --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.room + +import com.google.common.truth.Truth.assertThat +import org.junit.Test + +import io.element.android.libraries.matrix.api.room.MessageEventType +import org.matrix.rustcomponents.sdk.MessageLikeEventType + +class MessageEventTypeKtTest { + @Test + fun `map Rust type should result to correct Kotlin type`() { + assertThat(MessageLikeEventType.CALL_ANSWER.map()).isEqualTo(MessageEventType.CALL_ANSWER) + assertThat(MessageLikeEventType.CALL_INVITE.map()).isEqualTo(MessageEventType.CALL_INVITE) + assertThat(MessageLikeEventType.CALL_HANGUP.map()).isEqualTo(MessageEventType.CALL_HANGUP) + assertThat(MessageLikeEventType.CALL_CANDIDATES.map()).isEqualTo(MessageEventType.CALL_CANDIDATES) + assertThat(MessageLikeEventType.CALL_NOTIFY.map()).isEqualTo(MessageEventType.CALL_NOTIFY) + assertThat(MessageLikeEventType.KEY_VERIFICATION_READY.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_READY) + assertThat(MessageLikeEventType.KEY_VERIFICATION_START.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_START) + assertThat(MessageLikeEventType.KEY_VERIFICATION_CANCEL.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_CANCEL) + assertThat(MessageLikeEventType.KEY_VERIFICATION_ACCEPT.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_ACCEPT) + assertThat(MessageLikeEventType.KEY_VERIFICATION_KEY.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_KEY) + assertThat(MessageLikeEventType.KEY_VERIFICATION_MAC.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_MAC) + assertThat(MessageLikeEventType.KEY_VERIFICATION_DONE.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_DONE) + assertThat(MessageLikeEventType.REACTION.map()).isEqualTo(MessageEventType.REACTION) + assertThat(MessageLikeEventType.ROOM_ENCRYPTED.map()).isEqualTo(MessageEventType.ROOM_ENCRYPTED) + assertThat(MessageLikeEventType.ROOM_MESSAGE.map()).isEqualTo(MessageEventType.ROOM_MESSAGE) + assertThat(MessageLikeEventType.ROOM_REDACTION.map()).isEqualTo(MessageEventType.ROOM_REDACTION) + assertThat(MessageLikeEventType.STICKER.map()).isEqualTo(MessageEventType.STICKER) + assertThat(MessageLikeEventType.POLL_END.map()).isEqualTo(MessageEventType.POLL_END) + assertThat(MessageLikeEventType.POLL_RESPONSE.map()).isEqualTo(MessageEventType.POLL_RESPONSE) + assertThat(MessageLikeEventType.POLL_START.map()).isEqualTo(MessageEventType.POLL_START) + assertThat(MessageLikeEventType.UNSTABLE_POLL_END.map()).isEqualTo(MessageEventType.UNSTABLE_POLL_END) + assertThat(MessageLikeEventType.UNSTABLE_POLL_RESPONSE.map()).isEqualTo(MessageEventType.UNSTABLE_POLL_RESPONSE) + assertThat(MessageLikeEventType.UNSTABLE_POLL_START.map()).isEqualTo(MessageEventType.UNSTABLE_POLL_START) + } + + @Test + fun `map Kotlin type should result to correct Rust type`() { + assertThat(MessageEventType.CALL_ANSWER.map()).isEqualTo(MessageLikeEventType.CALL_ANSWER) + assertThat(MessageEventType.CALL_INVITE.map()).isEqualTo(MessageLikeEventType.CALL_INVITE) + assertThat(MessageEventType.CALL_HANGUP.map()).isEqualTo(MessageLikeEventType.CALL_HANGUP) + assertThat(MessageEventType.CALL_CANDIDATES.map()).isEqualTo(MessageLikeEventType.CALL_CANDIDATES) + assertThat(MessageEventType.CALL_NOTIFY.map()).isEqualTo(MessageLikeEventType.CALL_NOTIFY) + assertThat(MessageEventType.KEY_VERIFICATION_READY.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_READY) + assertThat(MessageEventType.KEY_VERIFICATION_START.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_START) + assertThat(MessageEventType.KEY_VERIFICATION_CANCEL.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_CANCEL) + assertThat(MessageEventType.KEY_VERIFICATION_ACCEPT.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_ACCEPT) + assertThat(MessageEventType.KEY_VERIFICATION_KEY.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_KEY) + assertThat(MessageEventType.KEY_VERIFICATION_MAC.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_MAC) + assertThat(MessageEventType.KEY_VERIFICATION_DONE.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_DONE) + assertThat(MessageEventType.REACTION.map()).isEqualTo(MessageLikeEventType.REACTION) + assertThat(MessageEventType.ROOM_ENCRYPTED.map()).isEqualTo(MessageLikeEventType.ROOM_ENCRYPTED) + assertThat(MessageEventType.ROOM_MESSAGE.map()).isEqualTo(MessageLikeEventType.ROOM_MESSAGE) + assertThat(MessageEventType.ROOM_REDACTION.map()).isEqualTo(MessageLikeEventType.ROOM_REDACTION) + assertThat(MessageEventType.STICKER.map()).isEqualTo(MessageLikeEventType.STICKER) + assertThat(MessageEventType.POLL_END.map()).isEqualTo(MessageLikeEventType.POLL_END) + assertThat(MessageEventType.POLL_RESPONSE.map()).isEqualTo(MessageLikeEventType.POLL_RESPONSE) + assertThat(MessageEventType.POLL_START.map()).isEqualTo(MessageLikeEventType.POLL_START) + assertThat(MessageEventType.UNSTABLE_POLL_END.map()).isEqualTo(MessageLikeEventType.UNSTABLE_POLL_END) + assertThat(MessageEventType.UNSTABLE_POLL_RESPONSE.map()).isEqualTo(MessageLikeEventType.UNSTABLE_POLL_RESPONSE) + assertThat(MessageEventType.UNSTABLE_POLL_START.map()).isEqualTo(MessageLikeEventType.UNSTABLE_POLL_START) + } +} From 79032235859b9af84e73b38c12071ca8c7970743 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 13:54:40 +0200 Subject: [PATCH 075/106] Change type of items in `alternativeAliases` from String to RoomAlias --- .../element/android/libraries/matrix/api/room/MatrixRoomInfo.kt | 2 +- .../android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt | 2 +- .../android/libraries/matrix/test/room/FakeMatrixRoom.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt index b466a28da6..e335996cd0 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt @@ -31,7 +31,7 @@ data class MatrixRoomInfo( val isTombstoned: Boolean, val isFavorite: Boolean, val canonicalAlias: RoomAlias?, - val alternativeAliases: ImmutableList, + val alternativeAliases: ImmutableList, val currentUserMembership: CurrentUserMembership, val inviter: RoomMember?, val activeMembersCount: Long, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt index 7fcef163b6..1126d3dab9 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt @@ -39,7 +39,7 @@ class MatrixRoomInfoMapper { isTombstoned = it.isTombstoned, isFavorite = it.isFavourite, canonicalAlias = it.canonicalAlias?.let(::RoomAlias), - alternativeAliases = it.alternativeAliases.toImmutableList(), + alternativeAliases = it.alternativeAliases.map(::RoomAlias).toImmutableList(), currentUserMembership = it.membership.map(), inviter = it.inviter?.let(RoomMemberMapper::map), activeMembersCount = it.activeMembersCount.toLong(), diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 54b52c6fb7..8ff9d70bcc 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -520,7 +520,7 @@ fun aRoomInfo( isTombstoned: Boolean = false, isFavorite: Boolean = false, canonicalAlias: RoomAlias? = null, - alternativeAliases: List = emptyList(), + alternativeAliases: List = emptyList(), currentUserMembership: CurrentUserMembership = CurrentUserMembership.JOINED, inviter: RoomMember? = null, activeMembersCount: Long = 1, From 97f0b65c03775eb86ed57718c6a19572199fab8c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 13:59:17 +0200 Subject: [PATCH 076/106] Change type of items in `activeRoomCallParticipants` from String to UserId --- .../element/android/libraries/matrix/api/room/MatrixRoomInfo.kt | 2 +- .../android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt | 2 +- .../android/libraries/matrix/test/room/FakeMatrixRoom.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt index e335996cd0..b83c2c98d6 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt @@ -42,7 +42,7 @@ data class MatrixRoomInfo( val notificationCount: Long, val userDefinedNotificationMode: RoomNotificationMode?, val hasRoomCall: Boolean, - val activeRoomCallParticipants: ImmutableList, + val activeRoomCallParticipants: ImmutableList, val heroes: ImmutableList, val pinnedEventIds: ImmutableList, val creator: UserId?, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt index 1126d3dab9..c7ed6c1205 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt @@ -50,7 +50,7 @@ class MatrixRoomInfoMapper { notificationCount = it.notificationCount.toLong(), userDefinedNotificationMode = it.cachedUserDefinedNotificationMode?.map(), hasRoomCall = it.hasRoomCall, - activeRoomCallParticipants = it.activeRoomCallParticipants.toImmutableList(), + activeRoomCallParticipants = it.activeRoomCallParticipants.map(::UserId).toImmutableList(), heroes = it.elementHeroes().toImmutableList(), pinnedEventIds = it.pinnedEventIds.map(::EventId).toImmutableList(), ) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 8ff9d70bcc..076baf5f2b 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -531,7 +531,7 @@ fun aRoomInfo( userDefinedNotificationMode: RoomNotificationMode? = null, hasRoomCall: Boolean = false, userPowerLevels: ImmutableMap = persistentMapOf(), - activeRoomCallParticipants: List = emptyList(), + activeRoomCallParticipants: List = emptyList(), heroes: List = emptyList(), pinnedEventIds: List = emptyList(), roomCreator: UserId? = null, From a60198a7167cc859f44c99be2a948035226f8c74 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:10:01 +0200 Subject: [PATCH 077/106] Add unit test on MatrixRoomInfoMapper --- .../matrix/impl/fixtures/RustRoomInfo.kt | 4 +- .../impl/room/MatrixRoomInfoMapperTest.kt | 189 ++++++++++++++++++ .../matrix/impl/room/RoomInfoExtTest.kt | 2 +- 3 files changed, 192 insertions(+), 3 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt index e64dabf27a..b78780ee23 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt @@ -18,8 +18,8 @@ import org.matrix.rustcomponents.sdk.RoomNotificationMode fun aRustRoomInfo( id: String = A_ROOM_ID.value, - displayName: String = A_ROOM_NAME, - rawName: String = A_ROOM_NAME, + displayName: String? = A_ROOM_NAME, + rawName: String? = A_ROOM_NAME, topic: String? = null, avatarUrl: String? = null, isDirect: Boolean = false, diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt new file mode 100644 index 0000000000..f0b02df6b7 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt @@ -0,0 +1,189 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.room + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomAlias +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.CurrentUserMembership +import io.element.android.libraries.matrix.api.room.MatrixRoomInfo +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.impl.room.member.aRustRoomMember +import io.element.android.libraries.matrix.impl.roomlist.aRustRoomInfo +import io.element.android.libraries.matrix.test.AN_AVATAR_URL +import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.A_ROOM_ALIAS +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.A_USER_ID_3 +import io.element.android.libraries.matrix.test.A_USER_ID_6 +import io.element.android.libraries.matrix.test.room.aRoomMember +import kotlinx.collections.immutable.toImmutableList +import kotlinx.collections.immutable.toImmutableMap +import kotlinx.collections.immutable.toPersistentList +import org.junit.Test +import org.matrix.rustcomponents.sdk.Membership +import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode + +class MatrixRoomInfoMapperTest { + @Test + fun `mapping of RustRoomInfo should map all the fields`() { + assertThat( + MatrixRoomInfoMapper().map( + aRustRoomInfo( + id = A_ROOM_ID.value, + displayName = "displayName", + rawName = "rawName", + topic = "topic", + avatarUrl = AN_AVATAR_URL, + isDirect = true, + isPublic = false, + isSpace = false, + isTombstoned = false, + isFavourite = false, + canonicalAlias = A_ROOM_ALIAS.value, + alternativeAliases = listOf(A_ROOM_ALIAS.value), + membership = Membership.JOINED, + inviter = aRustRoomMember(A_USER_ID), + heroes = listOf(aRoomHero()), + activeMembersCount = 2uL, + invitedMembersCount = 3uL, + joinedMembersCount = 4uL, + userPowerLevels = mapOf(A_USER_ID_6.value to 50L), + highlightCount = 10uL, + notificationCount = 11uL, + userDefinedNotificationMode = RustRoomNotificationMode.MUTE, + hasRoomCall = true, + activeRoomCallParticipants = listOf(A_USER_ID_3.value), + isMarkedUnread = false, + numUnreadMessages = 12uL, + numUnreadNotifications = 13uL, + numUnreadMentions = 14uL, + pinnedEventIds = listOf(AN_EVENT_ID.value), + ) + ) + ).isEqualTo( + MatrixRoomInfo( + id = A_ROOM_ID, + name = "displayName", + rawName = "rawName", + topic = "topic", + avatarUrl = AN_AVATAR_URL, + isDirect = true, + isPublic = false, + isSpace = false, + isTombstoned = false, + isFavorite = false, + canonicalAlias = A_ROOM_ALIAS, + alternativeAliases = listOf(A_ROOM_ALIAS).toImmutableList(), + currentUserMembership = CurrentUserMembership.JOINED, + inviter = aRoomMember(A_USER_ID), + activeMembersCount = 2L, + invitedMembersCount = 3L, + joinedMembersCount = 4L, + userPowerLevels = mapOf(A_USER_ID_6 to 50L).toImmutableMap(), + highlightCount = 10L, + notificationCount = 11L, + userDefinedNotificationMode = RoomNotificationMode.MUTE, + hasRoomCall = true, + activeRoomCallParticipants = listOf(A_USER_ID_3).toImmutableList(), + heroes = listOf( + MatrixUser( + userId = A_USER_ID, + displayName = "displayName", + avatarUrl = "avatarUrl", + ) + ).toImmutableList(), + pinnedEventIds = listOf(AN_EVENT_ID).toPersistentList(), + ) + ) + } + + @Test + fun `mapping of RustRoomInfo with null members should map all the fields`() { + assertThat( + MatrixRoomInfoMapper().map( + aRustRoomInfo( + id = A_ROOM_ID.value, + displayName = null, + rawName = null, + topic = null, + avatarUrl = null, + isDirect = false, + isPublic = true, + isSpace = false, + isTombstoned = false, + isFavourite = true, + canonicalAlias = null, + alternativeAliases = emptyList(), + membership = Membership.INVITED, + inviter = null, + heroes = listOf(aRoomHero()), + activeMembersCount = 2uL, + invitedMembersCount = 3uL, + joinedMembersCount = 4uL, + userPowerLevels = emptyMap(), + highlightCount = 10uL, + notificationCount = 11uL, + userDefinedNotificationMode = null, + hasRoomCall = false, + activeRoomCallParticipants = emptyList(), + isMarkedUnread = true, + numUnreadMessages = 12uL, + numUnreadNotifications = 13uL, + numUnreadMentions = 14uL, + pinnedEventIds = emptyList(), + ) + ) + ).isEqualTo( + MatrixRoomInfo( + id = A_ROOM_ID, + name = null, + rawName = null, + topic = null, + avatarUrl = null, + isDirect = false, + isPublic = true, + isSpace = false, + isTombstoned = false, + isFavorite = true, + canonicalAlias = null, + alternativeAliases = emptyList().toPersistentList(), + currentUserMembership = CurrentUserMembership.INVITED, + inviter = null, + activeMembersCount = 2L, + invitedMembersCount = 3L, + joinedMembersCount = 4L, + userPowerLevels = emptyMap().toImmutableMap(), + highlightCount = 10L, + notificationCount = 11L, + userDefinedNotificationMode = null, + hasRoomCall = false, + activeRoomCallParticipants = emptyList().toImmutableList(), + heroes = emptyList().toImmutableList(), + pinnedEventIds = emptyList().toPersistentList(), + ) + ) + } + + @Test + fun `mapping Membership`() { + assertThat(Membership.INVITED.map()).isEqualTo(CurrentUserMembership.INVITED) + assertThat(Membership.JOINED.map()).isEqualTo(CurrentUserMembership.JOINED) + assertThat(Membership.LEFT.map()).isEqualTo(CurrentUserMembership.LEFT) + } + + @Test + fun `mapping RoomNotificationMode`() { + assertThat(RustRoomNotificationMode.ALL_MESSAGES.map()).isEqualTo(RoomNotificationMode.ALL_MESSAGES) + assertThat(RustRoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY.map()).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) + assertThat(RustRoomNotificationMode.MUTE.map()).isEqualTo(RoomNotificationMode.MUTE) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt index 7c5c873155..7d671d0972 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt @@ -65,7 +65,7 @@ class RoomInfoExtTest { } } -private fun aRoomHero( +internal fun aRoomHero( userId: UserId = A_USER_ID, ): RoomHero { return RoomHero( From 8efdf6604b8f88aef9d7c4961db1be231a4a15d1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:11:41 +0200 Subject: [PATCH 078/106] Add unit test on ReceiptType.toRustReceiptType() --- .../impl/timeline/ReceiptTypeMapperKtTest.kt | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/ReceiptTypeMapperKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/ReceiptTypeMapperKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/ReceiptTypeMapperKtTest.kt new file mode 100644 index 0000000000..5ba93d26ce --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/ReceiptTypeMapperKtTest.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ +package io.element.android.libraries.matrix.impl.timeline + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.timeline.ReceiptType +import org.junit.Test +import org.matrix.rustcomponents.sdk.ReceiptType as RustReceiptType + +class ReceiptTypeMapperKtTest { + @Test + fun toRustReceiptType() { + assertThat(ReceiptType.READ.toRustReceiptType()).isEqualTo(RustReceiptType.READ) + assertThat(ReceiptType.READ_PRIVATE.toRustReceiptType()).isEqualTo(RustReceiptType.READ_PRIVATE) + assertThat(ReceiptType.FULLY_READ.toRustReceiptType()).isEqualTo(RustReceiptType.FULLY_READ) + } +} From 2514a7f71063325c61e5cac775378f20b31c92cd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:13:18 +0200 Subject: [PATCH 079/106] Add unit test on toRoomType --- .../matrix/impl/room/RoomTypeKtTest.kt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomTypeKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomTypeKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomTypeKtTest.kt new file mode 100644 index 0000000000..541598781e --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomTypeKtTest.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ +package io.element.android.libraries.matrix.impl.room + +import io.element.android.libraries.matrix.api.room.RoomType +import org.junit.Test + +class RoomTypeKtTest { + @Test + fun toRoomType() { + assert(null.toRoomType() == RoomType.Room) + assert("m.space".toRoomType() == RoomType.Space) + assert("m.other".toRoomType() == RoomType.Other("m.other")) + } +} From 88004db53177b702d12e6d2e052d22fb38add4c3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:14:59 +0200 Subject: [PATCH 080/106] Add unit test on UserProfileMapper --- .../impl/usersearch/UserProfileMapperTest.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt new file mode 100644 index 0000000000..0564186a78 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.usersearch + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.test.A_USER_ID +import org.junit.Test +import org.matrix.rustcomponents.sdk.UserProfile + +class UserProfileMapperTest { + @Test + fun map() { + assertThat(UserProfileMapper.map(UserProfile(A_USER_ID.value, "displayName", "avatarUrl"))) + .isEqualTo(MatrixUser(A_USER_ID, "displayName", "avatarUrl")) + } +} From e2a4fbbd61ef6ac46cbb4ea21936306e588fc4ce Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:18:54 +0200 Subject: [PATCH 081/106] Add unit test on UserSearchResultMapper --- .../usersearch/UserSearchResultMapperTest.kt | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapperTest.kt 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 new file mode 100644 index 0000000000..17ce3836ca --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapperTest.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.usersearch + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.test.A_USER_ID +import kotlinx.collections.immutable.toImmutableList +import org.junit.Test +import org.matrix.rustcomponents.sdk.SearchUsersResults +import org.matrix.rustcomponents.sdk.UserProfile + +class UserSearchResultMapperTest { + @Test + fun `map limited list`() { + assertThat( + UserSearchResultMapper.map( + SearchUsersResults( + results = listOf(UserProfile(A_USER_ID.value, "displayName", "avatarUrl")), + limited = true, + ) + ) + ) + .isEqualTo( + MatrixSearchUserResults( + results = listOf(MatrixUser(A_USER_ID, "displayName", "avatarUrl")).toImmutableList(), + limited = true, + ) + ) + } + + @Test + fun `map not limited list`() { + assertThat( + UserSearchResultMapper.map( + SearchUsersResults( + listOf(UserProfile(A_USER_ID.value, "displayName", "avatarUrl")), + false, + ) + ) + ) + .isEqualTo( + MatrixSearchUserResults( + results = listOf(MatrixUser(A_USER_ID, "displayName", "avatarUrl")).toImmutableList(), + limited = false, + ) + ) + } +} From 9ae7e998c00c04e4c3b8b36ebbc48363aaa9c615 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:22:11 +0200 Subject: [PATCH 082/106] Add unit test on SyncServiceState.toSyncState --- .../matrix/impl/sync/AppStateMapperKtTest.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/sync/AppStateMapperKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/sync/AppStateMapperKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/sync/AppStateMapperKtTest.kt new file mode 100644 index 0000000000..54fc06f8f1 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/sync/AppStateMapperKtTest.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.sync + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.sync.SyncState +import org.junit.Test +import org.matrix.rustcomponents.sdk.SyncServiceState + +class AppStateMapperKtTest { + @Test + fun toSyncState() { + assertThat(SyncServiceState.IDLE.toSyncState()).isEqualTo(SyncState.Idle) + assertThat(SyncServiceState.RUNNING.toSyncState()).isEqualTo(SyncState.Running) + assertThat(SyncServiceState.TERMINATED.toSyncState()).isEqualTo(SyncState.Terminated) + assertThat(SyncServiceState.ERROR.toSyncState()).isEqualTo(SyncState.Error) + } +} From 2d274a9b3486c242630bfa5bb227e37353ba2fdf Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:48:07 +0200 Subject: [PATCH 083/106] Add unit test on RoomDescriptionMapper --- .../roomdirectory/RoomDescriptionMapper.kt | 14 +++-- .../RoomDescriptionMapperTest.kt | 60 +++++++++++++++++++ 2 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapper.kt index e91242f165..267de74ba7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapper.kt @@ -21,13 +21,17 @@ class RoomDescriptionMapper { topic = roomDescription.topic, avatarUrl = roomDescription.avatarUrl, alias = roomDescription.alias?.let(::RoomAlias), - joinRule = when (roomDescription.joinRule) { - PublicRoomJoinRule.PUBLIC -> RoomDescription.JoinRule.PUBLIC - PublicRoomJoinRule.KNOCK -> RoomDescription.JoinRule.KNOCK - null -> RoomDescription.JoinRule.UNKNOWN - }, + joinRule = roomDescription.joinRule.map(), isWorldReadable = roomDescription.isWorldReadable, numberOfMembers = roomDescription.joinedMembers.toLong(), ) } } + +internal fun PublicRoomJoinRule?.map(): RoomDescription.JoinRule { + return when (this) { + PublicRoomJoinRule.PUBLIC -> RoomDescription.JoinRule.PUBLIC + PublicRoomJoinRule.KNOCK -> RoomDescription.JoinRule.KNOCK + null -> RoomDescription.JoinRule.UNKNOWN + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt new file mode 100644 index 0000000000..307cc33b54 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.roomdirectory + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.roomdirectory.RoomDescription +import io.element.android.libraries.matrix.test.A_ROOM_ALIAS +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.roomdirectory.aRoomDescription +import org.junit.Test +import org.matrix.rustcomponents.sdk.PublicRoomJoinRule +import org.matrix.rustcomponents.sdk.RoomDescription as RustRoomDescription + +class RoomDescriptionMapperTest { + @Test + fun map() { + assertThat(RoomDescriptionMapper().map(aRustRoomDescription())).isEqualTo( + aRoomDescription( + roomId = A_ROOM_ID, + name = "name", + topic = "topic", + alias = A_ROOM_ALIAS, + avatarUrl = "avatarUrl", + joinRule = RoomDescription.JoinRule.PUBLIC, + isWorldReadable = true, + joinedMembers = 2L + ) + ) + } + + @Test + fun mapWithNullAlias() { + assertThat(RoomDescriptionMapper().map(aRustRoomDescription().copy(alias = null)).alias).isNull() + } + + @Test + fun `map join rule`() { + assertThat(PublicRoomJoinRule.PUBLIC.map()).isEqualTo(RoomDescription.JoinRule.PUBLIC) + assertThat(PublicRoomJoinRule.KNOCK.map()).isEqualTo(RoomDescription.JoinRule.KNOCK) + assertThat(null.map()).isEqualTo(RoomDescription.JoinRule.UNKNOWN) + } +} + +internal fun aRustRoomDescription(): RustRoomDescription { + return RustRoomDescription( + roomId = A_ROOM_ID.value, + name = "name", + topic = "topic", + alias = A_ROOM_ALIAS.value, + avatarUrl = "avatarUrl", + joinRule = PublicRoomJoinRule.PUBLIC, + isWorldReadable = true, + joinedMembers = 2u + ) +} From 7b75affe2ddd06a3f66175d7049162e3a368e235 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:54:08 +0200 Subject: [PATCH 084/106] Add unit test on RoomPreviewMapper --- .../room/preview/RoomPreviewMapperTest.kt | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt new file mode 100644 index 0000000000..3e0fea4bdc --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt @@ -0,0 +1,96 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.room.preview + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.room.RoomType +import io.element.android.libraries.matrix.api.room.preview.RoomPreview +import io.element.android.libraries.matrix.test.A_ROOM_ALIAS +import io.element.android.libraries.matrix.test.A_ROOM_ID +import org.junit.Test +import org.matrix.rustcomponents.sdk.RoomPreview as RustRoomPreview + +class RoomPreviewMapperTest { + @Test + fun `map should map values 1`() { + assertThat( + RoomPreviewMapper.map( + aRustRoomPreview( + isJoined = false, + isInvited = false, + ) + ) + ).isEqualTo( + RoomPreview( + roomId = A_ROOM_ID, + canonicalAlias = A_ROOM_ALIAS, + name = "name", + topic = "topic", + avatarUrl = "avatarUrl", + numberOfJoinedMembers = 1L, + roomType = RoomType.Room, + isHistoryWorldReadable = true, + isJoined = false, + isInvited = false, + isPublic = true, + canKnock = true, + ) + ) + } + + @Test + fun `map should map values 2`() { + assertThat( + RoomPreviewMapper.map( + aRustRoomPreview( + canonicalAlias = null, + isPublic = false, + canKnock = false, + ) + ) + ).isEqualTo( + RoomPreview( + roomId = A_ROOM_ID, + canonicalAlias = null, + name = "name", + topic = "topic", + avatarUrl = "avatarUrl", + numberOfJoinedMembers = 1L, + roomType = RoomType.Room, + isHistoryWorldReadable = true, + isJoined = true, + isInvited = true, + isPublic = false, + canKnock = false, + ) + ) + } +} + +internal fun aRustRoomPreview( + canonicalAlias: String? = A_ROOM_ALIAS.value, + isJoined: Boolean = true, + isInvited: Boolean = true, + isPublic: Boolean = true, + canKnock: Boolean = true, +): RustRoomPreview { + return RustRoomPreview( + roomId = A_ROOM_ID.value, + canonicalAlias = canonicalAlias, + name = "name", + topic = "topic", + avatarUrl = "avatarUrl", + numJoinedMembers = 1u, + roomType = null, + isHistoryWorldReadable = true, + isJoined = isJoined, + isInvited = isInvited, + isPublic = isPublic, + canKnock = canKnock, + ) +} From b237485a6c59ae9bbf4d5135493500fc3add6cea Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:55:55 +0200 Subject: [PATCH 085/106] Add unit test on AssetType.toInner() --- .../impl/room/location/AssetTypeKtTest.kt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/AssetTypeKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/AssetTypeKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/AssetTypeKtTest.kt new file mode 100644 index 0000000000..78807bc324 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/AssetTypeKtTest.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.room.location + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.room.location.AssetType +import org.junit.Test + +class AssetTypeKtTest { + @Test + fun toInner() { + assertThat(AssetType.SENDER.toInner()).isEqualTo(org.matrix.rustcomponents.sdk.AssetType.SENDER) + assertThat(AssetType.PIN.toInner()).isEqualTo(org.matrix.rustcomponents.sdk.AssetType.PIN) + } +} From 98f6effd8d06d5711604c77cf825669273f25969 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 15:00:30 +0200 Subject: [PATCH 086/106] Add unit test on RoomMemberMapper --- .../impl/room/member/RoomMemberMapperTest.kt | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapperTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapperTest.kt new file mode 100644 index 0000000000..dcf3ed5ee1 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapperTest.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.room.member + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.room.RoomMember +import io.element.android.libraries.matrix.api.room.RoomMembershipState +import org.junit.Test +import uniffi.matrix_sdk.RoomMemberRole +import org.matrix.rustcomponents.sdk.MembershipState as RustMembershipState + +class RoomMemberMapperTest { + @Test + fun mapRole() { + assertThat(RoomMemberMapper.mapRole(RoomMemberRole.USER)).isEqualTo(RoomMember.Role.USER) + assertThat(RoomMemberMapper.mapRole(RoomMemberRole.MODERATOR)).isEqualTo(RoomMember.Role.MODERATOR) + assertThat(RoomMemberMapper.mapRole(RoomMemberRole.ADMINISTRATOR)).isEqualTo(RoomMember.Role.ADMIN) + } + + @Test + fun mapMembership() { + assertThat(RoomMemberMapper.mapMembership(RustMembershipState.BAN)).isEqualTo(RoomMembershipState.BAN) + assertThat(RoomMemberMapper.mapMembership(RustMembershipState.INVITE)).isEqualTo(RoomMembershipState.INVITE) + assertThat(RoomMemberMapper.mapMembership(RustMembershipState.JOIN)).isEqualTo(RoomMembershipState.JOIN) + assertThat(RoomMemberMapper.mapMembership(RustMembershipState.KNOCK)).isEqualTo(RoomMembershipState.KNOCK) + assertThat(RoomMemberMapper.mapMembership(RustMembershipState.LEAVE)).isEqualTo(RoomMembershipState.LEAVE) + } +} From 26260aed9fd0fb7154a77aabf9ce02c80a5bea60 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 16:47:11 +0200 Subject: [PATCH 087/106] Fix compilation issue after rebase. --- .../libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt index f0b02df6b7..ce04469ff8 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt @@ -67,6 +67,7 @@ class MatrixRoomInfoMapperTest { numUnreadNotifications = 13uL, numUnreadMentions = 14uL, pinnedEventIds = listOf(AN_EVENT_ID.value), + roomCreator = A_USER_ID.value, ) ) ).isEqualTo( @@ -102,6 +103,7 @@ class MatrixRoomInfoMapperTest { ) ).toImmutableList(), pinnedEventIds = listOf(AN_EVENT_ID).toPersistentList(), + creator = A_USER_ID, ) ) } @@ -140,6 +142,7 @@ class MatrixRoomInfoMapperTest { numUnreadNotifications = 13uL, numUnreadMentions = 14uL, pinnedEventIds = emptyList(), + roomCreator = null, ) ) ).isEqualTo( @@ -169,6 +172,7 @@ class MatrixRoomInfoMapperTest { activeRoomCallParticipants = emptyList().toImmutableList(), heroes = emptyList().toImmutableList(), pinnedEventIds = emptyList().toPersistentList(), + creator = null, ) ) } From 2ee71b5dee22833b20bf688daf22f449ca525efc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 17:05:11 +0200 Subject: [PATCH 088/106] Add unit test on LastForwardIndicatorsPostProcessor --- .../impl/timeline/postprocessor/Fixtures.kt | 46 +++++++++ .../LastForwardIndicatorsPostProcessorTest.kt | 94 +++++++++++++++++++ .../RoomBeginningPostProcessorTest.kt | 25 ----- 3 files changed, 140 insertions(+), 25 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessorTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt new file mode 100644 index 0000000000..16acfd718f --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.timeline.postprocessor + +import io.element.android.libraries.matrix.api.core.UniqueId +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange +import io.element.android.libraries.matrix.api.timeline.item.event.OtherState +import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent +import io.element.android.libraries.matrix.api.timeline.item.event.StateContent +import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.A_USER_ID_2 +import io.element.android.libraries.matrix.test.timeline.aMessageContent +import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem + +internal val roomCreateEvent = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.create"), + event = anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate)) +) +internal val roomCreatorJoinEvent = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.member"), + event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED)) +) +internal val otherMemberJoinEvent = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.member_other"), + event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED)) +) +internal val messageEvent = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.message"), + event = anEventTimelineItem(content = aMessageContent("hi")) +) +internal val messageEvent2 = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.message2"), + event = anEventTimelineItem(content = aMessageContent("hello")) +) +internal val dayEvent = MatrixTimelineItem.Virtual( + uniqueId = UniqueId("day"), + virtual = VirtualTimelineItem.DayDivider(0), +) + diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessorTest.kt new file mode 100644 index 0000000000..398b2f5883 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessorTest.kt @@ -0,0 +1,94 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.timeline.postprocessor + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.UniqueId +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem +import org.junit.Test + +class LastForwardIndicatorsPostProcessorTest { + @Test + fun `LastForwardIndicatorsPostProcessor does not alter the items with mode not FOCUSED_ON_EVENT`() { + val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.LIVE) + val result = sut.process(listOf(messageEvent), true) + assertThat(result).containsExactly(messageEvent) + } + + @Test + fun `LastForwardIndicatorsPostProcessor does not alter the items with mode FOCUSED_ON_EVENT but timeline not initialized`() { + val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.FOCUSED_ON_EVENT) + val result = sut.process(listOf(messageEvent), false) + assertThat(result).containsExactly(messageEvent) + } + + @Test + fun `LastForwardIndicatorsPostProcessor add virtual items`() { + val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.FOCUSED_ON_EVENT) + val result = sut.process(listOf(messageEvent), true) + assertThat(result).containsExactly( + messageEvent, + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("last_forward_indicator_${messageEvent.uniqueId}"), + virtual = VirtualTimelineItem.LastForwardIndicator + ) + ) + } + + @Test + fun `LastForwardIndicatorsPostProcessor add virtual items on empty list`() { + val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.FOCUSED_ON_EVENT) + val result = sut.process(listOf(), true) + assertThat(result).containsExactly( + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("last_forward_indicator_fake_id"), + virtual = VirtualTimelineItem.LastForwardIndicator + ) + ) + } + + @Test + fun `LastForwardIndicatorsPostProcessor add virtual items but does not alter the list if called a second time`() { + val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.FOCUSED_ON_EVENT) + // Process a first time + sut.process(listOf(messageEvent), true) + // Process a second time with the same Event + val result = sut.process(listOf(messageEvent), true) + assertThat(result).containsExactly( + messageEvent, + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("last_forward_indicator_${messageEvent.uniqueId}"), + virtual = VirtualTimelineItem.LastForwardIndicator + ) + ) + } + + @Test + fun `LastForwardIndicatorsPostProcessor add virtual items each time it is called with new Events`() { + val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.FOCUSED_ON_EVENT) + // Process a first time + sut.process(listOf(dayEvent, messageEvent), true) + // Process a second time with the same Event + val result = sut.process(listOf(dayEvent, messageEvent, messageEvent2), true) + assertThat(result).containsExactly( + dayEvent, + messageEvent, + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("last_forward_indicator_${messageEvent.uniqueId}"), + virtual = VirtualTimelineItem.LastForwardIndicator + ), + messageEvent2, + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("last_forward_indicator_${messageEvent2.uniqueId}"), + virtual = VirtualTimelineItem.LastForwardIndicator + ) + ) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt index fadc174cd1..41d175b348 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt @@ -8,36 +8,11 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.matrix.api.core.UniqueId -import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.Timeline -import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange -import io.element.android.libraries.matrix.api.timeline.item.event.OtherState -import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent -import io.element.android.libraries.matrix.api.timeline.item.event.StateContent import io.element.android.libraries.matrix.test.A_USER_ID -import io.element.android.libraries.matrix.test.A_USER_ID_2 -import io.element.android.libraries.matrix.test.timeline.aMessageContent -import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem import org.junit.Test class RoomBeginningPostProcessorTest { - private val roomCreateEvent = MatrixTimelineItem.Event( - uniqueId = UniqueId("m.room.create"), - event = anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate)) - ) - private val roomCreatorJoinEvent = MatrixTimelineItem.Event( - uniqueId = UniqueId("m.room.member"), - event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED)) - ) - private val otherMemberJoinEvent = MatrixTimelineItem.Event( - uniqueId = UniqueId("m.room.member_other"), - event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED)) - ) - private val messageEvent = MatrixTimelineItem.Event( - uniqueId = UniqueId("m.room.message"), - event = anEventTimelineItem(content = aMessageContent("hi")) - ) @Test fun `processor returns empty list when empty list is provided`() { From 32c210118422f81b973802150d96e828339fa3bd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 17:15:09 +0200 Subject: [PATCH 089/106] Add unit test on LoadingIndicatorsPostProcessor --- libraries/matrix/impl/build.gradle.kts | 1 + .../LoadingIndicatorsPostProcessorTest.kt | 127 ++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessorTest.kt diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index 76eb030615..5d386169ad 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -48,6 +48,7 @@ dependencies { testImplementation(libs.test.robolectric) testImplementation(projects.libraries.matrix.test) testImplementation(projects.services.analytics.test) + testImplementation(projects.services.toolbox.test) testImplementation(projects.tests.testutils) testImplementation(libs.coroutines.test) testImplementation(libs.test.turbine) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessorTest.kt new file mode 100644 index 0000000000..4859355917 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessorTest.kt @@ -0,0 +1,127 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.timeline.postprocessor + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.UniqueId +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem +import io.element.android.services.toolbox.test.systemclock.FakeSystemClock +import org.junit.Test + +class LoadingIndicatorsPostProcessorTest { + @Test + fun `LoadingIndicatorsPostProcessor does not alter the items is the timeline is not initialized`() { + val sut = LoadingIndicatorsPostProcessor(FakeSystemClock()) + val result = sut.process( + items = listOf(messageEvent, messageEvent2), + isTimelineInitialized = false, + hasMoreToLoadBackward = true, + hasMoreToLoadForward = true, + ) + assertThat(result).containsExactly(messageEvent, messageEvent2) + } + + @Test + fun `LoadingIndicatorsPostProcessor adds Loading indicator at the top of the list if hasMoreToLoadBackward is true`() { + val clock = FakeSystemClock() + val sut = LoadingIndicatorsPostProcessor(clock) + val result = sut.process( + items = listOf(messageEvent, messageEvent2), + isTimelineInitialized = true, + hasMoreToLoadBackward = true, + hasMoreToLoadForward = false, + ) + assertThat(result).containsExactly( + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("BackwardLoadingIndicator"), + virtual = VirtualTimelineItem.LoadingIndicator( + direction = Timeline.PaginationDirection.BACKWARDS, + timestamp = clock.epochMillis() + ) + ), + messageEvent, + messageEvent2, + ) + } + + @Test + fun `LoadingIndicatorsPostProcessor adds Loading indicator at the bottom of the list if hasMoreToLoadForward is true`() { + val clock = FakeSystemClock() + val sut = LoadingIndicatorsPostProcessor(clock) + val result = sut.process( + items = listOf(messageEvent, messageEvent2), + isTimelineInitialized = true, + hasMoreToLoadBackward = false, + hasMoreToLoadForward = true, + ) + assertThat(result).containsExactly( + messageEvent, + messageEvent2, + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("ForwardLoadingIndicator"), + virtual = VirtualTimelineItem.LoadingIndicator( + direction = Timeline.PaginationDirection.FORWARDS, + timestamp = clock.epochMillis() + ) + ), + ) + } + + @Test + fun `LoadingIndicatorsPostProcessor adds Loading indicator at the bottom and at the top of the list`() { + val clock = FakeSystemClock() + val sut = LoadingIndicatorsPostProcessor(clock) + val result = sut.process( + items = listOf(messageEvent, messageEvent2), + isTimelineInitialized = true, + hasMoreToLoadBackward = true, + hasMoreToLoadForward = true, + ) + assertThat(result).containsExactly( + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("BackwardLoadingIndicator"), + virtual = VirtualTimelineItem.LoadingIndicator( + direction = Timeline.PaginationDirection.BACKWARDS, + timestamp = clock.epochMillis() + ) + ), + messageEvent, + messageEvent2, + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("ForwardLoadingIndicator"), + virtual = VirtualTimelineItem.LoadingIndicator( + direction = Timeline.PaginationDirection.FORWARDS, + timestamp = clock.epochMillis() + ) + ), + ) + } + + @Test + fun `LoadingIndicatorsPostProcessor only adds 1 Loading indicator if there is no items in the list`() { + val clock = FakeSystemClock() + val sut = LoadingIndicatorsPostProcessor(clock) + val result = sut.process( + items = listOf(), + isTimelineInitialized = true, + hasMoreToLoadBackward = true, + hasMoreToLoadForward = true, + ) + assertThat(result).containsExactly( + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("BackwardLoadingIndicator"), + virtual = VirtualTimelineItem.LoadingIndicator( + direction = Timeline.PaginationDirection.BACKWARDS, + timestamp = clock.epochMillis() + ) + ), + ) + } +} From 51e661013e149a6ba968ca96e7b93e232799ef45 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 17:17:17 +0200 Subject: [PATCH 090/106] Add unit test on PollKind mapper --- .../matrix/impl/poll/PollKindKtTest.kt | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt new file mode 100644 index 0000000000..97f049bcb7 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2023, 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.poll + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.poll.PollKind +import org.junit.Test +import org.matrix.rustcomponents.sdk.PollKind as RustPollKind + + +class PollKindKtTest { + @Test + fun `map should return Disclosed when RustPollKind is Disclosed`() { + val pollKind = RustPollKind.DISCLOSED.map() + assertThat(pollKind).isEqualTo(PollKind.Disclosed) + } + + @Test + fun `map should return Undisclosed when RustPollKind is Undisclosed`() { + val pollKind = RustPollKind.UNDISCLOSED.map() + assertThat(pollKind).isEqualTo(PollKind.Undisclosed) + } + + @Test + fun `toInner should return DISCLOSED when PollKind is Disclosed`() { + val rustPollKind = PollKind.Disclosed.toInner() + assertThat(rustPollKind).isEqualTo(RustPollKind.DISCLOSED) + } + + @Test + fun `toInner should return UNDISCLOSED when PollKind is Undisclosed`() { + val rustPollKind = PollKind.Undisclosed.toInner() + assertThat(rustPollKind).isEqualTo(RustPollKind.UNDISCLOSED) + } +} From e111d78a24c43a19de1ebc846de21c89ba70a636 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 17:35:22 +0200 Subject: [PATCH 091/106] Add missing test for RoomListEntriesUpdate.Reset --- .../impl/roomlist/RoomSummaryListProcessorTest.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt index 93096ee227..45a023d636 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt @@ -13,6 +13,7 @@ import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoomListItem import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID_2 +import io.element.android.libraries.matrix.test.A_ROOM_ID_3 import io.element.android.libraries.matrix.test.room.aRoomSummary import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled import kotlinx.coroutines.flow.MutableStateFlow @@ -148,6 +149,18 @@ class RoomSummaryListProcessorTest { assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID) } + @Test + fun `Rest removes all entries and add the provided ones`() = runTest { + summaries.value = listOf(aRoomSummaryFilled(roomId = A_ROOM_ID), aRoomSummaryFilled(A_ROOM_ID_2)) + val processor = createProcessor() + val index = 0 + + processor.postUpdate(listOf(RoomListEntriesUpdate.Reset(listOf(FakeRustRoomListItem(A_ROOM_ID_3))))) + + assertThat(summaries.value.count()).isEqualTo(1) + assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_3) + } + private fun TestScope.createProcessor() = RoomSummaryListProcessor( summaries, fakeRoomListService, From 525186cb18e6afa4ed138bba81122eaed5aad732 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 17:41:29 +0200 Subject: [PATCH 092/106] Exclude RoomListEntriesUpdate.describe() from coverage, it's only used to debug the app. --- .../libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt index d0ed9bb777..e03c8529c7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt @@ -7,8 +7,11 @@ package io.element.android.libraries.matrix.impl.roomlist +import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate +@Suppress("unused") +@ExcludeFromCoverage internal fun RoomListEntriesUpdate.describe(): String { return when (this) { is RoomListEntriesUpdate.Set -> { From db311c4cccba1ec1c03e2304a8ffa38210bce54b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 17:44:34 +0200 Subject: [PATCH 093/106] Add unit test on DefaultUserServerResolver --- .../server/DefaultUserServerResolverTest.kt | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/server/DefaultUserServerResolverTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/server/DefaultUserServerResolverTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/server/DefaultUserServerResolverTest.kt new file mode 100644 index 0000000000..b9778190ef --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/server/DefaultUserServerResolverTest.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.server + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.test.FakeMatrixClient +import org.junit.Test + +class DefaultUserServerResolverTest { + @Test + fun resolve() { + // Given + val userServerResolver = DefaultUserServerResolver(FakeMatrixClient( + userIdServerNameLambda = { "dummy.org" } + )) + + // When + val result = userServerResolver.resolve() + + // Then + assertThat(result).isEqualTo("dummy.org") + } +} From c26e889d45c67f0e6a46d9fd78bf97aa863112a2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 17:56:00 +0200 Subject: [PATCH 094/106] Add unit test on DefaultPassphraseGenerator --- .../keys/DefaultPassphraseGeneratorTest.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultPassphraseGeneratorTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultPassphraseGeneratorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultPassphraseGeneratorTest.kt new file mode 100644 index 0000000000..e4ac3b591e --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultPassphraseGeneratorTest.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.keys + +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class DefaultPassphraseGeneratorTest { + @Test + fun `check that generated passphrase has the expected length`() { + val passphraseGenerator = DefaultPassphraseGenerator() + val passphrase = passphraseGenerator.generatePassphrase() + assertThat(passphrase!!.length).isEqualTo(342) + } +} From eea976bb18008da16209a7f5e640f42f385c900d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 18:09:12 +0200 Subject: [PATCH 095/106] Add unit test on toSessionData --- .../matrix/impl/mapper/SessionKtTest.kt | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt new file mode 100644 index 0000000000..aac34dfdab --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt @@ -0,0 +1,98 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.mapper + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.impl.paths.SessionPaths +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_HOMESERVER_URL_2 +import io.element.android.libraries.matrix.test.A_SECRET +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.sessionstorage.api.LoginType +import org.junit.Test +import org.matrix.rustcomponents.sdk.Session +import org.matrix.rustcomponents.sdk.SlidingSyncVersion +import java.io.File + +class SessionKtTest { + @Test + fun `toSessionData compute the expected result`() { + val result = aRustSession().toSessionData( + isTokenValid = true, + loginType = LoginType.PASSWORD, + passphrase = A_SECRET, + sessionPaths = SessionPaths(File("/a/file"), File("/a/cache")), + ) + assertThat(result.userId).isEqualTo(A_USER_ID.value) + assertThat(result.deviceId).isEqualTo(A_DEVICE_ID.value) + assertThat(result.accessToken).isEqualTo("accessToken") + assertThat(result.refreshToken).isEqualTo("refreshToken") + assertThat(result.homeserverUrl).isEqualTo(A_HOMESERVER_URL) + assertThat(result.isTokenValid).isTrue() + assertThat(result.oidcData).isNull() + assertThat(result.slidingSyncProxy).isNull() + assertThat(result.loginType).isEqualTo(LoginType.PASSWORD) + assertThat(result.loginTimestamp).isNotNull() + assertThat(result.passphrase).isEqualTo(A_SECRET) + assertThat(result.sessionPath).isEqualTo("/a/file") + assertThat(result.cachePath).isEqualTo("/a/cache") + } + + @Test + fun `toSessionData can change the validity of the token`() { + val result = aRustSession().toSessionData( + isTokenValid = false, + loginType = LoginType.PASSWORD, + passphrase = A_SECRET, + sessionPaths = SessionPaths(File("/a/file"), File("/a/cache")), + homeserverUrl = null, + ) + assertThat(result.isTokenValid).isFalse() + } + + @Test + fun `toSessionData can override the value of the homeserver url`() { + val result = aRustSession().toSessionData( + isTokenValid = true, + loginType = LoginType.PASSWORD, + passphrase = A_SECRET, + sessionPaths = SessionPaths(File("/a/file"), File("/a/cache")), + homeserverUrl = A_HOMESERVER_URL_2, + ) + assertThat(result.homeserverUrl).isEqualTo(A_HOMESERVER_URL_2) + } + + @Test + fun `toSessionData copy the sliding sync url if present`() { + val result = aRustSession( + proxy = SlidingSyncVersion.Proxy("proxyUrl") + ).toSessionData( + isTokenValid = true, + loginType = LoginType.PASSWORD, + passphrase = A_SECRET, + sessionPaths = SessionPaths(File("/a/file"), File("/a/cache")), + homeserverUrl = A_HOMESERVER_URL_2, + ) + assertThat(result.slidingSyncProxy).isEqualTo("proxyUrl") + } +} + +internal fun aRustSession( + proxy: SlidingSyncVersion = SlidingSyncVersion.None +): Session { + return Session( + accessToken = "accessToken", + refreshToken = "refreshToken", + userId = A_USER_ID.value, + deviceId = A_DEVICE_ID.value, + homeserverUrl = A_HOMESERVER_URL, + oidcData = null, + slidingSyncVersion = proxy, + ) +} From 6cb4d10375bcdcef9abe5b781fcc3a4b77b7f17b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 19:43:37 +0200 Subject: [PATCH 096/106] Fix typo --- .../matrix/impl/roomlist/RoomSummaryListProcessorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt index 45a023d636..d4b347af44 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt @@ -150,7 +150,7 @@ class RoomSummaryListProcessorTest { } @Test - fun `Rest removes all entries and add the provided ones`() = runTest { + fun `Reset removes all entries and add the provided ones`() = runTest { summaries.value = listOf(aRoomSummaryFilled(roomId = A_ROOM_ID), aRoomSummaryFilled(A_ROOM_ID_2)) val processor = createProcessor() val index = 0 From 619841fc8029b0d2c93e0b0375da3861c247f4c6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 19:48:21 +0200 Subject: [PATCH 097/106] Add unit test on MatrixTimelineDiffProcessor --- .../timeline/MatrixTimelineDiffProcessor.kt | 9 +- .../MatrixTimelineDiffProcessorTest.kt | 199 ++++++++++++++++++ 2 files changed, 204 insertions(+), 4 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt index 47be0fd07a..3523823d5e 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt @@ -15,7 +15,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import org.matrix.rustcomponents.sdk.TimelineChange -import org.matrix.rustcomponents.sdk.TimelineDiff +import org.matrix.rustcomponents.sdk.TimelineDiffInterface import org.matrix.rustcomponents.sdk.TimelineItem import timber.log.Timber @@ -36,7 +36,7 @@ internal class MatrixTimelineDiffProcessor( } } - suspend fun postDiffs(diffs: List) { + suspend fun postDiffs(diffs: List) { updateTimelineItems { Timber.v("Update timeline items from postDiffs (with ${diffs.size} items) on ${Thread.currentThread()}") diffs.forEach { diff -> @@ -52,7 +52,7 @@ internal class MatrixTimelineDiffProcessor( timelineItems.value = mutableTimelineItems } - private fun MutableList.applyDiff(diff: TimelineDiff) { + private fun MutableList.applyDiff(diff: TimelineDiffInterface) { when (diff.change()) { TimelineChange.APPEND -> { val items = diff.append()?.map { it.asMatrixTimelineItem() } ?: return @@ -100,7 +100,8 @@ internal class MatrixTimelineDiffProcessor( clear() } TimelineChange.TRUNCATE -> { - // Not supported + val index = diff.truncate() ?: return + subList(index.toInt(), size).clear() } } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt new file mode 100644 index 0000000000..84ce6e61f9 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt @@ -0,0 +1,199 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.timeline + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper +import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper +import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper +import io.element.android.libraries.matrix.test.A_UNIQUE_ID +import io.element.android.libraries.matrix.test.A_UNIQUE_ID_2 +import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.matrix.rustcomponents.sdk.EventTimelineItem +import org.matrix.rustcomponents.sdk.InsertData +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.SetData +import org.matrix.rustcomponents.sdk.TimelineChange +import org.matrix.rustcomponents.sdk.TimelineDiffInterface +import org.matrix.rustcomponents.sdk.TimelineItem +import org.matrix.rustcomponents.sdk.VirtualTimelineItem + +open class FakeTimelineDiff( + private val change: TimelineChange, + private val item: TimelineItem? = FakeTimelineItem() +) : TimelineDiffInterface { + override fun change() = change + override fun append(): List? = item?.let { listOf(it) } + override fun insert(): InsertData? = item?.let { InsertData(1u, it) } + override fun pushBack(): TimelineItem? = item + override fun pushFront(): TimelineItem? = item + override fun remove(): UInt? = 1u + override fun reset(): List? = item?.let { listOf(it) } + override fun set(): SetData? = item?.let { SetData(1u, it) } + override fun truncate(): UInt? = 1u +} + +class MatrixTimelineDiffProcessorTest { + private val timelineItems = MutableStateFlow>(emptyList()) + + private val anEvent = MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem()) + private val anEvent2 = MatrixTimelineItem.Event(A_UNIQUE_ID_2, anEventTimelineItem()) + + @Test + fun `Append adds new entries at the end of the list`() = runTest { + timelineItems.value = listOf(anEvent) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.APPEND))) + assertThat(timelineItems.value.count()).isEqualTo(2) + assertThat(timelineItems.value).containsExactly( + anEvent, + MatrixTimelineItem.Other, + ) + } + + @Test + fun `PushBack adds a new entry at the end of the list`() = runTest { + timelineItems.value = listOf(anEvent) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.PUSH_BACK))) + assertThat(timelineItems.value.count()).isEqualTo(2) + assertThat(timelineItems.value).containsExactly( + anEvent, + MatrixTimelineItem.Other, + ) + } + + @Test + fun `PushFront inserts a new entry at the start of the list`() = runTest { + timelineItems.value = listOf(anEvent) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.PUSH_FRONT))) + assertThat(timelineItems.value.count()).isEqualTo(2) + assertThat(timelineItems.value).containsExactly( + MatrixTimelineItem.Other, + anEvent, + ) + } + + @Test + fun `Set replaces an entry at some index`() = runTest { + timelineItems.value = listOf(anEvent, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.SET))) + assertThat(timelineItems.value.count()).isEqualTo(2) + assertThat(timelineItems.value).containsExactly( + anEvent, + MatrixTimelineItem.Other + ) + } + + @Test + fun `Insert inserts a new entry at the provided index`() = runTest { + timelineItems.value = listOf(anEvent, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.INSERT))) + assertThat(timelineItems.value.count()).isEqualTo(3) + assertThat(timelineItems.value).containsExactly( + anEvent, + MatrixTimelineItem.Other, + anEvent2, + ) + } + + @Test + fun `Remove removes an entry at some index`() = runTest { + timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.REMOVE))) + assertThat(timelineItems.value.count()).isEqualTo(2) + assertThat(timelineItems.value).containsExactly( + anEvent, + anEvent2, + ) + } + + @Test + fun `PopBack removes an entry at the end of the list`() = runTest { + timelineItems.value = listOf(anEvent, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.POP_BACK))) + assertThat(timelineItems.value.count()).isEqualTo(1) + assertThat(timelineItems.value).containsExactly( + anEvent, + ) + } + + @Test + fun `PopFront removes an entry at the start of the list`() = runTest { + timelineItems.value = listOf(anEvent, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.POP_FRONT))) + assertThat(timelineItems.value.count()).isEqualTo(1) + assertThat(timelineItems.value).containsExactly( + anEvent2, + ) + } + + @Test + fun `Clear removes all the entries`() = runTest { + timelineItems.value = listOf(anEvent, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.CLEAR))) + assertThat(timelineItems.value).isEmpty() + } + + @Test + fun `Truncate removes all entries after the provided length`() = runTest { + timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.TRUNCATE))) + assertThat(timelineItems.value.count()).isEqualTo(1) + assertThat(timelineItems.value).containsExactly( + anEvent, + ) + } + + @Test + fun `Reset removes all entries and add the provided ones`() = runTest { + timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.RESET))) + assertThat(timelineItems.value.count()).isEqualTo(1) + assertThat(timelineItems.value).containsExactly( + MatrixTimelineItem.Other, + ) + } + + private fun TestScope.createProcessor(): MatrixTimelineDiffProcessor { + val timelineEventContentMapper = TimelineEventContentMapper() + val timelineItemMapper = MatrixTimelineItemMapper( + fetchDetailsForEvent = { _ -> Result.success(Unit) }, + coroutineScope = this, + virtualTimelineItemMapper = VirtualTimelineItemMapper(), + eventTimelineItemMapper = EventTimelineItemMapper( + contentMapper = timelineEventContentMapper + ) + ) + return MatrixTimelineDiffProcessor( + timelineItems, + timelineItemFactory = timelineItemMapper, + ) + } +} + +class FakeTimelineItem : TimelineItem(NoPointer) { + override fun asEvent(): EventTimelineItem? = null + override fun asVirtual(): VirtualTimelineItem? = null + override fun fmtDebug(): String = "fmtDebug" + override fun uniqueId(): String = "uniqueId" +} From 5de84f6ad8f7a8bdfc9f78ec0a299f82c28f80da Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 20:25:53 +0200 Subject: [PATCH 098/106] Use aSessionData() from the test module. And fix typo. --- features/rageshake/impl/build.gradle.kts | 1 + .../impl/reporter/DefaultBugReporterTest.kt | 24 ++++--------------- .../signedout/impl/SignedOutStateProvider.kt | 9 ++++--- .../sessionstorage/test/SessionData.kt | 8 +++---- 4 files changed, 13 insertions(+), 29 deletions(-) diff --git a/features/rageshake/impl/build.gradle.kts b/features/rageshake/impl/build.gradle.kts index 9d15043804..2ba2f1767d 100644 --- a/features/rageshake/impl/build.gradle.kts +++ b/features/rageshake/impl/build.gradle.kts @@ -55,6 +55,7 @@ dependencies { testImplementation(libs.test.mockk) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.sessionStorage.implMemory) + testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.features.rageshake.test) testImplementation(projects.tests.testutils) testImplementation(projects.services.toolbox.test) 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 45aaf6eeda..a30112034e 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 @@ -17,9 +17,8 @@ import io.element.android.libraries.matrix.test.FakeSdkMetadata import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService import io.element.android.libraries.network.useragent.DefaultUserAgentProvider -import io.element.android.libraries.sessionstorage.api.LoginType -import io.element.android.libraries.sessionstorage.api.SessionData import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore +import io.element.android.libraries.sessionstorage.test.aSessionData import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest @@ -94,7 +93,7 @@ class DefaultBugReporterTest { server.start() val mockSessionStore = InMemorySessionStore().apply { - storeData(mockSessionData("@foo:eample.com", "ABCDEFGH")) + storeData(aSessionData(sessionId = "@foo:example.com", deviceId = "ABCDEFGH")) } val buildMeta = aBuildMeta() @@ -143,7 +142,7 @@ class DefaultBugReporterTest { assertThat(foundValues["can_contact"]).isEqualTo("true") assertThat(foundValues["device_id"]).isEqualTo("ABCDEFGH") assertThat(foundValues["sdk_sha"]).isEqualTo("123456789") - assertThat(foundValues["user_id"]).isEqualTo("@foo:eample.com") + assertThat(foundValues["user_id"]).isEqualTo("@foo:example.com") assertThat(foundValues["text"]).isEqualTo("a bug occurred") assertThat(foundValues["device_keys"]).isEqualTo("curve25519:CURVECURVECURVE, ed25519:EDKEYEDKEYEDKY") @@ -163,7 +162,7 @@ class DefaultBugReporterTest { server.start() val mockSessionStore = InMemorySessionStore().apply { - storeData(mockSessionData("@foo:eample.com", "ABCDEFGH")) + storeData(aSessionData("@foo:example.com", "ABCDEFGH")) } val buildMeta = aBuildMeta() @@ -267,21 +266,6 @@ class DefaultBugReporterTest { return foundValues } - private fun mockSessionData(userId: String, deviceId: String) = SessionData( - userId = userId, - deviceId = deviceId, - homeserverUrl = "example.com", - accessToken = "AA", - isTokenValid = true, - loginType = LoginType.DIRECT, - loginTimestamp = null, - oidcData = null, - refreshToken = null, - slidingSyncProxy = null, - passphrase = null, - sessionPath = "session", - cachePath = "cache", - ) @Test fun `test sendBugReport error`() = runTest { val server = MockWebServer() diff --git a/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutStateProvider.kt b/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutStateProvider.kt index 9221fb2e33..b6cdaaaa0e 100644 --- a/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutStateProvider.kt +++ b/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutStateProvider.kt @@ -8,7 +8,6 @@ package io.element.android.features.signedout.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.sessionstorage.api.LoginType import io.element.android.libraries.sessionstorage.api.SessionData @@ -20,18 +19,18 @@ open class SignedOutStateProvider : PreviewParameterProvider { ) } -fun aSignedOutState() = SignedOutState( +private fun aSignedOutState() = SignedOutState( appName = "AppName", signedOutSession = aSessionData(), eventSink = {}, ) -fun aSessionData( - sessionId: SessionId = SessionId("@alice:server.org"), +private fun aSessionData( + sessionId: String = "@alice:server.org", isTokenValid: Boolean = false, ): SessionData { return SessionData( - userId = sessionId.value, + userId = sessionId, deviceId = "aDeviceId", accessToken = "anAccessToken", refreshToken = "aRefreshToken", diff --git a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/SessionData.kt b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/SessionData.kt index 8b3a0e5b26..ad62337ae6 100644 --- a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/SessionData.kt +++ b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/SessionData.kt @@ -7,19 +7,19 @@ package io.element.android.libraries.sessionstorage.test -import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.sessionstorage.api.LoginType import io.element.android.libraries.sessionstorage.api.SessionData fun aSessionData( - sessionId: SessionId = SessionId("@alice:server.org"), + sessionId: String = "@alice:server.org", + deviceId: String = "aDeviceId", isTokenValid: Boolean = false, sessionPath: String = "/a/path/to/a/session", cachePath: String = "/a/path/to/a/cache", ): SessionData { return SessionData( - userId = sessionId.value, - deviceId = "aDeviceId", + userId = sessionId, + deviceId = deviceId, accessToken = "anAccessToken", refreshToken = "aRefreshToken", homeserverUrl = "aHomeserverUrl", From 85ff062c73739bff8098683e6987848ed7d70f7f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 20:34:39 +0200 Subject: [PATCH 099/106] Add unit test on SessionPathsProvider --- libraries/matrix/impl/build.gradle.kts | 2 + .../impl/util/SessionPathsProviderTest.kt | 39 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/util/SessionPathsProviderTest.kt diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index 5d386169ad..c13189b198 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -47,6 +47,8 @@ dependencies { testImplementation(libs.test.truth) testImplementation(libs.test.robolectric) testImplementation(projects.libraries.matrix.test) + testImplementation(projects.libraries.sessionStorage.implMemory) + testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.services.analytics.test) testImplementation(projects.services.toolbox.test) testImplementation(projects.tests.testutils) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/util/SessionPathsProviderTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/util/SessionPathsProviderTest.kt new file mode 100644 index 0000000000..f530fc04cc --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/util/SessionPathsProviderTest.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.util + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore +import io.element.android.libraries.sessionstorage.test.aSessionData +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class SessionPathsProviderTest { + @Test + fun `if session is not found, provides returns null`() = runTest { + val sut = SessionPathsProvider(InMemorySessionStore()) + val result = sut.provides(A_SESSION_ID) + assertThat(result).isNull() + } + + @Test + fun `if session is found, provides returns the data`() = runTest { + val store = InMemorySessionStore() + val sut = SessionPathsProvider(store) + store.storeData( + aSessionData( + sessionPath = "/a/path/to/a/session", + cachePath = "/a/path/to/a/cache", + ) + ) + val result = sut.provides(A_SESSION_ID)!! + assertThat(result.fileDirectory.absolutePath).isEqualTo("/a/path/to/a/session") + assertThat(result.cacheDirectory.absolutePath).isEqualTo("/a/path/to/a/cache") + } +} From e9a898ff82ab0bd049625b013ecad54670ab384f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 Sep 2024 18:07:57 +0200 Subject: [PATCH 100/106] Cleanup --- .../impl/migrations/AppMigration05Test.kt | 4 +- .../impl/migrations/AppMigration06Test.kt | 4 +- features/signedout/impl/build.gradle.kts | 1 + .../signedout/impl/SignedOutPresenterTest.kt | 1 + .../timeline/MatrixTimelineDiffProcessor.kt | 6 +-- .../QrLoginProgressExtensionsKtTest.kt | 2 - .../impl/encryption/BackupStateMapperTest.kt | 15 +++--- .../encryption/BackupUploadStateMapperTest.kt | 12 +++-- .../EnableRecoveryProgressMapperTest.kt | 13 ++--- .../encryption/RecoveryStateMapperTest.kt | 9 ++-- .../fixtures/factories/RoomDescription.kt | 26 ++++++++++ .../impl/fixtures/factories/RoomHero.kt | 22 ++++++++ .../RoomInfo.kt} | 2 +- .../RoomMember.kt} | 2 +- .../fixtures/factories/RoomPowerLevels.kt | 34 ++++++++++++ .../impl/fixtures/factories/RoomPreview.kt | 35 +++++++++++++ .../fixtures/factories/SearchUsersResults.kt | 20 +++++++ .../matrix/impl/fixtures/factories/Session.kt | 28 ++++++++++ .../impl/fixtures/factories/UserProfile.kt | 21 ++++++++ .../impl/fixtures/{ => fakes}/FakeRustRoom.kt | 2 +- .../{ => fakes}/FakeRustRoomListItem.kt | 3 +- .../FakeRustRoomMembersIterator.kt | 2 +- .../fixtures/fakes/FakeRustTimelineDiff.kt | 30 +++++++++++ .../fixtures/fakes/FakeRustTimelineItem.kt | 20 +++++++ .../matrix/impl/mapper/SessionKtTest.kt | 16 +----- .../matrix/impl/poll/PollKindKtTest.kt | 1 - .../impl/room/MatrixRoomInfoMapperTest.kt | 11 ++-- .../impl/room/MessageEventTypeKtTest.kt | 3 +- .../matrix/impl/room/RoomInfoExtTest.kt | 21 +++----- .../matrix/impl/room/StateEventTypeTest.kt | 3 +- .../room/member/RoomMemberListFetcherTest.kt | 6 +-- .../powerlevels/RoomPowerLevelsMapperTest.kt | 4 +- .../room/preview/RoomPreviewMapperTest.kt | 25 +-------- .../RoomDescriptionMapperTest.kt | 15 +----- .../roomlist/RoomSummaryListProcessorTest.kt | 2 +- .../MatrixTimelineDiffProcessorTest.kt | 52 +++++-------------- .../impl/timeline/postprocessor/Fixtures.kt | 1 - .../RoomBeginningPostProcessorTest.kt | 1 - .../impl/usersearch/UserProfileMapperTest.kt | 4 +- .../usersearch/UserSearchResultMapperTest.kt | 14 ++--- .../DefaultFirebaseNewTokenHandlerTest.kt | 10 ++-- 41 files changed, 327 insertions(+), 176 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomDescription.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomHero.kt rename libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/{RustRoomInfo.kt => factories/RoomInfo.kt} (97%) rename libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/{RustRoomMember.kt => factories/RoomMember.kt} (93%) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPowerLevels.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPreview.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/Session.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/UserProfile.kt rename libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/{ => fakes}/FakeRustRoom.kt (94%) rename libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/{ => fakes}/FakeRustRoomListItem.kt (85%) rename libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/{ => fakes}/FakeRustRoomMembersIterator.kt (92%) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineDiff.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineItem.kt diff --git a/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration05Test.kt b/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration05Test.kt index 394c4a34b3..850674cde7 100644 --- a/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration05Test.kt +++ b/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration05Test.kt @@ -21,7 +21,7 @@ class AppMigration05Test { val sessionStore = InMemorySessionStore().apply { updateData( aSessionData( - sessionId = A_SESSION_ID, + sessionId = A_SESSION_ID.value, sessionPath = "", ) ) @@ -37,7 +37,7 @@ class AppMigration05Test { val sessionStore = InMemorySessionStore().apply { updateData( aSessionData( - sessionId = A_SESSION_ID, + sessionId = A_SESSION_ID.value, sessionPath = "/a/path/existing", ) ) diff --git a/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration06Test.kt b/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration06Test.kt index 6e1b9a237d..f60a3af5ad 100644 --- a/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration06Test.kt +++ b/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration06Test.kt @@ -21,7 +21,7 @@ class AppMigration06Test { val sessionStore = InMemorySessionStore().apply { updateData( aSessionData( - sessionId = A_SESSION_ID, + sessionId = A_SESSION_ID.value, sessionPath = "/a/path/to/a/session/AN_ID", cachePath = "", ) @@ -38,7 +38,7 @@ class AppMigration06Test { val sessionStore = InMemorySessionStore().apply { updateData( aSessionData( - sessionId = A_SESSION_ID, + sessionId = A_SESSION_ID.value, cachePath = "/a/path/existing", ) ) diff --git a/features/signedout/impl/build.gradle.kts b/features/signedout/impl/build.gradle.kts index 35ad8ecb16..8d8b3f518c 100644 --- a/features/signedout/impl/build.gradle.kts +++ b/features/signedout/impl/build.gradle.kts @@ -37,5 +37,6 @@ dependencies { testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.sessionStorage.implMemory) + testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.tests.testutils) } diff --git a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt index 8945020da3..a5390c153e 100644 --- a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt +++ b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt @@ -16,6 +16,7 @@ import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore +import io.element.android.libraries.sessionstorage.test.aSessionData import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest import org.junit.Rule diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt index 3523823d5e..a48817efa5 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt @@ -15,7 +15,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import org.matrix.rustcomponents.sdk.TimelineChange -import org.matrix.rustcomponents.sdk.TimelineDiffInterface +import org.matrix.rustcomponents.sdk.TimelineDiff import org.matrix.rustcomponents.sdk.TimelineItem import timber.log.Timber @@ -36,7 +36,7 @@ internal class MatrixTimelineDiffProcessor( } } - suspend fun postDiffs(diffs: List) { + suspend fun postDiffs(diffs: List) { updateTimelineItems { Timber.v("Update timeline items from postDiffs (with ${diffs.size} items) on ${Thread.currentThread()}") diffs.forEach { diff -> @@ -52,7 +52,7 @@ internal class MatrixTimelineDiffProcessor( timelineItems.value = mutableTimelineItems } - private fun MutableList.applyDiff(diff: TimelineDiffInterface) { + private fun MutableList.applyDiff(diff: TimelineDiff) { when (diff.change()) { TimelineChange.APPEND -> { val items = diff.append()?.map { it.asMatrixTimelineItem() } ?: return diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt index 0de3d15e57..172b415e98 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt @@ -25,5 +25,3 @@ class QrLoginProgressExtensionsKtTest { .isEqualTo(QrCodeLoginStep.Finished) } } - - diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt index fc804b0978..f529aacbcb 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt @@ -15,12 +15,13 @@ import org.matrix.rustcomponents.sdk.BackupState as RustBackupState class BackupStateMapperTest { @Test fun `Ensure that mapping is correct`() { - assertThat(BackupStateMapper().map(RustBackupState.UNKNOWN)).isEqualTo(BackupState.UNKNOWN) - assertThat(BackupStateMapper().map(RustBackupState.CREATING)).isEqualTo(BackupState.CREATING) - assertThat(BackupStateMapper().map(RustBackupState.ENABLING)).isEqualTo(BackupState.ENABLING) - assertThat(BackupStateMapper().map(RustBackupState.RESUMING)).isEqualTo(BackupState.RESUMING) - assertThat(BackupStateMapper().map(RustBackupState.ENABLED)).isEqualTo(BackupState.ENABLED) - assertThat(BackupStateMapper().map(RustBackupState.DOWNLOADING)).isEqualTo(BackupState.DOWNLOADING) - assertThat(BackupStateMapper().map(RustBackupState.DISABLING)).isEqualTo(BackupState.DISABLING) + val sut = BackupStateMapper() + assertThat(sut.map(RustBackupState.UNKNOWN)).isEqualTo(BackupState.UNKNOWN) + assertThat(sut.map(RustBackupState.CREATING)).isEqualTo(BackupState.CREATING) + assertThat(sut.map(RustBackupState.ENABLING)).isEqualTo(BackupState.ENABLING) + assertThat(sut.map(RustBackupState.RESUMING)).isEqualTo(BackupState.RESUMING) + assertThat(sut.map(RustBackupState.ENABLED)).isEqualTo(BackupState.ENABLED) + assertThat(sut.map(RustBackupState.DOWNLOADING)).isEqualTo(BackupState.DOWNLOADING) + assertThat(sut.map(RustBackupState.DISABLING)).isEqualTo(BackupState.DISABLING) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt index 7c1ad1d7c5..6148cd6971 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt @@ -15,19 +15,21 @@ import org.matrix.rustcomponents.sdk.BackupUploadState as RustBackupUploadState class BackupUploadStateMapperTest { @Test fun `Ensure that mapping is correct`() { - assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Waiting)) + val sut = BackupUploadStateMapper() + assertThat(sut.map(RustBackupUploadState.Waiting)) .isEqualTo(BackupUploadState.Waiting) - assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Error)) + assertThat(sut.map(RustBackupUploadState.Error)) .isEqualTo(BackupUploadState.Error) - assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Done)) + assertThat(sut.map(RustBackupUploadState.Done)) .isEqualTo(BackupUploadState.Done) - assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Uploading(1.toUInt(), 2.toUInt()))) + assertThat(sut.map(RustBackupUploadState.Uploading(1.toUInt(), 2.toUInt()))) .isEqualTo(BackupUploadState.Uploading(1, 2)) } @Test fun `Ensure that full uploading is mapper to Done`() { - assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Uploading(2.toUInt(), 2.toUInt()))) + val sut = BackupUploadStateMapper() + assertThat(sut.map(RustBackupUploadState.Uploading(2.toUInt(), 2.toUInt()))) .isEqualTo(BackupUploadState.Done) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt index 191a7f3964..fb39ff2d38 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt @@ -15,17 +15,18 @@ import org.matrix.rustcomponents.sdk.EnableRecoveryProgress as RustEnableRecover class EnableRecoveryProgressMapperTest { @Test fun `Ensure that mapping is correct`() { - assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.CreatingRecoveryKey)) + val sut = EnableRecoveryProgressMapper() + assertThat(sut.map(RustEnableRecoveryProgress.CreatingRecoveryKey)) .isEqualTo(EnableRecoveryProgress.CreatingRecoveryKey) - assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.CreatingBackup)) + assertThat(sut.map(RustEnableRecoveryProgress.CreatingBackup)) .isEqualTo(EnableRecoveryProgress.CreatingBackup) - assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.Starting)) + assertThat(sut.map(RustEnableRecoveryProgress.Starting)) .isEqualTo(EnableRecoveryProgress.Starting) - assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.BackingUp(1.toUInt(), 2.toUInt()))) + assertThat(sut.map(RustEnableRecoveryProgress.BackingUp(1.toUInt(), 2.toUInt()))) .isEqualTo(EnableRecoveryProgress.BackingUp(1, 2)) - assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.RoomKeyUploadError)) + assertThat(sut.map(RustEnableRecoveryProgress.RoomKeyUploadError)) .isEqualTo(EnableRecoveryProgress.RoomKeyUploadError) - assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.Done("recoveryKey"))) + assertThat(sut.map(RustEnableRecoveryProgress.Done("recoveryKey"))) .isEqualTo(EnableRecoveryProgress.Done("recoveryKey")) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.kt index 9d7c2d0c04..b3c93af7ef 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.kt @@ -15,9 +15,10 @@ import org.matrix.rustcomponents.sdk.RecoveryState as RustRecoveryState class RecoveryStateMapperTest { @Test fun `Ensure that mapping is correct`() { - assertThat(RecoveryStateMapper().map(RustRecoveryState.UNKNOWN)).isEqualTo(RecoveryState.UNKNOWN) - assertThat(RecoveryStateMapper().map(RustRecoveryState.ENABLED)).isEqualTo(RecoveryState.ENABLED) - assertThat(RecoveryStateMapper().map(RustRecoveryState.DISABLED)).isEqualTo(RecoveryState.DISABLED) - assertThat(RecoveryStateMapper().map(RustRecoveryState.INCOMPLETE)).isEqualTo(RecoveryState.INCOMPLETE) + val sut = RecoveryStateMapper() + assertThat(sut.map(RustRecoveryState.UNKNOWN)).isEqualTo(RecoveryState.UNKNOWN) + assertThat(sut.map(RustRecoveryState.ENABLED)).isEqualTo(RecoveryState.ENABLED) + assertThat(sut.map(RustRecoveryState.DISABLED)).isEqualTo(RecoveryState.DISABLED) + assertThat(sut.map(RustRecoveryState.INCOMPLETE)).isEqualTo(RecoveryState.INCOMPLETE) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomDescription.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomDescription.kt new file mode 100644 index 0000000000..d80b3d3723 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomDescription.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE 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_ALIAS +import io.element.android.libraries.matrix.test.A_ROOM_ID +import org.matrix.rustcomponents.sdk.PublicRoomJoinRule +import org.matrix.rustcomponents.sdk.RoomDescription + +internal fun aRustRoomDescription(): RoomDescription { + return RoomDescription( + roomId = A_ROOM_ID.value, + name = "name", + topic = "topic", + alias = A_ROOM_ALIAS.value, + avatarUrl = "avatarUrl", + joinRule = PublicRoomJoinRule.PUBLIC, + isWorldReadable = true, + joinedMembers = 2u + ) +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomHero.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomHero.kt new file mode 100644 index 0000000000..0eac725c2e --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomHero.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.fixtures.factories + +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.test.A_USER_ID +import org.matrix.rustcomponents.sdk.RoomHero + +internal fun aRustRoomHero( + userId: UserId = A_USER_ID, +): RoomHero { + return RoomHero( + userId = userId.value, + displayName = "displayName", + avatarUrl = "avatarUrl", + ) +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt similarity index 97% rename from libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt rename to libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt index b78780ee23..e7e3ff219f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt @@ -5,7 +5,7 @@ * Please see LICENSE in the repository root for full details. */ -package io.element.android.libraries.matrix.impl.fixtures +package io.element.android.libraries.matrix.impl.fixtures.factories import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.test.A_ROOM_ID diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomMember.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomMember.kt similarity index 93% rename from libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomMember.kt rename to libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomMember.kt index 918ae1fe12..7aebed99ea 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomMember.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomMember.kt @@ -5,7 +5,7 @@ * Please see LICENSE in the repository root for full details. */ -package io.element.android.libraries.matrix.impl.fixtures +package io.element.android.libraries.matrix.impl.fixtures.factories import io.element.android.libraries.matrix.api.core.UserId import org.matrix.rustcomponents.sdk.MembershipState diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPowerLevels.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPowerLevels.kt new file mode 100644 index 0000000000..adfb65c19a --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPowerLevels.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.fixtures.factories + +import org.matrix.rustcomponents.sdk.RoomPowerLevels + +internal fun aRustRoomPowerLevels( + ban: Long, + invite: Long, + kick: Long, + redact: Long, + eventsDefault: Long, + stateDefault: Long, + usersDefault: Long, + roomName: Long, + roomAvatar: Long, + roomTopic: Long, +) = RoomPowerLevels( + ban = ban, + invite = invite, + kick = kick, + redact = redact, + eventsDefault = eventsDefault, + stateDefault = stateDefault, + usersDefault = usersDefault, + roomName = roomName, + roomAvatar = roomAvatar, + roomTopic = roomTopic, +) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPreview.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPreview.kt new file mode 100644 index 0000000000..54abeb90b8 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPreview.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE 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_ALIAS +import io.element.android.libraries.matrix.test.A_ROOM_ID +import org.matrix.rustcomponents.sdk.RoomPreview + +internal fun aRustRoomPreview( + canonicalAlias: String? = A_ROOM_ALIAS.value, + isJoined: Boolean = true, + isInvited: Boolean = true, + isPublic: Boolean = true, + canKnock: Boolean = true, +): RoomPreview { + return RoomPreview( + roomId = A_ROOM_ID.value, + canonicalAlias = canonicalAlias, + name = "name", + topic = "topic", + avatarUrl = "avatarUrl", + numJoinedMembers = 1u, + roomType = null, + isHistoryWorldReadable = true, + isJoined = isJoined, + isInvited = isInvited, + isPublic = isPublic, + canKnock = canKnock, + ) +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.kt new file mode 100644 index 0000000000..d051a1fb2d --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.fixtures.factories + +import org.matrix.rustcomponents.sdk.SearchUsersResults +import org.matrix.rustcomponents.sdk.UserProfile + +internal fun aRustSearchUsersResults( + results: List, + limited: Boolean, +) = SearchUsersResults( + results = results, + limited = limited, +) + diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/Session.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/Session.kt new file mode 100644 index 0000000000..64d1667157 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/Session.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.fixtures.factories + +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 org.matrix.rustcomponents.sdk.Session +import org.matrix.rustcomponents.sdk.SlidingSyncVersion + +internal fun aRustSession( + proxy: SlidingSyncVersion = SlidingSyncVersion.None +): Session { + return Session( + accessToken = "accessToken", + refreshToken = "refreshToken", + userId = A_USER_ID.value, + deviceId = A_DEVICE_ID.value, + homeserverUrl = A_HOMESERVER_URL, + oidcData = null, + slidingSyncVersion = proxy, + ) +} 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 new file mode 100644 index 0000000000..f6444d1376 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/UserProfile.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.fixtures.factories + +import io.element.android.libraries.matrix.test.A_USER_ID +import org.matrix.rustcomponents.sdk.UserProfile + +fun aRustUserProfile( + userId: String = A_USER_ID.value, + displayName: String = "displayName", + avatarUrl: String = "avatarUrl", +) = UserProfile( + userId = userId, + displayName = displayName, + avatarUrl = avatarUrl, +) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoom.kt similarity index 94% rename from libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt rename to libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoom.kt index a9321bf347..f066f37e9b 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoom.kt @@ -5,7 +5,7 @@ * Please see LICENSE in the repository root for full details. */ -package io.element.android.libraries.matrix.impl.fixtures +package io.element.android.libraries.matrix.impl.fixtures.fakes import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.test.A_ROOM_ID diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomListItem.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListItem.kt similarity index 85% rename from libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomListItem.kt rename to libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListItem.kt index 1b9adee435..6d20221d88 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomListItem.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListItem.kt @@ -5,9 +5,10 @@ * Please see LICENSE in the repository root for full details. */ -package io.element.android.libraries.matrix.impl.fixtures +package io.element.android.libraries.matrix.impl.fixtures.fakes import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo import org.matrix.rustcomponents.sdk.EventTimelineItem import org.matrix.rustcomponents.sdk.NoPointer import org.matrix.rustcomponents.sdk.RoomInfo diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomMembersIterator.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomMembersIterator.kt similarity index 92% rename from libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomMembersIterator.kt rename to libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomMembersIterator.kt index e5a0646303..6d44ccbc75 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomMembersIterator.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomMembersIterator.kt @@ -5,7 +5,7 @@ * Please see LICENSE in the repository root for full details. */ -package io.element.android.libraries.matrix.impl.fixtures +package io.element.android.libraries.matrix.impl.fixtures.fakes import org.matrix.rustcomponents.sdk.NoPointer import org.matrix.rustcomponents.sdk.RoomMember diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineDiff.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineDiff.kt new file mode 100644 index 0000000000..f4fe5e15d9 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineDiff.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.fixtures.fakes + +import org.matrix.rustcomponents.sdk.InsertData +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.SetData +import org.matrix.rustcomponents.sdk.TimelineChange +import org.matrix.rustcomponents.sdk.TimelineDiff +import org.matrix.rustcomponents.sdk.TimelineItem + +class FakeRustTimelineDiff( + private val change: TimelineChange, + private val item: TimelineItem? = FakeRustTimelineItem() +) : TimelineDiff(NoPointer) { + override fun change() = change + override fun append(): List? = item?.let { listOf(it) } + override fun insert(): InsertData? = item?.let { InsertData(1u, it) } + override fun pushBack(): TimelineItem? = item + override fun pushFront(): TimelineItem? = item + override fun remove(): UInt? = 1u + override fun reset(): List? = item?.let { listOf(it) } + override fun set(): SetData? = item?.let { SetData(1u, it) } + override fun truncate(): UInt? = 1u +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineItem.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineItem.kt new file mode 100644 index 0000000000..c20698fe62 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineItem.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.fixtures.fakes + +import org.matrix.rustcomponents.sdk.EventTimelineItem +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.TimelineItem +import org.matrix.rustcomponents.sdk.VirtualTimelineItem + +class FakeRustTimelineItem : TimelineItem(NoPointer) { + override fun asEvent(): EventTimelineItem? = null + override fun asVirtual(): VirtualTimelineItem? = null + override fun fmtDebug(): String = "fmtDebug" + override fun uniqueId(): String = "uniqueId" +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt index aac34dfdab..9e6d87957c 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt @@ -8,6 +8,7 @@ package io.element.android.libraries.matrix.impl.mapper import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSession import io.element.android.libraries.matrix.impl.paths.SessionPaths import io.element.android.libraries.matrix.test.A_DEVICE_ID import io.element.android.libraries.matrix.test.A_HOMESERVER_URL @@ -16,7 +17,6 @@ import io.element.android.libraries.matrix.test.A_SECRET import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.sessionstorage.api.LoginType import org.junit.Test -import org.matrix.rustcomponents.sdk.Session import org.matrix.rustcomponents.sdk.SlidingSyncVersion import java.io.File @@ -82,17 +82,3 @@ class SessionKtTest { assertThat(result.slidingSyncProxy).isEqualTo("proxyUrl") } } - -internal fun aRustSession( - proxy: SlidingSyncVersion = SlidingSyncVersion.None -): Session { - return Session( - accessToken = "accessToken", - refreshToken = "refreshToken", - userId = A_USER_ID.value, - deviceId = A_DEVICE_ID.value, - homeserverUrl = A_HOMESERVER_URL, - oidcData = null, - slidingSyncVersion = proxy, - ) -} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt index 97f049bcb7..4be515530c 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt @@ -12,7 +12,6 @@ import io.element.android.libraries.matrix.api.poll.PollKind import org.junit.Test import org.matrix.rustcomponents.sdk.PollKind as RustPollKind - class PollKindKtTest { @Test fun `map should return Disclosed when RustPollKind is Disclosed`() { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt index ce04469ff8..c9e80f493d 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt @@ -15,8 +15,9 @@ import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.user.MatrixUser -import io.element.android.libraries.matrix.impl.room.member.aRustRoomMember -import io.element.android.libraries.matrix.impl.roomlist.aRustRoomInfo +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomHero +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomMember import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_ROOM_ALIAS @@ -52,7 +53,7 @@ class MatrixRoomInfoMapperTest { alternativeAliases = listOf(A_ROOM_ALIAS.value), membership = Membership.JOINED, inviter = aRustRoomMember(A_USER_ID), - heroes = listOf(aRoomHero()), + heroes = listOf(aRustRoomHero()), activeMembersCount = 2uL, invitedMembersCount = 3uL, joinedMembersCount = 4uL, @@ -67,7 +68,7 @@ class MatrixRoomInfoMapperTest { numUnreadNotifications = 13uL, numUnreadMentions = 14uL, pinnedEventIds = listOf(AN_EVENT_ID.value), - roomCreator = A_USER_ID.value, + roomCreator = A_USER_ID, ) ) ).isEqualTo( @@ -127,7 +128,7 @@ class MatrixRoomInfoMapperTest { alternativeAliases = emptyList(), membership = Membership.INVITED, inviter = null, - heroes = listOf(aRoomHero()), + heroes = listOf(aRustRoomHero()), activeMembersCount = 2uL, invitedMembersCount = 3uL, joinedMembersCount = 4uL, diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt index 847c41e89a..3c439d28b0 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt @@ -8,9 +8,8 @@ package io.element.android.libraries.matrix.impl.room import com.google.common.truth.Truth.assertThat -import org.junit.Test - import io.element.android.libraries.matrix.api.room.MessageEventType +import org.junit.Test import org.matrix.rustcomponents.sdk.MessageLikeEventType class MessageEventTypeKtTest { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt index 7d671d0972..d65f042019 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt @@ -10,10 +10,10 @@ package io.element.android.libraries.matrix.impl.room import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.user.MatrixUser -import io.element.android.libraries.matrix.impl.fixtures.aRustRoomInfo +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomHero +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo import io.element.android.libraries.matrix.test.A_USER_ID import org.junit.Test -import org.matrix.rustcomponents.sdk.RoomHero class RoomInfoExtTest { @Test @@ -21,7 +21,7 @@ class RoomInfoExtTest { val result = aRustRoomInfo( isDirect = true, activeMembersCount = 2uL, - heroes = listOf(aRoomHero()) + heroes = listOf(aRustRoomHero()) ).elementHeroes() assertThat(result).isEqualTo( listOf( @@ -39,7 +39,7 @@ class RoomInfoExtTest { val result = aRustRoomInfo( isDirect = true, activeMembersCount = 2uL, - heroes = listOf(aRoomHero(), aRoomHero()) + heroes = listOf(aRustRoomHero(), aRustRoomHero()) ).elementHeroes() assertThat(result).isEmpty() } @@ -49,7 +49,7 @@ class RoomInfoExtTest { val result = aRustRoomInfo( isDirect = false, activeMembersCount = 2uL, - heroes = listOf(aRoomHero()) + heroes = listOf(aRustRoomHero()) ).elementHeroes() assertThat(result).isEmpty() } @@ -59,18 +59,9 @@ class RoomInfoExtTest { val result = aRustRoomInfo( isDirect = true, activeMembersCount = 3uL, - heroes = listOf(aRoomHero()) + heroes = listOf(aRustRoomHero()) ).elementHeroes() assertThat(result).isEmpty() } } -internal fun aRoomHero( - userId: UserId = A_USER_ID, -): RoomHero { - return RoomHero( - userId = userId.value, - displayName = "displayName", - avatarUrl = "avatarUrl", - ) -} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt index 3772ae780d..1900575bbf 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt @@ -8,9 +8,8 @@ package io.element.android.libraries.matrix.impl.room import com.google.common.truth.Truth.assertThat -import org.junit.Test - import io.element.android.libraries.matrix.api.room.StateEventType +import org.junit.Test import org.matrix.rustcomponents.sdk.StateEventType as RustStateEventType class StateEventTypeTest { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt index dc8489e48f..549f7e5ac2 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt @@ -11,9 +11,9 @@ import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.roomMembers -import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoom -import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoomMembersIterator -import io.element.android.libraries.matrix.impl.fixtures.aRustRoomMember +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoom +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomMembersIterator +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomMember import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.CACHE import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.CACHE_AND_SERVER import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.SERVER diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt index 2a8a89004d..20cbdc5deb 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt @@ -9,15 +9,15 @@ package io.element.android.libraries.matrix.impl.room.powerlevels import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.room.powerlevels.MatrixRoomPowerLevels +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomPowerLevels import org.junit.Test -import org.matrix.rustcomponents.sdk.RoomPowerLevels as RustRoomPowerLevels class RoomPowerLevelsMapperTest { @Test fun `test that mapping of RoomPowerLevels is correct`() { assertThat( RoomPowerLevelsMapper.map( - RustRoomPowerLevels( + aRustRoomPowerLevels( ban = 1, invite = 2, kick = 3, diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt index 3e0fea4bdc..7d7890198e 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt @@ -10,10 +10,10 @@ package io.element.android.libraries.matrix.impl.room.preview import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.room.RoomType import io.element.android.libraries.matrix.api.room.preview.RoomPreview +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomPreview import io.element.android.libraries.matrix.test.A_ROOM_ALIAS import io.element.android.libraries.matrix.test.A_ROOM_ID import org.junit.Test -import org.matrix.rustcomponents.sdk.RoomPreview as RustRoomPreview class RoomPreviewMapperTest { @Test @@ -71,26 +71,3 @@ class RoomPreviewMapperTest { ) } } - -internal fun aRustRoomPreview( - canonicalAlias: String? = A_ROOM_ALIAS.value, - isJoined: Boolean = true, - isInvited: Boolean = true, - isPublic: Boolean = true, - canKnock: Boolean = true, -): RustRoomPreview { - return RustRoomPreview( - roomId = A_ROOM_ID.value, - canonicalAlias = canonicalAlias, - name = "name", - topic = "topic", - avatarUrl = "avatarUrl", - numJoinedMembers = 1u, - roomType = null, - isHistoryWorldReadable = true, - isJoined = isJoined, - isInvited = isInvited, - isPublic = isPublic, - canKnock = canKnock, - ) -} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt index 307cc33b54..808b15dd1f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt @@ -9,12 +9,12 @@ package io.element.android.libraries.matrix.impl.roomdirectory import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.roomdirectory.RoomDescription +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomDescription import io.element.android.libraries.matrix.test.A_ROOM_ALIAS import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.roomdirectory.aRoomDescription import org.junit.Test import org.matrix.rustcomponents.sdk.PublicRoomJoinRule -import org.matrix.rustcomponents.sdk.RoomDescription as RustRoomDescription class RoomDescriptionMapperTest { @Test @@ -45,16 +45,3 @@ class RoomDescriptionMapperTest { assertThat(null.map()).isEqualTo(RoomDescription.JoinRule.UNKNOWN) } } - -internal fun aRustRoomDescription(): RustRoomDescription { - return RustRoomDescription( - roomId = A_ROOM_ID.value, - name = "name", - topic = "topic", - alias = A_ROOM_ALIAS.value, - avatarUrl = "avatarUrl", - joinRule = PublicRoomJoinRule.PUBLIC, - isWorldReadable = true, - joinedMembers = 2u - ) -} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt index d4b347af44..d6ed69706c 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt @@ -10,7 +10,7 @@ package io.element.android.libraries.matrix.impl.roomlist import com.google.common.truth.Truth.assertThat import com.sun.jna.Pointer import io.element.android.libraries.matrix.api.roomlist.RoomSummary -import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoomListItem +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomListItem import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID_2 import io.element.android.libraries.matrix.test.A_ROOM_ID_3 diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt index 84ce6e61f9..d442d004d6 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl.timeline import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustTimelineDiff import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper @@ -19,29 +20,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test -import org.matrix.rustcomponents.sdk.EventTimelineItem -import org.matrix.rustcomponents.sdk.InsertData -import org.matrix.rustcomponents.sdk.NoPointer -import org.matrix.rustcomponents.sdk.SetData import org.matrix.rustcomponents.sdk.TimelineChange -import org.matrix.rustcomponents.sdk.TimelineDiffInterface -import org.matrix.rustcomponents.sdk.TimelineItem -import org.matrix.rustcomponents.sdk.VirtualTimelineItem - -open class FakeTimelineDiff( - private val change: TimelineChange, - private val item: TimelineItem? = FakeTimelineItem() -) : TimelineDiffInterface { - override fun change() = change - override fun append(): List? = item?.let { listOf(it) } - override fun insert(): InsertData? = item?.let { InsertData(1u, it) } - override fun pushBack(): TimelineItem? = item - override fun pushFront(): TimelineItem? = item - override fun remove(): UInt? = 1u - override fun reset(): List? = item?.let { listOf(it) } - override fun set(): SetData? = item?.let { SetData(1u, it) } - override fun truncate(): UInt? = 1u -} class MatrixTimelineDiffProcessorTest { private val timelineItems = MutableStateFlow>(emptyList()) @@ -53,7 +32,7 @@ class MatrixTimelineDiffProcessorTest { fun `Append adds new entries at the end of the list`() = runTest { timelineItems.value = listOf(anEvent) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.APPEND))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.APPEND))) assertThat(timelineItems.value.count()).isEqualTo(2) assertThat(timelineItems.value).containsExactly( anEvent, @@ -65,7 +44,7 @@ class MatrixTimelineDiffProcessorTest { fun `PushBack adds a new entry at the end of the list`() = runTest { timelineItems.value = listOf(anEvent) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.PUSH_BACK))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.PUSH_BACK))) assertThat(timelineItems.value.count()).isEqualTo(2) assertThat(timelineItems.value).containsExactly( anEvent, @@ -77,7 +56,7 @@ class MatrixTimelineDiffProcessorTest { fun `PushFront inserts a new entry at the start of the list`() = runTest { timelineItems.value = listOf(anEvent) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.PUSH_FRONT))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.PUSH_FRONT))) assertThat(timelineItems.value.count()).isEqualTo(2) assertThat(timelineItems.value).containsExactly( MatrixTimelineItem.Other, @@ -89,7 +68,7 @@ class MatrixTimelineDiffProcessorTest { fun `Set replaces an entry at some index`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.SET))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.SET))) assertThat(timelineItems.value.count()).isEqualTo(2) assertThat(timelineItems.value).containsExactly( anEvent, @@ -101,7 +80,7 @@ class MatrixTimelineDiffProcessorTest { fun `Insert inserts a new entry at the provided index`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.INSERT))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.INSERT))) assertThat(timelineItems.value.count()).isEqualTo(3) assertThat(timelineItems.value).containsExactly( anEvent, @@ -114,7 +93,7 @@ class MatrixTimelineDiffProcessorTest { fun `Remove removes an entry at some index`() = runTest { timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.REMOVE))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.REMOVE))) assertThat(timelineItems.value.count()).isEqualTo(2) assertThat(timelineItems.value).containsExactly( anEvent, @@ -126,7 +105,7 @@ class MatrixTimelineDiffProcessorTest { fun `PopBack removes an entry at the end of the list`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.POP_BACK))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.POP_BACK))) assertThat(timelineItems.value.count()).isEqualTo(1) assertThat(timelineItems.value).containsExactly( anEvent, @@ -137,7 +116,7 @@ class MatrixTimelineDiffProcessorTest { fun `PopFront removes an entry at the start of the list`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.POP_FRONT))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.POP_FRONT))) assertThat(timelineItems.value.count()).isEqualTo(1) assertThat(timelineItems.value).containsExactly( anEvent2, @@ -148,7 +127,7 @@ class MatrixTimelineDiffProcessorTest { fun `Clear removes all the entries`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.CLEAR))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.CLEAR))) assertThat(timelineItems.value).isEmpty() } @@ -156,7 +135,7 @@ class MatrixTimelineDiffProcessorTest { fun `Truncate removes all entries after the provided length`() = runTest { timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.TRUNCATE))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.TRUNCATE))) assertThat(timelineItems.value.count()).isEqualTo(1) assertThat(timelineItems.value).containsExactly( anEvent, @@ -167,7 +146,7 @@ class MatrixTimelineDiffProcessorTest { fun `Reset removes all entries and add the provided ones`() = runTest { timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.RESET))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.RESET))) assertThat(timelineItems.value.count()).isEqualTo(1) assertThat(timelineItems.value).containsExactly( MatrixTimelineItem.Other, @@ -190,10 +169,3 @@ class MatrixTimelineDiffProcessorTest { ) } } - -class FakeTimelineItem : TimelineItem(NoPointer) { - override fun asEvent(): EventTimelineItem? = null - override fun asVirtual(): VirtualTimelineItem? = null - override fun fmtDebug(): String = "fmtDebug" - override fun uniqueId(): String = "uniqueId" -} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt index 16acfd718f..cc295d2517 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt @@ -43,4 +43,3 @@ internal val dayEvent = MatrixTimelineItem.Virtual( uniqueId = UniqueId("day"), virtual = VirtualTimelineItem.DayDivider(0), ) - diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt index 41d175b348..f7eadd0d47 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt @@ -13,7 +13,6 @@ import io.element.android.libraries.matrix.test.A_USER_ID import org.junit.Test class RoomBeginningPostProcessorTest { - @Test fun `processor returns empty list when empty list is provided`() { val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt index 0564186a78..f8bb7a0e0e 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt @@ -9,14 +9,14 @@ package io.element.android.libraries.matrix.impl.usersearch 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.test.A_USER_ID import org.junit.Test -import org.matrix.rustcomponents.sdk.UserProfile class UserProfileMapperTest { @Test fun map() { - assertThat(UserProfileMapper.map(UserProfile(A_USER_ID.value, "displayName", "avatarUrl"))) + assertThat(UserProfileMapper.map(aRustUserProfile(A_USER_ID.value, "displayName", "avatarUrl"))) .isEqualTo(MatrixUser(A_USER_ID, "displayName", "avatarUrl")) } } 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 17ce3836ca..068515e255 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 @@ -10,19 +10,19 @@ package io.element.android.libraries.matrix.impl.usersearch import com.google.common.truth.Truth.assertThat 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.test.A_USER_ID import kotlinx.collections.immutable.toImmutableList import org.junit.Test -import org.matrix.rustcomponents.sdk.SearchUsersResults -import org.matrix.rustcomponents.sdk.UserProfile class UserSearchResultMapperTest { @Test fun `map limited list`() { assertThat( UserSearchResultMapper.map( - SearchUsersResults( - results = listOf(UserProfile(A_USER_ID.value, "displayName", "avatarUrl")), + aRustSearchUsersResults( + results = listOf(aRustUserProfile(A_USER_ID.value, "displayName", "avatarUrl")), limited = true, ) ) @@ -39,9 +39,9 @@ class UserSearchResultMapperTest { fun `map not limited list`() { assertThat( UserSearchResultMapper.map( - SearchUsersResults( - listOf(UserProfile(A_USER_ID.value, "displayName", "avatarUrl")), - false, + aRustSearchUsersResults( + results = listOf(aRustUserProfile(A_USER_ID.value, "displayName", "avatarUrl")), + limited = false, ) ) ) diff --git a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/DefaultFirebaseNewTokenHandlerTest.kt b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/DefaultFirebaseNewTokenHandlerTest.kt index 2da1e8554d..668eeebf98 100644 --- a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/DefaultFirebaseNewTokenHandlerTest.kt +++ b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/DefaultFirebaseNewTokenHandlerTest.kt @@ -51,9 +51,9 @@ class DefaultFirebaseNewTokenHandlerTest { val pusherSubscriber = FakePusherSubscriber(registerPusherResult = registerPusherResult) val firebaseNewTokenHandler = createDefaultFirebaseNewTokenHandler( sessionStore = InMemoryMultiSessionsStore().apply { - storeData(aSessionData(A_USER_ID)) - storeData(aSessionData(A_USER_ID_2)) - storeData(aSessionData(A_USER_ID_3)) + storeData(aSessionData(A_USER_ID.value)) + storeData(aSessionData(A_USER_ID_2.value)) + storeData(aSessionData(A_USER_ID_3.value)) }, matrixClientProvider = FakeMatrixClientProvider { sessionId -> when (sessionId) { @@ -90,7 +90,7 @@ class DefaultFirebaseNewTokenHandlerTest { val pusherSubscriber = FakePusherSubscriber(registerPusherResult = registerPusherResult) val firebaseNewTokenHandler = createDefaultFirebaseNewTokenHandler( sessionStore = InMemoryMultiSessionsStore().apply { - storeData(aSessionData(A_USER_ID)) + storeData(aSessionData(A_USER_ID.value)) }, matrixClientProvider = FakeMatrixClientProvider { Result.failure(IllegalStateException()) @@ -114,7 +114,7 @@ class DefaultFirebaseNewTokenHandlerTest { val pusherSubscriber = FakePusherSubscriber(registerPusherResult = registerPusherResult) val firebaseNewTokenHandler = createDefaultFirebaseNewTokenHandler( sessionStore = InMemoryMultiSessionsStore().apply { - storeData(aSessionData(A_USER_ID)) + storeData(aSessionData(A_USER_ID.value)) }, matrixClientProvider = FakeMatrixClientProvider { Result.success(aMatrixClient1) From 4a4a8073fa33a00e923467f0c72382b02a9955e6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 Sep 2024 18:41:28 +0200 Subject: [PATCH 101/106] Cleanup --- .../matrix/impl/fixtures/factories/SearchUsersResults.kt | 1 - .../android/libraries/matrix/impl/room/RoomInfoExtTest.kt | 1 - .../matrix/impl/room/member/RoomMemberListFetcherTest.kt | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.kt index d051a1fb2d..f8397d066d 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.kt @@ -17,4 +17,3 @@ internal fun aRustSearchUsersResults( results = results, limited = limited, ) - diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt index d65f042019..8cf3134825 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt @@ -64,4 +64,3 @@ class RoomInfoExtTest { assertThat(result).isEmpty() } } - diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt index 549f7e5ac2..a65995fc86 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt @@ -11,9 +11,9 @@ import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.roomMembers +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomMember import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoom import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomMembersIterator -import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomMember import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.CACHE import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.CACHE_AND_SERVER import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.SERVER From 2d9b0bbe19eb12094279d28addbfa6e235a35c74 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 Sep 2024 18:50:54 +0200 Subject: [PATCH 102/106] Adapt Konsist test for Fake Rust classes. --- .../element/android/tests/konsist/KonsistClassNameTest.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt index 7ec2784c70..797f13dbe8 100644 --- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt +++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt @@ -68,11 +68,12 @@ class KonsistClassNameTest { .withoutName( "FakeFileSystem", "FakeImageLoader", - "FakeRustRoom", ) .assertTrue { - val interfaceName = it.name.replace("Fake", "") - it.name.startsWith("Fake") && + val interfaceName = it.name + .replace("FakeRust", "") + .replace("Fake", "") + (it.name.startsWith("Fake") || it.name.startsWith("FakeRust")) && it.parents().any { parent -> parent.name.replace(".", "") == interfaceName } } } From 730aa95da6992eaaa2530845e9572ccbebd7a548 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 18 Sep 2024 20:35:57 +0200 Subject: [PATCH 103/106] Rust sdk : update to 0.2.47 --- 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 14d38d3a2c..f33fa0275a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -162,7 +162,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.46" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.47" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } From b364cee500de37a416d4027e61d5d0102dbd9326 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 18 Sep 2024 21:07:39 +0200 Subject: [PATCH 104/106] Room list : debounce subscribe to visible rooms. --- .../android/features/roomlist/impl/RoomListPresenter.kt | 8 ++++++-- .../libraries/matrix/impl/roomlist/RustRoomListService.kt | 6 +----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt index 2983b6b695..bd65b2634d 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt @@ -61,7 +61,7 @@ import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.first @@ -73,6 +73,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject private const val EXTENDED_RANGE_SIZE = 40 +private const val SUBSCRIBE_TO_VISIBLE_ROOMS_DEBOUNCE_IN_MILLIS = 300L class RoomListPresenter @Inject constructor( private val client: MatrixClient, @@ -301,7 +302,10 @@ class RoomListPresenter @Inject constructor( private var currentUpdateVisibleRangeJob: Job? = null private fun CoroutineScope.updateVisibleRange(range: IntRange) { currentUpdateVisibleRangeJob?.cancel() - currentUpdateVisibleRangeJob = launch(SupervisorJob()) { + currentUpdateVisibleRangeJob = launch { + // Debounce the subscription to avoid subscribing to too many rooms + delay(SUBSCRIBE_TO_VISIBLE_ROOMS_DEBOUNCE_IN_MILLIS) + if (range.isEmpty()) return@launch val currentRoomList = roomListDataSource.allRooms.first() // Use extended range to 'prefetch' the next rooms info diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt index b203ec958f..ee0be05e4b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt @@ -53,11 +53,7 @@ internal class RustRoomListService( } override suspend fun subscribeToVisibleRooms(roomIds: List) { - val toSubscribe = roomIds.filterNot { roomSyncSubscriber.isSubscribedTo(it) } - if (toSubscribe.isNotEmpty()) { - Timber.d("Subscribe to ${toSubscribe.size} rooms: $toSubscribe") - roomSyncSubscriber.batchSubscribe(toSubscribe) - } + roomSyncSubscriber.batchSubscribe(roomIds) } override val allRooms: DynamicRoomList = roomListFactory.createRoomList( From 4b2ea110371974fcd62f0768ac6502370bd8137b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 19 Sep 2024 08:15:12 +0200 Subject: [PATCH 105/106] Fix and add test --- .../roomlist/impl/RoomListPresenterTest.kt | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt index 8b7294b165..c77f59a0a8 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt @@ -85,13 +85,16 @@ import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.test import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +import kotlin.time.Duration.Companion.seconds class RoomListPresenterTest { @get:Rule @@ -599,6 +602,38 @@ class RoomListPresenterTest { } } + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `present - UpdateVisibleRange will cancel the previous subscription if called too soon`() = runTest { + val subscribeToVisibleRoomsLambda = lambdaRecorder { _: List -> } + val roomListService = FakeRoomListService(subscribeToVisibleRoomsLambda = subscribeToVisibleRoomsLambda) + val scope = CoroutineScope(coroutineContext + SupervisorJob()) + val matrixClient = FakeMatrixClient( + roomListService = roomListService, + ) + val roomSummary = aRoomSummary( + currentUserMembership = CurrentUserMembership.INVITED + ) + roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1)) + roomListService.postAllRooms(listOf(roomSummary)) + val presenter = createRoomListPresenter( + coroutineScope = scope, + client = matrixClient, + ) + presenter.test { + val state = consumeItemsUntilPredicate { + it.contentState is RoomListContentState.Rooms + }.last() + + state.eventSink(RoomListEvents.UpdateVisibleRange(IntRange(0, 10))) + // If called again, it will cancel the current one, which should not result in a test failure + state.eventSink(RoomListEvents.UpdateVisibleRange(IntRange(0, 11))) + advanceTimeBy(1.seconds) + subscribeToVisibleRoomsLambda.assertions().isCalledOnce() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) @Test fun `present - UpdateVisibleRange subscribes to rooms in visible range`() = runTest { val subscribeToVisibleRoomsLambda = lambdaRecorder { _: List -> } @@ -622,10 +657,12 @@ class RoomListPresenterTest { }.last() state.eventSink(RoomListEvents.UpdateVisibleRange(IntRange(0, 10))) + advanceTimeBy(1.seconds) subscribeToVisibleRoomsLambda.assertions().isCalledOnce() - // If called again, it will cancel the current one, which should not result in a test failure + // If called again, it will subscribe to the next items state.eventSink(RoomListEvents.UpdateVisibleRange(IntRange(0, 11))) + advanceTimeBy(1.seconds) subscribeToVisibleRoomsLambda.assertions().isCalledExactly(2) } } From 7eac45e4d26329147e6ea1b129eb6c19b3296b21 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 10:36:33 +0200 Subject: [PATCH 106/106] Adding fastlane file for version 0.6.3 --- fastlane/metadata/android/en-US/changelogs/40006030.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/40006030.txt diff --git a/fastlane/metadata/android/en-US/changelogs/40006030.txt b/fastlane/metadata/android/en-US/changelogs/40006030.txt new file mode 100644 index 0000000000..0574894881 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40006030.txt @@ -0,0 +1,2 @@ +Element X is the new generation of Element for professional and personal use on mobile. It’s the fastest Matrix client with a seamless & intuitive user interface. +Full changelog: https://github.com/element-hq/element-x-android/releases