Refactor ManageChildHandling

This commit is contained in:
Jonas Lochmann 2023-02-27 01:00:00 +01:00
parent a33cdb34e4
commit 4e85a656c5
No known key found for this signature in database
GPG key ID: 8B8C9AEE10FA5B36
3 changed files with 70 additions and 59 deletions

View file

@ -77,13 +77,14 @@ sealed class State (val previous: State?): Serializable {
sealed class ManageChild( sealed class ManageChild(
previous: State, previous: State,
fragmentClass: Class<out Fragment>, fragmentClass: Class<out Fragment>,
val childId: String val childId: String,
val previousOverview: Overview
): FragmentStateLegacy(previous, fragmentClass) { ): FragmentStateLegacy(previous, fragmentClass) {
class Main( class Main(
val previousOverview: Overview, previousOverview: Overview,
childId: String, childId: String,
fromRedirect: Boolean fromRedirect: Boolean
): ManageChild(previous = previousOverview, ManageChildFragment::class.java, childId = childId) { ): ManageChild(previous = previousOverview, ManageChildFragment::class.java, childId = childId, previousOverview = previousOverview) {
@Transient @Transient
override val arguments = ManageChildFragmentArgs(childId = childId, fromRedirect = fromRedirect).toBundle() override val arguments = ManageChildFragmentArgs(childId = childId, fromRedirect = fromRedirect).toBundle()
@ -109,29 +110,29 @@ sealed class State (val previous: State?): Serializable {
) )
} }
class Apps(val previousChild: Main): ManageChild(previousChild, ChildAppsFragmentWrapper::class.java, previousChild.childId) { class Apps(val previousChild: Main): ManageChild(previousChild, ChildAppsFragmentWrapper::class.java, previousChild.childId, previousChild.previousOverview) {
@Transient @Transient
override val arguments: Bundle = ChildAppsFragmentWrapperArgs(previousChild.childId).toBundle() override val arguments: Bundle = ChildAppsFragmentWrapperArgs(previousChild.childId).toBundle()
} }
class Advanced(val previousChild: Main): ManageChild(previousChild, ChildAdvancedFragmentWrapper::class.java, previousChild.childId) { class Advanced(val previousChild: Main): ManageChild(previousChild, ChildAdvancedFragmentWrapper::class.java, previousChild.childId, previousChild.previousOverview) {
@Transient @Transient
override val arguments: Bundle = ChildAdvancedFragmentWrapperArgs(previousChild.childId).toBundle() override val arguments: Bundle = ChildAdvancedFragmentWrapperArgs(previousChild.childId).toBundle()
} }
class Contacts(val previousChild: Main): ManageChild(previousChild, ContactsFragment::class.java, previousChild.childId) class Contacts(val previousChild: Main): ManageChild(previousChild, ContactsFragment::class.java, previousChild.childId, previousChild.previousOverview)
class UsageHistory(val previousChild: Main): ManageChild(previousChild, ChildUsageHistoryFragmentWrapper::class.java, previousChild.childId) { class UsageHistory(val previousChild: Main): ManageChild(previousChild, ChildUsageHistoryFragmentWrapper::class.java, previousChild.childId, previousChild.previousOverview) {
@Transient @Transient
override val arguments: Bundle = ChildUsageHistoryFragmentWrapperArgs(previousChild.childId).toBundle() override val arguments: Bundle = ChildUsageHistoryFragmentWrapperArgs(previousChild.childId).toBundle()
} }
class Tasks(val previousChild: Main): ManageChild(previousChild, ChildTasksFragmentWrapper::class.java, previousChild.childId) { class Tasks(val previousChild: Main): ManageChild(previousChild, ChildTasksFragmentWrapper::class.java, previousChild.childId, previousChild.previousOverview) {
@Transient @Transient
override val arguments: Bundle = ChildTasksFragmentWrapperArgs(previousChild.childId).toBundle() override val arguments: Bundle = ChildTasksFragmentWrapperArgs(previousChild.childId).toBundle()
} }
sealed class ManageCategory(previous: State, fragmentClass: Class<out Fragment>, childId: String): ManageChild(previous, fragmentClass, childId) { sealed class ManageCategory(previous: State, fragmentClass: Class<out Fragment>, val previousChild: ManageChild.Main): ManageChild(previous, fragmentClass, previousChild.childId, previousChild.previousOverview) {
class Main( class Main(
val previousChild: ManageChild.Main, previousChild: ManageChild.Main,
val categoryId: String val categoryId: String
): ManageCategory(previous = previousChild, fragmentClass = ManageCategoryFragment::class.java, previousChild.childId) { ): ManageCategory(previous = previousChild, fragmentClass = ManageCategoryFragment::class.java, previousChild) {
@Transient @Transient
override val arguments: Bundle = ManageCategoryFragmentArgs( override val arguments: Bundle = ManageCategoryFragmentArgs(
childId = previousChild.childId, childId = previousChild.childId,
@ -147,7 +148,7 @@ sealed class State (val previous: State?): Serializable {
class BlockedTimes( class BlockedTimes(
val previousCategory: Main val previousCategory: Main
): ManageCategory(previous = previousCategory, fragmentClass = BlockedTimeAreasFragmentWrapper::class.java, childId = previousCategory.childId) { ): ManageCategory(previous = previousCategory, fragmentClass = BlockedTimeAreasFragmentWrapper::class.java, previousChild = previousCategory.previousChild) {
@Transient @Transient
override val arguments: Bundle = BlockedTimeAreasFragmentWrapperArgs( override val arguments: Bundle = BlockedTimeAreasFragmentWrapperArgs(
childId = previousCategory.previousChild.childId, childId = previousCategory.previousChild.childId,
@ -157,7 +158,7 @@ sealed class State (val previous: State?): Serializable {
class Advanced( class Advanced(
val previousCategory: Main val previousCategory: Main
): ManageCategory(previous = previousCategory, fragmentClass = CategoryAdvancedFragmentWrapper::class.java, childId = previousCategory.childId) { ): ManageCategory(previous = previousCategory, fragmentClass = CategoryAdvancedFragmentWrapper::class.java, previousChild = previousCategory.previousChild) {
@Transient @Transient
override val arguments: Bundle = CategoryAdvancedFragmentWrapperArgs( override val arguments: Bundle = CategoryAdvancedFragmentWrapperArgs(
childId = previousCategory.previousChild.childId, childId = previousCategory.previousChild.childId,

View file

@ -34,6 +34,8 @@ class CaseScope<LocalStateType>(
else oldState else oldState
} }
} }
fun <T> share(flow: Flow<T>): SharedFlow<T> = flow.shareIn(scope, SharingStarted.Lazily, 1)
} }
class Case<T, R>( class Case<T, R>(

View file

@ -16,7 +16,7 @@
package io.timelimit.android.ui.model.managechild package io.timelimit.android.ui.model.managechild
import io.timelimit.android.R import io.timelimit.android.R
import io.timelimit.android.data.model.UserType import io.timelimit.android.data.model.User
import io.timelimit.android.logic.AppLogic import io.timelimit.android.logic.AppLogic
import io.timelimit.android.ui.model.BackStackItem import io.timelimit.android.ui.model.BackStackItem
import io.timelimit.android.ui.model.Screen import io.timelimit.android.ui.model.Screen
@ -31,64 +31,72 @@ object ManageChildHandling {
logic: AppLogic, logic: AppLogic,
state: Flow<State.ManageChild>, state: Flow<State.ManageChild>,
updateState: ((State.ManageChild) -> State) -> Unit updateState: ((State.ManageChild) -> State) -> Unit
) = state.splitConflated( ): Flow<Screen> = state.splitConflated(
Case.simple<_, _, State.ManageChild.Main> { processMainState(logic, it, updateMethod(updateState)) }, Case.withKey<_, _, State.ManageChild, _>(
Case.simple<_, _, State.ManageChild.Apps> { processAppsState(logic, it, updateMethod(updateState)) } withKey = { it.childId },
producer = { childId, state2 ->
val state3 = share(state2)
val userLive = logic.database.user().getUserByIdFlow(childId)
val hasUserLive = userLive.map { it != null }.distinctUntilChanged()
val foundUserLive = userLive.filterNotNull()
val baseBackStackLive = state3.map { state ->
listOf(
BackStackItem(
Title.StringResource(R.string.main_tab_overview)
) { updateState { state.previousOverview } }
)
}
hasUserLive.transformLatest { hasUser ->
if (hasUser) emitAll(state3.splitConflated(
Case.simple<_, _, State.ManageChild.Main> { processMainState(it, baseBackStackLive, foundUserLive) },
Case.simple<_, _, State.ManageChild.Apps> { processAppsState(share(it), baseBackStackLive, foundUserLive, updateMethod(updateState)) }
))
else updateState { it.previousOverview }
}
}
)
) )
private fun processMainState( private fun processMainState(
logic: AppLogic,
stateLive: Flow<State.ManageChild.Main>, stateLive: Flow<State.ManageChild.Main>,
updateState: ((State.ManageChild.Main) -> State) -> Unit baseBackStackLive: Flow<List<BackStackItem>>,
): Flow<Screen> { userLive: Flow<User>
return stateLive.transformLatest { state -> ): Flow<Screen> = combine(stateLive, baseBackStackLive, userLive) { state, backStack, user ->
val userLive = logic.database.user().getUserByIdFlow(state.childId) Screen.ManageChildScreen(
emitAll(userLive.transform {user ->
if (user?.type != UserType.Child) updateState { state.previousOverview }
else emit(Screen.ManageChildScreen(
state, state,
state.toolbarIcons, state.toolbarIcons,
state.toolbarOptions, state.toolbarOptions,
state, state,
R.id.fragment_manage_child, R.id.fragment_manage_child,
user.name, user.name,
listOf( backStack
BackStackItem(
Title.StringResource(R.string.main_tab_overview)
) { updateState { state.previousOverview } }
) )
))
})
}
} }
private fun processAppsState( private fun processAppsState(
logic: AppLogic, stateLive: SharedFlow<State.ManageChild.Apps>,
stateLive: Flow<State.ManageChild.Apps>, baseBackStackLive: Flow<List<BackStackItem>>,
userLive: Flow<User>,
updateState: ((State.ManageChild.Apps) -> State) -> Unit updateState: ((State.ManageChild.Apps) -> State) -> Unit
): Flow<Screen> { ): Flow<Screen> {
return stateLive.transformLatest { state -> val subBackStackLive = combine(stateLive, baseBackStackLive, userLive) { state, baseBackStack, user ->
val userLive = logic.database.user().getUserByIdFlow(state.childId) baseBackStack + BackStackItem(
Title.Plain(user.name)
) { updateState { state.previousChild } }
}
emitAll(userLive.transform {user -> return stateLive.combine(subBackStackLive) { state, backStack ->
if (user?.type != UserType.Child) updateState { state.previousChild.previousOverview } Screen.ManageChildAppsScreen(
else emit(Screen.ManageChildAppsScreen(
state, state,
state.toolbarIcons, state.toolbarIcons,
state.toolbarOptions, state.toolbarOptions,
state, state,
R.id.fragment_manage_child_apps, R.id.fragment_manage_child_apps,
listOf( backStack
BackStackItem(
Title.StringResource(R.string.main_tab_overview)
) { updateState { state.previousChild.previousOverview } },
BackStackItem(
Title.Plain(user.name)
) { updateState { state.previousChild } }
) )
))
})
} }
} }
} }