Remove PresenterConnector and molecule runtime in feature modules, directly call Presenter.present method

This commit is contained in:
ganfra 2023-02-01 15:56:07 +01:00
parent 4b010e01df
commit fc07ff29f5
11 changed files with 18 additions and 95 deletions

View file

@ -21,8 +21,6 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@ -38,7 +36,6 @@ import com.bumble.appyx.navmodel.backstack.operation.push
import io.element.android.features.rageshake.bugreport.BugReportNode import io.element.android.features.rageshake.bugreport.BugReportNode
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.presenterConnector
import io.element.android.libraries.di.DaggerComponentOwner import io.element.android.libraries.di.DaggerComponentOwner
import io.element.android.libraries.matrix.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.auth.MatrixAuthenticationService
import io.element.android.libraries.matrix.core.SessionId import io.element.android.libraries.matrix.core.SessionId
@ -60,7 +57,7 @@ class RootFlowNode(
private val appComponentOwner: DaggerComponentOwner, private val appComponentOwner: DaggerComponentOwner,
private val authenticationService: MatrixAuthenticationService, private val authenticationService: MatrixAuthenticationService,
private val matrixClientsHolder: MatrixClientsHolder, private val matrixClientsHolder: MatrixClientsHolder,
presenter: RootPresenter private val presenter: RootPresenter
) : ) :
ParentNode<RootFlowNode.NavTarget>( ParentNode<RootFlowNode.NavTarget>(
navModel = backstack, navModel = backstack,
@ -69,8 +66,6 @@ class RootFlowNode(
DaggerComponentOwner by appComponentOwner { DaggerComponentOwner by appComponentOwner {
private val presenterConnector = presenterConnector(presenter)
override fun onBuilt() { override fun onBuilt() {
super.onBuilt() super.onBuilt()
observeLoggedInState() observeLoggedInState()
@ -131,7 +126,7 @@ class RootFlowNode(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val state by presenterConnector.stateFlow.collectAsState() val state = presenter.present()
RootView( RootView(
state = state, state = state,
modifier = modifier, modifier = modifier,

View file

@ -17,8 +17,6 @@
package io.element.android.features.login.changeserver package io.element.android.features.login.changeserver
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.Node
@ -26,25 +24,22 @@ import com.bumble.appyx.core.plugin.Plugin
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode import io.element.android.anvilannotations.ContributesNode
import io.element.android.libraries.architecture.presenterConnector
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope
@ContributesNode(AppScope::class) @ContributesNode(AppScope::class)
class ChangeServerNode @AssistedInject constructor( class ChangeServerNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
presenter: ChangeServerPresenter, private val presenter: ChangeServerPresenter,
) : Node(buildContext, plugins = plugins) { ) : Node(buildContext, plugins = plugins) {
private val presenterConnector = presenterConnector(presenter)
private fun onSuccess() { private fun onSuccess() {
navigateUp() navigateUp()
} }
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val state by presenterConnector.stateFlow.collectAsState() val state = presenter.present()
ChangeServerView( ChangeServerView(
state = state, state = state,
modifier = modifier, modifier = modifier,

View file

@ -17,8 +17,6 @@
package io.element.android.features.login.root package io.element.android.features.login.root
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.modality.BuildContext
@ -28,7 +26,6 @@ import com.bumble.appyx.core.plugin.plugins
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode import io.element.android.anvilannotations.ContributesNode
import io.element.android.libraries.architecture.presenterConnector
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope
@ -36,11 +33,9 @@ import io.element.android.libraries.di.AppScope
class LoginRootNode @AssistedInject constructor( class LoginRootNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
presenter: LoginRootPresenter, private val presenter: LoginRootPresenter,
) : Node(buildContext, plugins = plugins) { ) : Node(buildContext, plugins = plugins) {
private val presenterConnector = presenterConnector(presenter)
interface Callback : Plugin { interface Callback : Plugin {
fun onChangeHomeServer() fun onChangeHomeServer()
} }
@ -51,7 +46,7 @@ class LoginRootNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val state by presenterConnector.stateFlow.collectAsState() val state = presenter.present()
OnLifecycleEvent { _, event -> OnLifecycleEvent { _, event ->
when (event) { when (event) {
Lifecycle.Event.ON_RESUME -> state.eventSink(LoginRootEvents.RefreshHomeServer) Lifecycle.Event.ON_RESUME -> state.eventSink(LoginRootEvents.RefreshHomeServer)

View file

@ -17,8 +17,6 @@
package io.element.android.features.messages package io.element.android.features.messages
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.Node
@ -26,21 +24,18 @@ import com.bumble.appyx.core.plugin.Plugin
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode import io.element.android.anvilannotations.ContributesNode
import io.element.android.libraries.architecture.presenterConnector
import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.RoomScope
@ContributesNode(RoomScope::class) @ContributesNode(RoomScope::class)
class MessagesNode @AssistedInject constructor( class MessagesNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
presenter: MessagesPresenter, private val presenter: MessagesPresenter,
) : Node(buildContext, plugins = plugins) { ) : Node(buildContext, plugins = plugins) {
private val connector = presenterConnector(presenter)
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val state by connector.stateFlow.collectAsState() val state = presenter.present()
MessagesView( MessagesView(
state = state, state = state,
onBackPressed = this::navigateUp, onBackPressed = this::navigateUp,

View file

@ -20,6 +20,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.data.StableCharSequence import io.element.android.libraries.core.data.StableCharSequence
@ -40,7 +41,7 @@ class MessageComposerPresenter @Inject constructor(
val isFullScreen = rememberSaveable { val isFullScreen = rememberSaveable {
mutableStateOf(false) mutableStateOf(false)
} }
val text: MutableState<StableCharSequence> = rememberSaveable { val text: MutableState<StableCharSequence> = remember {
mutableStateOf(StableCharSequence("")) mutableStateOf(StableCharSequence(""))
} }
val composerMode: MutableState<MessageComposerMode> = rememberSaveable { val composerMode: MutableState<MessageComposerMode> = rememberSaveable {

View file

@ -17,8 +17,6 @@
package io.element.android.features.preferences.root package io.element.android.features.preferences.root
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.Node
@ -27,29 +25,26 @@ import com.bumble.appyx.core.plugin.plugins
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode import io.element.android.anvilannotations.ContributesNode
import io.element.android.libraries.architecture.presenterConnector
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
@ContributesNode(SessionScope::class) @ContributesNode(SessionScope::class)
class PreferencesRootNode @AssistedInject constructor( class PreferencesRootNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
presenter: PreferencesRootPresenter, private val presenter: PreferencesRootPresenter,
) : Node(buildContext, plugins = plugins) { ) : Node(buildContext, plugins = plugins) {
interface Callback : Plugin { interface Callback : Plugin {
fun onOpenBugReport() fun onOpenBugReport()
} }
private val presenterConnector = presenterConnector(presenter)
private fun onOpenBugReport() { private fun onOpenBugReport() {
plugins<Callback>().forEach { it.onOpenBugReport() } plugins<Callback>().forEach { it.onOpenBugReport() }
} }
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val state by presenterConnector.stateFlow.collectAsState() val state = presenter.present()
PreferencesRootView( PreferencesRootView(
state = state, state = state,
modifier = modifier, modifier = modifier,

View file

@ -17,8 +17,6 @@
package io.element.android.features.rageshake.bugreport package io.element.android.features.rageshake.bugreport
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.Node
@ -27,25 +25,22 @@ import com.bumble.appyx.core.plugin.plugins
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode import io.element.android.anvilannotations.ContributesNode
import io.element.android.libraries.architecture.presenterConnector
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope
@ContributesNode(AppScope::class) @ContributesNode(AppScope::class)
class BugReportNode @AssistedInject constructor( class BugReportNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
presenter: BugReportPresenter, private val presenter: BugReportPresenter,
) : Node(buildContext, plugins = plugins) { ) : Node(buildContext, plugins = plugins) {
private val presenterConnector = presenterConnector(presenter)
interface Callback : Plugin { interface Callback : Plugin {
fun onBugReportSent() fun onBugReportSent()
} }
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val state by presenterConnector.stateFlow.collectAsState() val state = presenter.present()
BugReportView( BugReportView(
state = state, state = state,
modifier = modifier, modifier = modifier,

View file

@ -17,8 +17,6 @@
package io.element.android.features.roomlist package io.element.android.features.roomlist
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.Node
@ -27,7 +25,6 @@ import com.bumble.appyx.core.plugin.plugins
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode import io.element.android.anvilannotations.ContributesNode
import io.element.android.libraries.architecture.presenterConnector
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.core.RoomId import io.element.android.libraries.matrix.core.RoomId
@ -35,7 +32,7 @@ import io.element.android.libraries.matrix.core.RoomId
class RoomListNode @AssistedInject constructor( class RoomListNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
presenter: RoomListPresenter, private val presenter: RoomListPresenter,
) : Node(buildContext, plugins = plugins) { ) : Node(buildContext, plugins = plugins) {
interface Callback : Plugin { interface Callback : Plugin {
@ -43,8 +40,6 @@ class RoomListNode @AssistedInject constructor(
fun onSettingsClicked() fun onSettingsClicked()
} }
private val connector = presenterConnector(presenter)
private fun onRoomClicked(roomId: RoomId) { private fun onRoomClicked(roomId: RoomId) {
plugins<Callback>().forEach { it.onRoomClicked(roomId) } plugins<Callback>().forEach { it.onRoomClicked(roomId) }
} }
@ -55,7 +50,7 @@ class RoomListNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val state by connector.stateFlow.collectAsState() val state = presenter.present()
RoomListView( RoomListView(
state = state, state = state,
modifier = modifier, modifier = modifier,

View file

@ -17,15 +17,12 @@
package io.element.android.features.template package io.element.android.features.template
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.bumble.appyx.core.modality.BuildContext 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.Plugin
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import io.element.android.libraries.architecture.presenterConnector
import io.element.android.anvilannotations.ContributesNode import io.element.android.anvilannotations.ContributesNode
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope
@ -34,14 +31,12 @@ import io.element.android.libraries.di.AppScope
class TemplateNode @AssistedInject constructor( class TemplateNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
presenter: TemplatePresenter, private val presenter: TemplatePresenter,
) : Node(buildContext, plugins = plugins) { ) : Node(buildContext, plugins = plugins) {
private val presenterConnector = presenterConnector(presenter)
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val state by presenterConnector.stateFlow.collectAsState() val state = presenter.present()
TemplateView( TemplateView(
state = state, state = state,
modifier = modifier modifier = modifier

View file

@ -28,6 +28,5 @@ dependencies {
api(projects.libraries.di) api(projects.libraries.di)
api(libs.dagger) api(libs.dagger)
api(libs.appyx.core) api(libs.appyx.core)
api(libs.molecule.runtime)
api(libs.androidx.lifecycle.runtime) api(libs.androidx.lifecycle.runtime)
} }

View file

@ -1,37 +0,0 @@
/*
* 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.libraries.architecture
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import app.cash.molecule.AndroidUiDispatcher
import app.cash.molecule.RecompositionClock
import app.cash.molecule.launchMolecule
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.StateFlow
inline fun <reified State> LifecycleOwner.presenterConnector(presenter: Presenter<State>): LifecyclePresenterConnector<State> =
LifecyclePresenterConnector(lifecycleOwner = this, presenter = presenter)
class LifecyclePresenterConnector<State>(lifecycleOwner: LifecycleOwner, presenter: Presenter<State>) {
private val moleculeScope = CoroutineScope(lifecycleOwner.lifecycleScope.coroutineContext + AndroidUiDispatcher.Main)
val stateFlow: StateFlow<State> = moleculeScope.launchMolecule(RecompositionClock.Immediate) {
presenter.present()
}
}