mirror of
https://github.com/ProtonMail/android-mail.git
synced 2026-06-14 09:54:47 +00:00
Reset category header scroll state on account switch
- ensure category bar returns to default position after account change
- added PrimaryAccountChanged event
ET-6232
This commit is contained in:
+4
-1
@@ -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<CategoryItemUiModel>
|
||||
val categories: List<CategoryItemUiModel>,
|
||||
val resetScrollEffect: Effect<Unit> = Effect.empty()
|
||||
) : Available
|
||||
}
|
||||
|
||||
|
||||
+9
-1
@@ -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) {
|
||||
|
||||
+8
@@ -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)
|
||||
|
||||
+2
@@ -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
|
||||
|
||||
+15
-3
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
|
||||
+20
-1
@@ -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<CategoryViewStatus>()
|
||||
val currentState = mockk<CategoryViewState>()
|
||||
val expectedState = mockk<CategoryViewState>()
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user