Cleanup nodes (#5358)

* Remove unused NavTarget.Empty

* Let SpaceEntryPoint.Inputs implement NodeInputs.

* Small cleanup

* Small cleanup

* Method can be private.

* Simplify code

* Rename to follow naming convention

* Rename Node to follow naming convention

* Add Konsist test.

* Remove useless line of code.
This commit is contained in:
Benoit Marty
2025-09-16 14:36:43 +02:00
committed by GitHub
13 changed files with 42 additions and 50 deletions

View File

@@ -37,16 +37,7 @@ class ChangeRolesNode(
) : NodeInputs
private val inputs: Inputs = inputs()
private val presenter = presenterFactory.run {
val role = when (inputs.listType) {
ChangeRoomMemberRolesListType.Admins -> RoomMember.Role.Admin
ChangeRoomMemberRolesListType.Moderators -> RoomMember.Role.Moderator
ChangeRoomMemberRolesListType.SelectNewOwnersWhenLeaving -> RoomMember.Role.Owner(isCreator = false)
}
create(role)
}
private val presenter = presenterFactory.create(inputs.listType.toRoomMemberRole())
private val stateFlow = launchMolecule { presenter.present() }
suspend fun waitForRoleChanged() {
@@ -63,3 +54,9 @@ class ChangeRolesNode(
)
}
}
private fun ChangeRoomMemberRolesListType.toRoomMemberRole() = when (this) {
ChangeRoomMemberRolesListType.Admins -> RoomMember.Role.Admin
ChangeRoomMemberRolesListType.Moderators -> RoomMember.Role.Moderator
ChangeRoomMemberRolesListType.SelectNewOwnersWhenLeaving -> RoomMember.Role.Owner(isCreator = false)
}

View File

