diff --git a/features/createroom/build.gradle.kts b/features/createroom/build.gradle.kts index 853783fa97..b32d578796 100644 --- a/features/createroom/build.gradle.kts +++ b/features/createroom/build.gradle.kts @@ -20,6 +20,7 @@ plugins { id("io.element.android-compose-library") alias(libs.plugins.ksp) alias(libs.plugins.anvil) + id("kotlin-parcelize") } android { diff --git a/features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomNode.kt b/features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomNode.kt index 584e4ddf1d..d474b56af8 100644 --- a/features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomNode.kt +++ b/features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomNode.kt @@ -16,29 +16,48 @@ package io.element.android.features.createroom +import android.os.Parcelable import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +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.plugin.Plugin -import dagger.assisted.Assisted -import dagger.assisted.AssistedInject -import io.element.android.anvilannotations.ContributesNode -import io.element.android.libraries.di.SessionScope +import com.bumble.appyx.core.node.ParentNode +import com.bumble.appyx.navmodel.backstack.BackStack +import io.element.android.features.createroom.root.CreateRoomRootNode +import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler +import io.element.android.libraries.architecture.createNode +import kotlinx.parcelize.Parcelize -@ContributesNode(SessionScope::class) -class CreateRoomNode @AssistedInject constructor( - @Assisted buildContext: BuildContext, - @Assisted plugins: List, - private val presenter: CreateRoomPresenter, -) : Node(buildContext, plugins = plugins) { +class CreateRoomNode( + buildContext: BuildContext, + private val backstack: BackStack = BackStack( + initialElement = NavTarget.Root, + savedStateMap = buildContext.savedStateMap, + ), +) : ParentNode( + navModel = backstack, + buildContext = buildContext +) { + + sealed interface NavTarget : Parcelable { + @Parcelize + object Root : NavTarget + } + + override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { + return when (navTarget) { + NavTarget.Root -> createNode(buildContext) + } + } @Composable override fun View(modifier: Modifier) { - val state = presenter.present() - CreateRoomView( - state = state, - modifier = modifier + Children( + navModel = backstack, + modifier = modifier, + // Animate transition to change server screen + transitionHandler = rememberDefaultTransitionHandler(), ) } } diff --git a/features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomEvents.kt b/features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootEvents.kt similarity index 83% rename from features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomEvents.kt rename to features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootEvents.kt index 616d6d9881..5c051abf69 100644 --- a/features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomEvents.kt +++ b/features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootEvents.kt @@ -14,9 +14,9 @@ * limitations under the License. */ -package io.element.android.features.createroom +package io.element.android.features.createroom.root // TODO Add your events or remove the file completely if no events -sealed interface CreateRoomEvents { - object MyEvent : CreateRoomEvents +sealed interface CreateRoomRootEvents { + object MyEvent : CreateRoomRootEvents } diff --git a/features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootNode.kt b/features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootNode.kt new file mode 100644 index 0000000000..0ddfcc4b96 --- /dev/null +++ b/features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootNode.kt @@ -0,0 +1,51 @@ +/* + * 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.createroom.root + +import android.os.Parcelable +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 dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.di.SessionScope +import kotlinx.parcelize.Parcelize + +@ContributesNode(SessionScope::class) +class CreateRoomRootNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenter: CreateRoomRootPresenter, +) : Node(buildContext, plugins = plugins) { + + sealed interface NavTarget : Parcelable { + @Parcelize + object Root : NavTarget + } + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + CreateRoomRootView( + state = state, + modifier = modifier + ) + } +} diff --git a/features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomPresenter.kt b/features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootPresenter.kt similarity index 72% rename from features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomPresenter.kt rename to features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootPresenter.kt index bebff13d1f..287e4d6e42 100644 --- a/features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomPresenter.kt +++ b/features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootPresenter.kt @@ -14,24 +14,24 @@ * limitations under the License. */ -package io.element.android.features.createroom +package io.element.android.features.createroom.root import androidx.compose.runtime.Composable import io.element.android.libraries.architecture.Presenter import javax.inject.Inject -class CreateRoomPresenter @Inject constructor() : Presenter { +class CreateRoomRootPresenter @Inject constructor() : Presenter { @Composable - override fun present(): CreateRoomState { + override fun present(): CreateRoomRootState { - fun handleEvents(event: CreateRoomEvents) { + fun handleEvents(event: CreateRoomRootEvents) { when (event) { - CreateRoomEvents.MyEvent -> Unit + CreateRoomRootEvents.MyEvent -> Unit } } - return CreateRoomState( + return CreateRoomRootState( eventSink = ::handleEvents ) } diff --git a/features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomState.kt b/features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootState.kt similarity index 84% rename from features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomState.kt rename to features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootState.kt index 57cdbdb394..9793cd950e 100644 --- a/features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomState.kt +++ b/features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootState.kt @@ -14,10 +14,10 @@ * limitations under the License. */ -package io.element.android.features.createroom +package io.element.android.features.createroom.root // TODO add your ui models. Remove the eventSink if you don't have events. // Do not use default value, so no member get forgotten in the presenters. -data class CreateRoomState( - val eventSink: (CreateRoomEvents) -> Unit +data class CreateRoomRootState( + val eventSink: (CreateRoomRootEvents) -> Unit ) diff --git a/features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomStateProvider.kt b/features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootStateProvider.kt similarity index 73% rename from features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomStateProvider.kt rename to features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootStateProvider.kt index 86118f2800..b5ff38bcec 100644 --- a/features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomStateProvider.kt +++ b/features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootStateProvider.kt @@ -14,18 +14,18 @@ * limitations under the License. */ -package io.element.android.features.createroom +package io.element.android.features.createroom.root import androidx.compose.ui.tooling.preview.PreviewParameterProvider -open class CreateRoomStateProvider : PreviewParameterProvider { - override val values: Sequence +open class CreateRoomRootStateProvider : PreviewParameterProvider { + override val values: Sequence get() = sequenceOf( - aCreateRoomState(), + aCreateRoomRootState(), // Add other state here ) } -fun aCreateRoomState() = CreateRoomState( +fun aCreateRoomRootState() = CreateRoomRootState( eventSink = {} ) diff --git a/features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomView.kt b/features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootView.kt similarity index 78% rename from features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomView.kt rename to features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootView.kt index 3b5ea6c20c..70ac7eea65 100644 --- a/features/createroom/src/main/kotlin/io/element/android/features/createroom/CreateRoomView.kt +++ b/features/createroom/src/main/kotlin/io/element/android/features/createroom/root/CreateRoomRootView.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.features.createroom +package io.element.android.features.createroom.root import androidx.compose.foundation.layout.Box import androidx.compose.material3.MaterialTheme @@ -28,8 +28,8 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.theme.components.Text @Composable -fun CreateRoomView( - state: CreateRoomState, +fun CreateRoomRootView( + state: CreateRoomRootState, modifier: Modifier = Modifier, ) { Box(modifier, contentAlignment = Alignment.Center) { @@ -42,17 +42,17 @@ fun CreateRoomView( @Preview @Composable -fun CreateRoomViewLightPreview(@PreviewParameter(CreateRoomStateProvider::class) state: CreateRoomState) = +fun CreateRoomRootViewLightPreview(@PreviewParameter(CreateRoomRootStateProvider::class) state: CreateRoomRootState) = ElementPreviewLight { ContentToPreview(state) } @Preview @Composable -fun CreateRoomViewDarkPreview(@PreviewParameter(CreateRoomStateProvider::class) state: CreateRoomState) = +fun CreateRoomRootViewDarkPreview(@PreviewParameter(CreateRoomRootStateProvider::class) state: CreateRoomRootState) = ElementPreviewDark { ContentToPreview(state) } @Composable -private fun ContentToPreview(state: CreateRoomState) { - CreateRoomView( +private fun ContentToPreview(state: CreateRoomRootState) { + CreateRoomRootView( state = state, ) } diff --git a/features/createroom/src/test/kotlin/io/element/android/features/createroom/CreateRoomPresenterTests.kt b/features/createroom/src/test/kotlin/io/element/android/features/createroom/root/CreateRoomRootPresenterTests.kt similarity index 84% rename from features/createroom/src/test/kotlin/io/element/android/features/createroom/CreateRoomPresenterTests.kt rename to features/createroom/src/test/kotlin/io/element/android/features/createroom/root/CreateRoomRootPresenterTests.kt index bd19a67ab0..c57c24d75c 100644 --- a/features/createroom/src/test/kotlin/io/element/android/features/createroom/CreateRoomPresenterTests.kt +++ b/features/createroom/src/test/kotlin/io/element/android/features/createroom/root/CreateRoomRootPresenterTests.kt @@ -16,7 +16,7 @@ @file:OptIn(ExperimentalCoroutinesApi::class) -package io.element.android.features.createroom +package io.element.android.features.createroom.root import app.cash.molecule.RecompositionClock import app.cash.molecule.moleculeFlow @@ -26,11 +26,11 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.Test -class CreateRoomPresenterTests { +class CreateRoomRootPresenterTests { @Test fun `present - initial state`() = runTest { - val presenter = CreateRoomPresenter() + val presenter = CreateRoomRootPresenter() moleculeFlow(RecompositionClock.Immediate) { presenter.present() }.test { @@ -41,12 +41,12 @@ class CreateRoomPresenterTests { @Test fun `present - send event`() = runTest { - val presenter = CreateRoomPresenter() + val presenter = CreateRoomRootPresenter() moleculeFlow(RecompositionClock.Immediate) { presenter.present() }.test { val initialState = awaitItem() - initialState.eventSink.invoke(CreateRoomEvents.MyEvent) + initialState.eventSink.invoke(CreateRoomRootEvents.MyEvent) } } }