diff --git a/newsfragment/3485.feature b/newsfragment/3485.feature new file mode 100644 index 0000000000..68c78267be --- /dev/null +++ b/newsfragment/3485.feature @@ -0,0 +1 @@ +Add beta warning to private space creation flow \ No newline at end of file diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceCreationActivity.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceCreationActivity.kt index 57c6b40404..dbcb9fd5bf 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceCreationActivity.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceCreationActivity.kt @@ -20,6 +20,7 @@ import android.content.Context import android.content.Intent import android.os.Bundle import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager import com.airbnb.mvrx.Loading import com.airbnb.mvrx.viewModel import com.airbnb.mvrx.withState @@ -28,6 +29,7 @@ import im.vector.app.R import im.vector.app.core.di.ScreenComponent import im.vector.app.core.extensions.toMvRxBundle import im.vector.app.core.platform.SimpleFragmentActivity +import im.vector.app.features.spaces.create.BetaWarningBottomSheet import im.vector.app.features.spaces.create.ChoosePrivateSpaceTypeFragment import im.vector.app.features.spaces.create.ChooseSpaceTypeFragment import im.vector.app.features.spaces.create.CreateSpaceAction @@ -40,7 +42,7 @@ import im.vector.app.features.spaces.create.SpaceTopology import im.vector.app.features.spaces.create.SpaceType import javax.inject.Inject -class SpaceCreationActivity : SimpleFragmentActivity(), CreateSpaceViewModel.Factory { +class SpaceCreationActivity : SimpleFragmentActivity(), CreateSpaceViewModel.Factory, BetaWarningBottomSheet.InteractionListener { @Inject lateinit var viewModelFactory: CreateSpaceViewModel.Factory @@ -51,18 +53,38 @@ class SpaceCreationActivity : SimpleFragmentActivity(), CreateSpaceViewModel.Fac val viewModel: CreateSpaceViewModel by viewModel() + private val fragmentLifecycleCallbacks = object : FragmentManager.FragmentLifecycleCallbacks() { + override fun onFragmentAttached(fm: FragmentManager, f: Fragment, context: Context) { + when (f) { + is BetaWarningBottomSheet -> { + f.interactionListener = this@SpaceCreationActivity + } + } + super.onFragmentAttached(fm, f, context) + } + + override fun onFragmentDetached(fm: FragmentManager, f: Fragment) { + when (f) { + is BetaWarningBottomSheet -> { + f.interactionListener = null + } + } + super.onFragmentDetached(fm, f) + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - + supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, false) if (isFirstCreation()) { when (withState(viewModel) { it.step }) { - CreateSpaceState.Step.ChooseType -> { + CreateSpaceState.Step.ChooseType -> { navigateToFragment(ChooseSpaceTypeFragment::class.java) } - CreateSpaceState.Step.SetDetails -> { + CreateSpaceState.Step.SetDetails -> { navigateToFragment(ChooseSpaceTypeFragment::class.java) } - CreateSpaceState.Step.AddRooms -> { + CreateSpaceState.Step.AddRooms -> { navigateToFragment(CreateSpaceDefaultRoomsFragment::class.java) } CreateSpaceState.Step.ChoosePrivateType -> { @@ -72,6 +94,11 @@ class SpaceCreationActivity : SimpleFragmentActivity(), CreateSpaceViewModel.Fac } } + override fun onDestroy() { + supportFragmentManager.unregisterFragmentLifecycleCallbacks(fragmentLifecycleCallbacks) + super.onDestroy() + } + override fun initUiAndData() { super.initUiAndData() @@ -81,29 +108,29 @@ class SpaceCreationActivity : SimpleFragmentActivity(), CreateSpaceViewModel.Fac viewModel.observeViewEvents { when (it) { - CreateSpaceEvents.NavigateToDetails -> { + CreateSpaceEvents.NavigateToDetails -> { navigateToFragment(CreateSpaceDetailsFragment::class.java) } - CreateSpaceEvents.NavigateToChooseType -> { + CreateSpaceEvents.NavigateToChooseType -> { navigateToFragment(ChooseSpaceTypeFragment::class.java) } - CreateSpaceEvents.Dismiss -> { + CreateSpaceEvents.Dismiss -> { finish() } - CreateSpaceEvents.NavigateToAddRooms -> { + CreateSpaceEvents.NavigateToAddRooms -> { navigateToFragment(CreateSpaceDefaultRoomsFragment::class.java) } CreateSpaceEvents.NavigateToChoosePrivateType -> { navigateToFragment(ChoosePrivateSpaceTypeFragment::class.java) } - is CreateSpaceEvents.ShowModalError -> { + is CreateSpaceEvents.ShowModalError -> { hideWaitingView() MaterialAlertDialogBuilder(this) .setMessage(it.errorMessage) .setPositiveButton(getString(R.string.ok), null) .show() } - is CreateSpaceEvents.FinishSuccess -> { + is CreateSpaceEvents.FinishSuccess -> { setResult(RESULT_OK, Intent().apply { putExtra(RESULT_DATA_CREATED_SPACE_ID, it.spaceId) putExtra(RESULT_DATA_DEFAULT_ROOM_ID, it.defaultRoomId) @@ -111,7 +138,7 @@ class SpaceCreationActivity : SimpleFragmentActivity(), CreateSpaceViewModel.Fac }) finish() } - CreateSpaceEvents.HideModalLoading -> { + CreateSpaceEvents.HideModalLoading -> { hideWaitingView() } } @@ -135,9 +162,9 @@ class SpaceCreationActivity : SimpleFragmentActivity(), CreateSpaceViewModel.Fac private fun renderState(state: CreateSpaceState) { val titleRes = when (state.step) { - CreateSpaceState.Step.ChooseType -> R.string.activity_create_space_title + CreateSpaceState.Step.ChooseType -> R.string.activity_create_space_title CreateSpaceState.Step.SetDetails, - CreateSpaceState.Step.AddRooms -> { + CreateSpaceState.Step.AddRooms -> { if (state.spaceType == SpaceType.Public) R.string.your_public_space else R.string.your_private_space } @@ -179,4 +206,8 @@ class SpaceCreationActivity : SimpleFragmentActivity(), CreateSpaceViewModel.Fac } override fun create(initialState: CreateSpaceState): CreateSpaceViewModel = viewModelFactory.create(initialState) + + override fun betaWarningOnContinueAnyway() { + viewModel.handle(CreateSpaceAction.ConfirmBetaWarning) + } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/BetaWarningBottomSheet.kt b/vector/src/main/java/im/vector/app/features/spaces/create/BetaWarningBottomSheet.kt new file mode 100644 index 0000000000..82e8721b07 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/spaces/create/BetaWarningBottomSheet.kt @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 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 im.vector.app.features.spaces.create + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment +import im.vector.app.databinding.BottomSheetSpaceCreatePrivateWarningBinding + +class BetaWarningBottomSheet : VectorBaseBottomSheetDialogFragment() { + + interface InteractionListener { + fun betaWarningOnContinueAnyway() + } + + var interactionListener: InteractionListener? = null + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) = + BottomSheetSpaceCreatePrivateWarningBinding.inflate(inflater, container, false) + + override val showExpanded = true + + override fun onDetach() { + interactionListener = null + super.onDetach() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + views.continueButton.debouncedClicks { + interactionListener?.betaWarningOnContinueAnyway() + dismiss() + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/ChoosePrivateSpaceTypeFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/create/ChoosePrivateSpaceTypeFragment.kt index 4f079551eb..49fe9a7dec 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/ChoosePrivateSpaceTypeFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/ChoosePrivateSpaceTypeFragment.kt @@ -46,12 +46,20 @@ class ChoosePrivateSpaceTypeFragment @Inject constructor( } views.teammatesButton.onClick { - sharedViewModel.handle(CreateSpaceAction.SetSpaceTopology(SpaceTopology.MeAndTeammates)) + BetaWarningBottomSheet().show(parentFragmentManager, "warning") } sharedViewModel.subscribe { state -> views.accessInfoHelpText.text = stringProvider.getString(R.string.create_spaces_make_sure_access, state.name ?: "") } + + sharedViewModel.observeViewEvents { + when (it) { + CreateSpaceEvents.OnConfirmBetaWarning -> { + sharedViewModel.handle(CreateSpaceAction.SetSpaceTopology(SpaceTopology.MeAndTeammates)) + } + } + } } override fun onBackPressed(toolbarButton: Boolean): Boolean { diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceAction.kt b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceAction.kt index cd31b40354..291679764f 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceAction.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceAction.kt @@ -29,4 +29,5 @@ sealed class CreateSpaceAction : VectorViewModelAction { object NextFromDefaultRooms : CreateSpaceAction() data class DefaultRoomNameChanged(val index: Int, val name: String) : CreateSpaceAction() data class SetSpaceTopology(val topology: SpaceTopology) : CreateSpaceAction() + object ConfirmBetaWarning : CreateSpaceAction() } diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceEvents.kt b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceEvents.kt index c3fa2b2068..3e40fc6ad7 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceEvents.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceEvents.kt @@ -27,4 +27,5 @@ sealed class CreateSpaceEvents : VectorViewEvents { data class FinishSuccess(val spaceId: String, val defaultRoomId: String?, val topology: SpaceTopology?) : CreateSpaceEvents() data class ShowModalError(val errorMessage: String) : CreateSpaceEvents() object HideModalLoading : CreateSpaceEvents() + object OnConfirmBetaWarning : CreateSpaceEvents() } diff --git a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt index 9881232f4d..3da6a7554f 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/create/CreateSpaceViewModel.kt @@ -118,6 +118,9 @@ class CreateSpaceViewModel @AssistedInject constructor( is CreateSpaceAction.SetSpaceTopology -> { handleSetTopology(action) } + CreateSpaceAction.ConfirmBetaWarning -> { + _viewEvents.post(CreateSpaceEvents.OnConfirmBetaWarning) + } }.exhaustive } diff --git a/vector/src/main/res/layout/bottom_sheet_space_create_private_warning.xml b/vector/src/main/res/layout/bottom_sheet_space_create_private_warning.xml new file mode 100644 index 0000000000..7292c7df55 --- /dev/null +++ b/vector/src/main/res/layout/bottom_sheet_space_create_private_warning.xml @@ -0,0 +1,46 @@ + + + + + + + + + +