@@ -39,16 +39,13 @@ class ChangeRoomMemberRolesRootNode(
roomComponentFactory: RoomComponentFactory,
) : ParentNode<ChangeRoomMemberRolesRootNode.NavTarget>(
navModel = PermanentNavModel(
navTargets = setOf(NavTarget.Root),
navTargets = setOf(NavTarget),
savedStateMap = buildContext.savedStateMap,
),
buildContext = buildContext,
plugins = plugins,
), DependencyInjectionGraphOwner, ChangeRoomMemberRolesEntryPoint.NodeProxy {
sealed interface NavTarget : Parcelable {
@Parcelize
object Root : NavTarget
}
@Parcelize object NavTarget : Parcelable
data class Inputs(
val joinedRoom: JoinedRoom,
@@ -60,14 +57,10 @@ class ChangeRoomMemberRolesRootNode(
override val graph = roomComponentFactory.create(inputs.joinedRoom)
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
return when (navTarget) {
NavTarget.Root -> {
createNode<ChangeRolesNode>(
buildContext = buildContext,
plugins = listOf(ChangeRolesNode.Inputs(listType = inputs.listType)),
)
}
}
return createNode<ChangeRolesNode>(
buildContext = buildContext,
plugins = listOf(ChangeRolesNode.Inputs(listType = inputs.listType)),
)
}
@Composable

View File

@@ -164,7 +164,7 @@ class HomeFlowNode(
stateFlow.value.roomListState.eventSink(RoomListEvents.LeaveRoom(roomId, needsConfirmation = false))
}
fun rootNode(buildContext: BuildContext): Node {
private fun rootNode(buildContext: BuildContext): Node {
return node(buildContext) { modifier ->
val state by stateFlow.collectAsState()
val activity = requireNotNull(LocalActivity.current)

View File

@@ -15,7 +15,6 @@ import androidx.lifecycle.lifecycleScope
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.node.node
import com.bumble.appyx.core.plugin.Plugin
import com.bumble.appyx.core.plugin.plugins
import com.bumble.appyx.navmodel.backstack.BackStack
@@ -126,9 +125,6 @@ class MessagesFlowNode(
plugins = plugins
) {
sealed interface NavTarget : Parcelable {
@Parcelize
data object Empty : NavTarget
@Parcelize
data class Messages(val focusedEventId: EventId?) : NavTarget
@@ -399,9 +395,6 @@ class MessagesFlowNode(
}
createNode<PinnedMessagesListNode>(buildContext, plugins = listOf(callback))
}
NavTarget.Empty -> {
node(buildContext) {}
}
NavTarget.KnockRequestsList -> {
knockRequestsListEntryPoint.createNode(this, buildContext)
}

View File

@@ -34,10 +34,7 @@ class ChangeRoomPermissionsNode(
) : NodeInputs, Parcelable
private val inputs: Inputs = inputs()
private val presenter = presenterFactory.run {
create(inputs.section)
}
private val presenter = presenterFactory.create(inputs.section)
@Composable
override fun View(modifier: Modifier) {

View File

@@ -11,6 +11,7 @@ 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.libraries.architecture.FeatureEntryPoint
import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.matrix.api.core.RoomId
interface SpaceEntryPoint : FeatureEntryPoint {
@@ -27,7 +28,7 @@ interface SpaceEntryPoint : FeatureEntryPoint {
data class Inputs(
val roomId: RoomId
) : Plugin
) : NodeInputs
interface Callback : Plugin {
fun onOpenRoom(roomId: RoomId)

View File

@@ -16,6 +16,7 @@ import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.Inject
import io.element.android.annotations.ContributesNode
import io.element.android.features.space.api.SpaceEntryPoint
import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.SessionScope
@ContributesNode(SessionScope::class)
@@ -25,7 +26,7 @@ class SpaceNode(
@Assisted plugins: List<Plugin>,
presenterFactory: SpacePresenter.Factory,
) : Node(buildContext, plugins = plugins) {
private val inputs = plugins.filterIsInstance<SpaceEntryPoint.Inputs>().single()
private val inputs: SpaceEntryPoint.Inputs = inputs()
private val callback = plugins.filterIsInstance<SpaceEntryPoint.Callback>().single()
private val presenter = presenterFactory.create(inputs)

View File

@@ -14,7 +14,7 @@ import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding
import dev.zacsweers.metro.Inject
import io.element.android.features.viewfolder.api.ViewFolderEntryPoint
import io.element.android.features.viewfolder.impl.root.ViewFolderRootNode
import io.element.android.features.viewfolder.impl.root.ViewFolderFlowNode
import io.element.android.libraries.architecture.createNode
@ContributesBinding(AppScope::class)
@@ -25,7 +25,7 @@ class DefaultViewFolderEntryPoint : ViewFolderEntryPoint {
return object : ViewFolderEntryPoint.NodeBuilder {
override fun params(params: ViewFolderEntryPoint.Params): ViewFolderEntryPoint.NodeBuilder {
plugins += ViewFolderRootNode.Inputs(params.rootPath)
plugins += ViewFolderFlowNode.Inputs(params.rootPath)
return this
}
@@ -35,7 +35,7 @@ class DefaultViewFolderEntryPoint : ViewFolderEntryPoint {
}
override fun build(): Node {
return parentNode.createNode<ViewFolderRootNode>(buildContext, plugins)
return parentNode.createNode<ViewFolderFlowNode>(buildContext, plugins)
}
}
}

View File

@@ -34,10 +34,10 @@ import kotlinx.parcelize.Parcelize
@ContributesNode(AppScope::class)
@Inject
class ViewFolderRootNode(
class ViewFolderFlowNode(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
) : BaseFlowNode<ViewFolderRootNode.NavTarget>(
) : BaseFlowNode<ViewFolderFlowNode.NavTarget>(
backstack = BackStack(
initialElement = NavTarget.Root,
savedStateMap = buildContext.savedStateMap,

View File

@@ -287,7 +287,6 @@ class RustMatrixClient(
}
override suspend fun getRoom(roomId: RoomId): BaseRoom? = withContext(sessionDispatcher) {
innerClient.rooms()
roomFactory.getBaseRoom(roomId)
}

View File

@@ -15,7 +15,7 @@ import dev.zacsweers.metro.ContributesBinding
import dev.zacsweers.metro.Inject
import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.mediaviewer.api.MediaGalleryEntryPoint
import io.element.android.libraries.mediaviewer.impl.gallery.root.MediaGalleryRootNode
import io.element.android.libraries.mediaviewer.impl.gallery.root.MediaGalleryFlowNode
@ContributesBinding(AppScope::class)
@Inject
@@ -30,7 +30,7 @@ class DefaultMediaGalleryEntryPoint : MediaGalleryEntryPoint {
}
override fun build(): Node {
return parentNode.createNode<MediaGalleryRootNode>(buildContext, plugins)
return parentNode.createNode<MediaGalleryFlowNode>(buildContext, plugins)
}
}
}

View File

@@ -41,11 +41,11 @@ import kotlinx.parcelize.Parcelize
@ContributesNode(RoomScope::class)
@Inject
class MediaGalleryRootNode(
class MediaGalleryFlowNode(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val mediaViewerEntryPoint: MediaViewerEntryPoint
) : BaseFlowNode<MediaGalleryRootNode.NavTarget>(
) : BaseFlowNode<MediaGalleryFlowNode.NavTarget>(
backstack = BackStack(
initialElement = NavTarget.Root,
savedStateMap = buildContext.savedStateMap,
@@ -87,11 +87,11 @@ class MediaGalleryRootNode(
NavTarget.Root -> {
val callback = object : MediaGalleryNode.Callback {
override fun onBackClick() {
this@MediaGalleryRootNode.onBackClick()
this@MediaGalleryFlowNode.onBackClick()
}
override fun onViewInTimeline(eventId: EventId) {
this@MediaGalleryRootNode.onViewInTimeline(eventId)
this@MediaGalleryFlowNode.onViewInTimeline(eventId)
}
override fun onItemClick(item: MediaItem.Event) {
@@ -122,7 +122,7 @@ class MediaGalleryRootNode(
}
override fun onViewInTimeline(eventId: EventId) {
this@MediaGalleryRootNode.onViewInTimeline(eventId)
this@MediaGalleryFlowNode.onViewInTimeline(eventId)
}
}
mediaViewerEntryPoint.nodeBuilder(this, buildContext)

View File

@@ -20,6 +20,7 @@ import com.lemonappdev.konsist.api.ext.list.withoutName
import com.lemonappdev.konsist.api.ext.list.withoutNameStartingWith
import com.lemonappdev.konsist.api.verify.assertEmpty
import com.lemonappdev.konsist.api.verify.assertTrue
import io.element.android.libraries.architecture.BaseFlowNode
import io.element.android.libraries.architecture.Presenter
import org.junit.Test
@@ -44,6 +45,16 @@ class KonsistClassNameTest {
}
}
@Test
fun `Classes extending 'BaseFlowNode' should have 'FlowNode' suffix`() {
Konsist.scopeFromProject()
.classes()
.withAllParentsOf(BaseFlowNode::class)
.assertTrue {
it.name.endsWith("FlowNode")
}
}
@Test
fun `Classes extending 'PreviewParameterProvider' name MUST end with 'Provider' and MUST contain provided class name`() {
Konsist.scopeFromProduction()