From b9aa07ab14800d7ee2a6fc77c8bc67a456a7f03a Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 5 Mar 2024 11:29:58 +0100 Subject: [PATCH 01/11] RoomListFilters: extract logic of selection/deselection and tweak a bit the animations. --- .../roomlist/impl/filters/RoomListFilter.kt | 6 +- .../impl/filters/RoomListFiltersEvents.kt | 2 +- .../impl/filters/RoomListFiltersPresenter.kt | 49 +++++--------- .../impl/filters/RoomListFiltersState.kt | 6 +- .../filters/RoomListFiltersStateProvider.kt | 12 ++-- .../impl/filters/RoomListFiltersView.kt | 47 +++++++------ .../DefaultFilterSelectionStrategy.kt | 67 +++++++++++++++++++ .../filters/selection/FilterSelectionState.kt | 24 +++++++ .../selection/FilterSelectionStrategy.kt | 38 +++++++++++ .../filters/RoomListFiltersPresenterTests.kt | 50 +++++++------- .../impl/filters/RoomListFiltersViewTests.kt | 6 +- 11 files changed, 211 insertions(+), 96 deletions(-) create mode 100644 features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/DefaultFilterSelectionStrategy.kt create mode 100644 features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/FilterSelectionState.kt create mode 100644 features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/FilterSelectionStrategy.kt diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFilter.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFilter.kt index 31405c45e7..51b9570c6d 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFilter.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFilter.kt @@ -20,12 +20,12 @@ import io.element.android.features.roomlist.impl.R /** * Enum class representing the different filters that can be applied to the room list. - * Order is important. + * Order is important, it'll be used as initial order in the UI. */ enum class RoomListFilter(val stringResource: Int) { - Rooms(R.string.screen_roomlist_filter_rooms), - People(R.string.screen_roomlist_filter_people), Unread(R.string.screen_roomlist_filter_unreads), + People(R.string.screen_roomlist_filter_people), + Rooms(R.string.screen_roomlist_filter_rooms), Favourites(R.string.screen_roomlist_filter_favourites); val oppositeFilter: RoomListFilter? diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEvents.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEvents.kt index d243ea7ca0..c7855444ef 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEvents.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEvents.kt @@ -17,6 +17,6 @@ package io.element.android.features.roomlist.impl.filters sealed interface RoomListFiltersEvents { - data object ClearSelectedFilters : RoomListFiltersEvents data class ToggleFilter(val filter: RoomListFilter) : RoomListFiltersEvents + data object ClearSelectedFilters : RoomListFiltersEvents } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenter.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenter.kt index 090b4e868a..058bfbbd8c 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenter.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenter.kt @@ -20,9 +20,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue +import io.element.android.features.roomlist.impl.filters.selection.FilterSelectionStrategy import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlags @@ -34,50 +32,39 @@ import io.element.android.libraries.matrix.api.roomlist.RoomListFilter as Matrix class RoomListFiltersPresenter @Inject constructor( private val roomListService: RoomListService, private val featureFlagService: FeatureFlagService, + private val filterSelectionStrategy: FilterSelectionStrategy, ) : Presenter { + @Composable override fun present(): RoomListFiltersState { - val isFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomListFilters).collectAsState(false) - var unselectedFilters: Set by rememberSaveable { - mutableStateOf(RoomListFilter.entries.toSet()) - } - var selectedFilters: Set by rememberSaveable { - mutableStateOf(emptySet()) - } - fun updateFilters(newSelectedFilters: Set) { - selectedFilters = newSelectedFilters - unselectedFilters = RoomListFilter.entries.toSet() - - selectedFilters - - selectedFilters.mapNotNull { it.oppositeFilter }.toSet() - } + val isFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomListFilters).collectAsState(false) + val filters by filterSelectionStrategy.filterSelectionStates.collectAsState() + fun handleEvents(event: RoomListFiltersEvents) { when (event) { - is RoomListFiltersEvents.ToggleFilter -> { - val newSelectedFilters = if (selectedFilters.contains(event.filter)) { - selectedFilters - event.filter - } else { - selectedFilters + event.filter - } - updateFilters(newSelectedFilters) - } RoomListFiltersEvents.ClearSelectedFilters -> { - updateFilters(newSelectedFilters = emptySet()) + filterSelectionStrategy.clear() + } + is RoomListFiltersEvents.ToggleFilter -> { + filterSelectionStrategy.toggle(event.filter) } } } LaunchedEffect(isFeatureEnabled) { if (!isFeatureEnabled) { - updateFilters(emptySet()) + filterSelectionStrategy.clear() } } - LaunchedEffect(selectedFilters) { + LaunchedEffect(filters) { val allRoomsFilter = MatrixRoomListFilter.All( - selectedFilters.map { roomListFilter -> - when (roomListFilter) { + filters + .filter { it.isSelected } + .map { roomListFilter -> + when (roomListFilter.filter) { RoomListFilter.Rooms -> MatrixRoomListFilter.Category.Group RoomListFilter.People -> MatrixRoomListFilter.Category.People RoomListFilter.Unread -> MatrixRoomListFilter.Unread @@ -88,9 +75,9 @@ class RoomListFiltersPresenter @Inject constructor( roomListService.allRooms.updateFilter(allRoomsFilter) } + return RoomListFiltersState( - unselectedFilters = unselectedFilters.toPersistentList(), - selectedFilters = selectedFilters.toPersistentList(), + filterSelectionStates = filters.toPersistentList(), isFeatureEnabled = isFeatureEnabled, eventSink = ::handleEvents ) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersState.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersState.kt index e496336742..f75fbf059f 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersState.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersState.kt @@ -16,13 +16,13 @@ package io.element.android.features.roomlist.impl.filters +import io.element.android.features.roomlist.impl.filters.selection.FilterSelectionState import kotlinx.collections.immutable.ImmutableList data class RoomListFiltersState( - val unselectedFilters: ImmutableList, - val selectedFilters: ImmutableList, + val filterSelectionStates: ImmutableList, val isFeatureEnabled: Boolean, val eventSink: (RoomListFiltersEvents) -> Unit, ) { - val hasAnyFilterSelected = selectedFilters.isNotEmpty() + val hasAnyFilterSelected = filterSelectionStates.any { it.isSelected } } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersStateProvider.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersStateProvider.kt index 281f014cc7..00d1352728 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersStateProvider.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersStateProvider.kt @@ -17,8 +17,7 @@ package io.element.android.features.roomlist.impl.filters import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.persistentListOf +import io.element.android.features.roomlist.impl.filters.selection.FilterSelectionState import kotlinx.collections.immutable.toImmutableList class RoomListFiltersStateProvider : PreviewParameterProvider { @@ -26,20 +25,17 @@ class RoomListFiltersStateProvider : PreviewParameterProvider = RoomListFilter.entries.toImmutableList(), - selectedFilters: ImmutableList = persistentListOf(), + filterSelectionStates: List = RoomListFilter.entries.map { FilterSelectionState(it, isSelected = false) }, isFeatureEnabled: Boolean = true, eventSink: (RoomListFiltersEvents) -> Unit = {}, ) = RoomListFiltersState( - unselectedFilters = unselectedFilters, - selectedFilters = selectedFilters, + filterSelectionStates = filterSelectionStates.toImmutableList(), isFeatureEnabled = isFeatureEnabled, eventSink = eventSink, ) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt index efabd5cf28..2c9a451665 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt @@ -17,6 +17,7 @@ package io.element.android.features.roomlist.impl.filters import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.tween import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -25,7 +26,6 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState @@ -34,6 +34,7 @@ import androidx.compose.material3.FilterChip import androidx.compose.material3.FilterChipDefaults import androidx.compose.material3.minimumInteractiveComponentSize import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -51,18 +52,19 @@ import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag -import kotlinx.collections.immutable.ImmutableList +@OptIn(ExperimentalFoundationApi::class) @Composable fun RoomListFiltersView( state: RoomListFiltersState, modifier: Modifier = Modifier ) { + fun onClearFiltersClicked() { state.eventSink(RoomListFiltersEvents.ClearSelectedFilters) } - fun onFilterClicked(filter: RoomListFilter) { + fun onToggleFilter(filter: RoomListFilter) { state.eventSink(RoomListFiltersEvents.ToggleFilter(filter)) } @@ -71,12 +73,14 @@ fun RoomListFiltersView( modifier = modifier.padding(start = startPadding, end = 16.dp), verticalAlignment = Alignment.CenterVertically, ) { + AnimatedVisibility(visible = state.hasAnyFilterSelected) { RoomListClearFiltersButton( modifier = Modifier.testTag(TestTags.homeScreenClearFilters), onClick = ::onClearFiltersClicked ) } + val lazyListState = rememberLazyListState() val fadingEdgesBrush = horizontalFadingEdgesBrush( showLeft = lazyListState.canScrollBackward, @@ -89,26 +93,25 @@ fun RoomListFiltersView( state = lazyListState, horizontalArrangement = Arrangement.spacedBy(8.dp) ) { - roomListFilters(state.selectedFilters, selected = true, onClick = ::onFilterClicked) - roomListFilters(state.unselectedFilters, selected = false, onClick = ::onFilterClicked) + items( + items = state.filterSelectionStates, + key = { it.filter.ordinal } + ) { filterWithSelection -> + RoomListFilterView( + modifier = Modifier.animateItemPlacement( + animationSpec = tween(200), + ), + roomListFilter = filterWithSelection.filter, + selected = filterWithSelection.isSelected, + onClick = ::onToggleFilter, + ) + } + } + LaunchedEffect(state.filterSelectionStates) { + if (lazyListState.canScrollBackward) { + lazyListState.animateScrollToItem(0) + } } - } -} - -@OptIn(ExperimentalFoundationApi::class) -private fun LazyListScope.roomListFilters( - filters: ImmutableList, - selected: Boolean, - onClick: (RoomListFilter) -> Unit, -) { - items( - items = filters, - ) { filter -> - RoomListFilterView( - roomListFilter = filter, - selected = selected, - onClick = onClick, - ) } } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/DefaultFilterSelectionStrategy.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/DefaultFilterSelectionStrategy.kt new file mode 100644 index 0000000000..4c2b4013b6 --- /dev/null +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/DefaultFilterSelectionStrategy.kt @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomlist.impl.filters.selection + +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.roomlist.impl.filters.RoomListFilter +import io.element.android.libraries.di.SessionScope +import kotlinx.coroutines.flow.MutableStateFlow +import javax.inject.Inject + +@ContributesBinding(SessionScope::class) +class DefaultFilterSelectionStrategy @Inject constructor() : FilterSelectionStrategy { + + private val selectedFilters = LinkedHashSet() + + override val filterSelectionStates = MutableStateFlow(buildFilters()) + + override fun select(filter: RoomListFilter) { + selectedFilters.add(filter) + filterSelectionStates.value = buildFilters() + } + + override fun deselect(filter: RoomListFilter) { + selectedFilters.remove(filter) + filterSelectionStates.value = buildFilters() + } + + override fun isSelected(filter: RoomListFilter): Boolean { + return selectedFilters.contains(filter) + } + + override fun clear() { + selectedFilters.clear() + filterSelectionStates.value = buildFilters() + } + + private fun buildFilters(): Set { + val selectedFilterStates = selectedFilters.map { + FilterSelectionState( + filter = it, + isSelected = true + ) + } + val unselectedFilters = RoomListFilter.entries - selectedFilters - selectedFilters.mapNotNull { it.oppositeFilter }.toSet() + val unselectedFilterStates = unselectedFilters.map { + FilterSelectionState( + filter = it, + isSelected = false + ) + } + return (selectedFilterStates + unselectedFilterStates).toSet() + } +} diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/FilterSelectionState.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/FilterSelectionState.kt new file mode 100644 index 0000000000..431eee7257 --- /dev/null +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/FilterSelectionState.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomlist.impl.filters.selection + +import io.element.android.features.roomlist.impl.filters.RoomListFilter + +data class FilterSelectionState( + val filter: RoomListFilter, + val isSelected: Boolean, +) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/FilterSelectionStrategy.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/FilterSelectionStrategy.kt new file mode 100644 index 0000000000..aa2f42384b --- /dev/null +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/FilterSelectionStrategy.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomlist.impl.filters.selection + +import io.element.android.features.roomlist.impl.filters.RoomListFilter +import kotlinx.coroutines.flow.StateFlow + +interface FilterSelectionStrategy { + + val filterSelectionStates: StateFlow> + + fun select(filter: RoomListFilter) + fun deselect(filter: RoomListFilter) + fun isSelected(filter: RoomListFilter): Boolean + fun clear() + + fun toggle(filter: RoomListFilter) { + if (isSelected(filter)) { + deselect(filter) + } else { + select(filter) + } + } +} diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenterTests.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenterTests.kt index 15ee711e82..e1f806f247 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenterTests.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenterTests.kt @@ -20,6 +20,8 @@ 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.roomlist.impl.filters.selection.DefaultFilterSelectionStrategy +import io.element.android.features.roomlist.impl.filters.selection.FilterSelectionState import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.roomlist.RoomListService @@ -37,13 +39,12 @@ class RoomListFiltersPresenterTests { presenter.present() }.test { awaitItem().let { state -> - assertThat(state.selectedFilters).isEmpty() assertThat(state.hasAnyFilterSelected).isFalse() - assertThat(state.unselectedFilters).containsExactly( - RoomListFilter.Rooms, - RoomListFilter.People, - RoomListFilter.Unread, - RoomListFilter.Favourites, + assertThat(state.filterSelectionStates).containsExactly( + filterSelectionState(RoomListFilter.Unread, false), + filterSelectionState(RoomListFilter.People, false), + filterSelectionState(RoomListFilter.Rooms, false), + filterSelectionState(RoomListFilter.Favourites, false), ) } cancelAndIgnoreRemainingEvents() @@ -58,32 +59,29 @@ class RoomListFiltersPresenterTests { presenter.present() }.test { awaitItem().eventSink.invoke(RoomListFiltersEvents.ToggleFilter(RoomListFilter.Rooms)) - awaitLastSequentialItem().let { state -> - assertThat(state.selectedFilters).containsExactly(RoomListFilter.Rooms) assertThat(state.hasAnyFilterSelected).isTrue() - assertThat(state.unselectedFilters).containsExactly( - RoomListFilter.Unread, - RoomListFilter.Favourites, - ) + assertThat(state.filterSelectionStates).containsExactly( + filterSelectionState(RoomListFilter.Rooms, true), + filterSelectionState(RoomListFilter.Unread, false), + filterSelectionState(RoomListFilter.Favourites, false), + ).inOrder() + val roomListCurrentFilter = roomListService.allRooms.currentFilter.value as MatrixRoomListFilter.All assertThat(roomListCurrentFilter.filters).containsExactly( MatrixRoomListFilter.Category.Group, ) - state.eventSink.invoke(RoomListFiltersEvents.ToggleFilter(RoomListFilter.Rooms)) } - awaitLastSequentialItem().let { state -> - assertThat(state.selectedFilters).isEmpty() assertThat(state.hasAnyFilterSelected).isFalse() - assertThat(state.unselectedFilters).containsExactly( - RoomListFilter.Rooms, - RoomListFilter.People, - RoomListFilter.Unread, - RoomListFilter.Favourites, - ) + assertThat(state.filterSelectionStates).containsExactly( + filterSelectionState(RoomListFilter.Unread, false), + filterSelectionState(RoomListFilter.People, false), + filterSelectionState(RoomListFilter.Rooms, false), + filterSelectionState(RoomListFilter.Favourites, false), + ).inOrder() val roomListCurrentFilter = roomListService.allRooms.currentFilter.value as MatrixRoomListFilter.All assertThat(roomListCurrentFilter.filters).isEmpty() } @@ -99,24 +97,28 @@ class RoomListFiltersPresenterTests { }.test { awaitItem().eventSink.invoke(RoomListFiltersEvents.ToggleFilter(RoomListFilter.Rooms)) awaitLastSequentialItem().let { state -> - assertThat(state.selectedFilters).isNotEmpty() assertThat(state.hasAnyFilterSelected).isTrue() state.eventSink.invoke(RoomListFiltersEvents.ClearSelectedFilters) } awaitLastSequentialItem().let { state -> - assertThat(state.selectedFilters).isEmpty() assertThat(state.hasAnyFilterSelected).isFalse() } } } } -fun createRoomListFiltersPresenter( +private fun filterSelectionState(filter: RoomListFilter, selected: Boolean) = FilterSelectionState( + filter = filter, + isSelected = selected, +) + +private fun createRoomListFiltersPresenter( roomListService: RoomListService = FakeRoomListService(), featureFlagService: FeatureFlagService = FakeFeatureFlagService(), ): RoomListFiltersPresenter { return RoomListFiltersPresenter( roomListService = roomListService, featureFlagService = featureFlagService, + filterSelectionStrategy = DefaultFilterSelectionStrategy(), ) } diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersViewTests.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersViewTests.kt index 6c9bd9e050..94897532e9 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersViewTests.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersViewTests.kt @@ -20,12 +20,11 @@ import androidx.activity.ComponentActivity import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.roomlist.impl.R +import io.element.android.features.roomlist.impl.filters.selection.FilterSelectionState import io.element.android.libraries.testtags.TestTags import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.pressTag -import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.toImmutableList import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -56,8 +55,7 @@ class RoomListFiltersViewTests { rule.setContent { RoomListFiltersView( state = aRoomListFiltersState( - unselectedFilters = persistentListOf(), - selectedFilters = RoomListFilter.entries.toImmutableList(), + filterSelectionStates = RoomListFilter.entries.map { FilterSelectionState(it, isSelected = true) }, eventSink = eventsRecorder ), ) From c06ded6bd061b747de7df1eca8e991b28ee9ff1f Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 7 Mar 2024 17:49:43 +0100 Subject: [PATCH 02/11] Update localazy --- features/messages/impl/src/main/res/values/localazy.xml | 7 +++++++ .../roomdetails/impl/src/main/res/values/localazy.xml | 3 +++ features/roomlist/impl/src/main/res/values/localazy.xml | 9 +++++++++ libraries/ui-strings/src/main/res/values/localazy.xml | 6 ++++++ 4 files changed, 25 insertions(+) diff --git a/features/messages/impl/src/main/res/values/localazy.xml b/features/messages/impl/src/main/res/values/localazy.xml index 02ada8105b..e3116edffc 100644 --- a/features/messages/impl/src/main/res/values/localazy.xml +++ b/features/messages/impl/src/main/res/values/localazy.xml @@ -41,11 +41,15 @@ "Change Room Name" "Change Room Topic" "Send messages" + "Edit Admins" "You will not be able to undo this action. You are promoting the user to have the same power level as you." "Add Admin?" "Demote" "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges." "Demote yourself?" + "Edit Moderators" + "You have unsaved changes." + "Save changes?" "Message history is currently unavailable." "Message history is unavailable in this room. Verify this device to see your message history." "Failed processing media to upload, please try again." @@ -75,6 +79,9 @@ "Send again" "Your message failed to send" "Admins" + "Change my role" + "Demote to member" + "Demote to moderator" "Member moderation" "Messages and content" "Moderators" diff --git a/features/roomdetails/impl/src/main/res/values/localazy.xml b/features/roomdetails/impl/src/main/res/values/localazy.xml index 0990f11418..d606b5bc70 100644 --- a/features/roomdetails/impl/src/main/res/values/localazy.xml +++ b/features/roomdetails/impl/src/main/res/values/localazy.xml @@ -32,6 +32,9 @@ "Share room" "Topic" "Updating room…" + "Ban" + "They won’t be able to join this room again if invited." + "Are you sure you want to ban this member?" "Banning %1$s" "%1$d person" diff --git a/features/roomlist/impl/src/main/res/values/localazy.xml b/features/roomlist/impl/src/main/res/values/localazy.xml index 08efd3a79f..5044fd61a5 100644 --- a/features/roomlist/impl/src/main/res/values/localazy.xml +++ b/features/roomlist/impl/src/main/res/values/localazy.xml @@ -8,10 +8,19 @@ "Get started by messaging someone." "No chats yet." "Favourites" + "You can add a chat to your favourites in the chat settings. +For now, you can deselect filters in order to see your other chats" + "You don’t have favourite chats yet" "Low Priority" + "You can deselect filters in order to see your other chats" + "You don’t have chats for this selection" "People" + "You don’t have any DMs yet" "Rooms" + "You’re not in any room yet" "Unreads" + "Congrats! +You don’t have any unread messages!" "Chats" "Mark as read" "Mark as unread" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index ebbcfcc8d5..ad1b804a80 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -57,6 +57,7 @@ "Enter PIN" "Forgot password?" "Forward" + "Go back" "Invite" "Invite people" "Invite people to %1$s" @@ -113,6 +114,7 @@ "Audio" "Blocked users" "Bubbles" + "Call in progress (unsupported)" "Chat backup" "Copyright" "Creating room…" @@ -181,6 +183,8 @@ "Room" "Room name" "e.g. your project name" + "Saved changes" + "Saving" "Screen lock" "Search for someone" "Search results" @@ -223,6 +227,8 @@ "Error" "Success" "Warning" + "Your changes have not been saved. Are you sure you want to go back?" + "Save changes?" "Failed creating the permalink" "%1$s could not load the map. Please try again later." "Failed loading messages" From de91b97949249d3b83e249633b266f7de283b8c2 Mon Sep 17 00:00:00 2001 From: ganfra Date: Sat, 9 Mar 2024 16:53:48 +0100 Subject: [PATCH 03/11] RoomList : refactor how we manage state so it's easier to reason about. --- .../roomlist/impl/RoomListPresenter.kt | 100 +++++-- .../features/roomlist/impl/RoomListState.kt | 21 +- .../roomlist/impl/RoomListStateProvider.kt | 15 +- .../features/roomlist/impl/RoomListView.kt | 129 ++------- .../impl/components/RoomListContentView.kt | 255 ++++++++++++++++++ .../impl/datasource/RoomListDataSource.kt | 12 +- .../datasource/RoomListRoomSummaryFactory.kt | 5 - 7 files changed, 368 insertions(+), 169 deletions(-) create mode 100644 features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt 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 245065a52f..4bd26a62cf 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 @@ -19,6 +19,7 @@ package io.element.android.features.roomlist.impl import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState +import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue @@ -26,6 +27,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow @@ -52,6 +54,7 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.RecoveryState +import io.element.android.libraries.matrix.api.roomlist.RoomList import io.element.android.libraries.matrix.api.sync.SyncService import io.element.android.libraries.matrix.api.sync.SyncState import io.element.android.libraries.matrix.api.timeline.ReceiptType @@ -60,6 +63,7 @@ import io.element.android.libraries.matrix.api.user.getCurrentUser import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analyticsproviders.api.trackers.captureInteraction +import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.collect @@ -100,11 +104,7 @@ class RoomListPresenter @Inject constructor( val matrixUser: MutableState = rememberSaveable { mutableStateOf(null) } - val roomList by produceState(initialValue = AsyncData.Loading()) { - roomListDataSource.allRooms.collect { value = AsyncData.Success(it) } - } val networkConnectionStatus by networkMonitor.connectivity.collectAsState() - val filtersState = filtersPresenter.present() val searchState = searchPresenter.present() @@ -113,28 +113,7 @@ class RoomListPresenter @Inject constructor( initialLoad(matrixUser) } - val isMigrating = migrationScreenPresenter.present().isMigrating - var securityBannerDismissed by rememberSaveable { mutableStateOf(false) } - val canVerifySession by sessionVerificationService.canVerifySessionFlow.collectAsState(initial = false) - val isLastDevice by encryptionService.isLastDevice.collectAsState() - val recoveryState by encryptionService.recoveryStateStateFlow.collectAsState() - val syncState by syncService.syncState.collectAsState() - val securityBannerState by remember { - derivedStateOf { - when { - securityBannerDismissed -> SecurityBannerState.None - canVerifySession -> if (isLastDevice) { - SecurityBannerState.RecoveryKeyConfirmation - } else { - SecurityBannerState.SessionVerification - } - recoveryState == RecoveryState.INCOMPLETE && - syncState == SyncState.Running -> SecurityBannerState.RecoveryKeyConfirmation - else -> SecurityBannerState.None - } - } - } // Avatar indicator val showAvatarIndicator by indicatorService.showRoomListTopBarIndicator() @@ -162,19 +141,18 @@ class RoomListPresenter @Inject constructor( val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState() + val contentState = roomListContentState(securityBannerDismissed) + return RoomListState( matrixUser = matrixUser.value, showAvatarIndicator = showAvatarIndicator, - roomList = roomList, - securityBannerState = securityBannerState, snackbarMessage = snackbarMessage, hasNetworkConnection = networkConnectionStatus == NetworkStatus.Online, - invitesState = inviteStateDataSource.inviteState(), contextMenu = contextMenu.value, leaveRoomState = leaveRoomState, filtersState = filtersState, searchState = searchState, - displayMigrationStatus = isMigrating, + contentState = contentState, eventSink = ::handleEvents, ) } @@ -183,6 +161,70 @@ class RoomListPresenter @Inject constructor( matrixUser.value = client.getCurrentUser() } + @Composable + private fun securityBannerState( + securityBannerDismissed: Boolean, + ): State { + val currentSecurityBannerDismissed by rememberUpdatedState(securityBannerDismissed) + val canVerifySession by sessionVerificationService.canVerifySessionFlow.collectAsState(initial = false) + val isLastDevice by encryptionService.isLastDevice.collectAsState() + val recoveryState by encryptionService.recoveryStateStateFlow.collectAsState() + val syncState by syncService.syncState.collectAsState() + return remember { + derivedStateOf { + when { + currentSecurityBannerDismissed -> SecurityBannerState.None + canVerifySession -> if (isLastDevice) { + SecurityBannerState.RecoveryKeyConfirmation + } else { + SecurityBannerState.SessionVerification + } + recoveryState == RecoveryState.INCOMPLETE && + syncState == SyncState.Running -> SecurityBannerState.RecoveryKeyConfirmation + else -> SecurityBannerState.None + } + } + } + } + + @Composable + private fun roomListContentState( + securityBannerDismissed: Boolean, + ): RoomListContentState { + val roomSummaries by produceState(initialValue = AsyncData.Loading()) { + roomListDataSource.allRooms.collect { value = AsyncData.Success(it) } + } + val loadingState by roomListDataSource.loadingState.collectAsState() + val showMigration = migrationScreenPresenter.present().isMigrating + val showSkeleton by remember { + derivedStateOf { + loadingState == RoomList.LoadingState.NotLoaded || roomSummaries is AsyncData.Loading + } + } + val showEmpty by remember { + derivedStateOf { + (loadingState as? RoomList.LoadingState.Loaded)?.numberOfRooms == 0 + } + } + return when { + showMigration -> RoomListContentState.Migration + showSkeleton -> RoomListContentState.Skeleton(count = 16) + showEmpty -> { + val invitesState = inviteStateDataSource.inviteState() + RoomListContentState.Empty(invitesState) + } + else -> { + val invitesState = inviteStateDataSource.inviteState() + val securityBannerState by securityBannerState(securityBannerDismissed) + RoomListContentState.Rooms( + invitesState = invitesState, + securityBannerState = securityBannerState, + summaries = roomSummaries.dataOrNull().orEmpty().toPersistentList() + ) + } + } + } + @OptIn(ExperimentalCoroutinesApi::class) private fun CoroutineScope.showContextMenu(event: RoomListEvents.ShowContextMenu, contextMenuState: MutableState) = launch { val initialState = RoomListState.ContextMenu.Shown( diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt index c4581732eb..58b36636c8 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt @@ -21,7 +21,6 @@ import io.element.android.features.leaveroom.api.LeaveRoomState import io.element.android.features.roomlist.impl.filters.RoomListFiltersState import io.element.android.features.roomlist.impl.model.RoomListRoomSummary import io.element.android.features.roomlist.impl.search.RoomListSearchState -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.user.MatrixUser @@ -31,20 +30,17 @@ import kotlinx.collections.immutable.ImmutableList data class RoomListState( val matrixUser: MatrixUser?, val showAvatarIndicator: Boolean, - val roomList: AsyncData>, - val securityBannerState: SecurityBannerState, val hasNetworkConnection: Boolean, val snackbarMessage: SnackbarMessage?, - val invitesState: InvitesState, val contextMenu: ContextMenu, val leaveRoomState: LeaveRoomState, val filtersState: RoomListFiltersState, val searchState: RoomListSearchState, - val displayMigrationStatus: Boolean, + val contentState: RoomListContentState, val eventSink: (RoomListEvents) -> Unit, ) { - val displayFilters = filtersState.isFeatureEnabled && !displayMigrationStatus - val displayEmptyState = roomList is AsyncData.Success && roomList.data.isEmpty() + val displayFilters = filtersState.isFeatureEnabled && contentState is RoomListContentState.Rooms + val displayActions = contentState !is RoomListContentState.Migration sealed interface ContextMenu { data object Hidden : ContextMenu @@ -70,3 +66,14 @@ enum class SecurityBannerState { SessionVerification, RecoveryKeyConfirmation, } + +sealed interface RoomListContentState { + data object Migration : RoomListContentState + data class Skeleton(val count: Int) : RoomListContentState + data class Empty(val invitesState: InvitesState) : RoomListContentState + data class Rooms( + val invitesState: InvitesState, + val securityBannerState: SecurityBannerState, + val summaries: ImmutableList, + ) : RoomListContentState +} diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt index bfc155f2d2..a47baf4bbc 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt @@ -19,7 +19,6 @@ package io.element.android.features.roomlist.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.leaveroom.api.LeaveRoomState import io.element.android.features.leaveroom.api.aLeaveRoomState -import io.element.android.features.roomlist.impl.datasource.RoomListRoomSummaryFactory import io.element.android.features.roomlist.impl.filters.RoomListFiltersState import io.element.android.features.roomlist.impl.filters.aRoomListFiltersState import io.element.android.features.roomlist.impl.model.RoomListRoomSummary @@ -36,6 +35,7 @@ import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toPersistentList open class RoomListStateProvider : PreviewParameterProvider { override val values: Sequence @@ -50,7 +50,7 @@ open class RoomListStateProvider : PreviewParameterProvider { aRoomListState(securityBannerState = SecurityBannerState.SessionVerification), aRoomListState(securityBannerState = SecurityBannerState.RecoveryKeyConfirmation), aRoomListState(roomList = AsyncData.Success(persistentListOf())), - aRoomListState(roomList = AsyncData.Loading(prevData = RoomListRoomSummaryFactory.createFakeList())), + //aRoomListState(roomList = AsyncData.Loading(prevData = RoomListRoomSummaryFactory.createFakeList())), aRoomListState(matrixUser = null, displayMigrationStatus = true), aRoomListState(searchState = aRoomListSearchState(isSearchActive = true, query = "Test")), aRoomListState(filtersState = aRoomListFiltersState(isFeatureEnabled = true)), @@ -74,16 +74,17 @@ internal fun aRoomListState( ) = RoomListState( matrixUser = matrixUser, showAvatarIndicator = showAvatarIndicator, - roomList = roomList, hasNetworkConnection = hasNetworkConnection, snackbarMessage = snackbarMessage, - securityBannerState = securityBannerState, - invitesState = invitesState, contextMenu = contextMenu, leaveRoomState = leaveRoomState, - searchState = searchState, filtersState = filtersState, - displayMigrationStatus = displayMigrationStatus, + searchState = searchState, + contentState = RoomListContentState.Rooms( + invitesState = invitesState, + securityBannerState = securityBannerState, + summaries = roomList.dataOrNull().orEmpty().toPersistentList(), + ), eventSink = eventSink, ) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt index ab261c0cd5..08accccc67 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt @@ -53,6 +53,7 @@ import io.element.android.features.leaveroom.api.LeaveRoomView import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorContainer import io.element.android.features.roomlist.impl.components.ConfirmRecoveryKeyBanner import io.element.android.features.roomlist.impl.components.RequestVerificationHeader +import io.element.android.features.roomlist.impl.components.RoomListContentView import io.element.android.features.roomlist.impl.components.RoomListMenuAction import io.element.android.features.roomlist.impl.components.RoomListTopBar import io.element.android.features.roomlist.impl.components.RoomSummaryRow @@ -108,7 +109,7 @@ fun RoomListView( LeaveRoomView(state = state.leaveRoomState) - RoomListContent( + RoomListScaffold( modifier = Modifier.padding(top = topPadding), state = state, onVerifyClicked = onVerifyClicked, @@ -135,43 +136,9 @@ fun RoomListView( } } -@Composable -private fun EmptyRoomListView( - onCreateRoomClicked: () -> Unit, - modifier: Modifier = Modifier -) { - Column( - modifier = modifier - .fillMaxSize() - .padding(horizontal = 16.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Text( - text = stringResource(R.string.screen_roomlist_empty_title), - style = ElementTheme.typography.fontBodyLgRegular, - color = ElementTheme.colors.textSecondary, - textAlign = TextAlign.Center, - ) - Spacer(modifier = Modifier.height(4.dp)) - Text( - text = stringResource(R.string.screen_roomlist_empty_message), - style = ElementTheme.typography.fontBodyLgRegular, - color = ElementTheme.colors.textSecondary, - textAlign = TextAlign.Center, - ) - Spacer(modifier = Modifier.height(16.dp)) - Button( - text = stringResource(CommonStrings.action_start_chat), - leadingIcon = IconSource.Vector(CompoundIcons.Compose()), - onClick = onCreateRoomClicked, - ) - } -} - @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun RoomListContent( +private fun RoomListScaffold( state: RoomListState, onVerifyClicked: () -> Unit, onConfirmRecoveryKeyClicked: () -> Unit, @@ -188,26 +155,7 @@ private fun RoomListContent( } val appBarState = rememberTopAppBarState() - val lazyListState = rememberLazyListState() - - val visibleRange by remember { - derivedStateOf { - val layoutInfo = lazyListState.layoutInfo - val firstItemIndex = layoutInfo.visibleItemsInfo.firstOrNull()?.index ?: 0 - val size = layoutInfo.visibleItemsInfo.size - firstItemIndex until firstItemIndex + size - } - } val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(appBarState) - val nestedScrollConnection = remember { - object : NestedScrollConnection { - override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity { - state.eventSink(RoomListEvents.UpdateVisibleRange(visibleRange)) - return super.onPostFling(consumed, available) - } - } - } - val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage) Scaffold( @@ -222,7 +170,7 @@ private fun RoomListContent( onMenuActionClicked = onMenuActionClicked, onOpenSettings = onOpenSettings, scrollBehavior = scrollBehavior, - displayMenuItems = !state.displayMigrationStatus, + displayMenuItems = !state.displayActions, ) if (state.displayFilters) { RoomListFiltersView(state = state.filtersState) @@ -230,69 +178,22 @@ private fun RoomListContent( } }, content = { padding -> - LazyColumn( + RoomListContentView( + contentState = state.contentState, + eventSink = state.eventSink, + onVerifyClicked = onVerifyClicked, + onConfirmRecoveryKeyClicked = onConfirmRecoveryKeyClicked, + onRoomClicked = ::onRoomClicked, + onRoomLongClicked = onRoomLongClicked, + onCreateRoomClicked = onCreateRoomClicked, + onInvitesClicked = onInvitesClicked, modifier = Modifier .padding(padding) .consumeWindowInsets(padding) - .nestedScroll(nestedScrollConnection), - state = lazyListState, - // FAB height is 56dp, bottom padding is 16dp, we add 8dp as extra margin -> 56+16+8 = 80 - contentPadding = PaddingValues(bottom = 80.dp) - ) { - when { - state.displayEmptyState -> Unit - state.securityBannerState == SecurityBannerState.SessionVerification -> { - item { - RequestVerificationHeader( - onVerifyClicked = onVerifyClicked, - onDismissClicked = { state.eventSink(RoomListEvents.DismissRequestVerificationPrompt) } - ) - } - } - state.securityBannerState == SecurityBannerState.RecoveryKeyConfirmation -> { - item { - ConfirmRecoveryKeyBanner( - onContinueClicked = onConfirmRecoveryKeyClicked, - onDismissClicked = { state.eventSink(RoomListEvents.DismissRecoveryKeyPrompt) } - ) - } - } - } - - if (state.invitesState != InvitesState.NoInvites) { - item { - InvitesEntryPointView(onInvitesClicked, state.invitesState) - } - } - - val roomList = state.roomList.dataOrNull().orEmpty() - // Note: do not use a key for the LazyColumn, or the scroll will not behave as expected if a room - // is moved to the top of the list. - itemsIndexed( - items = roomList, - contentType = { _, room -> room.contentType() }, - ) { index, room -> - RoomSummaryRow( - room = room, - onClick = ::onRoomClicked, - onLongClick = onRoomLongClicked, - ) - if (index != roomList.lastIndex) { - HorizontalDivider() - } - } - } - if (state.displayEmptyState) { - if (state.filtersState.hasAnyFilterSelected) { - // TODO add empty state for filtered rooms - } else { - EmptyRoomListView(onCreateRoomClicked) - } - } - MigrationScreenView(isMigrating = state.displayMigrationStatus) + ) }, floatingActionButton = { - if (!state.displayMigrationStatus) { + if (state.displayActions) { FloatingActionButton( // FIXME align on Design system theme containerColor = MaterialTheme.colorScheme.primary, diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt new file mode 100644 index 0000000000..b58b8ebeb1 --- /dev/null +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomlist.impl.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.NestedScrollConnection +import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.Velocity +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.roomlist.impl.InvitesEntryPointView +import io.element.android.features.roomlist.impl.InvitesState +import io.element.android.features.roomlist.impl.R +import io.element.android.features.roomlist.impl.RoomListContentState +import io.element.android.features.roomlist.impl.RoomListEvents +import io.element.android.features.roomlist.impl.SecurityBannerState +import io.element.android.features.roomlist.impl.contentType +import io.element.android.features.roomlist.impl.migration.MigrationScreenView +import io.element.android.features.roomlist.impl.model.RoomListRoomSummary +import io.element.android.libraries.designsystem.theme.components.Button +import io.element.android.libraries.designsystem.theme.components.HorizontalDivider +import io.element.android.libraries.designsystem.theme.components.IconSource +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun RoomListContentView( + contentState: RoomListContentState, + eventSink: (RoomListEvents) -> Unit, + onVerifyClicked: () -> Unit, + onConfirmRecoveryKeyClicked: () -> Unit, + onRoomClicked: (RoomListRoomSummary) -> Unit, + onRoomLongClicked: (RoomListRoomSummary) -> Unit, + onCreateRoomClicked: () -> Unit, + onInvitesClicked: () -> Unit, + modifier: Modifier = Modifier, +) { + Box(modifier = modifier) { + when (contentState) { + is RoomListContentState.Migration -> { + MigrationScreenView(isMigrating = true) + } + is RoomListContentState.Skeleton -> { + SkeletonView( + count = contentState.count, + ) + } + is RoomListContentState.Empty -> { + EmptyView( + state = contentState, + onInvitesClicked = onInvitesClicked, + onCreateRoomClicked = onCreateRoomClicked, + ) + } + is RoomListContentState.Rooms -> { + RoomsView( + state = contentState, + eventSink = eventSink, + onVerifyClicked = onVerifyClicked, + onConfirmRecoveryKeyClicked = onConfirmRecoveryKeyClicked, + onRoomClicked = onRoomClicked, + onRoomLongClicked = onRoomLongClicked, + onInvitesClicked = onInvitesClicked, + ) + } + } + } +} + +@Composable +private fun SkeletonView(count: Int, modifier: Modifier = Modifier) { + LazyColumn(modifier = modifier) { + repeat(count) { index -> + item { + RoomSummaryPlaceholderRow() + if (index != count - 1) { + HorizontalDivider() + } + } + } + } +} + +@Composable +private fun EmptyView( + state: RoomListContentState.Empty, + onCreateRoomClicked: () -> Unit, + onInvitesClicked: () -> Unit, + modifier: Modifier = Modifier +) { + Box( + modifier = modifier.fillMaxSize(), + ) { + if (state.invitesState != InvitesState.NoInvites) { + InvitesEntryPointView(onInvitesClicked, state.invitesState) + } + EmptyScaffold( + title = { + Text( + text = stringResource(R.string.screen_roomlist_empty_title), + style = ElementTheme.typography.fontBodyLgRegular, + color = ElementTheme.colors.textSecondary, + textAlign = TextAlign.Center, + ) + }, + subtitle = { + Text( + text = stringResource(R.string.screen_roomlist_empty_message), + style = ElementTheme.typography.fontBodyLgRegular, + color = ElementTheme.colors.textSecondary, + textAlign = TextAlign.Center, + ) + }, + action = { + Button( + text = stringResource(CommonStrings.action_start_chat), + leadingIcon = IconSource.Vector(CompoundIcons.Compose()), + onClick = onCreateRoomClicked, + ) + }, + modifier = Modifier, + ) + } +} + +@Composable +private fun RoomsView( + state: RoomListContentState.Rooms, + eventSink: (RoomListEvents) -> Unit, + onVerifyClicked: () -> Unit, + onConfirmRecoveryKeyClicked: () -> Unit, + onRoomClicked: (RoomListRoomSummary) -> Unit, + onRoomLongClicked: (RoomListRoomSummary) -> Unit, + onInvitesClicked: () -> Unit, + modifier: Modifier = Modifier, +) { + val lazyListState = rememberLazyListState() + val visibleRange by remember { + derivedStateOf { + val layoutInfo = lazyListState.layoutInfo + val firstItemIndex = layoutInfo.visibleItemsInfo.firstOrNull()?.index ?: 0 + val size = layoutInfo.visibleItemsInfo.size + firstItemIndex until firstItemIndex + size + } + } + val nestedScrollConnection = remember { + object : NestedScrollConnection { + override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity { + eventSink(RoomListEvents.UpdateVisibleRange(visibleRange)) + return super.onPostFling(consumed, available) + } + } + } + LazyColumn( + state = lazyListState, + modifier = modifier.nestedScroll(nestedScrollConnection), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + when (state.securityBannerState) { + SecurityBannerState.SessionVerification -> { + item { + RequestVerificationHeader( + onVerifyClicked = onVerifyClicked, + onDismissClicked = { eventSink(RoomListEvents.DismissRequestVerificationPrompt) } + ) + } + } + SecurityBannerState.RecoveryKeyConfirmation -> { + item { + ConfirmRecoveryKeyBanner( + onContinueClicked = onConfirmRecoveryKeyClicked, + onDismissClicked = { eventSink(RoomListEvents.DismissRecoveryKeyPrompt) } + ) + } + } + else -> Unit + } + + if (state.invitesState != InvitesState.NoInvites) { + item { + InvitesEntryPointView(onInvitesClicked, state.invitesState) + } + } + // Note: do not use a key for the LazyColumn, or the scroll will not behave as expected if a room + // is moved to the top of the list. + itemsIndexed( + items = state.summaries, + contentType = { _, room -> room.contentType() }, + ) { index, room -> + RoomSummaryRow( + room = room, + onClick = onRoomClicked, + onLongClick = onRoomLongClicked, + ) + if (index != state.summaries.lastIndex) { + HorizontalDivider() + } + } + } +} + +@Composable +private fun EmptyScaffold( + title: @Composable () -> Unit, + modifier: Modifier = Modifier, + subtitle: @Composable (() -> Unit)? = null, + action: @Composable (() -> Unit)? = null, +) { + Column( + modifier = modifier + .fillMaxSize() + .padding(horizontal = 60.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + title() + Spacer(modifier = Modifier.height(4.dp)) + subtitle?.invoke() + Spacer(modifier = Modifier.height(16.dp)) + action?.invoke() + } +} + diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt index cb61701342..5d92a55ba7 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt @@ -27,8 +27,10 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -62,19 +64,15 @@ class RoomListDataSource @Inject constructor( roomListService .allRooms .summaries - .onStart { - // If we have no cached results, display a placeholder loading state - if (diffCache.isEmpty()) { - _allRooms.emit(RoomListRoomSummaryFactory.createFakeList()) - } - } .onEach { roomSummaries -> replaceWith(roomSummaries) } .launchIn(coroutineScope) } - val allRooms: SharedFlow> = _allRooms + val allRooms: Flow> = _allRooms + + val loadingState = roomListService.allRooms.loadingState @OptIn(FlowPreview::class) private fun observeNotificationSettings() { diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListRoomSummaryFactory.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListRoomSummaryFactory.kt index 02f87de745..aea57d32ab 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListRoomSummaryFactory.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListRoomSummaryFactory.kt @@ -53,11 +53,6 @@ class RoomListRoomSummaryFactory @Inject constructor( ) } - fun createFakeList(): ImmutableList { - return List(16) { - createPlaceholder("!fakeRoom$it:domain") - }.toImmutableList() - } } fun create(roomSummary: RoomSummary.Filled): RoomListRoomSummary { From 4adbf5e2974e593ebb403220f83fed53d8d79cea Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 11 Mar 2024 18:59:59 +0100 Subject: [PATCH 04/11] RoomList : add empty state when filtering --- .../features/roomlist/impl/RoomListView.kt | 1 + .../impl/components/RoomListContentView.kt | 108 +++++++++++++----- .../RoomListFiltersEmptyStateResources.kt | 66 +++++++++++ .../impl/filters/RoomListFiltersState.kt | 4 + 4 files changed, 149 insertions(+), 30 deletions(-) create mode 100644 features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEmptyStateResources.kt diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt index 08accccc67..f8cb6f137b 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt @@ -180,6 +180,7 @@ private fun RoomListScaffold( content = { padding -> RoomListContentView( contentState = state.contentState, + filtersState = state.filtersState, eventSink = state.eventSink, onVerifyClicked = onVerifyClicked, onConfirmRecoveryKeyClicked = onConfirmRecoveryKeyClicked, diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt index b58b8ebeb1..612264bb0c 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt @@ -16,9 +16,13 @@ package io.element.android.features.roomlist.impl.components +import androidx.annotation.StringRes +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height @@ -47,6 +51,9 @@ import io.element.android.features.roomlist.impl.RoomListContentState import io.element.android.features.roomlist.impl.RoomListEvents import io.element.android.features.roomlist.impl.SecurityBannerState import io.element.android.features.roomlist.impl.contentType +import io.element.android.features.roomlist.impl.filters.RoomListFilter +import io.element.android.features.roomlist.impl.filters.RoomListFiltersEmptyStateResources +import io.element.android.features.roomlist.impl.filters.RoomListFiltersState import io.element.android.features.roomlist.impl.migration.MigrationScreenView import io.element.android.features.roomlist.impl.model.RoomListRoomSummary import io.element.android.libraries.designsystem.theme.components.Button @@ -58,6 +65,7 @@ import io.element.android.libraries.ui.strings.CommonStrings @Composable fun RoomListContentView( contentState: RoomListContentState, + filtersState: RoomListFiltersState, eventSink: (RoomListEvents) -> Unit, onVerifyClicked: () -> Unit, onConfirmRecoveryKeyClicked: () -> Unit, @@ -87,6 +95,7 @@ fun RoomListContentView( is RoomListContentState.Rooms -> { RoomsView( state = contentState, + filtersState = filtersState, eventSink = eventSink, onVerifyClicked = onVerifyClicked, onConfirmRecoveryKeyClicked = onConfirmRecoveryKeyClicked, @@ -127,22 +136,8 @@ private fun EmptyView( InvitesEntryPointView(onInvitesClicked, state.invitesState) } EmptyScaffold( - title = { - Text( - text = stringResource(R.string.screen_roomlist_empty_title), - style = ElementTheme.typography.fontBodyLgRegular, - color = ElementTheme.colors.textSecondary, - textAlign = TextAlign.Center, - ) - }, - subtitle = { - Text( - text = stringResource(R.string.screen_roomlist_empty_message), - style = ElementTheme.typography.fontBodyLgRegular, - color = ElementTheme.colors.textSecondary, - textAlign = TextAlign.Center, - ) - }, + title = R.string.screen_roomlist_empty_title, + subtitle = R.string.screen_roomlist_empty_message, action = { Button( text = stringResource(CommonStrings.action_start_chat), @@ -150,13 +145,44 @@ private fun EmptyView( onClick = onCreateRoomClicked, ) }, - modifier = Modifier, + modifier = Modifier.fillMaxSize(), ) } } @Composable private fun RoomsView( + state: RoomListContentState.Rooms, + filtersState: RoomListFiltersState, + eventSink: (RoomListEvents) -> Unit, + onVerifyClicked: () -> Unit, + onConfirmRecoveryKeyClicked: () -> Unit, + onRoomClicked: (RoomListRoomSummary) -> Unit, + onRoomLongClicked: (RoomListRoomSummary) -> Unit, + onInvitesClicked: () -> Unit, + modifier: Modifier = Modifier, +) { + if (state.summaries.isEmpty() && filtersState.hasAnyFilterSelected) { + EmptyViewForFilterStates( + selectedFilters = filtersState.selectedFilters(), + modifier = modifier.fillMaxSize() + ) + } else { + RoomsViewList( + state = state, + eventSink = eventSink, + onVerifyClicked = onVerifyClicked, + onConfirmRecoveryKeyClicked = onConfirmRecoveryKeyClicked, + onRoomClicked = onRoomClicked, + onRoomLongClicked = onRoomLongClicked, + onInvitesClicked = onInvitesClicked, + modifier = modifier.fillMaxSize(), + ) + } +} + +@Composable +private fun RoomsViewList( state: RoomListContentState.Rooms, eventSink: (RoomListEvents) -> Unit, onVerifyClicked: () -> Unit, @@ -186,7 +212,9 @@ private fun RoomsView( LazyColumn( state = lazyListState, modifier = modifier.nestedScroll(nestedScrollConnection), - verticalArrangement = Arrangement.spacedBy(8.dp) + // FAB height is 56dp, bottom padding is 16dp, we add 8dp as extra margin -> 56+16+8 = 80 + contentPadding = PaddingValues(bottom = 80.dp) + ) { when (state.securityBannerState) { SecurityBannerState.SessionVerification -> { @@ -232,24 +260,44 @@ private fun RoomsView( } @Composable -private fun EmptyScaffold( - title: @Composable () -> Unit, +private fun EmptyViewForFilterStates( + selectedFilters: List, modifier: Modifier = Modifier, - subtitle: @Composable (() -> Unit)? = null, - action: @Composable (() -> Unit)? = null, +) { + val emptyStateResources = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters) ?: return + EmptyScaffold( + title = emptyStateResources.title, + subtitle = emptyStateResources.subtitle, + modifier = modifier, + ) +} + +@Composable +private fun EmptyScaffold( + @StringRes title: Int, + @StringRes subtitle: Int, + modifier: Modifier = Modifier, + action: @Composable (ColumnScope.() -> Unit)? = null, ) { Column( - modifier = modifier - .fillMaxSize() - .padding(horizontal = 60.dp), + modifier = modifier.padding(horizontal = 60.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { - title() - Spacer(modifier = Modifier.height(4.dp)) - subtitle?.invoke() + Text( + text = stringResource(title), + style = ElementTheme.typography.fontHeadingMdBold, + color = ElementTheme.colors.textPrimary, + textAlign = TextAlign.Center, + ) Spacer(modifier = Modifier.height(16.dp)) - action?.invoke() + Text( + text = stringResource(subtitle), + style = ElementTheme.typography.fontBodyLgRegular, + color = ElementTheme.colors.textSecondary, + textAlign = TextAlign.Center, + ) + Spacer(modifier = Modifier.height(32.dp)) + action?.invoke(this) } } - diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEmptyStateResources.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEmptyStateResources.kt new file mode 100644 index 0000000000..f0f29b0db6 --- /dev/null +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEmptyStateResources.kt @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomlist.impl.filters + +import androidx.annotation.StringRes +import io.element.android.features.roomlist.impl.R + +/** + * Holds the resources for the empty state when filters are applied to the room list. + * @param title the title of the empty state + * @param subtitle the subtitle of the empty state + */ +data class RoomListFiltersEmptyStateResources( + @StringRes val title: Int, + @StringRes val subtitle: Int, +) { + + companion object { + /** + * Create a [RoomListFiltersEmptyStateResources] from a list of selected filters. + */ + fun fromSelectedFilters(selectedFilters: List): RoomListFiltersEmptyStateResources? { + return when { + selectedFilters.isEmpty() -> null + selectedFilters.size == 1 -> { + when (selectedFilters.first()) { + RoomListFilter.Unread -> RoomListFiltersEmptyStateResources( + title = R.string.screen_roomlist_filter_unreads_empty_state_title, + subtitle = R.string.screen_roomlist_filter_mixed_empty_state_subtitle + ) + RoomListFilter.People -> RoomListFiltersEmptyStateResources( + title = R.string.screen_roomlist_filter_people_empty_state_title, + subtitle = R.string.screen_roomlist_filter_mixed_empty_state_subtitle + ) + RoomListFilter.Rooms -> RoomListFiltersEmptyStateResources( + title = R.string.screen_roomlist_filter_rooms_empty_state_title, + subtitle = R.string.screen_roomlist_filter_mixed_empty_state_subtitle + ) + RoomListFilter.Favourites -> RoomListFiltersEmptyStateResources( + title = R.string.screen_roomlist_filter_favourites_empty_state_title, + subtitle = R.string.screen_roomlist_filter_favourites_empty_state_subtitle + ) + } + } + else -> RoomListFiltersEmptyStateResources( + title = R.string.screen_roomlist_filter_mixed_empty_state_title, + subtitle = R.string.screen_roomlist_filter_mixed_empty_state_subtitle + ) + } + } + } +} diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersState.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersState.kt index f75fbf059f..7fce841aaf 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersState.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersState.kt @@ -25,4 +25,8 @@ data class RoomListFiltersState( val eventSink: (RoomListFiltersEvents) -> Unit, ) { val hasAnyFilterSelected = filterSelectionStates.any { it.isSelected } + + fun selectedFilters(): List { + return filterSelectionStates.filter { it.isSelected }.map { it.filter } + } } From 0db6ff4263cf8c72ab95c3071c4e7b768a63d459 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 11 Mar 2024 20:25:01 +0100 Subject: [PATCH 05/11] RoomListFilters : improve look and feel --- .../impl/filters/RoomListFiltersView.kt | 97 ++++++++----------- 1 file changed, 38 insertions(+), 59 deletions(-) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt index 2c9a451665..57f4fa0a9c 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt @@ -16,23 +16,20 @@ package io.element.android.features.roomlist.impl.filters -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.core.tween import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.FilterChip import androidx.compose.material3.FilterChipDefaults -import androidx.compose.material3.minimumInteractiveComponentSize import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment @@ -43,12 +40,9 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons -import io.element.android.libraries.designsystem.modifiers.fadingEdge -import io.element.android.libraries.designsystem.modifiers.horizontalFadingEdgesBrush import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Icon -import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.testtags.TestTags import io.element.android.libraries.testtags.testTag @@ -68,49 +62,40 @@ fun RoomListFiltersView( state.eventSink(RoomListFiltersEvents.ToggleFilter(filter)) } - val startPadding = if (state.hasAnyFilterSelected) 4.dp else 16.dp - Row( - modifier = modifier.padding(start = startPadding, end = 16.dp), + val lazyListState = rememberLazyListState() + LazyRow( + contentPadding = PaddingValues(start = 8.dp, end = 16.dp), + modifier = modifier.fillMaxWidth(), + state = lazyListState, + horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically, ) { - - AnimatedVisibility(visible = state.hasAnyFilterSelected) { - RoomListClearFiltersButton( - modifier = Modifier.testTag(TestTags.homeScreenClearFilters), - onClick = ::onClearFiltersClicked - ) + item("clear_filters") { + if (state.hasAnyFilterSelected) { + RoomListClearFiltersButton( + modifier = Modifier + .padding(start = 8.dp) + .testTag(TestTags.homeScreenClearFilters), + onClick = ::onClearFiltersClicked + ) + } } - - val lazyListState = rememberLazyListState() - val fadingEdgesBrush = horizontalFadingEdgesBrush( - showLeft = lazyListState.canScrollBackward, - showRight = lazyListState.canScrollForward - ) - LazyRow( - modifier = Modifier - .fillMaxWidth() - .fadingEdge(fadingEdgesBrush), - state = lazyListState, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - items( - items = state.filterSelectionStates, - key = { it.filter.ordinal } - ) { filterWithSelection -> + for (filterWithSelection in state.filterSelectionStates) { + item(filterWithSelection.filter) { RoomListFilterView( - modifier = Modifier.animateItemPlacement( - animationSpec = tween(200), - ), + modifier = Modifier.animateItemPlacement(), roomListFilter = filterWithSelection.filter, selected = filterWithSelection.isSelected, onClick = ::onToggleFilter, ) } } - LaunchedEffect(state.filterSelectionStates) { - if (lazyListState.canScrollBackward) { - lazyListState.animateScrollToItem(0) - } + } + LaunchedEffect(state.filterSelectionStates) { + // Checking for canScrollBackward is necessary for the itemPlacementAnimation to work correctly. + // We don't want the itemPlacementAnimation to be triggered when clearing the filters. + if (!state.hasAnyFilterSelected || lazyListState.canScrollBackward) { + lazyListState.animateScrollToItem(0) } } } @@ -120,22 +105,18 @@ private fun RoomListClearFiltersButton( onClick: () -> Unit, modifier: Modifier = Modifier ) { - IconButton( - modifier = modifier, - onClick = onClick, + Box( + modifier = modifier + .clip(CircleShape) + .background(ElementTheme.colors.bgActionPrimaryRest) + .clickable(onClick = onClick) ) { - Box( - modifier = Modifier - .clip(CircleShape) - .background(ElementTheme.colors.bgActionPrimaryRest) - ) { - Icon( - modifier = Modifier.align(Alignment.Center), - imageVector = CompoundIcons.Close(), - tint = ElementTheme.colors.iconOnSolidPrimary, - contentDescription = stringResource(id = io.element.android.libraries.ui.strings.R.string.action_clear), - ) - } + Icon( + modifier = Modifier.align(Alignment.Center), + imageVector = CompoundIcons.Close(), + tint = ElementTheme.colors.iconOnSolidPrimary, + contentDescription = stringResource(id = io.element.android.libraries.ui.strings.R.string.action_clear), + ) } } @@ -149,9 +130,7 @@ private fun RoomListFilterView( FilterChip( selected = selected, onClick = { onClick(roomListFilter) }, - modifier = modifier - .minimumInteractiveComponentSize() - .height(36.dp), + modifier = modifier.height(36.dp), shape = CircleShape, colors = FilterChipDefaults.filterChipColors( containerColor = ElementTheme.colors.bgCanvasDefault, From a2c4d7debde28922988781e6fe214ecdd3d1451c Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 11 Mar 2024 21:27:14 +0100 Subject: [PATCH 06/11] RoomListFilters : integrate with TopBar (and bloom) --- .../features/roomlist/impl/RoomListView.kt | 54 +---- .../impl/components/RoomListTopBar.kt | 226 ++++++++++-------- 2 files changed, 144 insertions(+), 136 deletions(-) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt index f8cb6f137b..23a105f143 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt @@ -17,63 +17,36 @@ package io.element.android.features.roomlist.impl import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarState import androidx.compose.runtime.Composable -import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.unit.Velocity -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.leaveroom.api.LeaveRoomView import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorContainer -import io.element.android.features.roomlist.impl.components.ConfirmRecoveryKeyBanner -import io.element.android.features.roomlist.impl.components.RequestVerificationHeader import io.element.android.features.roomlist.impl.components.RoomListContentView import io.element.android.features.roomlist.impl.components.RoomListMenuAction import io.element.android.features.roomlist.impl.components.RoomListTopBar -import io.element.android.features.roomlist.impl.components.RoomSummaryRow -import io.element.android.features.roomlist.impl.filters.RoomListFiltersView -import io.element.android.features.roomlist.impl.migration.MigrationScreenView import io.element.android.features.roomlist.impl.model.RoomListRoomSummary import io.element.android.features.roomlist.impl.search.RoomListSearchView 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.FloatingActionButton -import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.Icon -import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.Scaffold -import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.ui.strings.CommonStrings @Composable fun RoomListView( @@ -161,21 +134,18 @@ private fun RoomListScaffold( Scaffold( modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection), topBar = { - Column { - RoomListTopBar( - matrixUser = state.matrixUser, - showAvatarIndicator = state.showAvatarIndicator, - areSearchResultsDisplayed = state.searchState.isSearchActive, - onToggleSearch = { state.eventSink(RoomListEvents.ToggleSearchResults) }, - onMenuActionClicked = onMenuActionClicked, - onOpenSettings = onOpenSettings, - scrollBehavior = scrollBehavior, - displayMenuItems = !state.displayActions, - ) - if (state.displayFilters) { - RoomListFiltersView(state = state.filtersState) - } - } + RoomListTopBar( + matrixUser = state.matrixUser, + showAvatarIndicator = state.showAvatarIndicator, + areSearchResultsDisplayed = state.searchState.isSearchActive, + onToggleSearch = { state.eventSink(RoomListEvents.ToggleSearchResults) }, + onMenuActionClicked = onMenuActionClicked, + onOpenSettings = onOpenSettings, + scrollBehavior = scrollBehavior, + displayMenuItems = state.displayActions, + displayFilters = state.displayFilters, + filtersState = state.filtersState, + ) }, content = { padding -> RoomListContentView( diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt index 0d0a750a9f..50b4144225 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt @@ -17,6 +17,7 @@ package io.element.android.features.roomlist.impl.components import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -40,7 +41,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.graphics.Color -import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalInspectionMode @@ -52,8 +52,12 @@ import io.element.android.appconfig.RoomListConfig import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.roomlist.impl.R +import io.element.android.features.roomlist.impl.filters.RoomListFiltersState +import io.element.android.features.roomlist.impl.filters.RoomListFiltersView +import io.element.android.features.roomlist.impl.filters.aRoomListFiltersState import io.element.android.libraries.designsystem.atomic.atoms.RedIndicatorAtom import io.element.android.libraries.designsystem.components.avatar.Avatar +import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatarBloom import io.element.android.libraries.designsystem.preview.ElementPreview @@ -91,6 +95,8 @@ fun RoomListTopBar( onOpenSettings: () -> Unit, scrollBehavior: TopAppBarScrollBehavior, displayMenuItems: Boolean, + displayFilters: Boolean, + filtersState: RoomListFiltersState, modifier: Modifier = Modifier, ) { DefaultRoomListTopBar( @@ -102,6 +108,8 @@ fun RoomListTopBar( onMenuActionClicked = onMenuActionClicked, scrollBehavior = scrollBehavior, displayMenuItems = displayMenuItems, + displayFilters = displayFilters, + filtersState = filtersState, modifier = modifier, ) } @@ -117,6 +125,8 @@ private fun DefaultRoomListTopBar( onSearchClicked: () -> Unit, onMenuActionClicked: (RoomListMenuAction) -> Unit, displayMenuItems: Boolean, + displayFilters: Boolean, + filtersState: RoomListFiltersState, modifier: Modifier = Modifier, ) { // We need this to manually clip the top app bar in preview mode @@ -153,12 +163,11 @@ private fun DefaultRoomListTopBar( titleLarge = collapsedTitleTextStyle ), ) { - MediumTopAppBar( + Column( modifier = Modifier .onSizeChanged { appBarHeight = it.height } - .nestedScroll(scrollBehavior.nestedScrollConnection) .avatarBloom( avatarData = avatarData, background = if (ElementTheme.isLightTheme) { @@ -178,113 +187,104 @@ private fun DefaultRoomListTopBar( DpSize.Unspecified }, bottomSoftEdgeColor = ElementTheme.materialColors.background, - bottomSoftEdgeAlpha = 1f - collapsedFraction, + bottomSoftEdgeAlpha = if (displayFilters) { + 1f + } else { + 1f - collapsedFraction + }, alpha = if (areSearchResultsDisplayed) 0f else 1f, ) .statusBarsPadding(), - colors = TopAppBarDefaults.mediumTopAppBarColors( - containerColor = Color.Transparent, - scrolledContainerColor = Color.Transparent, - ), - title = { - Text(text = stringResource(id = R.string.screen_roomlist_main_space_title)) - }, - navigationIcon = { - IconButton( - modifier = Modifier.testTag(TestTags.homeScreenSettings), - onClick = onOpenSettings - ) { - if (avatarData != null) { - Avatar( - avatarData = avatarData!!, - contentDescription = stringResource(CommonStrings.common_settings), - ) - } else { - // Placeholder avatar until the avatarData is available - Surface( - modifier = Modifier.size(AvatarSize.CurrentUserTopBar.dp), - shape = CircleShape, - color = ElementTheme.colors.iconSecondary, - content = {} - ) - } - if (showAvatarIndicator) { - RedIndicatorAtom( - modifier = Modifier - .padding(4.5.dp) - .align(Alignment.TopEnd) - ) - } - } - }, - actions = { - if (displayMenuItems) { - IconButton( - onClick = onSearchClicked, - ) { - Icon( - imageVector = CompoundIcons.Search(), - contentDescription = stringResource(CommonStrings.action_search), - ) - } - if (RoomListConfig.HAS_DROP_DOWN_MENU) { - var showMenu by remember { mutableStateOf(false) } + ) { + MediumTopAppBar( + colors = TopAppBarDefaults.mediumTopAppBarColors( + containerColor = Color.Transparent, + scrolledContainerColor = Color.Transparent, + ), + title = { + Text(text = stringResource(id = R.string.screen_roomlist_main_space_title)) + }, + navigationIcon = { + NavigationIcon( + avatarData = avatarData, + showAvatarIndicator = showAvatarIndicator, + onClick = onOpenSettings, + ) + }, + actions = { + if (displayMenuItems) { IconButton( - onClick = { showMenu = !showMenu } + onClick = onSearchClicked, ) { Icon( - imageVector = CompoundIcons.OverflowVertical(), - contentDescription = null, + imageVector = CompoundIcons.Search(), + contentDescription = stringResource(CommonStrings.action_search), ) } - DropdownMenu( - expanded = showMenu, - onDismissRequest = { showMenu = false } - ) { - if (RoomListConfig.SHOW_INVITE_MENU_ITEM) { - DropdownMenuItem( - onClick = { - showMenu = false - onMenuActionClicked(RoomListMenuAction.InviteFriends) - }, - text = { Text(stringResource(id = CommonStrings.action_invite)) }, - leadingIcon = { - Icon( - imageVector = CompoundIcons.ShareAndroid(), - tint = ElementTheme.materialColors.secondary, - contentDescription = null, - ) - } + if (RoomListConfig.HAS_DROP_DOWN_MENU) { + var showMenu by remember { mutableStateOf(false) } + IconButton( + onClick = { showMenu = !showMenu } + ) { + Icon( + imageVector = CompoundIcons.OverflowVertical(), + contentDescription = null, ) } - if (RoomListConfig.SHOW_REPORT_PROBLEM_MENU_ITEM) { - DropdownMenuItem( - onClick = { - showMenu = false - onMenuActionClicked(RoomListMenuAction.ReportBug) - }, - text = { Text(stringResource(id = CommonStrings.common_report_a_problem)) }, - leadingIcon = { - Icon( - imageVector = CompoundIcons.ChatProblem(), - tint = ElementTheme.materialColors.secondary, - contentDescription = null, - ) - } - ) + DropdownMenu( + expanded = showMenu, + onDismissRequest = { showMenu = false } + ) { + if (RoomListConfig.SHOW_INVITE_MENU_ITEM) { + DropdownMenuItem( + onClick = { + showMenu = false + onMenuActionClicked(RoomListMenuAction.InviteFriends) + }, + text = { Text(stringResource(id = CommonStrings.action_invite)) }, + leadingIcon = { + Icon( + imageVector = CompoundIcons.ShareAndroid(), + tint = ElementTheme.materialColors.secondary, + contentDescription = null, + ) + } + ) + } + if (RoomListConfig.SHOW_REPORT_PROBLEM_MENU_ITEM) { + DropdownMenuItem( + onClick = { + showMenu = false + onMenuActionClicked(RoomListMenuAction.ReportBug) + }, + text = { Text(stringResource(id = CommonStrings.common_report_a_problem)) }, + leadingIcon = { + Icon( + imageVector = CompoundIcons.ChatProblem(), + tint = ElementTheme.materialColors.secondary, + contentDescription = null, + ) + } + ) + } } } } - } - }, - scrollBehavior = scrollBehavior, - windowInsets = WindowInsets(0.dp), - ) + }, + scrollBehavior = scrollBehavior, + windowInsets = WindowInsets(0.dp), + ) + if (displayFilters) { + RoomListFiltersView( + state = filtersState, + modifier = Modifier.padding(bottom = 16.dp) + ) + } + } } HorizontalDivider( - modifier = - Modifier + modifier = Modifier .fillMaxWidth() .alpha(collapsedFraction) .align(Alignment.BottomCenter), @@ -293,6 +293,40 @@ private fun DefaultRoomListTopBar( } } +@Composable +private fun NavigationIcon( + avatarData: AvatarData?, + showAvatarIndicator: Boolean, + onClick: () -> Unit, +) { + IconButton( + modifier = Modifier.testTag(TestTags.homeScreenSettings), + onClick = onClick, + ) { + Box { + if (avatarData != null) { + Avatar( + avatarData = avatarData, + contentDescription = stringResource(CommonStrings.common_settings), + ) + } else { + // Placeholder avatar until the avatarData is available + Surface( + modifier = Modifier.size(AvatarSize.CurrentUserTopBar.dp), + shape = CircleShape, + color = ElementTheme.colors.iconSecondary, + content = {} + ) + } + if (showAvatarIndicator) { + RedIndicatorAtom( + modifier = Modifier.align(Alignment.TopEnd) + ) + } + } + } +} + @OptIn(ExperimentalMaterial3Api::class) @PreviewsDayNight @Composable @@ -305,6 +339,8 @@ internal fun DefaultRoomListTopBarPreview() = ElementPreview { onOpenSettings = {}, onSearchClicked = {}, displayMenuItems = true, + displayFilters = true, + filtersState = aRoomListFiltersState(), onMenuActionClicked = {}, ) } @@ -321,6 +357,8 @@ internal fun DefaultRoomListTopBarWithIndicatorPreview() = ElementPreview { onOpenSettings = {}, onSearchClicked = {}, displayMenuItems = true, + displayFilters = true, + filtersState = aRoomListFiltersState(), onMenuActionClicked = {}, ) } From bf68261ed9a5b775ec2c8ff8a03e3c410253ac49 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 12 Mar 2024 15:38:33 +0100 Subject: [PATCH 07/11] RoomList: refactor and fix tests --- .../impl/RoomListContentStateProvider.kt | 49 ++++++ .../roomlist/impl/RoomListPresenter.kt | 16 +- .../features/roomlist/impl/RoomListState.kt | 1 + .../roomlist/impl/RoomListStateProvider.kt | 27 ++-- .../impl/components/RoomListContentView.kt | 25 +++- .../impl/datasource/RoomListDataSource.kt | 3 - .../datasource/RoomListRoomSummaryFactory.kt | 3 - .../roomlist/impl/di/RoomListModule.kt | 5 + .../RoomListFiltersEmptyStateResources.kt | 1 - .../impl/filters/RoomListFiltersPresenter.kt | 4 - .../impl/filters/RoomListFiltersState.kt | 8 +- .../impl/filters/RoomListFiltersView.kt | 1 - .../DefaultFilterSelectionStrategy.kt | 1 - .../selection/FilterSelectionStrategy.kt | 1 - .../roomlist/impl/RoomListPresenterTests.kt | 139 +++++++++++------- .../features/roomlist/impl/RoomListState.kt | 19 +++ .../roomlist/impl/RoomListViewTest.kt | 18 +-- .../android/samples/minimal/RoomListScreen.kt | 2 + tests/testutils/build.gradle.kts | 1 + .../tests/testutils/MutablePresenter.kt | 35 +++++ 20 files changed, 252 insertions(+), 107 deletions(-) create mode 100644 features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContentStateProvider.kt create mode 100644 features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt create mode 100644 tests/testutils/src/main/kotlin/io/element/android/tests/testutils/MutablePresenter.kt diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContentStateProvider.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContentStateProvider.kt new file mode 100644 index 0000000000..7f066628df --- /dev/null +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContentStateProvider.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomlist.impl + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.features.roomlist.impl.model.RoomListRoomSummary +import kotlinx.collections.immutable.ImmutableList + +open class RoomListContentStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aRoomsContentState(), + aSkeletonContentState(), + anEmptyContentState(), + aMigrationContentState(), + ) +} + +internal fun aRoomsContentState( + invitesState: InvitesState = InvitesState.NoInvites, + securityBannerState: SecurityBannerState = SecurityBannerState.None, + summaries: ImmutableList = aRoomListRoomSummaryList(), +) = RoomListContentState.Rooms( + invitesState = invitesState, + securityBannerState = securityBannerState, + summaries = summaries, +) + +internal fun aMigrationContentState() = RoomListContentState.Migration + +internal fun aSkeletonContentState() = RoomListContentState.Skeleton(16) + +internal fun anEmptyContentState( + invitesState: InvitesState = InvitesState.NoInvites, +) = RoomListContentState.Empty(invitesState) 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 4bd26a62cf..5197361f2d 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 @@ -40,7 +40,7 @@ import io.element.android.features.preferences.api.store.SessionPreferencesStore import io.element.android.features.roomlist.impl.datasource.InviteStateDataSource import io.element.android.features.roomlist.impl.datasource.RoomListDataSource import io.element.android.features.roomlist.impl.filters.RoomListFiltersState -import io.element.android.features.roomlist.impl.migration.MigrationScreenPresenter +import io.element.android.features.roomlist.impl.migration.MigrationScreenState import io.element.android.features.roomlist.impl.search.RoomListSearchEvents import io.element.android.features.roomlist.impl.search.RoomListSearchState import io.element.android.libraries.architecture.AsyncData @@ -89,7 +89,7 @@ class RoomListPresenter @Inject constructor( private val indicatorService: IndicatorService, private val filtersPresenter: Presenter, private val searchPresenter: Presenter, - private val migrationScreenPresenter: MigrationScreenPresenter, + private val migrationScreenPresenter: Presenter, private val sessionPreferencesStore: SessionPreferencesStore, private val analyticsService: AnalyticsService, ) : Presenter { @@ -196,23 +196,23 @@ class RoomListPresenter @Inject constructor( } val loadingState by roomListDataSource.loadingState.collectAsState() val showMigration = migrationScreenPresenter.present().isMigrating - val showSkeleton by remember { - derivedStateOf { - loadingState == RoomList.LoadingState.NotLoaded || roomSummaries is AsyncData.Loading - } - } val showEmpty by remember { derivedStateOf { (loadingState as? RoomList.LoadingState.Loaded)?.numberOfRooms == 0 } } + val showSkeleton by remember { + derivedStateOf { + loadingState == RoomList.LoadingState.NotLoaded || roomSummaries is AsyncData.Loading + } + } return when { showMigration -> RoomListContentState.Migration - showSkeleton -> RoomListContentState.Skeleton(count = 16) showEmpty -> { val invitesState = inviteStateDataSource.inviteState() RoomListContentState.Empty(invitesState) } + showSkeleton -> RoomListContentState.Skeleton(count = 16) else -> { val invitesState = inviteStateDataSource.inviteState() val securityBannerState by securityBannerState(securityBannerDismissed) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt index 58b36636c8..73a1460ad9 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt @@ -67,6 +67,7 @@ enum class SecurityBannerState { RecoveryKeyConfirmation, } +@Immutable sealed interface RoomListContentState { data object Migration : RoomListContentState data class Skeleton(val count: Int) : RoomListContentState diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt index a47baf4bbc..3d577d9ea9 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt @@ -25,7 +25,6 @@ import io.element.android.features.roomlist.impl.model.RoomListRoomSummary import io.element.android.features.roomlist.impl.model.aRoomListRoomSummary import io.element.android.features.roomlist.impl.search.RoomListSearchState import io.element.android.features.roomlist.impl.search.aRoomListSearchState -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage @@ -35,7 +34,6 @@ import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.toPersistentList open class RoomListStateProvider : PreviewParameterProvider { override val values: Sequence @@ -43,15 +41,15 @@ open class RoomListStateProvider : PreviewParameterProvider { aRoomListState(), aRoomListState(snackbarMessage = SnackbarMessage(CommonStrings.common_verification_complete)), aRoomListState(hasNetworkConnection = false), - aRoomListState(invitesState = InvitesState.SeenInvites), - aRoomListState(invitesState = InvitesState.NewInvites), + aRoomListState(contentState = aRoomsContentState(invitesState = InvitesState.SeenInvites)), + aRoomListState(contentState = aRoomsContentState(invitesState = InvitesState.NewInvites)), aRoomListState(contextMenu = aContextMenuShown(roomName = "A nice room name")), aRoomListState(contextMenu = aContextMenuShown(isFavorite = true)), - aRoomListState(securityBannerState = SecurityBannerState.SessionVerification), - aRoomListState(securityBannerState = SecurityBannerState.RecoveryKeyConfirmation), - aRoomListState(roomList = AsyncData.Success(persistentListOf())), - //aRoomListState(roomList = AsyncData.Loading(prevData = RoomListRoomSummaryFactory.createFakeList())), - aRoomListState(matrixUser = null, displayMigrationStatus = true), + aRoomListState(contentState = aRoomsContentState(securityBannerState = SecurityBannerState.SessionVerification)), + aRoomListState(contentState = aRoomsContentState(securityBannerState = SecurityBannerState.RecoveryKeyConfirmation)), + aRoomListState(contentState = anEmptyContentState()), + aRoomListState(contentState = aSkeletonContentState()), + aRoomListState(matrixUser = null, contentState = aMigrationContentState()), aRoomListState(searchState = aRoomListSearchState(isSearchActive = true, query = "Test")), aRoomListState(filtersState = aRoomListFiltersState(isFeatureEnabled = true)), ) @@ -60,16 +58,13 @@ open class RoomListStateProvider : PreviewParameterProvider { internal fun aRoomListState( matrixUser: MatrixUser? = MatrixUser(userId = UserId("@id:domain"), displayName = "User#1"), showAvatarIndicator: Boolean = false, - roomList: AsyncData> = AsyncData.Success(aRoomListRoomSummaryList()), hasNetworkConnection: Boolean = true, snackbarMessage: SnackbarMessage? = null, - securityBannerState: SecurityBannerState = SecurityBannerState.None, - invitesState: InvitesState = InvitesState.NoInvites, contextMenu: RoomListState.ContextMenu = RoomListState.ContextMenu.Hidden, leaveRoomState: LeaveRoomState = aLeaveRoomState(), searchState: RoomListSearchState = aRoomListSearchState(), filtersState: RoomListFiltersState = aRoomListFiltersState(isFeatureEnabled = false), - displayMigrationStatus: Boolean = false, + contentState: RoomListContentState = aRoomsContentState(), eventSink: (RoomListEvents) -> Unit = {} ) = RoomListState( matrixUser = matrixUser, @@ -80,11 +75,7 @@ internal fun aRoomListState( leaveRoomState = leaveRoomState, filtersState = filtersState, searchState = searchState, - contentState = RoomListContentState.Rooms( - invitesState = invitesState, - securityBannerState = securityBannerState, - summaries = roomList.dataOrNull().orEmpty().toPersistentList(), - ), + contentState = contentState, eventSink = eventSink, ) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt index 612264bb0c..1e3d66750f 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt @@ -17,7 +17,6 @@ package io.element.android.features.roomlist.impl.components import androidx.annotation.StringRes -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -40,6 +39,7 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.Velocity import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -48,19 +48,24 @@ import io.element.android.features.roomlist.impl.InvitesEntryPointView import io.element.android.features.roomlist.impl.InvitesState import io.element.android.features.roomlist.impl.R import io.element.android.features.roomlist.impl.RoomListContentState +import io.element.android.features.roomlist.impl.RoomListContentStateProvider import io.element.android.features.roomlist.impl.RoomListEvents import io.element.android.features.roomlist.impl.SecurityBannerState import io.element.android.features.roomlist.impl.contentType import io.element.android.features.roomlist.impl.filters.RoomListFilter import io.element.android.features.roomlist.impl.filters.RoomListFiltersEmptyStateResources import io.element.android.features.roomlist.impl.filters.RoomListFiltersState +import io.element.android.features.roomlist.impl.filters.aRoomListFiltersState import io.element.android.features.roomlist.impl.migration.MigrationScreenView import io.element.android.features.roomlist.impl.model.RoomListRoomSummary +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.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.ui.strings.CommonStrings +import kotlinx.collections.immutable.ImmutableList @Composable fun RoomListContentView( @@ -214,7 +219,6 @@ private fun RoomsViewList( modifier = modifier.nestedScroll(nestedScrollConnection), // FAB height is 56dp, bottom padding is 16dp, we add 8dp as extra margin -> 56+16+8 = 80 contentPadding = PaddingValues(bottom = 80.dp) - ) { when (state.securityBannerState) { SecurityBannerState.SessionVerification -> { @@ -261,7 +265,7 @@ private fun RoomsViewList( @Composable private fun EmptyViewForFilterStates( - selectedFilters: List, + selectedFilters: ImmutableList, modifier: Modifier = Modifier, ) { val emptyStateResources = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters) ?: return @@ -301,3 +305,18 @@ private fun EmptyScaffold( action?.invoke(this) } } + +@PreviewsDayNight +@Composable +internal fun RoomListContentViewPreview(@PreviewParameter(RoomListContentStateProvider::class) state: RoomListContentState) = ElementPreview { + RoomListContentView( + contentState = state, + filtersState = aRoomListFiltersState(), + eventSink = {}, + onVerifyClicked = { }, + onConfirmRecoveryKeyClicked = { }, + onRoomClicked = {}, + onRoomLongClicked = {}, + onCreateRoomClicked = { }, + onInvitesClicked = { }) +} diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt index 5d92a55ba7..2f078d7a69 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt @@ -29,12 +29,9 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListRoomSummaryFactory.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListRoomSummaryFactory.kt index aea57d32ab..07cdabea8e 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListRoomSummaryFactory.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListRoomSummaryFactory.kt @@ -24,8 +24,6 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.roomlist.RoomSummary -import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.toImmutableList import javax.inject.Inject class RoomListRoomSummaryFactory @Inject constructor( @@ -52,7 +50,6 @@ class RoomListRoomSummaryFactory @Inject constructor( isFavorite = false, ) } - } fun create(roomSummary: RoomSummary.Filled): RoomListRoomSummary { diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/di/RoomListModule.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/di/RoomListModule.kt index b66401695e..7176ddef1e 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/di/RoomListModule.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/di/RoomListModule.kt @@ -21,6 +21,8 @@ import dagger.Binds import dagger.Module import io.element.android.features.roomlist.impl.filters.RoomListFiltersPresenter import io.element.android.features.roomlist.impl.filters.RoomListFiltersState +import io.element.android.features.roomlist.impl.migration.MigrationScreenPresenter +import io.element.android.features.roomlist.impl.migration.MigrationScreenState import io.element.android.features.roomlist.impl.search.RoomListSearchPresenter import io.element.android.features.roomlist.impl.search.RoomListSearchState import io.element.android.libraries.architecture.Presenter @@ -34,4 +36,7 @@ interface RoomListModule { @Binds fun bindFiltersPresenter(presenter: RoomListFiltersPresenter): Presenter + + @Binds + fun bindMigrationScreenPresenter(presenter: MigrationScreenPresenter): Presenter } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEmptyStateResources.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEmptyStateResources.kt index f0f29b0db6..53763abd0d 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEmptyStateResources.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEmptyStateResources.kt @@ -28,7 +28,6 @@ data class RoomListFiltersEmptyStateResources( @StringRes val title: Int, @StringRes val subtitle: Int, ) { - companion object { /** * Create a [RoomListFiltersEmptyStateResources] from a list of selected filters. diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenter.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenter.kt index 058bfbbd8c..27edc91627 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenter.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenter.kt @@ -34,14 +34,11 @@ class RoomListFiltersPresenter @Inject constructor( private val featureFlagService: FeatureFlagService, private val filterSelectionStrategy: FilterSelectionStrategy, ) : Presenter { - @Composable override fun present(): RoomListFiltersState { - val isFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomListFilters).collectAsState(false) val filters by filterSelectionStrategy.filterSelectionStates.collectAsState() - fun handleEvents(event: RoomListFiltersEvents) { when (event) { RoomListFiltersEvents.ClearSelectedFilters -> { @@ -75,7 +72,6 @@ class RoomListFiltersPresenter @Inject constructor( roomListService.allRooms.updateFilter(allRoomsFilter) } - return RoomListFiltersState( filterSelectionStates = filters.toPersistentList(), isFeatureEnabled = isFeatureEnabled, diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersState.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersState.kt index 7fce841aaf..14850ef82e 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersState.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersState.kt @@ -18,6 +18,7 @@ package io.element.android.features.roomlist.impl.filters import io.element.android.features.roomlist.impl.filters.selection.FilterSelectionState import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toPersistentList data class RoomListFiltersState( val filterSelectionStates: ImmutableList, @@ -26,7 +27,10 @@ data class RoomListFiltersState( ) { val hasAnyFilterSelected = filterSelectionStates.any { it.isSelected } - fun selectedFilters(): List { - return filterSelectionStates.filter { it.isSelected }.map { it.filter } + fun selectedFilters(): ImmutableList { + return filterSelectionStates + .filter { it.isSelected } + .map { it.filter } + .toPersistentList() } } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt index 57f4fa0a9c..fcdc260c6e 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersView.kt @@ -53,7 +53,6 @@ fun RoomListFiltersView( state: RoomListFiltersState, modifier: Modifier = Modifier ) { - fun onClearFiltersClicked() { state.eventSink(RoomListFiltersEvents.ClearSelectedFilters) } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/DefaultFilterSelectionStrategy.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/DefaultFilterSelectionStrategy.kt index 4c2b4013b6..d56c84a572 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/DefaultFilterSelectionStrategy.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/DefaultFilterSelectionStrategy.kt @@ -24,7 +24,6 @@ import javax.inject.Inject @ContributesBinding(SessionScope::class) class DefaultFilterSelectionStrategy @Inject constructor() : FilterSelectionStrategy { - private val selectedFilters = LinkedHashSet() override val filterSelectionStates = MutableStateFlow(buildFilters()) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/FilterSelectionStrategy.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/FilterSelectionStrategy.kt index aa2f42384b..415c67fc7b 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/FilterSelectionStrategy.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/filters/selection/FilterSelectionStrategy.kt @@ -20,7 +20,6 @@ import io.element.android.features.roomlist.impl.filters.RoomListFilter import kotlinx.coroutines.flow.StateFlow interface FilterSelectionStrategy { - val filterSelectionStates: StateFlow> fun select(filter: RoomListFilter) diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt index 4e83e681fd..aa89c4fac2 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt @@ -33,8 +33,7 @@ import io.element.android.features.roomlist.impl.datasource.RoomListDataSource import io.element.android.features.roomlist.impl.datasource.RoomListRoomSummaryFactory import io.element.android.features.roomlist.impl.filters.RoomListFiltersState import io.element.android.features.roomlist.impl.filters.aRoomListFiltersState -import io.element.android.features.roomlist.impl.migration.InMemoryMigrationScreenStore -import io.element.android.features.roomlist.impl.migration.MigrationScreenPresenter +import io.element.android.features.roomlist.impl.migration.MigrationScreenState import io.element.android.features.roomlist.impl.model.createRoomListRoomSummary import io.element.android.features.roomlist.impl.search.RoomListSearchEvents import io.element.android.features.roomlist.impl.search.RoomListSearchState @@ -54,13 +53,12 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.encryption.BackupState import io.element.android.libraries.matrix.api.encryption.RecoveryState import io.element.android.libraries.matrix.api.room.RoomNotificationMode -import io.element.android.libraries.matrix.api.roomlist.RoomListService +import io.element.android.libraries.matrix.api.roomlist.RoomList import io.element.android.libraries.matrix.api.sync.SyncState import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.A_ROOM_ID -import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.A_USER_NAME import io.element.android.libraries.matrix.test.FakeMatrixClient @@ -75,6 +73,7 @@ import io.element.android.libraries.matrix.test.verification.FakeSessionVerifica import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.EventsRecorder +import io.element.android.tests.testutils.MutablePresenter import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.consumeItemsUntilPredicate import io.element.android.tests.testutils.testCoroutineDispatchers @@ -127,7 +126,6 @@ class RoomListPresenterTests { moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { - skipItems(1) val initialState = awaitItem() assertThat(initialState.showAvatarIndicator).isTrue() sessionVerificationService.givenCanVerifySession(false) @@ -169,11 +167,9 @@ class RoomListPresenterTests { moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { - val initialState = consumeItemsUntilPredicate(timeout = 3.seconds) { state -> state.roomList.dataOrNull()?.size == 16 }.last() - // Room list is loaded with 16 placeholders - val initialItems = initialState.roomList.dataOrNull().orEmpty() - assertThat(initialItems.size).isEqualTo(16) - assertThat(initialItems.all { it.isPlaceholder }).isTrue() + val initialState = consumeItemsUntilPredicate(timeout = 3.seconds) { state -> state.contentState is RoomListContentState.Skeleton }.last() + assertThat(initialState.contentState).isInstanceOf(RoomListContentState.Skeleton::class.java) + roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1)) roomListService.postAllRooms( listOf( aRoomSummaryFilled( @@ -182,10 +178,10 @@ class RoomListPresenterTests { ) ) ) - val withRoomState = consumeItemsUntilPredicate { state -> state.roomList.dataOrNull()?.size == 1 }.last() - val withRoomStateItems = withRoomState.roomList.dataOrNull().orEmpty() - assertThat(withRoomStateItems.size).isEqualTo(1) - assertThat(withRoomStateItems.first()).isEqualTo( + val withRoomsState = + consumeItemsUntilPredicate { state -> state.contentState is RoomListContentState.Rooms && state.contentAsRooms().summaries.isNotEmpty() }.last() + assertThat(withRoomsState.contentAsRooms().summaries).hasSize(1) + assertThat(withRoomsState.contentAsRooms().summaries.first()).isEqualTo( createRoomListRoomSummary( numberOfUnreadMentions = 1, numberOfUnreadMessages = 2, @@ -241,23 +237,28 @@ class RoomListPresenterTests { @Test fun `present - handle RecoveryKeyConfirmation last session`() = runTest { val scope = CoroutineScope(context = coroutineContext + SupervisorJob()) + val roomListService = FakeRoomListService().apply { + postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1)) + } val presenter = createRoomListPresenter( coroutineScope = scope, client = FakeMatrixClient( encryptionService = FakeEncryptionService().apply { emitIsLastDevice(true) - } + }, + roomListService = roomListService ), ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { - skipItems(1) - val eventSink = awaitItem().eventSink + val eventSink = consumeItemsUntilPredicate { + it.contentState is RoomListContentState.Rooms + }.last().eventSink // For the last session, the state is not SessionVerification, but RecoveryKeyConfirmation - assertThat(awaitItem().securityBannerState).isEqualTo(SecurityBannerState.RecoveryKeyConfirmation) + assertThat(awaitItem().contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.RecoveryKeyConfirmation) eventSink(RoomListEvents.DismissRequestVerificationPrompt) - assertThat(awaitItem().securityBannerState).isEqualTo(SecurityBannerState.None) + assertThat(awaitItem().contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.None) scope.cancel() } } @@ -265,16 +266,22 @@ class RoomListPresenterTests { @Test fun `present - handle DismissRequestVerificationPrompt`() = runTest { val scope = CoroutineScope(context = coroutineContext + SupervisorJob()) + val roomListService = FakeRoomListService().apply { + postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1)) + } val presenter = createRoomListPresenter( + client = FakeMatrixClient(roomListService = roomListService), coroutineScope = scope, ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { - val eventSink = awaitItem().eventSink - assertThat(awaitItem().securityBannerState).isEqualTo(SecurityBannerState.SessionVerification) + val eventSink = consumeItemsUntilPredicate { + it.contentState is RoomListContentState.Rooms + }.last().eventSink + assertThat(awaitItem().contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.SessionVerification) eventSink(RoomListEvents.DismissRequestVerificationPrompt) - assertThat(awaitItem().securityBannerState).isEqualTo(SecurityBannerState.None) + assertThat(awaitItem().contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.None) scope.cancel() } } @@ -282,7 +289,11 @@ class RoomListPresenterTests { @Test fun `present - handle DismissRecoveryKeyPrompt`() = runTest { val encryptionService = FakeEncryptionService() + val roomListService = FakeRoomListService().apply { + postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1)) + } val matrixClient = FakeMatrixClient( + roomListService = roomListService, encryptionService = encryptionService, sessionVerificationService = FakeSessionVerificationService().apply { givenCanVerifySession(false) @@ -297,15 +308,16 @@ class RoomListPresenterTests { moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { - skipItems(1) - val initialState = awaitItem() - assertThat(initialState.securityBannerState).isEqualTo(SecurityBannerState.None) + val initialState = consumeItemsUntilPredicate { + it.contentState is RoomListContentState.Rooms + }.last() + assertThat(initialState.contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.None) encryptionService.emitRecoveryState(RecoveryState.INCOMPLETE) val nextState = awaitItem() - assertThat(nextState.securityBannerState).isEqualTo(SecurityBannerState.RecoveryKeyConfirmation) + assertThat(nextState.contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.RecoveryKeyConfirmation) nextState.eventSink(RoomListEvents.DismissRecoveryKeyPrompt) val finalState = awaitItem() - assertThat(finalState.securityBannerState).isEqualTo(SecurityBannerState.None) + assertThat(finalState.contentAsRooms().securityBannerState).isEqualTo(SecurityBannerState.None) scope.cancel() } } @@ -314,22 +326,30 @@ class RoomListPresenterTests { fun `present - sets invite state`() = runTest { val inviteStateFlow = MutableStateFlow(InvitesState.NoInvites) val inviteStateDataSource = FakeInviteDataSource(inviteStateFlow) + val roomListService = FakeRoomListService() val scope = CoroutineScope(coroutineContext + SupervisorJob()) - val presenter = createRoomListPresenter(inviteStateDataSource = inviteStateDataSource, coroutineScope = scope) + val presenter = createRoomListPresenter( + inviteStateDataSource = inviteStateDataSource, + coroutineScope = scope, + client = FakeMatrixClient(roomListService = roomListService), + ) + roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1)) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { - skipItems(1) - assertThat(awaitItem().invitesState).isEqualTo(InvitesState.NoInvites) + consumeItemsUntilPredicate { + it.contentState is RoomListContentState.Rooms + } + assertThat(awaitItem().contentAsRooms().invitesState).isEqualTo(InvitesState.NoInvites) inviteStateFlow.value = InvitesState.SeenInvites - assertThat(awaitItem().invitesState).isEqualTo(InvitesState.SeenInvites) + assertThat(awaitItem().contentAsRooms().invitesState).isEqualTo(InvitesState.SeenInvites) inviteStateFlow.value = InvitesState.NewInvites - assertThat(awaitItem().invitesState).isEqualTo(InvitesState.NewInvites) + assertThat(awaitItem().contentAsRooms().invitesState).isEqualTo(InvitesState.NewInvites) inviteStateFlow.value = InvitesState.NoInvites - assertThat(awaitItem().invitesState).isEqualTo(InvitesState.NoInvites) + assertThat(awaitItem().contentAsRooms().invitesState).isEqualTo(InvitesState.NoInvites) scope.cancel() } } @@ -477,6 +497,7 @@ class RoomListPresenterTests { val userDefinedMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY val notificationSettingsService = FakeNotificationSettingsService() val roomListService = FakeRoomListService() + roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1)) roomListService.postAllRooms(listOf(aRoomSummaryFilled(notificationMode = userDefinedMode))) val matrixClient = FakeMatrixClient( roomListService = roomListService, @@ -488,12 +509,13 @@ class RoomListPresenterTests { presenter.present() }.test { notificationSettingsService.setRoomNotificationMode(A_ROOM_ID, userDefinedMode) - val updatedState = consumeItemsUntilPredicate { state -> - state.roomList.dataOrNull().orEmpty().any { it.id == A_ROOM_ID.value && it.userDefinedNotificationMode == userDefinedMode } + (state.contentState as? RoomListContentState.Rooms)?.summaries.orEmpty().any { summary -> + summary.id == A_ROOM_ID.value && summary.userDefinedNotificationMode == userDefinedMode + } }.last() - val room = updatedState.roomList.dataOrNull()?.find { it.id == A_ROOM_ID.value } + val room = updatedState.contentAsRooms().summaries.find { it.id == A_ROOM_ID.value } assertThat(room?.userDefinedNotificationMode).isEqualTo(userDefinedMode) cancelAndIgnoreRemainingEvents() scope.cancel() @@ -526,30 +548,46 @@ class RoomListPresenterTests { } } - fun `present - change in migration presenter state modifies isMigrating`() = runTest { - val client = FakeMatrixClient(sessionId = A_SESSION_ID) - val migrationStore = InMemoryMigrationScreenStore() - val migrationScreenPresenter = MigrationScreenPresenter(client, migrationStore) + @Test + fun `present - change in migration presenter state modifies contentState`() = runTest { + val migrationScreenPresenter = MutablePresenter(MigrationScreenState(true)) val scope = CoroutineScope(coroutineContext + SupervisorJob()) val presenter = createRoomListPresenter( - client = client, coroutineScope = scope, migrationScreenPresenter = migrationScreenPresenter, ) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { + skipItems(1) val initialState = awaitItem() // The migration screen is shown if the migration screen has not been shown before - assertThat(initialState.displayMigrationStatus).isTrue() - skipItems(2) - + assertThat(initialState.contentState).isInstanceOf(RoomListContentState.Migration::class.java) // Set migration as done and set the room list service as running to trigger a refresh of the presenter value - (client.roomListService as FakeRoomListService).postState(RoomListService.State.Running) - migrationStore.setMigrationScreenShown(A_SESSION_ID) - + migrationScreenPresenter.updateState(MigrationScreenState(false)) // The migration screen is not shown anymore - assertThat(awaitItem().displayMigrationStatus).isFalse() + assertThat(awaitItem().contentState).isInstanceOf(RoomListContentState.Skeleton::class.java) + scope.cancel() + } + } + + @Test + fun `present - when room service returns no room, then contentState is Empty `() = runTest { + val scope = CoroutineScope(coroutineContext + SupervisorJob()) + val roomListService = FakeRoomListService() + roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(0)) + val matrixClient = FakeMatrixClient( + roomListService = roomListService, + ) + val presenter = createRoomListPresenter( + client = matrixClient, + coroutineScope = scope, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(1) + assertThat(awaitItem().contentState).isInstanceOf(RoomListContentState.Empty::class.java) scope.cancel() } } @@ -609,10 +647,7 @@ class RoomListPresenterTests { sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(), featureFlagService: FeatureFlagService = FakeFeatureFlagService(), coroutineScope: CoroutineScope, - migrationScreenPresenter: MigrationScreenPresenter = MigrationScreenPresenter( - matrixClient = client, - migrationScreenStore = InMemoryMigrationScreenStore(), - ), + migrationScreenPresenter: Presenter = Presenter { MigrationScreenState(false) }, analyticsService: AnalyticsService = FakeAnalyticsService(), filtersPresenter: Presenter = Presenter { aRoomListFiltersState() }, searchPresenter: Presenter = Presenter { aRoomListSearchState() }, diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt new file mode 100644 index 0000000000..27c4f33f1b --- /dev/null +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomlist.impl + +internal fun RoomListState.contentAsRooms() = contentState as RoomListContentState.Rooms diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListViewTest.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListViewTest.kt index 347ff65687..f545b27860 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListViewTest.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListViewTest.kt @@ -26,7 +26,6 @@ import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTouchInput import androidx.test.ext.junit.runners.AndroidJUnit4 import io.element.android.features.roomlist.impl.components.RoomListMenuAction -import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled @@ -35,7 +34,6 @@ import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.ensureCalledOnceWithParam -import kotlinx.collections.immutable.persistentListOf import org.junit.Rule import org.junit.Test import org.junit.rules.TestRule @@ -50,7 +48,7 @@ class RoomListViewTest { val eventsRecorder = EventsRecorder() rule.setRoomListView( state = aRoomListState( - securityBannerState = SecurityBannerState.SessionVerification, + contentState = aRoomsContentState(securityBannerState = SecurityBannerState.SessionVerification), eventSink = eventsRecorder, ) ) @@ -65,7 +63,7 @@ class RoomListViewTest { ensureCalledOnce { callback -> rule.setRoomListView( state = aRoomListState( - securityBannerState = SecurityBannerState.SessionVerification, + contentState = aRoomsContentState(securityBannerState = SecurityBannerState.SessionVerification), eventSink = eventsRecorder, ), onVerifyClicked = callback, @@ -79,7 +77,7 @@ class RoomListViewTest { val eventsRecorder = EventsRecorder() rule.setRoomListView( state = aRoomListState( - securityBannerState = SecurityBannerState.RecoveryKeyConfirmation, + contentState = aRoomsContentState(securityBannerState = SecurityBannerState.RecoveryKeyConfirmation), eventSink = eventsRecorder, ) ) @@ -94,7 +92,7 @@ class RoomListViewTest { ensureCalledOnce { callback -> rule.setRoomListView( state = aRoomListState( - securityBannerState = SecurityBannerState.RecoveryKeyConfirmation, + contentState = aRoomsContentState(securityBannerState = SecurityBannerState.RecoveryKeyConfirmation), eventSink = eventsRecorder, ), onConfirmRecoveryKeyClicked = callback, @@ -110,7 +108,7 @@ class RoomListViewTest { rule.setRoomListView( state = aRoomListState( eventSink = eventsRecorder, - roomList = AsyncData.Success(persistentListOf()), + contentState = anEmptyContentState(), ), onCreateRoomClicked = callback, ) @@ -124,7 +122,7 @@ class RoomListViewTest { val state = aRoomListState( eventSink = eventsRecorder, ) - val room0 = state.roomList.dataOrNull()!!.first() + val room0 = state.contentAsRooms().summaries.first() ensureCalledOnceWithParam(room0.roomId) { callback -> rule.setRoomListView( state = state, @@ -140,7 +138,7 @@ class RoomListViewTest { val state = aRoomListState( eventSink = eventsRecorder, ) - val room0 = state.roomList.dataOrNull()!!.first() + val room0 = state.contentAsRooms().summaries.first() rule.setRoomListView( state = state, ) @@ -170,7 +168,7 @@ class RoomListViewTest { fun `clicking on invites invokes the expected callback`() { val eventsRecorder = EventsRecorder() val state = aRoomListState( - invitesState = InvitesState.NewInvites, + contentState = aRoomsContentState(invitesState = InvitesState.NewInvites), eventSink = eventsRecorder, ) ensureCalledOnce { callback -> 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 0b4c47800c..e651e8f968 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 @@ -29,6 +29,7 @@ import io.element.android.features.roomlist.impl.datasource.DefaultInviteStateDa import io.element.android.features.roomlist.impl.datasource.RoomListDataSource import io.element.android.features.roomlist.impl.datasource.RoomListRoomSummaryFactory import io.element.android.features.roomlist.impl.filters.RoomListFiltersPresenter +import io.element.android.features.roomlist.impl.filters.selection.DefaultFilterSelectionStrategy import io.element.android.features.roomlist.impl.migration.MigrationScreenPresenter import io.element.android.features.roomlist.impl.migration.SharedPrefsMigrationScreenStore import io.element.android.features.roomlist.impl.search.RoomListSearchDataSource @@ -127,6 +128,7 @@ class RoomListScreen( filtersPresenter = RoomListFiltersPresenter( roomListService = matrixClient.roomListService, featureFlagService = featureFlagService, + filterSelectionStrategy = DefaultFilterSelectionStrategy(), ), analyticsService = NoopAnalyticsService(), ) diff --git a/tests/testutils/build.gradle.kts b/tests/testutils/build.gradle.kts index 4b586043dc..8e985bf2ca 100644 --- a/tests/testutils/build.gradle.kts +++ b/tests/testutils/build.gradle.kts @@ -30,6 +30,7 @@ dependencies { implementation(libs.test.junit) implementation(libs.test.truth) implementation(libs.coroutines.test) + implementation(projects.libraries.architecture) implementation(projects.libraries.core) implementation(projects.libraries.uiStrings) implementation(libs.test.turbine) diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/MutablePresenter.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/MutablePresenter.kt new file mode 100644 index 0000000000..02870f88c5 --- /dev/null +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/MutablePresenter.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.tests.testutils + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import io.element.android.libraries.architecture.Presenter +import kotlinx.coroutines.flow.MutableStateFlow + +class MutablePresenter(initialState: State) : Presenter { + private val stateFlow = MutableStateFlow(initialState) + + fun updateState(state: State) { + stateFlow.value = state + } + + @Composable + override fun present(): State { + return stateFlow.collectAsState().value + } +} From eae8d5673b247db00e2c70ddefd8887f55aad573 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Tue, 12 Mar 2024 16:30:46 +0000 Subject: [PATCH 08/11] Update screenshots --- ...omListTopBarWithIndicator-Day-7_8_null,NEXUS_5,1.0,en].png | 3 --- ...omListTopBarWithIndicator-Day-8_9_null,NEXUS_5,1.0,en].png | 3 +++ ...ListTopBarWithIndicator-Night-7_9_null,NEXUS_5,1.0,en].png | 3 --- ...istTopBarWithIndicator-Night-8_10_null,NEXUS_5,1.0,en].png | 3 +++ ...ull_DefaultRoomListTopBar-Day-6_7_null,NEXUS_5,1.0,en].png | 3 --- ...ull_DefaultRoomListTopBar-Day-7_8_null,NEXUS_5,1.0,en].png | 3 +++ ...l_DefaultRoomListTopBar-Night-6_8_null,NEXUS_5,1.0,en].png | 3 --- ...l_DefaultRoomListTopBar-Night-7_9_null,NEXUS_5,1.0,en].png | 3 +++ ...ull_RoomListContentView-Day-6_7_null_0,NEXUS_5,1.0,en].png | 3 +++ ...ull_RoomListContentView-Day-6_7_null_1,NEXUS_5,1.0,en].png | 3 +++ ...ull_RoomListContentView-Day-6_7_null_2,NEXUS_5,1.0,en].png | 3 +++ ...ll_RoomListContentView-Day-6_7_null_3,NEXUS_5,1.0,en].png} | 0 ...l_RoomListContentView-Night-6_8_null_0,NEXUS_5,1.0,en].png | 3 +++ ...l_RoomListContentView-Night-6_8_null_1,NEXUS_5,1.0,en].png | 3 +++ ...l_RoomListContentView-Night-6_8_null_2,NEXUS_5,1.0,en].png | 3 +++ ..._RoomListContentView-Night-6_8_null_3,NEXUS_5,1.0,en].png} | 0 ...omSummaryPlaceholderRow-Day-9_10_null,NEXUS_5,1.0,en].png} | 0 ...SummaryPlaceholderRow-Night-9_11_null,NEXUS_5,1.0,en].png} | 0 ..._null_RoomSummaryRow-Day-10_11_null_0,NEXUS_5,1.0,en].png} | 0 ..._null_RoomSummaryRow-Day-10_11_null_1,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_10,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_11,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_12,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_13,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_14,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_15,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_16,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_17,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_18,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_19,NEXUS_5,1.0,en].png} | 0 ..._null_RoomSummaryRow-Day-10_11_null_2,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_20,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_21,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_22,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_23,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_24,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_25,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_26,NEXUS_5,1.0,en].png} | 0 ...null_RoomSummaryRow-Day-10_11_null_27,NEXUS_5,1.0,en].png} | 0 ..._null_RoomSummaryRow-Day-10_11_null_3,NEXUS_5,1.0,en].png} | 0 ..._null_RoomSummaryRow-Day-10_11_null_4,NEXUS_5,1.0,en].png} | 0 ..._null_RoomSummaryRow-Day-10_11_null_5,NEXUS_5,1.0,en].png} | 0 ..._null_RoomSummaryRow-Day-10_11_null_6,NEXUS_5,1.0,en].png} | 0 ..._null_RoomSummaryRow-Day-10_11_null_7,NEXUS_5,1.0,en].png} | 0 ..._null_RoomSummaryRow-Day-10_11_null_8,NEXUS_5,1.0,en].png} | 0 ..._null_RoomSummaryRow-Day-10_11_null_9,NEXUS_5,1.0,en].png} | 0 ...ull_RoomSummaryRow-Night-10_12_null_0,NEXUS_5,1.0,en].png} | 0 ...ull_RoomSummaryRow-Night-10_12_null_1,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_10,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_11,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_12,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_13,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_14,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_15,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_16,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_17,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_18,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_19,NEXUS_5,1.0,en].png} | 0 ...ull_RoomSummaryRow-Night-10_12_null_2,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_20,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_21,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_22,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_23,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_24,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_25,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_26,NEXUS_5,1.0,en].png} | 0 ...ll_RoomSummaryRow-Night-10_12_null_27,NEXUS_5,1.0,en].png} | 0 ...ull_RoomSummaryRow-Night-10_12_null_3,NEXUS_5,1.0,en].png} | 0 ...ull_RoomSummaryRow-Night-10_12_null_4,NEXUS_5,1.0,en].png} | 0 ...ull_RoomSummaryRow-Night-10_12_null_5,NEXUS_5,1.0,en].png} | 0 ...ull_RoomSummaryRow-Night-10_12_null_6,NEXUS_5,1.0,en].png} | 0 ...ull_RoomSummaryRow-Night-10_12_null_7,NEXUS_5,1.0,en].png} | 0 ...ull_RoomSummaryRow-Night-10_12_null_8,NEXUS_5,1.0,en].png} | 0 ...ull_RoomSummaryRow-Night-10_12_null_9,NEXUS_5,1.0,en].png} | 0 ...l_RoomListFiltersView-Day-10_11_null_0,NEXUS_5,1.0,en].png | 3 --- ...l_RoomListFiltersView-Day-10_11_null_1,NEXUS_5,1.0,en].png | 3 --- ...l_RoomListFiltersView-Day-11_12_null_0,NEXUS_5,1.0,en].png | 3 +++ ...l_RoomListFiltersView-Day-11_12_null_1,NEXUS_5,1.0,en].png | 3 +++ ...RoomListFiltersView-Night-10_12_null_0,NEXUS_5,1.0,en].png | 3 --- ...RoomListFiltersView-Night-10_12_null_1,NEXUS_5,1.0,en].png | 3 --- ...RoomListFiltersView-Night-11_13_null_0,NEXUS_5,1.0,en].png | 3 +++ ...RoomListFiltersView-Night-11_13_null_1,NEXUS_5,1.0,en].png | 3 +++ ...View_null_MigrationView-Day-12_13_null,NEXUS_5,1.0,en].png | 3 +++ ...ew_null_MigrationView-Night-12_14_null,NEXUS_5,1.0,en].png | 3 +++ ...tSearchResultContent-Day-13_14_null_0,NEXUS_5,1.0,en].png} | 0 ...tSearchResultContent-Day-13_14_null_1,NEXUS_5,1.0,en].png} | 0 ...earchResultContent-Night-13_15_null_0,NEXUS_5,1.0,en].png} | 0 ...earchResultContent-Night-13_15_null_1,NEXUS_5,1.0,en].png} | 0 ...View_null_RoomListView-Day-3_4_null_11,NEXUS_5,1.0,en].png | 4 ++-- ...View_null_RoomListView-Day-3_4_null_13,NEXUS_5,1.0,en].png | 4 ++-- ...tView_null_RoomListView-Day-3_4_null_9,NEXUS_5,1.0,en].png | 4 ++-- ...ew_null_RoomListView-Night-3_5_null_11,NEXUS_5,1.0,en].png | 4 ++-- ...ew_null_RoomListView-Night-3_5_null_13,NEXUS_5,1.0,en].png | 4 ++-- ...iew_null_RoomListView-Night-3_5_null_9,NEXUS_5,1.0,en].png | 4 ++-- 94 files changed, 60 insertions(+), 36 deletions(-) delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Day-7_8_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Day-8_9_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Night-7_9_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Night-8_10_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Day-6_7_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Day-7_8_null,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Night-6_8_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Night-7_9_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_1,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_2,NEXUS_5,1.0,en].png rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Day-11_12_null,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_3,NEXUS_5,1.0,en].png} (100%) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_1,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_2,NEXUS_5,1.0,en].png rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Night-11_13_null,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_3,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryPlaceholderRow_null_RoomSummaryPlaceholderRow-Day-8_9_null,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryPlaceholderRow_null_RoomSummaryPlaceholderRow-Day-9_10_null,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryPlaceholderRow_null_RoomSummaryPlaceholderRow-Night-8_10_null,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryPlaceholderRow_null_RoomSummaryPlaceholderRow-Night-9_11_null,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_0,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_0,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_1,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_1,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_10,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_10,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_11,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_11,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_12,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_12,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_13,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_13,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_14,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_14,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_15,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_15,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_16,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_16,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_17,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_17,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_18,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_18,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_19,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_19,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_2,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_2,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_20,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_20,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_21,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_21,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_22,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_22,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_23,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_23,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_24,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_24,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_25,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_25,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_26,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_26,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_27,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_27,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_3,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_3,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_4,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_4,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_5,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_5,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_6,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_6,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_7,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_7,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_8,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_8,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_9,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_9,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_0,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_0,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_1,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_1,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_10,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_10,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_11,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_11,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_12,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_12,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_13,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_13,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_14,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_14,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_15,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_15,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_16,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_16,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_17,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_17,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_18,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_18,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_19,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_19,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_2,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_2,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_20,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_20,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_21,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_21,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_22,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_22,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_23,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_23,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_24,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_24,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_25,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_25,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_26,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_26,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_27,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_27,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_3,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_3,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_4,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_4,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_5,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_5,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_6,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_6,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_7,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_7,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_8,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_8,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_9,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_9,NEXUS_5,1.0,en].png} (100%) delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-10_11_null_0,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-10_11_null_1,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-11_12_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-11_12_null_1,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-10_12_null_0,NEXUS_5,1.0,en].png delete mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-10_12_null_1,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-11_13_null_0,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-11_13_null_1,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Day-12_13_null,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Night-12_14_null,NEXUS_5,1.0,en].png rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-12_13_null_0,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-13_14_null_0,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-12_13_null_1,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-13_14_null_1,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-12_14_null_0,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-13_15_null_0,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-12_14_null_1,NEXUS_5,1.0,en].png => ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-13_15_null_1,NEXUS_5,1.0,en].png} (100%) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Day-7_8_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Day-7_8_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 71bb3edfb9..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Day-7_8_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f29850d64823d7243ab2b6ec3f885fae2cf88aa763b18f96735094ebef9f19cd -size 36421 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Day-8_9_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Day-8_9_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..bbaee0b3b3 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Day-8_9_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d429c0ce8f4f34e7155775689bf8bc2efa61e83db6704e225592a2ea2c494b6 +size 48004 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Night-7_9_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Night-7_9_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 2d2f436468..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Night-7_9_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1f783da840d0b70462c9361cf5cd89f0c5636758925b99a4095ab82bab53fe10 -size 42000 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Night-8_10_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Night-8_10_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..0d738df47f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBarWithIndicator_null_DefaultRoomListTopBarWithIndicator-Night-8_10_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:855f3544c544966b8ff7a4a83f02feb9326e9dc80dd792f6749575045fe6c951 +size 52543 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Day-6_7_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Day-6_7_null,NEXUS_5,1.0,en].png deleted file mode 100644 index ad7aac5334..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Day-6_7_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7b036518dc3f7d67d97a747f98a2909ff39461b4219a184200abc4e49d83e38b -size 36041 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Day-7_8_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Day-7_8_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..5502bf853f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Day-7_8_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ec97a339d25fb7d0f928209567a81e13d65c2817ac21b372ff8573dc6d2f184 +size 47603 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Night-6_8_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Night-6_8_null,NEXUS_5,1.0,en].png deleted file mode 100644 index 2676f71941..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Night-6_8_null,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4743f2334377effb907c28b0bf0f550cd06f47f59ae6b71bf46de1299cf7c890 -size 41609 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Night-7_9_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Night-7_9_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..14edd4016d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_DefaultRoomListTopBar_null_DefaultRoomListTopBar-Night-7_9_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad5dee1ca507cbc94f4ba21141afb75c074766dc7ef25eaa13ea7f296bcd6e32 +size 52194 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..67eee6dc7a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9097d88f12cd44680cdcef752d45b12884217c65bac846d3007f16393b3d7233 +size 28036 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_1,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..8758ca3027 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_1,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01c07ac21d9ac4d9d916a4a15b27edc3d06f0f6206a736bc2ee5f0206c786523 +size 16006 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_2,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..016826429b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_2,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7dd6178952670e12aa6f581793102afe44854457360bff654d7ca6089c8450ec +size 20112 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Day-11_12_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_3,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Day-11_12_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_3,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..752c60afa4 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f4e503d1c883b1b1b5a98f979afc04a2bc65aa23ba674ca3b96bcab3d7888773 +size 27993 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_1,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..4cb9285f79 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_1,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ce4c893f2a0aa99384d16c531776604cbf2eab9040467f64b42a6e625fdb217 +size 15264 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_2,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..de981b0b85 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_2,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c2301c797291b295a3433e2d26e2ec485f9e3b0ea825dea8794bb06fe608c48 +size 19117 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Night-11_13_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_3,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Night-11_13_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_3,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryPlaceholderRow_null_RoomSummaryPlaceholderRow-Day-8_9_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryPlaceholderRow_null_RoomSummaryPlaceholderRow-Day-9_10_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryPlaceholderRow_null_RoomSummaryPlaceholderRow-Day-8_9_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryPlaceholderRow_null_RoomSummaryPlaceholderRow-Day-9_10_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryPlaceholderRow_null_RoomSummaryPlaceholderRow-Night-8_10_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryPlaceholderRow_null_RoomSummaryPlaceholderRow-Night-9_11_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryPlaceholderRow_null_RoomSummaryPlaceholderRow-Night-8_10_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryPlaceholderRow_null_RoomSummaryPlaceholderRow-Night-9_11_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_0,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_0,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_0,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_1,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_1,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_1,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_10,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_10,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_10,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_11,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_11,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_11,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_11,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_12,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_12,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_12,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_13,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_13,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_13,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_13,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_14,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_14,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_14,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_14,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_15,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_15,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_15,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_15,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_16,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_16,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_16,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_16,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_17,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_17,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_17,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_17,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_18,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_18,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_18,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_18,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_19,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_19,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_19,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_19,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_2,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_2,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_2,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_20,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_20,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_20,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_20,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_21,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_21,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_21,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_21,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_22,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_22,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_22,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_22,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_23,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_23,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_23,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_23,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_24,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_24,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_24,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_24,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_25,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_25,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_25,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_25,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_26,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_26,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_26,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_26,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_27,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_27,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_27,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_27,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_3,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_3,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_3,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_4,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_4,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_4,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_5,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_5,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_5,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_6,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_6,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_6,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_7,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_7,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_7,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_8,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_8,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_8,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_9,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-9_10_null_9,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Day-10_11_null_9,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_0,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_0,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_0,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_1,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_1,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_1,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_10,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_10,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_10,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_10,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_11,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_11,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_11,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_11,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_12,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_12,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_12,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_12,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_13,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_13,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_13,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_13,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_14,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_14,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_14,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_14,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_15,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_15,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_15,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_15,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_16,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_16,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_16,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_16,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_17,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_17,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_17,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_17,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_18,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_18,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_18,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_18,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_19,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_19,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_19,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_19,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_2,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_2,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_2,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_20,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_20,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_20,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_20,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_21,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_21,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_21,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_21,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_22,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_22,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_22,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_22,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_23,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_23,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_23,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_23,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_24,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_24,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_24,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_24,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_25,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_25,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_25,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_25,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_26,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_26,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_26,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_26,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_27,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_27,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_27,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_27,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_3,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_3,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_3,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_4,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_4,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_4,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_5,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_5,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_5,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_5,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_6,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_6,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_6,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_6,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_7,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_7,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_7,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_7,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_8,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_8,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_8,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_8,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_9,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-9_11_null_9,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomSummaryRow_null_RoomSummaryRow-Night-10_12_null_9,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-10_11_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-10_11_null_0,NEXUS_5,1.0,en].png deleted file mode 100644 index 4df8ca69f4..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-10_11_null_0,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0bb5af2c6ad9a295f48dd1e7dbb0df838e55c294ba941658a34356bf1066bf88 -size 15056 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-10_11_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-10_11_null_1,NEXUS_5,1.0,en].png deleted file mode 100644 index 38895fcaba..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-10_11_null_1,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:034ddb5e1a44b27f86f115741540e826b636d0130f44ea5afea41ada0cd42ea1 -size 14141 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-11_12_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-11_12_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..b8292e1095 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-11_12_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a7ba4a60d167eaf29fb05343cd0c9fcc7c1790be840504e438a15812ee0fd47 +size 15780 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-11_12_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-11_12_null_1,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..20473f8f40 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Day-11_12_null_1,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:13ea28681890a7ba8d8718782e6b29330de000d0643a5802be2468e8b8333a3d +size 14314 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-10_12_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-10_12_null_0,NEXUS_5,1.0,en].png deleted file mode 100644 index e8cdd870e8..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-10_12_null_0,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8022de099e17b4e247f7d7f009425afeea7dc9ff3d8381cf0462392259e04968 -size 14943 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-10_12_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-10_12_null_1,NEXUS_5,1.0,en].png deleted file mode 100644 index 8e5c5d0bd1..0000000000 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-10_12_null_1,NEXUS_5,1.0,en].png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:46aa240613c675c37f4152679c5103bdfc538238acc723952e311cd3a08666ae -size 13794 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-11_13_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-11_13_null_0,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..64c67a2a51 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-11_13_null_0,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:02cad5768bb49b824bcf93bf2e527531d5f252cd241a2067cceb3dd66a8f2ea8 +size 14902 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-11_13_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-11_13_null_1,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..2e7671de72 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.filters_RoomListFiltersView_null_RoomListFiltersView-Night-11_13_null_1,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:55161cf8679ff87887a87e7fe39e03227e528709c0d189b37e26ed5b1f9ff888 +size 12961 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Day-12_13_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Day-12_13_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..99a9e03973 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Day-12_13_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c9d9aa75b2b01e9b0106377fbcd88a92fb8b4d6a34323b18264fed8f9a48cab +size 133347 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Night-12_14_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Night-12_14_null,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..46a349cbce --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.migration_MigrationView_null_MigrationView-Night-12_14_null,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fea824bf7f4c74c827fa3c1fa892b9beeb9d11e0863fc9e5c104c725236c7d10 +size 156506 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-12_13_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-13_14_null_0,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-12_13_null_0,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-13_14_null_0,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-12_13_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-13_14_null_1,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-12_13_null_1,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Day-13_14_null_1,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-12_14_null_0,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-13_15_null_0,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-12_14_null_0,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-13_15_null_0,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-12_14_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-13_15_null_1,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-12_14_null_1,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.search_RoomListSearchResultContent_null_RoomListSearchResultContent-Night-13_15_null_1,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_11,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_11,NEXUS_5,1.0,en].png index 67c12d1f9e..23df601373 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_11,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_11,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec79bcbd77e37a9fe6fa2c553571ec2665f5fee666926e25d96f365705a7ad26 -size 136977 +oid sha256:0151879112a55b3b310aaf0ed33a4409597572bd78063f6617e8869d95cb5362 +size 137048 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_13,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_13,NEXUS_5,1.0,en].png index 0beb0e6949..19b6010d17 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_13,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_13,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d3a65168c2219a33bcdde4644522adb1dad4606ae4e2843d5df47d271aabe24a -size 74218 +oid sha256:46e28da384551af27bf9c52a45c17b8441f8875494b3d3fd901ad66f5d7ff89b +size 74803 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_9,NEXUS_5,1.0,en].png index 534122c6a6..6efd101dac 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_9,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Day-3_4_null_9,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f2117daf834ffabc8ca24e738c26436b2a4c8bc02e478b928e5bc9f472ae2ef6 -size 54995 +oid sha256:a0037f0401b53088f2a75af67f8e4df374866fbce80c052535af1d97354c9b22 +size 56605 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_11,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_11,NEXUS_5,1.0,en].png index bafefb3d7a..106eadb403 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_11,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_11,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa3ed3df422a194420b24e6cd36bc3d822ff205f99ade1e2166f837b91553237 -size 160352 +oid sha256:a9723e58db10eb39c1b63a4c916e9d5d6c22de934945eec20703ca43f0f189f8 +size 159766 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_13,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_13,NEXUS_5,1.0,en].png index 2a11b0fb05..52eccc7865 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_13,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_13,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5937fb0364f92fb2d5d6e2f4849d6725581903d0eff6c6c7c53b62430531eb4c -size 76907 +oid sha256:58ce650742396cd4addf9f545b2488bc2666e848b361a501d3ea2508c92c2a8a +size 76908 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_9,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_9,NEXUS_5,1.0,en].png index 1654802e05..9b8391501a 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_9,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl_RoomListView_null_RoomListView-Night-3_5_null_9,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7522060e94ab9a3c221b58c314e8f4680ce1aef07c1820995dd0ece8a3c4ecf -size 57179 +oid sha256:528d43fa1989f1368c33f4f447347caa2fefb92c3a0a1e48846974ad96f262de +size 58510 From 65fa3bf6a476ba16483cf5b53af4e4afe4314408 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 13 Mar 2024 12:44:59 +0100 Subject: [PATCH 09/11] Tests: raise default timeout of consumeItemsUntilPredicate to 3 seconds (like awaitItem) --- .../android/features/roomlist/impl/RoomListPresenterTests.kt | 3 +-- .../io/element/android/tests/testutils/ReceiveTurbine.kt | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt index aa89c4fac2..beffffa8ef 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt @@ -85,7 +85,6 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test -import kotlin.time.Duration.Companion.seconds class RoomListPresenterTests { @get:Rule @@ -167,7 +166,7 @@ class RoomListPresenterTests { moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { - val initialState = consumeItemsUntilPredicate(timeout = 3.seconds) { state -> state.contentState is RoomListContentState.Skeleton }.last() + val initialState = consumeItemsUntilPredicate { state -> state.contentState is RoomListContentState.Skeleton }.last() assertThat(initialState.contentState).isInstanceOf(RoomListContentState.Skeleton::class.java) roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1)) roomListService.postAllRooms( diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/ReceiveTurbine.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/ReceiveTurbine.kt index 0c8bd89951..abac27a14f 100644 --- a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/ReceiveTurbine.kt +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/ReceiveTurbine.kt @@ -22,6 +22,7 @@ import app.cash.turbine.withTurbineTimeout import io.element.android.libraries.core.bool.orFalse import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds /** * Consume all items until timeout is reached waiting for an event or we receive terminal event. @@ -48,7 +49,7 @@ suspend fun ReceiveTurbine.awaitLastSequentialItem(): T { * @return the list of consumed items. */ suspend fun ReceiveTurbine.consumeItemsUntilPredicate( - timeout: Duration = 100.milliseconds, + timeout: Duration = 3.seconds, ignoreTimeoutError: Boolean = false, predicate: (T) -> Boolean, ): List { From b368480aff32ba5de3c47f1f15ca981b424352f5 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 13 Mar 2024 15:25:36 +0100 Subject: [PATCH 10/11] RoomList : add some more tests --- .../impl/RoomListContentStateProvider.kt | 2 + .../impl/components/RoomListContentView.kt | 5 +- .../RoomListFiltersEmptyStateResourcesTest.kt | 75 +++++++++++++++++++ .../filters/RoomListFiltersPresenterTests.kt | 4 + 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEmptyStateResourcesTest.kt diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContentStateProvider.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContentStateProvider.kt index 7f066628df..284abb5d0f 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContentStateProvider.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContentStateProvider.kt @@ -19,11 +19,13 @@ package io.element.android.features.roomlist.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.roomlist.impl.model.RoomListRoomSummary import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf open class RoomListContentStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( aRoomsContentState(), + aRoomsContentState(summaries = persistentListOf()), aSkeletonContentState(), anEmptyContentState(), aMigrationContentState(), diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt index 1e3d66750f..1bb5af4e7a 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt @@ -56,6 +56,7 @@ import io.element.android.features.roomlist.impl.filters.RoomListFilter import io.element.android.features.roomlist.impl.filters.RoomListFiltersEmptyStateResources import io.element.android.features.roomlist.impl.filters.RoomListFiltersState import io.element.android.features.roomlist.impl.filters.aRoomListFiltersState +import io.element.android.features.roomlist.impl.filters.selection.FilterSelectionState import io.element.android.features.roomlist.impl.migration.MigrationScreenView import io.element.android.features.roomlist.impl.model.RoomListRoomSummary import io.element.android.libraries.designsystem.preview.ElementPreview @@ -311,7 +312,9 @@ private fun EmptyScaffold( internal fun RoomListContentViewPreview(@PreviewParameter(RoomListContentStateProvider::class) state: RoomListContentState) = ElementPreview { RoomListContentView( contentState = state, - filtersState = aRoomListFiltersState(), + filtersState = aRoomListFiltersState( + filterSelectionStates = RoomListFilter.entries.map { FilterSelectionState(it, isSelected = true) } + ), eventSink = {}, onVerifyClicked = { }, onConfirmRecoveryKeyClicked = { }, diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEmptyStateResourcesTest.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEmptyStateResourcesTest.kt new file mode 100644 index 0000000000..b9cdf5a03f --- /dev/null +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersEmptyStateResourcesTest.kt @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.roomlist.impl.filters + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.roomlist.impl.R +import org.junit.Test + +class RoomListFiltersEmptyStateResourcesTest { + @Test + fun `fromSelectedFilters should return null when selectedFilters is empty`() { + val selectedFilters = emptyList() + val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters) + assertThat(result).isNull() + } + + @Test + fun `fromSelectedFilters should return exact RoomListFiltersEmptyStateResources when selectedFilters has only unread filter`() { + val selectedFilters = listOf(RoomListFilter.Unread) + val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters) + assertThat(result).isNotNull() + assertThat(result?.title).isEqualTo(R.string.screen_roomlist_filter_unreads_empty_state_title) + assertThat(result?.subtitle).isEqualTo(R.string.screen_roomlist_filter_mixed_empty_state_subtitle) + } + + @Test + fun `fromSelectedFilters should return exact RoomListFiltersEmptyStateResources when selectedFilters has only people filter`() { + val selectedFilters = listOf(RoomListFilter.People) + val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters) + assertThat(result).isNotNull() + assertThat(result?.title).isEqualTo(R.string.screen_roomlist_filter_people_empty_state_title) + assertThat(result?.subtitle).isEqualTo(R.string.screen_roomlist_filter_mixed_empty_state_subtitle) + } + + @Test + fun `fromSelectedFilters should return exact RoomListFiltersEmptyStateResources when selectedFilters has only rooms filter`() { + val selectedFilters = listOf(RoomListFilter.Rooms) + val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters) + assertThat(result).isNotNull() + assertThat(result?.title).isEqualTo(R.string.screen_roomlist_filter_rooms_empty_state_title) + assertThat(result?.subtitle).isEqualTo(R.string.screen_roomlist_filter_mixed_empty_state_subtitle) + } + + @Test + fun `fromSelectedFilters should return exact RoomListFiltersEmptyStateResources when selectedFilters has only favourites filter`() { + val selectedFilters = listOf(RoomListFilter.Favourites) + val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters) + assertThat(result).isNotNull() + assertThat(result?.title).isEqualTo(R.string.screen_roomlist_filter_favourites_empty_state_title) + assertThat(result?.subtitle).isEqualTo(R.string.screen_roomlist_filter_favourites_empty_state_subtitle) + } + + @Test + fun `fromSelectedFilters should return exact RoomListFiltersEmptyStateResources when selectedFilters has multiple filters`() { + val selectedFilters = listOf(RoomListFilter.Unread, RoomListFilter.People, RoomListFilter.Rooms, RoomListFilter.Favourites) + val result = RoomListFiltersEmptyStateResources.fromSelectedFilters(selectedFilters) + assertThat(result).isNotNull() + assertThat(result?.title).isEqualTo(R.string.screen_roomlist_filter_mixed_empty_state_title) + assertThat(result?.subtitle).isEqualTo(R.string.screen_roomlist_filter_mixed_empty_state_subtitle) + } +} diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenterTests.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenterTests.kt index e1f806f247..756fe1aa0e 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenterTests.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/filters/RoomListFiltersPresenterTests.kt @@ -68,6 +68,9 @@ class RoomListFiltersPresenterTests { filterSelectionState(RoomListFilter.Favourites, false), ).inOrder() + assertThat(state.selectedFilters()).containsExactly( + RoomListFilter.Rooms, + ) val roomListCurrentFilter = roomListService.allRooms.currentFilter.value as MatrixRoomListFilter.All assertThat(roomListCurrentFilter.filters).containsExactly( MatrixRoomListFilter.Category.Group, @@ -82,6 +85,7 @@ class RoomListFiltersPresenterTests { filterSelectionState(RoomListFilter.Rooms, false), filterSelectionState(RoomListFilter.Favourites, false), ).inOrder() + assertThat(state.selectedFilters()).isEmpty() val roomListCurrentFilter = roomListService.allRooms.currentFilter.value as MatrixRoomListFilter.All assertThat(roomListCurrentFilter.filters).isEmpty() } From e1b8a220b99647b4c2eaabf28332e51c8dffdb4a Mon Sep 17 00:00:00 2001 From: ElementBot Date: Wed, 13 Mar 2024 14:32:39 +0000 Subject: [PATCH 11/11] Update screenshots --- ...ull_RoomListContentView-Day-6_7_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...ull_RoomListContentView-Day-6_7_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...ull_RoomListContentView-Day-6_7_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...ull_RoomListContentView-Day-6_7_null_4,NEXUS_5,1.0,en].png | 3 +++ ...l_RoomListContentView-Night-6_8_null_1,NEXUS_5,1.0,en].png | 4 ++-- ...l_RoomListContentView-Night-6_8_null_2,NEXUS_5,1.0,en].png | 4 ++-- ...l_RoomListContentView-Night-6_8_null_3,NEXUS_5,1.0,en].png | 4 ++-- ...l_RoomListContentView-Night-6_8_null_4,NEXUS_5,1.0,en].png | 3 +++ 8 files changed, 18 insertions(+), 12 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_4,NEXUS_5,1.0,en].png create mode 100644 tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_4,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_1,NEXUS_5,1.0,en].png index 8758ca3027..14ed38eba4 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:01c07ac21d9ac4d9d916a4a15b27edc3d06f0f6206a736bc2ee5f0206c786523 -size 16006 +oid sha256:8f99dc73a1c501c8f3e2a61cce1f479b35cdf75fa3909a8a282f396d9ac93237 +size 24013 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_2,NEXUS_5,1.0,en].png index 016826429b..8758ca3027 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7dd6178952670e12aa6f581793102afe44854457360bff654d7ca6089c8450ec -size 20112 +oid sha256:01c07ac21d9ac4d9d916a4a15b27edc3d06f0f6206a736bc2ee5f0206c786523 +size 16006 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_3,NEXUS_5,1.0,en].png index 99a9e03973..016826429b 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c9d9aa75b2b01e9b0106377fbcd88a92fb8b4d6a34323b18264fed8f9a48cab -size 133347 +oid sha256:7dd6178952670e12aa6f581793102afe44854457360bff654d7ca6089c8450ec +size 20112 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_4,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..99a9e03973 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Day-6_7_null_4,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c9d9aa75b2b01e9b0106377fbcd88a92fb8b4d6a34323b18264fed8f9a48cab +size 133347 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_1,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_1,NEXUS_5,1.0,en].png index 4cb9285f79..67d9d5a9aa 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_1,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_1,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ce4c893f2a0aa99384d16c531776604cbf2eab9040467f64b42a6e625fdb217 -size 15264 +oid sha256:30f05250641da8458b7891f881e6d50cd65f9e8d519672094df0ef7ed6c1afba +size 22795 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_2,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_2,NEXUS_5,1.0,en].png index de981b0b85..4cb9285f79 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_2,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_2,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3c2301c797291b295a3433e2d26e2ec485f9e3b0ea825dea8794bb06fe608c48 -size 19117 +oid sha256:7ce4c893f2a0aa99384d16c531776604cbf2eab9040467f64b42a6e625fdb217 +size 15264 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_3,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_3,NEXUS_5,1.0,en].png index 46a349cbce..de981b0b85 100644 --- a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_3,NEXUS_5,1.0,en].png +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_3,NEXUS_5,1.0,en].png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fea824bf7f4c74c827fa3c1fa892b9beeb9d11e0863fc9e5c104c725236c7d10 -size 156506 +oid sha256:3c2301c797291b295a3433e2d26e2ec485f9e3b0ea825dea8794bb06fe608c48 +size 19117 diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_4,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_4,NEXUS_5,1.0,en].png new file mode 100644 index 0000000000..46a349cbce --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/ui_S_t[f.roomlist.impl.components_RoomListContentView_null_RoomListContentView-Night-6_8_null_4,NEXUS_5,1.0,en].png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fea824bf7f4c74c827fa3c1fa892b9beeb9d11e0863fc9e5c104c725236c7d10 +size 156506