diff --git a/mail-category-view/presentation/src/main/kotlin/ch/protonmail/android/mailcategory/presentation/model/CategoryViewState.kt b/mail-category-view/presentation/src/main/kotlin/ch/protonmail/android/mailcategory/presentation/model/CategoryViewState.kt index bd48725edd..0249ebabb0 100644 --- a/mail-category-view/presentation/src/main/kotlin/ch/protonmail/android/mailcategory/presentation/model/CategoryViewState.kt +++ b/mail-category-view/presentation/src/main/kotlin/ch/protonmail/android/mailcategory/presentation/model/CategoryViewState.kt @@ -18,13 +18,16 @@ package ch.protonmail.android.mailcategory.presentation.model +import ch.protonmail.android.mailcommon.presentation.Effect + sealed interface CategoryViewState { sealed interface Available : CategoryViewState { data object Loading : Available data class Data( - val categories: List + val categories: List, + val resetScrollEffect: Effect = Effect.empty() ) : Available } diff --git a/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/MailboxStickyHeader.kt b/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/MailboxStickyHeader.kt index d39d2c4538..9cdf30c192 100644 --- a/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/MailboxStickyHeader.kt +++ b/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/MailboxStickyHeader.kt @@ -36,6 +36,7 @@ import ch.protonmail.android.design.compose.theme.ProtonDimens import ch.protonmail.android.mailcategory.presentation.CategoryViewMenu import ch.protonmail.android.mailcategory.presentation.model.CategoryItemUiModel import ch.protonmail.android.mailcategory.presentation.model.CategoryViewState +import ch.protonmail.android.mailcommon.presentation.ConsumableLaunchedEffect import ch.protonmail.android.mailcommon.presentation.compose.MailDimens import ch.protonmail.android.mailmailbox.presentation.mailbox.model.MailboxListState import ch.protonmail.android.mailmailbox.presentation.mailbox.model.MailboxState @@ -50,6 +51,13 @@ fun MailboxStickyHeader( actions: MailboxStickyHeader.Actions, isCategoryViewEnabled: Boolean ) { + val horizontalScrollState = rememberScrollState() + + (state.categoryViewState as? CategoryViewState.Available.Data)?.let { categoryViewData -> + ConsumableLaunchedEffect(effect = categoryViewData.resetScrollEffect) { + horizontalScrollState.animateScrollTo(0) + } + } val isCategoryViewVisible = isCategoryViewEnabled && @@ -78,7 +86,7 @@ fun MailboxStickyHeader( bottom = bottomPadding, top = 0.dp ) - .horizontalScroll(rememberScrollState()), + .horizontalScroll(horizontalScrollState), horizontalArrangement = Arrangement.Start ) { if (state.mailboxListState is MailboxListState.Data.SelectionMode) { diff --git a/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/MailboxViewModel.kt b/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/MailboxViewModel.kt index 0fef5ffe37..0b3ba80df0 100644 --- a/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/MailboxViewModel.kt +++ b/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/MailboxViewModel.kt @@ -347,6 +347,14 @@ class MailboxViewModel @Inject constructor( } .launchIn(viewModelScope) + primaryUserId + .distinctUntilChanged() + .drop(1) + .onEach { + emitNewStateFrom(MailboxEvent.PrimaryAccountChanged) + } + .launchIn(viewModelScope) + observePrimaryAccountAvatarItem().onEach { item -> emitNewStateFrom(MailboxEvent.PrimaryAccountAvatarChanged(item)) }.launchIn(viewModelScope) diff --git a/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/model/MailboxOperation.kt b/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/model/MailboxOperation.kt index 46ecad6009..94ffd48326 100644 --- a/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/model/MailboxOperation.kt +++ b/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/model/MailboxOperation.kt @@ -299,6 +299,8 @@ internal sealed interface MailboxEvent : MailboxOperation { data class PrimaryAccountAvatarChanged(val item: CoreAccountAvatarItem?) : MailboxEvent, AffectingTopAppBar + data object PrimaryAccountChanged : MailboxEvent, AffectingCategoryView + data class LoadingBarStateUpdated(val state: LoadingBarUiState) : MailboxEvent, AffectingMailboxList data class PaginatorInvalidated(val event: PageInvalidationEvent) : MailboxEvent, AffectingMailboxList diff --git a/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxCategoryViewReducer.kt b/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxCategoryViewReducer.kt index 35e87f36b8..941dd50a96 100644 --- a/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxCategoryViewReducer.kt +++ b/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxCategoryViewReducer.kt @@ -19,8 +19,8 @@ package ch.protonmail.android.mailmailbox.presentation.mailbox.reducer import ch.protonmail.android.mailcategory.presentation.mapper.CategoryViewUiModelMapper -import ch.protonmail.android.mailcategory.presentation.mapper.toUiModel import ch.protonmail.android.mailcategory.presentation.model.CategoryViewState +import ch.protonmail.android.mailcommon.presentation.Effect import ch.protonmail.android.mailmailbox.presentation.mailbox.model.MailboxEvent import ch.protonmail.android.mailmailbox.presentation.mailbox.model.MailboxOperation import javax.inject.Inject @@ -29,12 +29,24 @@ class MailboxCategoryViewReducer @Inject constructor( private val categoryViewUiModelMapper: CategoryViewUiModelMapper ) { - internal fun newStateFrom(operation: MailboxOperation.AffectingCategoryView): CategoryViewState { + internal fun newStateFrom( + currentState: CategoryViewState, + operation: MailboxOperation.AffectingCategoryView + ): CategoryViewState { return when (operation) { - is MailboxEvent.CategoryViewStatusChanged -> { categoryViewUiModelMapper.toUiModel(operation.categoryViewStatus) } + + MailboxEvent.PrimaryAccountChanged -> { + when (currentState) { + is CategoryViewState.Available.Data -> { + currentState.copy(resetScrollEffect = Effect.of(Unit)) + } + + else -> currentState + } + } } } } diff --git a/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxReducer.kt b/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxReducer.kt index 650e7c4e46..770a844800 100644 --- a/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxReducer.kt +++ b/mail-mailbox/presentation/src/main/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxReducer.kt @@ -76,7 +76,7 @@ class MailboxReducer @Inject constructor( private fun MailboxState.toNewCategoryViewStateFrom(operation: MailboxOperation): CategoryViewState { return if (operation is MailboxOperation.AffectingCategoryView) { - categoryViewReducer.newStateFrom(operation) + categoryViewReducer.newStateFrom(this.categoryViewState, operation) } else { categoryViewState } diff --git a/mail-mailbox/presentation/src/test/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxCategoryViewReducerTest.kt b/mail-mailbox/presentation/src/test/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxCategoryViewReducerTest.kt index 2ca5f8be61..7ed90af866 100644 --- a/mail-mailbox/presentation/src/test/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxCategoryViewReducerTest.kt +++ b/mail-mailbox/presentation/src/test/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxCategoryViewReducerTest.kt @@ -21,7 +21,9 @@ package ch.protonmail.android.mailmailbox.presentation.mailbox.reducer import ch.protonmail.android.mailcategory.domain.model.CategoryViewStatus import ch.protonmail.android.mailcategory.presentation.mapper.CategoryViewUiModelMapper import ch.protonmail.android.mailcategory.presentation.mapper.toUiModel +import ch.protonmail.android.mailcategory.presentation.sample.CategoryItemUiModelSample import ch.protonmail.android.mailcategory.presentation.model.CategoryViewState +import ch.protonmail.android.mailcommon.presentation.Effect import ch.protonmail.android.mailmailbox.presentation.mailbox.model.MailboxEvent import io.mockk.every import io.mockk.mockk @@ -40,6 +42,7 @@ class MailboxCategoryViewReducerTest { fun `should map category view status changed event to category view state`() { // Given val categoryViewStatus = mockk() + val currentState = mockk() val expectedState = mockk() every { @@ -51,9 +54,25 @@ class MailboxCategoryViewReducerTest { ) // When - val actual = reducer.newStateFrom(operation) + val actual = reducer.newStateFrom(currentState, operation) // Then assertEquals(expectedState, actual) } + + @Test + fun `should emit reset scroll effect when primary account changes and category view is available data`() { + // Given + val currentState = CategoryViewState.Available.Data( + categories = CategoryItemUiModelSample.all, + resetScrollEffect = Effect.empty() + ) + + // When + val actual = reducer.newStateFrom(currentState, MailboxEvent.PrimaryAccountChanged) + + // Then + assertEquals(CategoryItemUiModelSample.all, (actual as CategoryViewState.Available.Data).categories) + assertEquals(Unit, actual.resetScrollEffect.consume()) + } } diff --git a/mail-mailbox/presentation/src/test/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxReducerTest.kt b/mail-mailbox/presentation/src/test/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxReducerTest.kt index 5430188633..cdc54afa54 100644 --- a/mail-mailbox/presentation/src/test/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxReducerTest.kt +++ b/mail-mailbox/presentation/src/test/kotlin/ch/protonmail/android/mailmailbox/presentation/mailbox/reducer/MailboxReducerTest.kt @@ -93,7 +93,7 @@ internal class MailboxReducerTest( } private val categoryViewReducer: MailboxCategoryViewReducer = mockk { - every { newStateFrom(any()) } returns reducedState.categoryViewState + every { newStateFrom(any(), any()) } returns reducedState.categoryViewState } private val mailboxReducer = MailboxReducer(