From e2ba1442aa379e1090725d4efd05b4af7a044d81 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com> Date: Mon, 13 Mar 2023 10:34:15 +0100 Subject: [PATCH] Adding selectmembers node with navigation --- .../createroom/impl/CreateRoomFlowNode.kt | 15 ++- .../impl/root/CreateRoomRootEvents.kt | 1 - .../impl/root/CreateRoomRootNode.kt | 10 ++ .../impl/root/CreateRoomRootPresenter.kt | 1 - .../impl/root/CreateRoomRootView.kt | 3 +- .../impl/selectmembers/SelectMembersEvents.kt | 19 ++++ .../impl/selectmembers/SelectMembersNode.kt | 46 ++++++++ .../selectmembers/SelectMembersPresenter.kt | 36 +++++++ .../impl/selectmembers/SelectMembersState.kt | 21 ++++ .../SelectMembersStateProvider.kt | 30 ++++++ .../impl/selectmembers/SelectMembersView.kt | 102 ++++++++++++++++++ 11 files changed, 280 insertions(+), 4 deletions(-) create mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersEvents.kt create mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersNode.kt create mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersPresenter.kt create mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersState.kt create mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersStateProvider.kt create mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersView.kt diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomFlowNode.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomFlowNode.kt index 618eda0166..805d11a319 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomFlowNode.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomFlowNode.kt @@ -24,10 +24,12 @@ 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.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.createroom.impl.root.CreateRoomRootNode +import io.element.android.features.createroom.impl.selectmembers.SelectMembersNode import io.element.android.libraries.architecture.BackstackNode import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.createNode @@ -50,11 +52,22 @@ class CreateRoomFlowNode @AssistedInject constructor( sealed interface NavTarget : Parcelable { @Parcelize object Root : NavTarget + + @Parcelize + object NewRoom : NavTarget } override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { return when (navTarget) { - NavTarget.Root -> createNode(buildContext) + NavTarget.Root -> { + val callback = object : CreateRoomRootNode.Callback { + override fun onCreateNewRoom() { + backstack.push(NavTarget.NewRoom) + } + } + createNode(buildContext, plugins = listOf(callback)) + } + NavTarget.NewRoom -> createNode(buildContext) } } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootEvents.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootEvents.kt index ddf2003e83..b9e508032a 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootEvents.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootEvents.kt @@ -21,7 +21,6 @@ import io.element.android.libraries.matrix.ui.model.MatrixUser sealed interface CreateRoomRootEvents { data class UpdateSearchQuery(val query: String) : CreateRoomRootEvents data class StartDM(val matrixUser: MatrixUser) : CreateRoomRootEvents - object CreateRoom : CreateRoomRootEvents object InvitePeople : CreateRoomRootEvents data class OnSearchActiveChanged(val active: Boolean) : CreateRoomRootEvents } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootNode.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootNode.kt index 16a965695f..dadc16efc4 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootNode.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootNode.kt @@ -22,6 +22,7 @@ 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 @@ -35,6 +36,14 @@ class CreateRoomRootNode @AssistedInject constructor( private val presenter: CreateRoomRootPresenter, ) : Node(buildContext, plugins = plugins) { + interface Callback : Plugin { + fun onCreateNewRoom() + } + + private fun onCreateNewRoom() { + plugins().forEach { it.onCreateNewRoom() } + } + sealed interface NavTarget : Parcelable { @Parcelize object Root : NavTarget @@ -47,6 +56,7 @@ class CreateRoomRootNode @AssistedInject constructor( state = state, modifier = modifier, onClosePressed = this::navigateUp, + onNewRoomClicked = this::onCreateNewRoom, ) } } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenter.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenter.kt index 828f531211..23c8d8eaf3 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenter.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenter.kt @@ -49,7 +49,6 @@ class CreateRoomRootPresenter @Inject constructor() : Presenter isSearchActive = event.active is CreateRoomRootEvents.UpdateSearchQuery -> searchQuery = event.query is CreateRoomRootEvents.StartDM -> handleStartDM(event.matrixUser) - CreateRoomRootEvents.CreateRoom -> Unit // Todo Handle create room action CreateRoomRootEvents.InvitePeople -> Unit // Todo Handle invite people action } } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootView.kt index bab42c6964..5417ca82da 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootView.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootView.kt @@ -65,6 +65,7 @@ fun CreateRoomRootView( state: CreateRoomRootState, modifier: Modifier = Modifier, onClosePressed: () -> Unit = {}, + onNewRoomClicked: () -> Unit = {}, ) { Scaffold( modifier = modifier.fillMaxWidth(), @@ -91,7 +92,7 @@ fun CreateRoomRootView( if (!state.isSearchActive) { CreateRoomActionButtonsList( - onNewRoomClicked = { state.eventSink(CreateRoomRootEvents.CreateRoom) }, + onNewRoomClicked = onNewRoomClicked, onInvitePeopleClicked = { state.eventSink(CreateRoomRootEvents.InvitePeople) }, ) } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersEvents.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersEvents.kt new file mode 100644 index 0000000000..b751e9249e --- /dev/null +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersEvents.kt @@ -0,0 +1,19 @@ +/* + * 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.impl.selectmembers + +sealed interface SelectMembersEvents diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersNode.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersNode.kt new file mode 100644 index 0000000000..2fd6227e38 --- /dev/null +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersNode.kt @@ -0,0 +1,46 @@ +/* + * 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.impl.selectmembers + +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.AppScope + +@ContributesNode(AppScope::class) +class SelectMembersNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenter: SelectMembersPresenter, +) : Node(buildContext, plugins = plugins) { + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + SelectMembersView( + state = state, + modifier = modifier, + onBackPressed = { navigateUp() }, + onNextPressed = { }, + ) + } +} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersPresenter.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersPresenter.kt new file mode 100644 index 0000000000..a434656298 --- /dev/null +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersPresenter.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.features.createroom.impl.selectmembers + +import androidx.compose.runtime.Composable +import io.element.android.libraries.architecture.Presenter +import javax.inject.Inject + +class SelectMembersPresenter @Inject constructor() : Presenter { + + @Composable + override fun present(): SelectMembersState { + + fun handleEvents(event: SelectMembersEvents) { + // do nothing for now + } + + return SelectMembersState( + eventSink = ::handleEvents + ) + } +} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersState.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersState.kt new file mode 100644 index 0000000000..7e78e48126 --- /dev/null +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersState.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.createroom.impl.selectmembers + +data class SelectMembersState( + val eventSink: (SelectMembersEvents) -> Unit, +) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersStateProvider.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersStateProvider.kt new file mode 100644 index 0000000000..0ed1ae14f7 --- /dev/null +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersStateProvider.kt @@ -0,0 +1,30 @@ +/* + * 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.impl.selectmembers + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider + +open class SelectMembersStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aSelectMembersState(), + ) +} + +fun aSelectMembersState() = SelectMembersState( + eventSink = {} +) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersView.kt new file mode 100644 index 0000000000..100a4f495d --- /dev/null +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/selectmembers/SelectMembersView.kt @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2022 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.impl.selectmembers + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.sp +import io.element.android.libraries.designsystem.components.button.BackButton +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.designsystem.theme.components.CenterAlignedTopAppBar +import io.element.android.libraries.designsystem.theme.components.Scaffold +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.ui.strings.R + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SelectMembersView( + state: SelectMembersState, + modifier: Modifier = Modifier, + onBackPressed: () -> Unit = {}, + onNextPressed: () -> Unit = {}, +) { + val eventSink = state.eventSink + + Scaffold( + topBar = { + SelectMembersViewTopBar( + onBackPressed = onBackPressed, + onNextPressed = onNextPressed, + ) + } + ) { padding -> + Box( + modifier = modifier + .fillMaxSize() + .padding(padding) + ) { + Text(text = "Hello!") + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SelectMembersViewTopBar( + modifier: Modifier = Modifier, + onBackPressed: () -> Unit = {}, + onNextPressed: () -> Unit = {}, +) { + CenterAlignedTopAppBar( + modifier = modifier, + title = { + Text( + text = stringResource(id = R.string.add_people), + fontSize = 16.sp, + fontWeight = FontWeight.SemiBold, + ) + }, + navigationIcon = { BackButton(onClick = onBackPressed) }, + actions = { + + } + ) +} + +@Preview +@Composable +internal fun ChangeServerViewLightPreview(@PreviewParameter(SelectMembersStateProvider::class) state: SelectMembersState) = + ElementPreviewLight { ContentToPreview(state) } + +@Preview +@Composable +internal fun ChangeServerViewDarkPreview(@PreviewParameter(SelectMembersStateProvider::class) state: SelectMembersState) = + ElementPreviewDark { ContentToPreview(state) } + +@Composable +private fun ContentToPreview(state: SelectMembersState) { + SelectMembersView(state = state) +}