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(
previous: State,
fragmentClass: Class<out Fragment>,
val childId: String
val childId: String,
val previousOverview: Overview
): FragmentStateLegacy(previous, fragmentClass) {
class Main(
val previousOverview: Overview,
previousOverview: Overview,
childId: String,
fromRedirect: Boolean
): ManageChild(previous = previousOverview, ManageChildFragment::class.java, childId = childId) {
): ManageChild(previous = previousOverview, ManageChildFragment::class.java, childId = childId, previousOverview = previousOverview) {
@Transient
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
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
override val arguments: Bundle = ChildAdvancedFragmentWrapperArgs(previousChild.childId).toBundle()
}
class Contacts(val previousChild: Main): ManageChild(previousChild, ContactsFragment::class.java, previousChild.childId)
class UsageHistory(val previousChild: Main): ManageChild(previousChild, ChildUsageHistoryFragmentWrapper::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, previousChild.previousOverview) {
@Transient
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
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(
val previousChild: ManageChild.Main,
previousChild: ManageChild.Main,
val categoryId: String
): ManageCategory(previous = previousChild, fragmentClass = ManageCategoryFragment::class.java, previousChild.childId) {
): ManageCategory(previous = previousChild, fragmentClass = ManageCategoryFragment::class.java, previousChild) {
@Transient
override val arguments: Bundle = ManageCategoryFragmentArgs(
childId = previousChild.childId,
@ -147,7 +148,7 @@ sealed class State (val previous: State?): Serializable {
class BlockedTimes(
val previousCategory: Main
): ManageCategory(previous = previousCategory, fragmentClass = BlockedTimeAreasFragmentWrapper::class.java, childId = previousCategory.childId) {
): ManageCategory(previous = previousCategory, fragmentClass = BlockedTimeAreasFragmentWrapper::class.java, previousChild = previousCategory.previousChild) {
@Transient
override val arguments: Bundle = BlockedTimeAreasFragmentWrapperArgs(
childId = previousCategory.previousChild.childId,
@ -157,7 +158,7 @@ sealed class State (val previous: State?): Serializable {
class Advanced(
val previousCategory: Main
): ManageCategory(previous = previousCategory, fragmentClass = CategoryAdvancedFragmentWrapper::class.java, childId = previousCategory.childId) {
): ManageCategory(previous = previousCategory, fragmentClass = CategoryAdvancedFragmentWrapper::class.java, previousChild = previousCategory.previousChild) {
@Transient
override val arguments: Bundle = CategoryAdvancedFragmentWrapperArgs(
childId = previousCategory.previousChild.childId,

View file

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

View file

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