DI: rework how components are created and provided
This commit is contained in:
parent
d9113448b6
commit
1a14a18a29
13 changed files with 120 additions and 128 deletions
|
|
@ -31,12 +31,13 @@ import com.bumble.appyx.core.plugin.plugins
|
|||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import io.element.android.anvilannotations.ContributesNode
|
||||
import io.element.android.appnav.di.SessionComponentFactory
|
||||
import io.element.android.libraries.architecture.NodeInputs
|
||||
import io.element.android.libraries.architecture.bindings
|
||||
import io.element.android.libraries.architecture.createNode
|
||||
import io.element.android.libraries.architecture.inputs
|
||||
import io.element.android.libraries.architecture.waitForChildAttached
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.DaggerComponentOwner
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.ui.di.MatrixUIBindings
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
|
@ -50,6 +51,7 @@ import kotlinx.parcelize.Parcelize
|
|||
class LoggedInAppScopeFlowNode @AssistedInject constructor(
|
||||
@Assisted buildContext: BuildContext,
|
||||
@Assisted plugins: List<Plugin>,
|
||||
sessionComponentFactory: SessionComponentFactory,
|
||||
) : ParentNode<LoggedInAppScopeFlowNode.NavTarget>(
|
||||
navModel = PermanentNavModel(
|
||||
navTargets = setOf(NavTarget),
|
||||
|
|
@ -57,7 +59,7 @@ class LoggedInAppScopeFlowNode @AssistedInject constructor(
|
|||
),
|
||||
buildContext = buildContext,
|
||||
plugins = plugins
|
||||
) {
|
||||
), DaggerComponentOwner {
|
||||
interface Callback : Plugin {
|
||||
fun onOpenBugReport()
|
||||
}
|
||||
|
|
@ -65,29 +67,20 @@ class LoggedInAppScopeFlowNode @AssistedInject constructor(
|
|||
@Parcelize
|
||||
object NavTarget : Parcelable
|
||||
|
||||
interface LifecycleCallback : NodeLifecycleCallback {
|
||||
fun onFlowCreated(identifier: String, client: MatrixClient)
|
||||
|
||||
fun onFlowReleased(identifier: String, client: MatrixClient)
|
||||
}
|
||||
|
||||
data class Inputs(
|
||||
val matrixClient: MatrixClient
|
||||
) : NodeInputs
|
||||
|
||||
private val inputs: Inputs = inputs()
|
||||
override val daggerComponent = sessionComponentFactory.create(inputs.matrixClient)
|
||||
|
||||
override fun onBuilt() {
|
||||
super.onBuilt()
|
||||
lifecycle.subscribe(
|
||||
onCreate = {
|
||||
plugins<LifecycleCallback>().forEach { it.onFlowCreated(id, inputs.matrixClient) }
|
||||
val imageLoaderFactory = bindings<MatrixUIBindings>().loggedInImageLoaderFactory()
|
||||
Coil.setImageLoader(imageLoaderFactory)
|
||||
},
|
||||
onDestroy = {
|
||||
plugins<LifecycleCallback>().forEach { it.onFlowReleased(id, inputs.matrixClient) }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -97,13 +90,10 @@ class LoggedInAppScopeFlowNode @AssistedInject constructor(
|
|||
plugins<Callback>().forEach { it.onOpenBugReport() }
|
||||
}
|
||||
}
|
||||
val nodeLifecycleCallbacks = plugins<NodeLifecycleCallback>()
|
||||
return createNode<LoggedInFlowNode>(buildContext, nodeLifecycleCallbacks + callback)
|
||||
return createNode<LoggedInFlowNode>(buildContext, listOf(callback))
|
||||
}
|
||||
|
||||
suspend fun attachSession(): LoggedInFlowNode {
|
||||
return waitForChildAttached { _ -> true }
|
||||
}
|
||||
suspend fun attachSession(): LoggedInFlowNode = waitForChildAttached()
|
||||
|
||||
@Composable
|
||||
override fun View(modifier: Modifier) {
|
||||
|
|
|
|||
|
|
@ -227,14 +227,13 @@ class LoggedInFlowNode @AssistedInject constructor(
|
|||
.build()
|
||||
}
|
||||
is NavTarget.Room -> {
|
||||
val nodeLifecycleCallbacks = plugins<NodeLifecycleCallback>()
|
||||
val callback = object : RoomLoadedFlowNode.Callback {
|
||||
override fun onForwardedToSingleRoom(roomId: RoomId) {
|
||||
coroutineScope.launch { attachRoom(roomId) }
|
||||
}
|
||||
}
|
||||
val inputs = RoomFlowNode.Inputs(roomId = navTarget.roomId, initialElement = navTarget.initialElement)
|
||||
createNode<RoomFlowNode>(buildContext, plugins = listOf(inputs, callback) + nodeLifecycleCallbacks)
|
||||
createNode<RoomFlowNode>(buildContext, plugins = listOf(inputs, callback))
|
||||
}
|
||||
NavTarget.Settings -> {
|
||||
val callback = object : PreferencesEntryPoint.Callback {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ import com.bumble.appyx.core.modality.BuildContext
|
|||
import com.bumble.appyx.core.node.Node
|
||||
import com.bumble.appyx.core.node.node
|
||||
import com.bumble.appyx.core.plugin.Plugin
|
||||
import com.bumble.appyx.core.plugin.plugins
|
||||
import com.bumble.appyx.core.state.MutableSavedStateMap
|
||||
import com.bumble.appyx.navmodel.backstack.BackStack
|
||||
import com.bumble.appyx.navmodel.backstack.operation.pop
|
||||
|
|
@ -196,8 +195,7 @@ class RootFlowNode @AssistedInject constructor(
|
|||
backstack.push(NavTarget.BugReport)
|
||||
}
|
||||
}
|
||||
val nodeLifecycleCallbacks = plugins<NodeLifecycleCallback>()
|
||||
createNode<LoggedInAppScopeFlowNode>(buildContext, plugins = listOf(inputs, callback) + nodeLifecycleCallbacks)
|
||||
createNode<LoggedInAppScopeFlowNode>(buildContext, plugins = listOf(inputs, callback))
|
||||
}
|
||||
NavTarget.NotLoggedInFlow -> createNode<NotLoggedInFlowNode>(buildContext)
|
||||
NavTarget.SplashScreen -> splashNode(buildContext)
|
||||
|
|
|
|||
|
|
@ -14,8 +14,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.appnav
|
||||
package io.element.android.appnav.di
|
||||
|
||||
import com.bumble.appyx.core.plugin.Plugin
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
|
||||
interface NodeLifecycleCallback : Plugin
|
||||
interface RoomComponentFactory {
|
||||
fun create(room: MatrixRoom): Any
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.appnav.di
|
||||
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
|
||||
interface SessionComponentFactory {
|
||||
fun create(client: MatrixClient): Any
|
||||
}
|
||||
|
|
@ -36,7 +36,6 @@ import com.bumble.appyx.navmodel.backstack.operation.newRoot
|
|||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import io.element.android.anvilannotations.ContributesNode
|
||||
import io.element.android.appnav.NodeLifecycleCallback
|
||||
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
||||
import io.element.android.features.networkmonitor.api.NetworkStatus
|
||||
import io.element.android.libraries.architecture.BackstackNode
|
||||
|
|
@ -103,12 +102,11 @@ class RoomFlowNode @AssistedInject constructor(
|
|||
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
|
||||
return when (navTarget) {
|
||||
NavTarget.Loaded -> {
|
||||
val nodeLifecycleCallbacks = plugins<NodeLifecycleCallback>()
|
||||
val roomFlowNodeCallback = plugins<RoomLoadedFlowNode.Callback>()
|
||||
val awaitRoomState = loadingRoomStateStateFlow.value
|
||||
if (awaitRoomState is LoadingRoomState.Loaded) {
|
||||
val inputs = RoomLoadedFlowNode.Inputs(awaitRoomState.room, initialElement = inputs.initialElement)
|
||||
createNode<RoomLoadedFlowNode>(buildContext, plugins = listOf(inputs) + roomFlowNodeCallback + nodeLifecycleCallbacks)
|
||||
createNode<RoomLoadedFlowNode>(buildContext, plugins = listOf(inputs) + roomFlowNodeCallback)
|
||||
} else {
|
||||
loadingNode(buildContext, this::navigateUp)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,19 +27,19 @@ import com.bumble.appyx.core.lifecycle.subscribe
|
|||
import com.bumble.appyx.core.modality.BuildContext
|
||||
import com.bumble.appyx.core.node.Node
|
||||
import com.bumble.appyx.core.plugin.Plugin
|
||||
import com.bumble.appyx.core.plugin.plugins
|
||||
import com.bumble.appyx.navmodel.backstack.BackStack
|
||||
import com.bumble.appyx.navmodel.backstack.operation.push
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import io.element.android.anvilannotations.ContributesNode
|
||||
import io.element.android.appnav.NodeLifecycleCallback
|
||||
import io.element.android.appnav.di.RoomComponentFactory
|
||||
import io.element.android.features.messages.api.MessagesEntryPoint
|
||||
import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint
|
||||
import io.element.android.libraries.architecture.BackstackNode
|
||||
import io.element.android.libraries.architecture.NodeInputs
|
||||
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
|
||||
import io.element.android.libraries.architecture.inputs
|
||||
import io.element.android.libraries.di.DaggerComponentOwner
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
|
|
@ -60,6 +60,7 @@ class RoomLoadedFlowNode @AssistedInject constructor(
|
|||
private val messagesEntryPoint: MessagesEntryPoint,
|
||||
private val roomDetailsEntryPoint: RoomDetailsEntryPoint,
|
||||
private val appNavigationStateService: AppNavigationStateService,
|
||||
roomComponentFactory: RoomComponentFactory,
|
||||
roomMembershipObserver: RoomMembershipObserver,
|
||||
) : BackstackNode<RoomLoadedFlowNode.NavTarget>(
|
||||
backstack = BackStack(
|
||||
|
|
@ -68,17 +69,12 @@ class RoomLoadedFlowNode @AssistedInject constructor(
|
|||
),
|
||||
buildContext = buildContext,
|
||||
plugins = plugins,
|
||||
) {
|
||||
), DaggerComponentOwner {
|
||||
|
||||
interface Callback : Plugin {
|
||||
fun onForwardedToSingleRoom(roomId: RoomId)
|
||||
}
|
||||
|
||||
interface LifecycleCallback : NodeLifecycleCallback {
|
||||
fun onFlowCreated(identifier: String, room: MatrixRoom)
|
||||
fun onFlowReleased(identifier: String, room: MatrixRoom)
|
||||
}
|
||||
|
||||
data class Inputs(
|
||||
val room: MatrixRoom,
|
||||
val initialElement: NavTarget = NavTarget.Messages,
|
||||
|
|
@ -86,18 +82,17 @@ class RoomLoadedFlowNode @AssistedInject constructor(
|
|||
|
||||
private val inputs: Inputs = inputs()
|
||||
private val callbacks = plugins.filterIsInstance<Callback>()
|
||||
override val daggerComponent = roomComponentFactory.create(inputs.room)
|
||||
|
||||
init {
|
||||
lifecycle.subscribe(
|
||||
onCreate = {
|
||||
Timber.v("OnCreate")
|
||||
plugins<LifecycleCallback>().forEach { it.onFlowCreated(id, inputs.room) }
|
||||
Timber.v("OnCreate => ${inputs.room.roomId}")
|
||||
appNavigationStateService.onNavigateToRoom(id, inputs.room.roomId)
|
||||
fetchRoomMembers()
|
||||
},
|
||||
onDestroy = {
|
||||
Timber.v("OnDestroy")
|
||||
plugins<LifecycleCallback>().forEach { it.onFlowReleased(id, inputs.room) }
|
||||
appNavigationStateService.onLeavingRoom(id)
|
||||
}
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue