Some cleanup:

- Remove unnecessary `GlobalScope`.
- Rename `Component` to `Graph`, `DaggerComponentOwner` to `DependencyInjectionGraphOwner`.
- Rename component builders to factories, where necessary.
This commit is contained in:
Jorge Martín 2025-09-01 16:11:10 +02:00
parent 36bca71a46
commit 2907cef47e
20 changed files with 99 additions and 127 deletions

View file

@ -9,17 +9,16 @@ package io.element.android.x
import android.app.Application import android.app.Application
import androidx.startup.AppInitializer import androidx.startup.AppInitializer
import dev.zacsweers.metro.asContribution import dev.zacsweers.metro.createGraphFactory
import io.element.android.features.cachecleaner.api.CacheCleanerInitializer import io.element.android.features.cachecleaner.api.CacheCleanerInitializer
import io.element.android.libraries.di.DaggerComponentOwner import io.element.android.libraries.di.DependencyInjectionGraphOwner
import io.element.android.x.di.AppComponent import io.element.android.x.di.AppGraph
import io.element.android.x.di.globalGraph
import io.element.android.x.info.logApplicationInfo import io.element.android.x.info.logApplicationInfo
import io.element.android.x.initializer.CrashInitializer import io.element.android.x.initializer.CrashInitializer
import io.element.android.x.initializer.PlatformInitializer import io.element.android.x.initializer.PlatformInitializer
class ElementXApplication : Application(), DaggerComponentOwner { class ElementXApplication : Application(), DependencyInjectionGraphOwner {
override val daggerComponent: AppComponent = globalGraph.asContribution<AppComponent.Factory>().create(this) override val graph: AppGraph = createGraphFactory<AppGraph.Factory>().create(this)
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()

View file

@ -21,7 +21,7 @@ import com.bumble.appyx.core.node.ParentNode
import com.bumble.appyx.core.plugin.Plugin import com.bumble.appyx.core.plugin.Plugin
import io.element.android.appnav.RootFlowNode import io.element.android.appnav.RootFlowNode
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.di.DaggerComponentOwner import io.element.android.libraries.di.DependencyInjectionGraphOwner
import io.element.android.libraries.di.annotations.ApplicationContext import io.element.android.libraries.di.annotations.ApplicationContext
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@ -38,8 +38,8 @@ class MainNode(
buildContext = buildContext, buildContext = buildContext,
plugins = plugins, plugins = plugins,
), ),
DaggerComponentOwner { DependencyInjectionGraphOwner {
override val daggerComponent = (context as DaggerComponentOwner).daggerComponent override val graph = (context as DependencyInjectionGraphOwner).graph
override fun resolve(navTarget: RootNavTarget, buildContext: BuildContext): Node { override fun resolve(navTarget: RootNavTarget, buildContext: BuildContext): Node {
return createNode<RootFlowNode>(buildContext = buildContext) return createNode<RootFlowNode>(buildContext = buildContext)

View file

@ -9,22 +9,20 @@ package io.element.android.x.di
import android.content.Context import android.content.Context
import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesTo import dev.zacsweers.metro.DependencyGraph
import dev.zacsweers.metro.GraphExtension
import dev.zacsweers.metro.Provides import dev.zacsweers.metro.Provides
import io.element.android.libraries.architecture.NodeFactoriesBindings import io.element.android.libraries.architecture.NodeFactoriesBindings
import io.element.android.libraries.di.annotations.ApplicationContext import io.element.android.libraries.di.annotations.ApplicationContext
@GraphExtension(AppScope::class) @DependencyGraph(AppScope::class)
interface AppComponent : NodeFactoriesBindings { interface AppGraph : NodeFactoriesBindings {
val sessionComponentFactory: SessionComponent.Factory val sessionGraphFactory: SessionGraph.Factory
@ContributesTo(GlobalScope::class) @DependencyGraph.Factory
@GraphExtension.Factory
interface Factory { interface Factory {
fun create( fun create(
@ApplicationContext @Provides @ApplicationContext @Provides
context: Context context: Context
): AppComponent ): AppGraph
} }
} }

View file

@ -16,10 +16,10 @@ import io.element.android.libraries.matrix.api.room.JoinedRoom
@ContributesBinding(SessionScope::class) @ContributesBinding(SessionScope::class)
@Inject @Inject
class DefaultRoomComponentFactory( class DefaultRoomComponentFactory(
private val sessionComponent: SessionComponent, private val sessionGraph: SessionGraph,
) : RoomComponentFactory { ) : RoomComponentFactory {
override fun create(room: JoinedRoom): Any { override fun create(room: JoinedRoom): Any {
return sessionComponent.roomComponentFactory return sessionGraph.roomGraphFactory
.create(room, room) .create(room, room)
} }
} }

View file

@ -10,15 +10,15 @@ package io.element.android.x.di
import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.ContributesBinding
import dev.zacsweers.metro.Inject import dev.zacsweers.metro.Inject
import io.element.android.appnav.di.SessionComponentFactory import io.element.android.appnav.di.SessionGraphFactory
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
@Inject @Inject
class DefaultSessionComponentFactory( class DefaultSessionGraphFactory(
private val appComponent: AppComponent private val appGraph: AppGraph
) : SessionComponentFactory { ) : SessionGraphFactory {
override fun create(client: MatrixClient): Any { override fun create(client: MatrixClient): Any {
return appComponent.sessionComponentFactory.createSessionComponent(client) return appGraph.sessionGraphFactory.create(client)
} }
} }

View file

@ -1,16 +0,0 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.x.di
import dev.zacsweers.metro.DependencyGraph
import dev.zacsweers.metro.createGraph
@DependencyGraph(GlobalScope::class)
interface GlobalGraph
internal val globalGraph = createGraph<GlobalGraph>()

View file

@ -1,10 +0,0 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.x.di
class GlobalScope private constructor()

View file

@ -17,13 +17,13 @@ import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.JoinedRoom
@GraphExtension(RoomScope::class) @GraphExtension(RoomScope::class)
interface RoomComponent : NodeFactoriesBindings { interface RoomGraph : NodeFactoriesBindings {
@ContributesTo(SessionScope::class) @ContributesTo(SessionScope::class)
@GraphExtension.Factory @GraphExtension.Factory
interface Factory { interface Factory {
fun create( fun create(
@Provides joinedRoom: JoinedRoom, @Provides joinedRoom: JoinedRoom,
@Provides baseRoom: BaseRoom @Provides baseRoom: BaseRoom
): RoomComponent ): RoomGraph
} }
} }

View file

@ -16,12 +16,12 @@ import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
@GraphExtension(SessionScope::class) @GraphExtension(SessionScope::class)
interface SessionComponent : NodeFactoriesBindings { interface SessionGraph : NodeFactoriesBindings {
val roomComponentFactory: RoomComponent.Factory val roomGraphFactory: RoomGraph.Factory
@ContributesTo(AppScope::class) @ContributesTo(AppScope::class)
@GraphExtension.Factory @GraphExtension.Factory
interface Factory { interface Factory {
fun createSessionComponent(@Provides matrixClient: MatrixClient): SessionComponent fun create(@Provides matrixClient: MatrixClient): SessionGraph
} }
} }

View file

@ -26,11 +26,11 @@ import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.Inject import dev.zacsweers.metro.Inject
import io.element.android.anvilannotations.ContributesNode import io.element.android.anvilannotations.ContributesNode
import io.element.android.appnav.di.SessionComponentFactory import io.element.android.appnav.di.SessionGraphFactory
import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.inputs import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.DaggerComponentOwner import io.element.android.libraries.di.DependencyInjectionGraphOwner
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.ui.media.ImageLoaderHolder import io.element.android.libraries.matrix.ui.media.ImageLoaderHolder
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@ -45,7 +45,7 @@ import kotlinx.parcelize.Parcelize
class LoggedInAppScopeFlowNode( class LoggedInAppScopeFlowNode(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
sessionComponentFactory: SessionComponentFactory, sessionGraphFactory: SessionGraphFactory,
private val imageLoaderHolder: ImageLoaderHolder, private val imageLoaderHolder: ImageLoaderHolder,
) : ParentNode<LoggedInAppScopeFlowNode.NavTarget>( ) : ParentNode<LoggedInAppScopeFlowNode.NavTarget>(
navModel = PermanentNavModel( navModel = PermanentNavModel(
@ -54,7 +54,7 @@ class LoggedInAppScopeFlowNode(
), ),
buildContext = buildContext, buildContext = buildContext,
plugins = plugins plugins = plugins
), DaggerComponentOwner { ), DependencyInjectionGraphOwner {
interface Callback : Plugin { interface Callback : Plugin {
fun onOpenBugReport() fun onOpenBugReport()
} }
@ -67,7 +67,7 @@ class LoggedInAppScopeFlowNode(
) : NodeInputs ) : NodeInputs
private val inputs: Inputs = inputs() private val inputs: Inputs = inputs()
override val daggerComponent = sessionComponentFactory.create(inputs.matrixClient) override val graph = sessionGraphFactory.create(inputs.matrixClient)
override fun onBuilt() { override fun onBuilt() {
super.onBuilt() super.onBuilt()

View file

@ -9,6 +9,6 @@ package io.element.android.appnav.di
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
interface SessionComponentFactory { interface SessionGraphFactory {
fun create(client: MatrixClient): Any fun create(client: MatrixClient): Any
} }

View file

@ -28,7 +28,7 @@ import io.element.android.libraries.architecture.BackstackView
import io.element.android.libraries.architecture.BaseFlowNode import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.inputs import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.DaggerComponentOwner import io.element.android.libraries.di.DependencyInjectionGraphOwner
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.di.annotations.SessionCoroutineScope
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
@ -68,7 +68,7 @@ class JoinedRoomLoadedFlowNode(
), ),
buildContext = buildContext, buildContext = buildContext,
plugins = plugins, plugins = plugins,
), DaggerComponentOwner { ), DependencyInjectionGraphOwner {
interface Callback : Plugin { interface Callback : Plugin {
fun onOpenRoom(roomId: RoomId, serverNames: List<String>) fun onOpenRoom(roomId: RoomId, serverNames: List<String>)
fun onPermalinkClick(data: PermalinkData, pushToBackstack: Boolean) fun onPermalinkClick(data: PermalinkData, pushToBackstack: Boolean)
@ -83,7 +83,7 @@ class JoinedRoomLoadedFlowNode(
private val inputs: Inputs = inputs() private val inputs: Inputs = inputs()
private val callbacks = plugins.filterIsInstance<Callback>() private val callbacks = plugins.filterIsInstance<Callback>()
override val daggerComponent = roomComponentFactory.create(inputs.room) override val graph = roomComponentFactory.create(inputs.room)
init { init {
lifecycle.subscribe( lifecycle.subscribe(

View file

@ -25,7 +25,7 @@ import io.element.android.features.changeroommemberroes.api.ChangeRoomMemberRole
import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.inputs import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.DaggerComponentOwner import io.element.android.libraries.di.DependencyInjectionGraphOwner
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.JoinedRoom
@ -44,7 +44,7 @@ class ChangeRoomMemberRolesRootNode(
), ),
buildContext = buildContext, buildContext = buildContext,
plugins = plugins, plugins = plugins,
), DaggerComponentOwner, ChangeRoomMemberRolesEntryPoint.NodeProxy { ), DependencyInjectionGraphOwner, ChangeRoomMemberRolesEntryPoint.NodeProxy {
sealed interface NavTarget : Parcelable { sealed interface NavTarget : Parcelable {
@Parcelize @Parcelize
object Root : NavTarget object Root : NavTarget
@ -57,7 +57,7 @@ class ChangeRoomMemberRolesRootNode(
private val inputs = inputs<Inputs>() private val inputs = inputs<Inputs>()
override val daggerComponent = roomComponentFactory.create(inputs.joinedRoom) override val graph = roomComponentFactory.create(inputs.joinedRoom)
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
return when (navTarget) { return when (navTarget) {

View file

@ -13,10 +13,10 @@ import dev.zacsweers.metro.GraphExtension
import io.element.android.libraries.architecture.NodeFactoriesBindings import io.element.android.libraries.architecture.NodeFactoriesBindings
@GraphExtension(QrCodeLoginScope::class) @GraphExtension(QrCodeLoginScope::class)
interface QrCodeLoginComponent : NodeFactoriesBindings { interface QrCodeLoginGraph : NodeFactoriesBindings {
@ContributesTo(AppScope::class) @ContributesTo(AppScope::class)
@GraphExtension.Factory @GraphExtension.Factory
interface Factory { interface Factory {
fun create(): QrCodeLoginComponent fun create(): QrCodeLoginGraph
} }
} }

View file

@ -26,7 +26,7 @@ import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.Inject import dev.zacsweers.metro.Inject
import io.element.android.anvilannotations.ContributesNode import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.login.impl.di.QrCodeLoginBindings import io.element.android.features.login.impl.di.QrCodeLoginBindings
import io.element.android.features.login.impl.di.QrCodeLoginComponent import io.element.android.features.login.impl.di.QrCodeLoginGraph
import io.element.android.features.login.impl.screens.qrcode.confirmation.QrCodeConfirmationNode import io.element.android.features.login.impl.screens.qrcode.confirmation.QrCodeConfirmationNode
import io.element.android.features.login.impl.screens.qrcode.confirmation.QrCodeConfirmationStep import io.element.android.features.login.impl.screens.qrcode.confirmation.QrCodeConfirmationStep
import io.element.android.features.login.impl.screens.qrcode.error.QrCodeErrorNode import io.element.android.features.login.impl.screens.qrcode.error.QrCodeErrorNode
@ -38,7 +38,7 @@ import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.bindings import io.element.android.libraries.architecture.bindings
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.di.DaggerComponentOwner import io.element.android.libraries.di.DependencyInjectionGraphOwner
import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData
import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep
import io.element.android.libraries.matrix.api.auth.qrlogin.QrLoginException import io.element.android.libraries.matrix.api.auth.qrlogin.QrLoginException
@ -53,7 +53,7 @@ import timber.log.Timber
class QrCodeLoginFlowNode( class QrCodeLoginFlowNode(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
qrCodeLoginComponentBuilder: QrCodeLoginComponent.Factory, qrCodeLoginGraphFactory: QrCodeLoginGraph.Factory,
private val coroutineDispatchers: CoroutineDispatchers, private val coroutineDispatchers: CoroutineDispatchers,
) : BaseFlowNode<QrCodeLoginFlowNode.NavTarget>( ) : BaseFlowNode<QrCodeLoginFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
@ -62,10 +62,10 @@ class QrCodeLoginFlowNode(
), ),
buildContext = buildContext, buildContext = buildContext,
plugins = plugins, plugins = plugins,
), DaggerComponentOwner { ), DependencyInjectionGraphOwner {
private var authenticationJob: Job? = null private var authenticationJob: Job? = null
override val daggerComponent = qrCodeLoginComponentBuilder.create() override val graph = qrCodeLoginGraphFactory.create()
private val qrCodeLoginManager by lazy { bindings<QrCodeLoginBindings>().qrCodeLoginManager() } private val qrCodeLoginManager by lazy { bindings<QrCodeLoginBindings>().qrCodeLoginManager() }
sealed interface NavTarget : Parcelable { sealed interface NavTarget : Parcelable {

View file

@ -1,40 +0,0 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.login.impl.di
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import io.element.android.features.login.impl.qrcode.FakeQrCodeLoginManager
import io.element.android.features.login.impl.qrcode.QrCodeLoginFlowNode
import io.element.android.features.login.impl.qrcode.QrCodeLoginManager
import io.element.android.libraries.architecture.AssistedNodeFactory
import io.element.android.libraries.architecture.createNode
internal class FakeMergedQrCodeLoginComponent(private val qrCodeLoginManager: QrCodeLoginManager) :
MergedQrCodeLoginComponent {
// Ignore this error, it does override a method once code generation is done
override fun qrCodeLoginManager(): QrCodeLoginManager = qrCodeLoginManager
class Builder(private val qrCodeLoginManager: QrCodeLoginManager = FakeQrCodeLoginManager()) :
QrCodeLoginComponent.Factory {
override fun create(): QrCodeLoginComponent {
return FakeMergedQrCodeLoginComponent(qrCodeLoginManager)
}
}
override fun nodeFactories(): Map<Class<out Node>, AssistedNodeFactory<*>> {
return mapOf(
QrCodeLoginFlowNode::class.java to object : AssistedNodeFactory<QrCodeLoginFlowNode> {
override fun create(buildContext: BuildContext, plugins: List<Plugin>): QrCodeLoginFlowNode {
return createNode<QrCodeLoginFlowNode>(buildContext, plugins)
}
}
)
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.login.impl.di
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import io.element.android.features.login.impl.qrcode.FakeQrCodeLoginManager
import io.element.android.features.login.impl.qrcode.QrCodeLoginFlowNode
import io.element.android.features.login.impl.qrcode.QrCodeLoginManager
import io.element.android.libraries.architecture.AssistedNodeFactory
import io.element.android.libraries.architecture.createNode
internal class FakeQrCodeLoginGraph(
private val qrCodeLoginManager: QrCodeLoginManager,
) : QrCodeLoginGraph, QrCodeLoginBindings {
override fun nodeFactories(): Map<KClass<out Node>, AssistedNodeFactory<*>> {
return mapOf(
QrCodeLoginFlowNode::class to object : AssistedNodeFactory<QrCodeLoginFlowNode> {
override fun create(buildContext: BuildContext, plugins: List<Plugin>): QrCodeLoginFlowNode {
return createNode<QrCodeLoginFlowNode>(buildContext, plugins)
}
}
)
}
override fun qrCodeLoginManager(): QrCodeLoginManager = qrCodeLoginManager
internal class Builder(
private val qrCodeLoginManager: QrCodeLoginManager,
) : QrCodeLoginComponent.Factory {
override fun create(): QrCodeLoginComponent {
return FakeQrCodeLoginComponent(qrCodeLoginManager)
}
}
}

View file

@ -12,7 +12,7 @@ import com.bumble.appyx.core.modality.AncestryInfo
import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.utils.customisations.NodeCustomisationDirectoryImpl import com.bumble.appyx.utils.customisations.NodeCustomisationDirectoryImpl
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.features.login.impl.di.FakeMergedQrCodeLoginComponent import io.element.android.features.login.impl.di.FakeQrCodeLoginGraph
import io.element.android.features.login.impl.screens.qrcode.confirmation.QrCodeConfirmationStep import io.element.android.features.login.impl.screens.qrcode.confirmation.QrCodeConfirmationStep
import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep
@ -183,7 +183,7 @@ class QrCodeLoginFlowNodeTest {
return QrCodeLoginFlowNode( return QrCodeLoginFlowNode(
buildContext = buildContext, buildContext = buildContext,
plugins = emptyList(), plugins = emptyList(),
qrCodeLoginComponentBuilder = FakeMergedQrCodeLoginComponent.Builder(qrCodeLoginManager), qrCodeLoginGraphFactory = FakeQrCodeLoginGraph.Builder(qrCodeLoginManager),
coroutineDispatchers = coroutineDispatchers, coroutineDispatchers = coroutineDispatchers,
) )
} }

View file

@ -10,7 +10,7 @@ package io.element.android.libraries.architecture
import android.content.Context import android.content.Context
import android.content.ContextWrapper import android.content.ContextWrapper
import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.Node
import io.element.android.libraries.di.DaggerComponentOwner import io.element.android.libraries.di.DependencyInjectionGraphOwner
inline fun <reified T : Any> Node.optionalBindings() = optionalBindings(T::class.java) inline fun <reified T : Any> Node.optionalBindings() = optionalBindings(T::class.java)
inline fun <reified T : Any> Node.bindings() = bindings(T::class.java) inline fun <reified T : Any> Node.bindings() = bindings(T::class.java)
@ -20,9 +20,9 @@ fun <T : Any> Context.bindings(klass: Class<T>): T {
// search dagger components in the context hierarchy // search dagger components in the context hierarchy
return generateSequence(this) { (it as? ContextWrapper)?.baseContext } return generateSequence(this) { (it as? ContextWrapper)?.baseContext }
.plus(applicationContext) .plus(applicationContext)
.filterIsInstance<DaggerComponentOwner>() .filterIsInstance<DependencyInjectionGraphOwner>()
.map { it.daggerComponent } .map { it.graph }
.flatMap { if (it is Collection<*>) it else listOf(it) } .flatMap { it as? Collection<*> ?: listOf(it) }
.filterIsInstance(klass) .filterIsInstance(klass)
.firstOrNull() .firstOrNull()
?: error("Unable to find bindings for ${klass.name}") ?: error("Unable to find bindings for ${klass.name}")
@ -31,9 +31,9 @@ fun <T : Any> Context.bindings(klass: Class<T>): T {
fun <T : Any> Node.optionalBindings(klass: Class<T>): T? { fun <T : Any> Node.optionalBindings(klass: Class<T>): T? {
// search dagger components in node hierarchy // search dagger components in node hierarchy
return generateSequence(this, Node::parent) return generateSequence(this, Node::parent)
.filterIsInstance<DaggerComponentOwner>() .filterIsInstance<DependencyInjectionGraphOwner>()
.map { it.daggerComponent } .map { it.graph }
.flatMap { if (it is Collection<*>) it else listOf(it) } .flatMap { it as? Collection<*> ?: listOf(it) }
.filterIsInstance(klass) .filterIsInstance(klass)
.firstOrNull() .firstOrNull()
} }

View file

@ -8,10 +8,10 @@
package io.element.android.libraries.di package io.element.android.libraries.di
/** /**
* A [DaggerComponentOwner] is anything that "owns" a Dagger Component. * A [DependencyInjectionGraphOwner] is anything that "owns" a DI Graph.
* *
*/ */
interface DaggerComponentOwner { interface DependencyInjectionGraphOwner {
/** This is either a component, or a list of components. */ /** This is either a graph, or a list of graphs. */
val daggerComponent: Any val graph: Any
} }