diff --git a/app/src/main/java/io/timelimit/android/ui/model/State.kt b/app/src/main/java/io/timelimit/android/ui/model/State.kt index 194462a..a8ce772 100644 --- a/app/src/main/java/io/timelimit/android/ui/model/State.kt +++ b/app/src/main/java/io/timelimit/android/ui/model/State.kt @@ -77,13 +77,14 @@ sealed class State (val previous: State?): Serializable { sealed class ManageChild( previous: State, fragmentClass: Class, - 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, childId: String): ManageChild(previous, fragmentClass, childId) { + sealed class ManageCategory(previous: State, fragmentClass: Class, 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, diff --git a/app/src/main/java/io/timelimit/android/ui/model/flow/SplitFlow.kt b/app/src/main/java/io/timelimit/android/ui/model/flow/SplitFlow.kt index 02173d9..7bc231d 100644 --- a/app/src/main/java/io/timelimit/android/ui/model/flow/SplitFlow.kt +++ b/app/src/main/java/io/timelimit/android/ui/model/flow/SplitFlow.kt @@ -34,6 +34,8 @@ class CaseScope( else oldState } } + + fun share(flow: Flow): SharedFlow = flow.shareIn(scope, SharingStarted.Lazily, 1) } class Case( diff --git a/app/src/main/java/io/timelimit/android/ui/model/managechild/ManageChildHandling.kt b/app/src/main/java/io/timelimit/android/ui/model/managechild/ManageChildHandling.kt index 8cf5be2..79e4360 100644 --- a/app/src/main/java/io/timelimit/android/ui/model/managechild/ManageChildHandling.kt +++ b/app/src/main/java/io/timelimit/android/ui/model/managechild/ManageChildHandling.kt @@ -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, 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 = 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, - updateState: ((State.ManageChild.Main) -> State) -> Unit - ): Flow { - 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, + baseBackStackLive: Flow>, + userLive: Flow + ): Flow = 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, + stateLive: SharedFlow, + baseBackStackLive: Flow>, + userLive: Flow, updateState: ((State.ManageChild.Apps) -> State) -> Unit ): Flow { - 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 + ) } } } \ No newline at end of file