diff --git a/app/src/main/kotlin/io/element/android/x/MainActivity.kt b/app/src/main/kotlin/io/element/android/x/MainActivity.kt index c37a35476d..999f654727 100644 --- a/app/src/main/kotlin/io/element/android/x/MainActivity.kt +++ b/app/src/main/kotlin/io/element/android/x/MainActivity.kt @@ -26,8 +26,8 @@ import androidx.core.view.WindowCompat import com.bumble.appyx.core.integration.NodeHost import com.bumble.appyx.core.integrationpoint.NodeComponentActivity import io.element.android.libraries.architecture.bindings +import io.element.android.libraries.architecture.createNode import io.element.android.libraries.designsystem.theme.ElementTheme -import io.element.android.libraries.di.DaggerComponentOwner import io.element.android.x.di.AppBindings import io.element.android.x.node.RootFlowNode @@ -45,13 +45,7 @@ class MainActivity : NodeComponentActivity() { modifier = Modifier.fillMaxSize(), ) { NodeHost(integrationPoint = appyxIntegrationPoint) { - RootFlowNode( - buildContext = it, - appComponentOwner = applicationContext as DaggerComponentOwner, - authenticationService = appBindings.authenticationService(), - presenter = appBindings.rootPresenter(), - matrixClientsHolder = appBindings.matrixClientsHolder() - ) + createNode(it) } } } diff --git a/app/src/main/kotlin/io/element/android/x/node/LoggedInFlowNode.kt b/app/src/main/kotlin/io/element/android/x/node/LoggedInFlowNode.kt index 10e00d30ef..ac58edbc93 100644 --- a/app/src/main/kotlin/io/element/android/x/node/LoggedInFlowNode.kt +++ b/app/src/main/kotlin/io/element/android/x/node/LoggedInFlowNode.kt @@ -29,38 +29,69 @@ import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.ParentNode 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.features.preferences.PreferencesFlowNode -import io.element.android.features.roomlist.RoomListNode +import io.element.android.features.roomlist.api.RoomListEntryPoint +import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.bindings import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.architecture.nodeInputs +import io.element.android.libraries.architecture.nodeInputsProvider import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.DaggerComponentOwner import io.element.android.libraries.matrix.MatrixClient import io.element.android.libraries.matrix.core.RoomId -import io.element.android.libraries.matrix.core.SessionId import io.element.android.libraries.matrix.ui.di.MatrixUIBindings import io.element.android.x.di.SessionComponent import kotlinx.parcelize.Parcelize +@ContributesNode(AppScope::class) class LoggedInFlowNode( buildContext: BuildContext, - val sessionId: SessionId, - private val matrixClient: MatrixClient, - private val onOpenBugReport: () -> Unit, - private val backstack: BackStack = BackStack( - initialElement = NavTarget.RoomList, - savedStateMap = buildContext.savedStateMap, - ), + plugins: List, + private val backstack: BackStack, + private val roomListEntryPoint: RoomListEntryPoint, ) : ParentNode( navModel = backstack, - buildContext = buildContext + buildContext = buildContext, + plugins = plugins ), DaggerComponentOwner { + @AssistedInject + constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + roomListEntryPoint: RoomListEntryPoint, + ) : this( + buildContext = buildContext, + plugins = plugins, + roomListEntryPoint = roomListEntryPoint, + backstack = BackStack( + initialElement = NavTarget.RoomList, + savedStateMap = buildContext.savedStateMap, + ) + ) + + interface Callback : Plugin { + fun onOpenBugReport() + } + + data class Inputs( + val matrixClient: MatrixClient + ) : NodeInputs + + private val inputs: Inputs by nodeInputs() + override val daggerComponent: Any by lazy { - parent!!.bindings().sessionComponentBuilder().client(matrixClient).build() + parent!!.bindings().sessionComponentBuilder().client(inputs.matrixClient).build() } override fun onBuilt() { @@ -69,7 +100,7 @@ class LoggedInFlowNode( onCreate = { val imageLoaderFactory = bindings().loggedInImageLoaderFactory() Coil.setImageLoader(imageLoaderFactory) - matrixClient.startSync() + inputs.matrixClient.startSync() }, onDestroy = { val imageLoaderFactory = bindings().notLoggedInImageLoaderFactory() @@ -78,16 +109,6 @@ class LoggedInFlowNode( ) } - private val roomListCallback = object : RoomListNode.Callback { - override fun onRoomClicked(roomId: RoomId) { - backstack.push(NavTarget.Room(roomId)) - } - - override fun onSettingsClicked() { - backstack.push(NavTarget.Settings) - } - } - sealed interface NavTarget : Parcelable { @Parcelize object RoomList : NavTarget @@ -102,10 +123,19 @@ class LoggedInFlowNode( override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { return when (navTarget) { NavTarget.RoomList -> { - createNode(buildContext, plugins = listOf(roomListCallback)) + val callback = object : RoomListEntryPoint.Callback { + override fun onRoomClicked(roomId: RoomId) { + backstack.push(NavTarget.Room(roomId)) + } + + override fun onSettingsClicked() { + backstack.push(NavTarget.Settings) + } + } + roomListEntryPoint.node(this, buildContext, plugins = listOf(callback)) } is NavTarget.Room -> { - val room = matrixClient.getRoom(roomId = navTarget.roomId) + val room = inputs.matrixClient.getRoom(roomId = navTarget.roomId) if (room == null) { // TODO CREATE UNKNOWN ROOM NODE node(buildContext) { @@ -114,11 +144,17 @@ class LoggedInFlowNode( } } } else { - RoomFlowNode(buildContext, room) + val inputsProvider = nodeInputsProvider(RoomFlowNode.Inputs(room)) + createNode(buildContext, plugins = listOf(inputsProvider)) } } NavTarget.Settings -> { - PreferencesFlowNode(buildContext, onOpenBugReport) + val callback = object : PreferencesFlowNode.Callback { + override fun onOpenBugReport() { + plugins().forEach { it.onOpenBugReport() } + } + } + createNode(buildContext, plugins = listOf(callback)) } } } diff --git a/app/src/main/kotlin/io/element/android/x/node/NotLoggedInFlowNode.kt b/app/src/main/kotlin/io/element/android/x/node/NotLoggedInFlowNode.kt index b9e38d1063..6a8b66c7f9 100644 --- a/app/src/main/kotlin/io/element/android/x/node/NotLoggedInFlowNode.kt +++ b/app/src/main/kotlin/io/element/android/x/node/NotLoggedInFlowNode.kt @@ -24,25 +24,45 @@ 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.ParentNode -import com.bumble.appyx.core.node.node +import com.bumble.appyx.core.plugin.Plugin import com.bumble.appyx.navmodel.backstack.BackStack import com.bumble.appyx.navmodel.backstack.operation.push -import io.element.android.features.login.LoginFlowNode -import io.element.android.features.onboarding.OnBoardingScreen +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.features.login.api.LoginEntryPoint +import io.element.android.features.onboarding.api.OnBoardingEntryPoint import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler +import io.element.android.libraries.di.AppScope import kotlinx.parcelize.Parcelize import timber.log.Timber -class NotLoggedInFlowNode( +@ContributesNode(AppScope::class) +class NotLoggedInFlowNode private constructor( buildContext: BuildContext, - private val backstack: BackStack = BackStack( - initialElement = NavTarget.OnBoarding, - savedStateMap = buildContext.savedStateMap, - ), + plugins: List, + private val onBoardingEntryPoint: OnBoardingEntryPoint, + private val loginEntryPoint: LoginEntryPoint, + private val backstack: BackStack, ) : ParentNode( navModel = backstack, - buildContext = buildContext + buildContext = buildContext, + plugins = plugins, ) { + @AssistedInject + constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + onBoardingEntryPoint: OnBoardingEntryPoint, + loginEntryPoint: LoginEntryPoint, + ) + : this( + buildContext = buildContext, + plugins = plugins, + onBoardingEntryPoint = onBoardingEntryPoint, + loginEntryPoint = loginEntryPoint, + backstack = BackStack(initialElement = NavTarget.OnBoarding, savedStateMap = buildContext.savedStateMap), + ) init { lifecycle.subscribe( @@ -61,12 +81,21 @@ class NotLoggedInFlowNode( override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { return when (navTarget) { - NavTarget.OnBoarding -> node(buildContext) { - OnBoardingScreen( - onSignIn = { backstack.push(NavTarget.LoginFlow) } - ) + NavTarget.OnBoarding -> { + val callback = object : OnBoardingEntryPoint.Callback { + override fun onSignUp() { + //NOOP + } + + override fun onSignIn() { + backstack.push(NavTarget.LoginFlow) + } + } + onBoardingEntryPoint.node(this, buildContext, plugins = listOf(callback)) + } + NavTarget.LoginFlow -> { + loginEntryPoint.node(this, buildContext) } - NavTarget.LoginFlow -> LoginFlowNode(buildContext) } } diff --git a/app/src/main/kotlin/io/element/android/x/node/RoomFlowNode.kt b/app/src/main/kotlin/io/element/android/x/node/RoomFlowNode.kt index bae60841d6..900d0f7989 100644 --- a/app/src/main/kotlin/io/element/android/x/node/RoomFlowNode.kt +++ b/app/src/main/kotlin/io/element/android/x/node/RoomFlowNode.kt @@ -24,30 +24,52 @@ 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.ParentNode +import com.bumble.appyx.core.plugin.Plugin import com.bumble.appyx.navmodel.backstack.BackStack +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode import io.element.android.features.messages.MessagesNode +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.nodeInputs import io.element.android.libraries.di.DaggerComponentOwner +import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.room.MatrixRoom import io.element.android.x.di.RoomComponent import kotlinx.parcelize.Parcelize import timber.log.Timber +@ContributesNode(SessionScope::class) class RoomFlowNode( buildContext: BuildContext, - private val room: MatrixRoom, - private val backstack: BackStack = BackStack( - initialElement = NavTarget.Messages, - savedStateMap = buildContext.savedStateMap, - ), + plugins: List, + private val backstack: BackStack, ) : ParentNode( navModel = backstack, - buildContext = buildContext + buildContext = buildContext, + plugins = plugins, ), DaggerComponentOwner { + data class Inputs( + val room: MatrixRoom, + ) : NodeInputs + + @AssistedInject + constructor(@Assisted buildContext: BuildContext, @Assisted plugins: List) : this( + buildContext = buildContext, + plugins = plugins, + backstack = BackStack( + initialElement = NavTarget.Messages, + savedStateMap = buildContext.savedStateMap, + ), + ) + + private val inputs: Inputs by nodeInputs() + override val daggerComponent: Any by lazy { - parent!!.bindings().roomComponentBuilder().room(room).build() + parent!!.bindings().roomComponentBuilder().room(inputs.room).build() } init { diff --git a/app/src/main/kotlin/io/element/android/x/node/RootFlowNode.kt b/app/src/main/kotlin/io/element/android/x/node/RootFlowNode.kt index 37fd284b3f..b35ddba736 100644 --- a/app/src/main/kotlin/io/element/android/x/node/RootFlowNode.kt +++ b/app/src/main/kotlin/io/element/android/x/node/RootFlowNode.kt @@ -16,6 +16,7 @@ package io.element.android.x.node +import android.content.Context import android.os.Parcelable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize @@ -28,14 +29,21 @@ import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.ParentNode import com.bumble.appyx.core.node.node +import com.bumble.appyx.core.plugin.Plugin import com.bumble.appyx.navmodel.backstack.BackStack import com.bumble.appyx.navmodel.backstack.operation.newRoot import com.bumble.appyx.navmodel.backstack.operation.pop import com.bumble.appyx.navmodel.backstack.operation.push -import io.element.android.features.rageshake.bugreport.BugReportNode +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.features.rageshake.bugreport.BugReportEntryPoint import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.architecture.nodeInputsProvider import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator +import io.element.android.libraries.di.AppScope +import io.element.android.libraries.di.ApplicationContext import io.element.android.libraries.di.DaggerComponentOwner import io.element.android.libraries.matrix.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.core.SessionId @@ -48,7 +56,8 @@ import kotlinx.coroutines.flow.onEach import kotlinx.parcelize.Parcelize import timber.log.Timber -class RootFlowNode( +@ContributesNode(AppScope::class) +class RootFlowNode private constructor( private val buildContext: BuildContext, private val backstack: BackStack = BackStack( initialElement = NavTarget.SplashScreen, @@ -57,7 +66,8 @@ class RootFlowNode( private val appComponentOwner: DaggerComponentOwner, private val authenticationService: MatrixAuthenticationService, private val matrixClientsHolder: MatrixClientsHolder, - private val presenter: RootPresenter + private val presenter: RootPresenter, + private val bugReportEntryPoint: BugReportEntryPoint, ) : ParentNode( navModel = backstack, @@ -66,6 +76,28 @@ class RootFlowNode( DaggerComponentOwner by appComponentOwner { + @AssistedInject + constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + @ApplicationContext context: Context, + authenticationService: MatrixAuthenticationService, + matrixClientsHolder: MatrixClientsHolder, + presenter: RootPresenter, + bugReportEntryPoint: BugReportEntryPoint, + ) : this( + buildContext = buildContext, + backstack = BackStack( + initialElement = NavTarget.SplashScreen, + savedStateMap = buildContext.savedStateMap, + ), + appComponentOwner = context.applicationContext as DaggerComponentOwner, + authenticationService = authenticationService, + matrixClientsHolder = matrixClientsHolder, + presenter = presenter, + bugReportEntryPoint = bugReportEntryPoint, + ) + override fun onBuilt() { super.onBuilt() observeLoggedInState() @@ -140,12 +172,6 @@ class RootFlowNode( } } - private val bugReportNodeCallback = object : BugReportNode.Callback { - override fun onBugReportSent() { - backstack.pop() - } - } - sealed interface NavTarget : Parcelable { @Parcelize object SplashScreen : NavTarget @@ -167,16 +193,24 @@ class RootFlowNode( Timber.w("Couldn't find any session, go through SplashScreen") backstack.newRoot(NavTarget.SplashScreen) } - LoggedInFlowNode( - buildContext = buildContext, - sessionId = navTarget.sessionId, - matrixClient = matrixClient, - onOpenBugReport = this::onOpenBugReport - ) + val inputsProvider = nodeInputsProvider(LoggedInFlowNode.Inputs(matrixClient)) + val callback = object : LoggedInFlowNode.Callback { + override fun onOpenBugReport() { + backstack.push(NavTarget.BugReport) + } + } + createNode(buildContext, plugins = listOf(inputsProvider, callback)) } - NavTarget.NotLoggedInFlow -> NotLoggedInFlowNode(buildContext) + NavTarget.NotLoggedInFlow -> createNode(buildContext) NavTarget.SplashScreen -> splashNode(buildContext) - NavTarget.BugReport -> createNode(buildContext, plugins = listOf(bugReportNodeCallback)) + NavTarget.BugReport -> { + val callback = object : BugReportEntryPoint.Callback { + override fun onBugReportSent() { + backstack.pop() + } + } + bugReportEntryPoint.node(this, buildContext, plugins = listOf(callback)) + } } } diff --git a/features/login/src/main/kotlin/io/element/android/features/login/api/LoginEntryPoint.kt b/features/login/src/main/kotlin/io/element/android/features/login/api/LoginEntryPoint.kt new file mode 100644 index 0000000000..6a64b459d2 --- /dev/null +++ b/features/login/src/main/kotlin/io/element/android/features/login/api/LoginEntryPoint.kt @@ -0,0 +1,21 @@ +/* + * 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.features.login.api + +import io.element.android.libraries.architecture.EntryPoint + +interface LoginEntryPoint : EntryPoint diff --git a/features/login/src/main/kotlin/io/element/android/features/login/implementation/DefaultLoginEntryPoint.kt b/features/login/src/main/kotlin/io/element/android/features/login/implementation/DefaultLoginEntryPoint.kt new file mode 100644 index 0000000000..08d7080baf --- /dev/null +++ b/features/login/src/main/kotlin/io/element/android/features/login/implementation/DefaultLoginEntryPoint.kt @@ -0,0 +1,33 @@ +/* + * 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.features.login.implementation + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.login.api.LoginEntryPoint +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.AppScope +import javax.inject.Inject + +@ContributesBinding(AppScope::class) +class DefaultLoginEntryPoint @Inject constructor() : LoginEntryPoint { + override fun node(parentNode: Node, buildContext: BuildContext, plugins: List): Node { + return parentNode.createNode(buildContext, plugins) + } +} diff --git a/features/login/src/main/kotlin/io/element/android/features/login/LoginFlowNode.kt b/features/login/src/main/kotlin/io/element/android/features/login/implementation/LoginFlowNode.kt similarity index 60% rename from features/login/src/main/kotlin/io/element/android/features/login/LoginFlowNode.kt rename to features/login/src/main/kotlin/io/element/android/features/login/implementation/LoginFlowNode.kt index 641435642d..923d2aacea 100644 --- a/features/login/src/main/kotlin/io/element/android/features/login/LoginFlowNode.kt +++ b/features/login/src/main/kotlin/io/element/android/features/login/implementation/LoginFlowNode.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login +package io.element.android.features.login.implementation import android.os.Parcelable import androidx.compose.runtime.Composable @@ -23,30 +23,39 @@ import com.bumble.appyx.core.composable.Children import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.ParentNode +import com.bumble.appyx.core.plugin.Plugin import com.bumble.appyx.navmodel.backstack.BackStack import com.bumble.appyx.navmodel.backstack.operation.push -import io.element.android.features.login.changeserver.ChangeServerNode -import io.element.android.features.login.root.LoginRootNode +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.features.login.implementation.changeserver.ChangeServerNode +import io.element.android.features.login.implementation.root.LoginRootNode import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.AppScope import kotlinx.parcelize.Parcelize +@ContributesNode(AppScope::class) class LoginFlowNode( buildContext: BuildContext, - private val backstack: BackStack = BackStack( - initialElement = NavTarget.Root, - savedStateMap = buildContext.savedStateMap, - ), + plugins: List, + private val backstack: BackStack, ) : ParentNode( navModel = backstack, - buildContext = buildContext + buildContext = buildContext, + plugins = plugins, ) { - private val loginRootCallback = object : LoginRootNode.Callback { - override fun onChangeHomeServer() { - backstack.push(NavTarget.ChangeServer) - } - } + @AssistedInject + constructor(@Assisted buildContext: BuildContext, @Assisted plugins: List) : this( + buildContext = buildContext, + plugins = plugins, + backstack = BackStack( + initialElement = NavTarget.Root, + savedStateMap = buildContext.savedStateMap, + ), + ) sealed interface NavTarget : Parcelable { @Parcelize @@ -58,7 +67,14 @@ class LoginFlowNode( override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { return when (navTarget) { - NavTarget.Root -> createNode(buildContext, plugins = listOf(loginRootCallback)) + NavTarget.Root -> { + val callback = object : LoginRootNode.Callback { + override fun onChangeHomeServer() { + backstack.push(NavTarget.ChangeServer) + } + } + createNode(buildContext, plugins = listOf(callback)) + } NavTarget.ChangeServer -> createNode(buildContext) } } diff --git a/features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerEvents.kt b/features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerEvents.kt similarity index 91% rename from features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerEvents.kt rename to features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerEvents.kt index 70b57b5038..8796c1b2cf 100644 --- a/features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerEvents.kt +++ b/features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerEvents.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.changeserver +package io.element.android.features.login.implementation.changeserver sealed interface ChangeServerEvents { data class SetServer(val server: String) : ChangeServerEvents diff --git a/features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerNode.kt b/features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerNode.kt similarity index 95% rename from features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerNode.kt rename to features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerNode.kt index 232b0a6497..760f22ba2f 100644 --- a/features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerNode.kt +++ b/features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerNode.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.changeserver +package io.element.android.features.login.implementation.changeserver import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier diff --git a/features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerPresenter.kt b/features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerPresenter.kt similarity index 97% rename from features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerPresenter.kt rename to features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerPresenter.kt index 038d2ecea1..4cfc4090d4 100644 --- a/features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerPresenter.kt +++ b/features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerPresenter.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.changeserver +package io.element.android.features.login.implementation.changeserver import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState diff --git a/features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerState.kt b/features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerState.kt similarity index 92% rename from features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerState.kt rename to features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerState.kt index 3463e1f238..bc1b8bc6c8 100644 --- a/features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerState.kt +++ b/features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerState.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.changeserver +package io.element.android.features.login.implementation.changeserver import io.element.android.libraries.architecture.Async diff --git a/features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerStateProvider.kt b/features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerStateProvider.kt similarity index 95% rename from features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerStateProvider.kt rename to features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerStateProvider.kt index cc70345415..948d2dbc10 100644 --- a/features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerStateProvider.kt +++ b/features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerStateProvider.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.changeserver +package io.element.android.features.login.implementation.changeserver import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.architecture.Async diff --git a/features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerView.kt b/features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerView.kt similarity index 98% rename from features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerView.kt rename to features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerView.kt index 9610e43f3f..671b71b0dd 100644 --- a/features/login/src/main/kotlin/io/element/android/features/login/changeserver/ChangeServerView.kt +++ b/features/login/src/main/kotlin/io/element/android/features/login/implementation/changeserver/ChangeServerView.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.changeserver +package io.element.android.features.login.implementation.changeserver import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box @@ -46,7 +46,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import io.element.android.features.login.R -import io.element.android.features.login.error.changeServerError +import io.element.android.features.login.implementation.error.changeServerError import io.element.android.libraries.architecture.Async import io.element.android.libraries.designsystem.components.form.textFieldState import io.element.android.libraries.designsystem.preview.ElementPreviewDark diff --git a/features/login/src/main/kotlin/io/element/android/features/login/error/ErrorFormatter.kt b/features/login/src/main/kotlin/io/element/android/features/login/implementation/error/ErrorFormatter.kt similarity index 91% rename from features/login/src/main/kotlin/io/element/android/features/login/error/ErrorFormatter.kt rename to features/login/src/main/kotlin/io/element/android/features/login/implementation/error/ErrorFormatter.kt index 6527a3a141..c5954d9d57 100644 --- a/features/login/src/main/kotlin/io/element/android/features/login/error/ErrorFormatter.kt +++ b/features/login/src/main/kotlin/io/element/android/features/login/implementation/error/ErrorFormatter.kt @@ -14,11 +14,11 @@ * limitations under the License. */ -package io.element.android.features.login.error +package io.element.android.features.login.implementation.error import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import io.element.android.features.login.root.LoginFormState +import io.element.android.features.login.implementation.root.LoginFormState import io.element.android.libraries.core.uri.isValidUrl import io.element.android.libraries.ui.strings.R as StringR diff --git a/features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootEvents.kt b/features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootEvents.kt similarity index 93% rename from features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootEvents.kt rename to features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootEvents.kt index 623f80abc7..ed640018f6 100644 --- a/features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootEvents.kt +++ b/features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootEvents.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.root +package io.element.android.features.login.implementation.root sealed interface LoginRootEvents { object RefreshHomeServer : LoginRootEvents diff --git a/features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootNode.kt b/features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootNode.kt similarity index 97% rename from features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootNode.kt rename to features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootNode.kt index f29eb2a7e5..0ac8f0a337 100644 --- a/features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootNode.kt +++ b/features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootNode.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.root +package io.element.android.features.login.implementation.root import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier diff --git a/features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootPresenter.kt b/features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootPresenter.kt similarity index 98% rename from features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootPresenter.kt rename to features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootPresenter.kt index d51dc5b5f8..dde86ad67e 100644 --- a/features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootPresenter.kt +++ b/features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootPresenter.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.root +package io.element.android.features.login.implementation.root import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState diff --git a/features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootScreen.kt b/features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootScreen.kt similarity index 98% rename from features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootScreen.kt rename to features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootScreen.kt index 740b147bbd..0045d3d6ac 100644 --- a/features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootScreen.kt +++ b/features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootScreen.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.root +package io.element.android.features.login.implementation.root import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -48,7 +48,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import io.element.android.features.login.error.loginError +import io.element.android.features.login.implementation.error.loginError import io.element.android.libraries.designsystem.components.form.textFieldState import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight diff --git a/features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootState.kt b/features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootState.kt similarity index 95% rename from features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootState.kt rename to features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootState.kt index 27af06b11e..f38c876f84 100644 --- a/features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootState.kt +++ b/features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootState.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.root +package io.element.android.features.login.implementation.root import android.os.Parcelable import io.element.android.libraries.matrix.core.SessionId diff --git a/features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootStateProvider.kt b/features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootStateProvider.kt similarity index 92% rename from features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootStateProvider.kt rename to features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootStateProvider.kt index 2a5b737719..b532c6e790 100644 --- a/features/login/src/main/kotlin/io/element/android/features/login/root/LoginRootStateProvider.kt +++ b/features/login/src/main/kotlin/io/element/android/features/login/implementation/root/LoginRootStateProvider.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.login.root +package io.element.android.features.login.implementation.root fun aLoginRootState() = LoginRootState( homeserver = "", diff --git a/features/login/src/test/kotlin/io/element/android/features/login/changeserver/ChangeServerPresenterTest.kt b/features/login/src/test/kotlin/io/element/android/features/login/changeserver/ChangeServerPresenterTest.kt index b22c03dc35..69cc327015 100644 --- a/features/login/src/test/kotlin/io/element/android/features/login/changeserver/ChangeServerPresenterTest.kt +++ b/features/login/src/test/kotlin/io/element/android/features/login/changeserver/ChangeServerPresenterTest.kt @@ -22,6 +22,8 @@ import app.cash.molecule.RecompositionClock import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import io.element.android.features.login.implementation.changeserver.ChangeServerEvents +import io.element.android.features.login.implementation.changeserver.ChangeServerPresenter import io.element.android.libraries.architecture.Async import io.element.android.libraries.matrixtest.A_HOMESERVER import io.element.android.libraries.matrixtest.auth.FakeAuthenticationService diff --git a/features/login/src/test/kotlin/io/element/android/features/login/root/LoginRootPresenterTest.kt b/features/login/src/test/kotlin/io/element/android/features/login/root/LoginRootPresenterTest.kt index 3fa20ae93a..36f4081ca9 100644 --- a/features/login/src/test/kotlin/io/element/android/features/login/root/LoginRootPresenterTest.kt +++ b/features/login/src/test/kotlin/io/element/android/features/login/root/LoginRootPresenterTest.kt @@ -22,6 +22,10 @@ import app.cash.molecule.RecompositionClock import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import io.element.android.features.login.implementation.root.LoggedInState +import io.element.android.features.login.implementation.root.LoginFormState +import io.element.android.features.login.implementation.root.LoginRootEvents +import io.element.android.features.login.implementation.root.LoginRootPresenter import io.element.android.libraries.matrix.core.SessionId import io.element.android.libraries.matrixtest.A_HOMESERVER import io.element.android.libraries.matrixtest.A_HOMESERVER_2 diff --git a/features/onboarding/build.gradle.kts b/features/onboarding/build.gradle.kts index fcefcb0068..d9636304aa 100644 --- a/features/onboarding/build.gradle.kts +++ b/features/onboarding/build.gradle.kts @@ -19,15 +19,23 @@ plugins { id("io.element.android-compose-library") alias(libs.plugins.ksp) + alias(libs.plugins.anvil) } android { namespace = "io.element.android.features.onboarding" } +anvil { + generateDaggerFactories.set(true) +} + + dependencies { implementation(projects.libraries.core) implementation(projects.libraries.elementresources) + implementation(projects.anvilannotations) + anvil(projects.anvilcodegen) implementation(projects.libraries.uiStrings) implementation(projects.libraries.designsystem) implementation(projects.libraries.architecture) diff --git a/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/api/OnBoardingEntryPoint.kt b/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/api/OnBoardingEntryPoint.kt new file mode 100644 index 0000000000..b603e8d40e --- /dev/null +++ b/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/api/OnBoardingEntryPoint.kt @@ -0,0 +1,27 @@ +/* + * 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.features.onboarding.api + +import com.bumble.appyx.core.plugin.Plugin +import io.element.android.libraries.architecture.EntryPoint + +interface OnBoardingEntryPoint : EntryPoint { + interface Callback : Plugin { + fun onSignUp() + fun onSignIn() + } +} diff --git a/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/implementation/DefaultOnBoardingEntryPoint.kt b/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/implementation/DefaultOnBoardingEntryPoint.kt new file mode 100644 index 0000000000..fc6b19d6a4 --- /dev/null +++ b/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/implementation/DefaultOnBoardingEntryPoint.kt @@ -0,0 +1,33 @@ +/* + * 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.features.onboarding.implementation + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.onboarding.api.OnBoardingEntryPoint +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.AppScope +import javax.inject.Inject + +@ContributesBinding(AppScope::class) +class DefaultOnBoardingEntryPoint @Inject constructor() : OnBoardingEntryPoint { + override fun node(parentNode: Node, buildContext: BuildContext, plugins: List): Node { + return parentNode.createNode(buildContext, plugins) + } +} diff --git a/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/implementation/OnBoardingNode.kt b/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/implementation/OnBoardingNode.kt new file mode 100644 index 0000000000..f46d8e7b07 --- /dev/null +++ b/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/implementation/OnBoardingNode.kt @@ -0,0 +1,56 @@ +/* + * 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.features.onboarding.implementation + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +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 dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.features.onboarding.api.OnBoardingEntryPoint +import io.element.android.libraries.di.AppScope + +@ContributesNode(AppScope::class) +class OnBoardingNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, +) : Node( + buildContext = buildContext, + plugins = plugins +) { + + private fun onSignIn() { + plugins().forEach { it.onSignIn() } + } + + private fun onSignUp() { + plugins().forEach { it.onSignUp() } + } + + @Composable + override fun View(modifier: Modifier) { + OnBoardingScreen( + modifier = modifier, + onSignIn = this::onSignIn, + onSignUp = this::onSignUp + ) + } +} diff --git a/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/OnBoardingScreen.kt b/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/implementation/OnBoardingScreen.kt similarity index 98% rename from features/onboarding/src/main/kotlin/io/element/android/features/onboarding/OnBoardingScreen.kt rename to features/onboarding/src/main/kotlin/io/element/android/features/onboarding/implementation/OnBoardingScreen.kt index a83043e199..d154aec02c 100644 --- a/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/OnBoardingScreen.kt +++ b/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/implementation/OnBoardingScreen.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 New Vector Ltd + * 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.onboarding +package io.element.android.features.onboarding.implementation import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box diff --git a/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/SplashCarouselData.kt b/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/implementation/SplashCarouselData.kt similarity index 89% rename from features/onboarding/src/main/kotlin/io/element/android/features/onboarding/SplashCarouselData.kt rename to features/onboarding/src/main/kotlin/io/element/android/features/onboarding/implementation/SplashCarouselData.kt index 58d1b6534c..184c85a90e 100644 --- a/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/SplashCarouselData.kt +++ b/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/implementation/SplashCarouselData.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 New Vector Ltd + * 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.onboarding +package io.element.android.features.onboarding.implementation import androidx.annotation.DrawableRes import androidx.annotation.StringRes diff --git a/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/SplashCarouselDataFactory.kt b/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/implementation/SplashCarouselDataFactory.kt similarity index 95% rename from features/onboarding/src/main/kotlin/io/element/android/features/onboarding/SplashCarouselDataFactory.kt rename to features/onboarding/src/main/kotlin/io/element/android/features/onboarding/implementation/SplashCarouselDataFactory.kt index e2848839ce..a8d358387f 100644 --- a/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/SplashCarouselDataFactory.kt +++ b/features/onboarding/src/main/kotlin/io/element/android/features/onboarding/implementation/SplashCarouselDataFactory.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 New Vector Ltd + * 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. @@ -14,9 +14,10 @@ * limitations under the License. */ -package io.element.android.features.onboarding +package io.element.android.features.onboarding.implementation import androidx.annotation.DrawableRes +import io.element.android.features.onboarding.R import io.element.android.libraries.ui.strings.R as StringR class SplashCarouselDataFactory { diff --git a/features/preferences/src/main/kotlin/io/element/android/features/preferences/PreferencesFlowNode.kt b/features/preferences/src/main/kotlin/io/element/android/features/preferences/PreferencesFlowNode.kt index 5407072398..54eb593ee7 100644 --- a/features/preferences/src/main/kotlin/io/element/android/features/preferences/PreferencesFlowNode.kt +++ b/features/preferences/src/main/kotlin/io/element/android/features/preferences/PreferencesFlowNode.kt @@ -23,27 +23,46 @@ import com.bumble.appyx.core.composable.Children import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.ParentNode +import com.bumble.appyx.core.plugin.Plugin +import com.bumble.appyx.core.plugin.plugins import com.bumble.appyx.navmodel.backstack.BackStack +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode import io.element.android.features.preferences.root.PreferencesRootNode import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.SessionScope import kotlinx.parcelize.Parcelize +@ContributesNode(SessionScope::class) class PreferencesFlowNode( buildContext: BuildContext, - private val onOpenBugReport: () -> Unit, - private val backstack: BackStack = BackStack( - initialElement = NavTarget.Root, - savedStateMap = buildContext.savedStateMap, - ), + plugins: List, + private val backstack: BackStack, ) : ParentNode( navModel = backstack, - buildContext = buildContext + buildContext = buildContext, + plugins = plugins ) { + @AssistedInject + constructor(@Assisted buildContext: BuildContext, @Assisted plugins: List) : this( + buildContext = buildContext, + plugins = plugins, + backstack = BackStack( + initialElement = NavTarget.Root, + savedStateMap = buildContext.savedStateMap, + ) + ) + + interface Callback : Plugin { + fun onOpenBugReport() + } + private val preferencesRootNodeCallback = object : PreferencesRootNode.Callback { override fun onOpenBugReport() { - onOpenBugReport.invoke() + plugins().forEach { it.onOpenBugReport() } } } diff --git a/features/rageshake/src/main/kotlin/io/element/android/features/rageshake/bugreport/BugReportEntryPoint.kt b/features/rageshake/src/main/kotlin/io/element/android/features/rageshake/bugreport/BugReportEntryPoint.kt new file mode 100644 index 0000000000..43f916328d --- /dev/null +++ b/features/rageshake/src/main/kotlin/io/element/android/features/rageshake/bugreport/BugReportEntryPoint.kt @@ -0,0 +1,26 @@ +/* + * 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.features.rageshake.bugreport + +import com.bumble.appyx.core.plugin.Plugin +import io.element.android.libraries.architecture.EntryPoint + +interface BugReportEntryPoint : EntryPoint { + interface Callback : Plugin { + fun onBugReportSent() + } +} diff --git a/features/rageshake/src/main/kotlin/io/element/android/features/rageshake/bugreport/BugReportNode.kt b/features/rageshake/src/main/kotlin/io/element/android/features/rageshake/bugreport/BugReportNode.kt index 8c0ffceee8..79c1beec0f 100644 --- a/features/rageshake/src/main/kotlin/io/element/android/features/rageshake/bugreport/BugReportNode.kt +++ b/features/rageshake/src/main/kotlin/io/element/android/features/rageshake/bugreport/BugReportNode.kt @@ -34,10 +34,6 @@ class BugReportNode @AssistedInject constructor( private val presenter: BugReportPresenter, ) : Node(buildContext, plugins = plugins) { - interface Callback : Plugin { - fun onBugReportSent() - } - @Composable override fun View(modifier: Modifier) { val state = presenter.present() @@ -49,6 +45,6 @@ class BugReportNode @AssistedInject constructor( } private fun onDone() { - plugins().forEach { it.onBugReportSent() } + plugins().forEach { it.onBugReportSent() } } } diff --git a/features/rageshake/src/main/kotlin/io/element/android/features/rageshake/bugreport/DefaultBugReportEntryPoint.kt b/features/rageshake/src/main/kotlin/io/element/android/features/rageshake/bugreport/DefaultBugReportEntryPoint.kt new file mode 100644 index 0000000000..819a33ca72 --- /dev/null +++ b/features/rageshake/src/main/kotlin/io/element/android/features/rageshake/bugreport/DefaultBugReportEntryPoint.kt @@ -0,0 +1,32 @@ +/* + * 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.features.rageshake.bugreport + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.AppScope +import javax.inject.Inject + +@ContributesBinding(AppScope::class) +class DefaultBugReportEntryPoint @Inject constructor() : BugReportEntryPoint { + override fun node(parentNode: Node, buildContext: BuildContext, plugins: List): Node { + return parentNode.createNode(buildContext, plugins) + } +} diff --git a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/api/RoomListEntryPoint.kt b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/api/RoomListEntryPoint.kt new file mode 100644 index 0000000000..cadd4ea93d --- /dev/null +++ b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/api/RoomListEntryPoint.kt @@ -0,0 +1,28 @@ +/* + * 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.features.roomlist.api + +import com.bumble.appyx.core.plugin.Plugin +import io.element.android.libraries.architecture.EntryPoint +import io.element.android.libraries.matrix.core.RoomId + +interface RoomListEntryPoint : EntryPoint { + interface Callback : Plugin { + fun onRoomClicked(roomId: RoomId) + fun onSettingsClicked() + } +} diff --git a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/DefaultRoomListEntryPoint.kt b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/DefaultRoomListEntryPoint.kt new file mode 100644 index 0000000000..4a1e5d6a09 --- /dev/null +++ b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/DefaultRoomListEntryPoint.kt @@ -0,0 +1,33 @@ +/* + * 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.features.roomlist.impl + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.roomlist.api.RoomListEntryPoint +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.AppScope +import javax.inject.Inject + +@ContributesBinding(AppScope::class) +class DefaultRoomListEntryPoint @Inject constructor() : RoomListEntryPoint { + override fun node(parentNode: Node, buildContext: BuildContext, plugins: List): Node { + return parentNode.createNode(buildContext, plugins) + } +} diff --git a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListEvents.kt b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListEvents.kt similarity index 93% rename from features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListEvents.kt rename to features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListEvents.kt index 4349c93341..40248b3723 100644 --- a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListEvents.kt +++ b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListEvents.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.roomlist.model +package io.element.android.features.roomlist.impl sealed interface RoomListEvents { data class UpdateFilter(val newFilter: String) : RoomListEvents diff --git a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/RoomListNode.kt b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListNode.kt similarity index 85% rename from features/roomlist/src/main/kotlin/io/element/android/features/roomlist/RoomListNode.kt rename to features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListNode.kt index ecf6dc3c98..de2ea0bfee 100644 --- a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/RoomListNode.kt +++ b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListNode.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.roomlist +package io.element.android.features.roomlist.impl import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -25,6 +25,7 @@ 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.features.roomlist.api.RoomListEntryPoint import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.core.RoomId @@ -35,17 +36,12 @@ class RoomListNode @AssistedInject constructor( private val presenter: RoomListPresenter, ) : Node(buildContext, plugins = plugins) { - interface Callback : Plugin { - fun onRoomClicked(roomId: RoomId) - fun onSettingsClicked() - } - private fun onRoomClicked(roomId: RoomId) { - plugins().forEach { it.onRoomClicked(roomId) } + plugins().forEach { it.onRoomClicked(roomId) } } private fun onOpenSettings() { - plugins().forEach { it.onSettingsClicked() } + plugins().forEach { it.onSettingsClicked() } } @Composable diff --git a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/RoomListPresenter.kt b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt similarity index 94% rename from features/roomlist/src/main/kotlin/io/element/android/features/roomlist/RoomListPresenter.kt rename to features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt index a36e7729a6..52758eadf6 100644 --- a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/RoomListPresenter.kt +++ b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.roomlist +package io.element.android.features.roomlist.impl import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -25,10 +25,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue -import io.element.android.features.roomlist.model.RoomListEvents -import io.element.android.features.roomlist.model.RoomListRoomSummary -import io.element.android.features.roomlist.model.RoomListRoomSummaryPlaceholders -import io.element.android.features.roomlist.model.RoomListState import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.parallelMap import io.element.android.libraries.dateformatter.LastMessageFormatter diff --git a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListRoomSummary.kt b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListRoomSummary.kt similarity index 95% rename from features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListRoomSummary.kt rename to features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListRoomSummary.kt index 5f9e883e5d..44fcc5dc26 100644 --- a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListRoomSummary.kt +++ b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListRoomSummary.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.roomlist.model +package io.element.android.features.roomlist.impl import androidx.compose.runtime.Immutable import io.element.android.libraries.designsystem.components.avatar.AvatarData diff --git a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListRoomSummaryPlaceholders.kt b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListRoomSummaryPlaceholders.kt similarity index 93% rename from features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListRoomSummaryPlaceholders.kt rename to features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListRoomSummaryPlaceholders.kt index b1f48c8ab2..b81803f5a9 100644 --- a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListRoomSummaryPlaceholders.kt +++ b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListRoomSummaryPlaceholders.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 New Vector Ltd + * 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.roomlist.model +package io.element.android.features.roomlist.impl import io.element.android.libraries.designsystem.components.avatar.AvatarData diff --git a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListRoomSummaryProvider.kt b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListRoomSummaryProvider.kt similarity index 94% rename from features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListRoomSummaryProvider.kt rename to features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListRoomSummaryProvider.kt index 41a6f96473..9aef9fd732 100644 --- a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListRoomSummaryProvider.kt +++ b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListRoomSummaryProvider.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 New Vector Ltd + * 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.roomlist.model +package io.element.android.features.roomlist.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.designsystem.components.avatar.AvatarData diff --git a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListState.kt b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt similarity index 94% rename from features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListState.kt rename to features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt index e9a48a7249..69e47a4250 100644 --- a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListState.kt +++ b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.roomlist.model +package io.element.android.features.roomlist.impl import androidx.compose.runtime.Immutable import io.element.android.libraries.matrix.ui.model.MatrixUser diff --git a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListStateProvider.kt b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt similarity index 97% rename from features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListStateProvider.kt rename to features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt index fd361e6b02..9b4b2e93ca 100644 --- a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/model/RoomListStateProvider.kt +++ b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.roomlist.model +package io.element.android.features.roomlist.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.designsystem.components.avatar.AvatarData diff --git a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/RoomListView.kt b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt similarity index 92% rename from features/roomlist/src/main/kotlin/io/element/android/features/roomlist/RoomListView.kt rename to features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt index 1ebc2328db..ee6a267190 100644 --- a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/RoomListView.kt +++ b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 New Vector Ltd + * 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.roomlist +package io.element.android.features.roomlist.impl import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding @@ -34,12 +34,8 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.Velocity -import io.element.android.features.roomlist.components.RoomListTopBar -import io.element.android.features.roomlist.components.RoomSummaryRow -import io.element.android.features.roomlist.model.RoomListEvents -import io.element.android.features.roomlist.model.RoomListRoomSummary -import io.element.android.features.roomlist.model.RoomListState -import io.element.android.features.roomlist.model.RoomListStateProvider +import io.element.android.features.roomlist.impl.components.RoomListTopBar +import io.element.android.features.roomlist.impl.components.RoomSummaryRow import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.theme.components.Scaffold diff --git a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/components/RoomListTopBar.kt b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt similarity index 98% rename from features/roomlist/src/main/kotlin/io/element/android/features/roomlist/components/RoomListTopBar.kt rename to features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt index e27b8eaba9..f8dd16a873 100644 --- a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/components/RoomListTopBar.kt +++ b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 New Vector Ltd + * 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. @@ -16,7 +16,7 @@ @file:OptIn(ExperimentalMaterial3Api::class) -package io.element.android.features.roomlist.components +package io.element.android.features.roomlist.impl.components import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.fillMaxWidth diff --git a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/components/RoomSummaryRow.kt b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt similarity index 96% rename from features/roomlist/src/main/kotlin/io/element/android/features/roomlist/components/RoomSummaryRow.kt rename to features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt index 506ced9a1d..ebacfeb917 100644 --- a/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/components/RoomSummaryRow.kt +++ b/features/roomlist/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 New Vector Ltd + * 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.roomlist.components +package io.element.android.features.roomlist.impl.components import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -53,8 +53,8 @@ import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.google.accompanist.placeholder.material.placeholder -import io.element.android.features.roomlist.model.RoomListRoomSummary -import io.element.android.features.roomlist.model.RoomListRoomSummaryProvider +import io.element.android.features.roomlist.impl.RoomListRoomSummary +import io.element.android.features.roomlist.impl.RoomListRoomSummaryProvider import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight diff --git a/features/roomlist/src/test/kotlin/io/element/android/features/roomlist/RoomListPresenterTests.kt b/features/roomlist/src/test/kotlin/io/element/android/features/roomlist/RoomListPresenterTests.kt index 743fd2d888..b43efdab28 100644 --- a/features/roomlist/src/test/kotlin/io/element/android/features/roomlist/RoomListPresenterTests.kt +++ b/features/roomlist/src/test/kotlin/io/element/android/features/roomlist/RoomListPresenterTests.kt @@ -22,8 +22,9 @@ import app.cash.molecule.RecompositionClock import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat -import io.element.android.features.roomlist.model.RoomListEvents -import io.element.android.features.roomlist.model.RoomListRoomSummary +import io.element.android.features.roomlist.impl.RoomListPresenter +import io.element.android.features.roomlist.impl.RoomListEvents +import io.element.android.features.roomlist.impl.RoomListRoomSummary import io.element.android.libraries.dateformatter.LastMessageFormatter import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.matrix.core.SessionId diff --git a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/EntryPoint.kt b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/EntryPoint.kt new file mode 100644 index 0000000000..4330b67e7e --- /dev/null +++ b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/EntryPoint.kt @@ -0,0 +1,25 @@ +/* + * 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 com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin + +interface EntryPoint { + fun node(parentNode: Node, buildContext: BuildContext, plugins: List = emptyList()): Node +} diff --git a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt index 6a4d52d20e..82ec21667b 100644 --- a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt +++ b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeFactories.kt @@ -16,14 +16,24 @@ package io.element.android.libraries.architecture +import android.content.Context import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin inline fun Node.createNode(context: BuildContext, plugins: List = emptyList()): NODE { - val nodeClass = NODE::class.java val bindings: NodeFactoriesBindings = bindings() - val nodeFactoryMap = bindings.nodeFactories() + return bindings.createNode(context, plugins) +} + +inline fun Context.createNode(context: BuildContext, plugins: List = emptyList()): NODE { + val bindings: NodeFactoriesBindings = bindings() + return bindings.createNode(context, plugins) +} + +inline fun NodeFactoriesBindings.createNode(context: BuildContext, plugins: List = emptyList()): NODE { + val nodeClass = NODE::class.java + val nodeFactoryMap = nodeFactories() val nodeFactory = nodeFactoryMap[nodeClass] ?: error("Cannot find NodeFactory for ${nodeClass.name}.") @Suppress("UNCHECKED_CAST") diff --git a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeInputs.kt b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeInputs.kt new file mode 100644 index 0000000000..d51c49c118 --- /dev/null +++ b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/NodeInputs.kt @@ -0,0 +1,36 @@ +/* + * 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 com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import com.bumble.appyx.core.plugin.plugins +import kotlin.properties.ReadOnlyProperty + +interface NodeInputs + +interface NodeInputsProvider : Plugin { + fun inputs(): I +} + +inline fun nodeInputsProvider(inputs: I) = object : NodeInputsProvider { + override fun inputs() = inputs +} + +fun nodeInputs() = ReadOnlyProperty { thisRef, _ -> + thisRef.plugins>().first().inputs() +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementTheme.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementTheme.kt index cbeb84badb..545834ac3c 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementTheme.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementTheme.kt @@ -57,7 +57,7 @@ fun ElementTheme( ) { val systemUiController = rememberSystemUiController() val useDarkIcons = !darkTheme - val currentColor = remember { if (darkTheme) darkColors else lightColors } + val currentColor = remember(darkTheme) { if (darkTheme) darkColors else lightColors } val colorScheme = when { dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { val context = LocalContext.current diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/LoginScreen.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/LoginScreen.kt index a6a28ed9d0..d735f9124b 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/LoginScreen.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/LoginScreen.kt @@ -19,8 +19,8 @@ package io.element.android.samples.minimal import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import io.element.android.features.login.root.LoginRootPresenter -import io.element.android.features.login.root.LoginRootScreen +import io.element.android.features.login.implementation.root.LoginRootPresenter +import io.element.android.features.login.implementation.root.LoginRootScreen import io.element.android.libraries.matrix.auth.MatrixAuthenticationService class LoginScreen(private val authenticationService: MatrixAuthenticationService) { diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt index 0158c77eab..32d9820d4d 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt @@ -19,8 +19,8 @@ package io.element.android.samples.minimal import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.ui.Modifier -import io.element.android.features.roomlist.RoomListPresenter -import io.element.android.features.roomlist.RoomListView +import io.element.android.features.roomlist.impl.RoomListPresenter +import io.element.android.features.roomlist.impl.RoomListView import io.element.android.libraries.dateformatter.impl.DateFormatters import io.element.android.libraries.dateformatter.impl.DefaultLastMessageFormatter import io.element.android.libraries.dateformatter.impl.LocalDateTimeProvider