From 45b72483fe0de364d9456b8fd8cd41ac3d59fde3 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 19 Sep 2022 10:22:33 +0200 Subject: [PATCH 01/19] Adding changelog entry --- changelog.d/7158.wip | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/7158.wip diff --git a/changelog.d/7158.wip b/changelog.d/7158.wip new file mode 100644 index 0000000000..6c303281d8 --- /dev/null +++ b/changelog.d/7158.wip @@ -0,0 +1 @@ +[Device management] Rename a session From 1091ae41ad95c41bb5aa6f7331081c3b269c0a5d Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 19 Sep 2022 11:18:49 +0200 Subject: [PATCH 02/19] Default structure for the new code --- vector/src/main/AndroidManifest.xml | 1 + .../v2/rename/RenameSessionActivity.kt | 52 +++++++++++++++ .../devices/v2/rename/RenameSessionArgs.kt | 25 ++++++++ .../v2/rename/RenameSessionFragment.kt | 63 +++++++++++++++++++ .../v2/rename/RenameSessionViewEvent.kt | 23 +++++++ .../v2/rename/RenameSessionViewModel.kt | 57 +++++++++++++++++ .../v2/rename/RenameSessionViewNavigator.kt | 28 +++++++++ .../v2/rename/RenameSessionViewState.kt | 28 +++++++++ .../res/layout/fragment_session_rename.xml | 8 +++ 9 files changed, 285 insertions(+) create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionActivity.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionArgs.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewEvent.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewModel.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewNavigator.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewState.kt create mode 100644 vector/src/main/res/layout/fragment_session_rename.xml diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index bb8ca8cf5f..b16e4505a6 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -325,6 +325,7 @@ + diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionActivity.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionActivity.kt new file mode 100644 index 0000000000..36161610cd --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionActivity.kt @@ -0,0 +1,52 @@ +/* + * Copyright 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 im.vector.app.features.settings.devices.v2.rename + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.airbnb.mvrx.Mavericks +import dagger.hilt.android.AndroidEntryPoint +import im.vector.app.core.extensions.addFragment +import im.vector.app.core.platform.SimpleFragmentActivity + +/** + * Display the screen to rename a Session. + */ +@AndroidEntryPoint +class RenameSessionActivity : SimpleFragmentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + if (isFirstCreation()) { + addFragment( + container = views.container, + fragmentClass = RenameSessionFragment::class.java, + params = intent.getParcelableExtra(Mavericks.KEY_ARG) + ) + } + } + + companion object { + fun newIntent(context: Context, deviceId: String): Intent { + return Intent(context, RenameSessionActivity::class.java).apply { + putExtra(Mavericks.KEY_ARG, RenameSessionArgs(deviceId)) + } + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionArgs.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionArgs.kt new file mode 100644 index 0000000000..d43d472946 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionArgs.kt @@ -0,0 +1,25 @@ +/* + * 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 im.vector.app.features.settings.devices.v2.rename + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class RenameSessionArgs( + val deviceId: String +) : Parcelable diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt new file mode 100644 index 0000000000..2b071e524d --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt @@ -0,0 +1,63 @@ +/* + * 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 im.vector.app.features.settings.devices.v2.rename + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.airbnb.mvrx.fragmentViewModel +import com.airbnb.mvrx.withState +import dagger.hilt.android.AndroidEntryPoint +import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.databinding.FragmentSessionRenameBinding +import javax.inject.Inject + +/** + * Display the screen to rename a Session. + */ +@AndroidEntryPoint +class RenameSessionFragment : + VectorBaseFragment() { + + private val viewModel: RenameSessionViewModel by fragmentViewModel() + + @Inject lateinit var viewNavigator: RenameSessionViewNavigator + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSessionRenameBinding { + return FragmentSessionRenameBinding.inflate(inflater, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + observeViewEvents() + } + + private fun observeViewEvents() { + viewModel.observeViewEvents { + when (it) { + is RenameSessionViewEvent.SessionRenamed -> { + viewNavigator.navigateBack(requireActivity()) + } + } + } + } + + override fun invalidate() = withState(viewModel) { _ -> + // TODO + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewEvent.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewEvent.kt new file mode 100644 index 0000000000..656c5bb165 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewEvent.kt @@ -0,0 +1,23 @@ +/* + * 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 im.vector.app.features.settings.devices.v2.rename + +import im.vector.app.core.platform.VectorViewEvents + +sealed class RenameSessionViewEvent : VectorViewEvents { + object SessionRenamed : RenameSessionViewEvent() +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewModel.kt new file mode 100644 index 0000000000..ebd30b7ef6 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewModel.kt @@ -0,0 +1,57 @@ +/* + * 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 im.vector.app.features.settings.devices.v2.rename + +import com.airbnb.mvrx.MavericksViewModelFactory +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import im.vector.app.core.di.MavericksAssistedViewModelFactory +import im.vector.app.core.di.hiltMavericksViewModelFactory +import im.vector.app.core.platform.EmptyAction +import im.vector.app.core.platform.VectorViewModel +import im.vector.app.features.settings.devices.v2.overview.GetDeviceFullInfoUseCase +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach + +// TODO add unit tests +class RenameSessionViewModel @AssistedInject constructor( + @Assisted val initialState: RenameSessionViewState, + private val getDeviceFullInfoUseCase: GetDeviceFullInfoUseCase, +) : VectorViewModel(initialState) { + + companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() + + @AssistedFactory + interface Factory : MavericksAssistedViewModelFactory { + override fun create(initialState: RenameSessionViewState): RenameSessionViewModel + } + + init { + observeSessionInfo(initialState.deviceId) + } + + private fun observeSessionInfo(deviceId: String) { + getDeviceFullInfoUseCase.execute(deviceId) + .onEach { setState { copy(deviceName = it.deviceInfo.displayName.orEmpty()) } } + .launchIn(viewModelScope) + } + + override fun handle(action: EmptyAction) { + // do nothing + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewNavigator.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewNavigator.kt new file mode 100644 index 0000000000..229d0bc70c --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewNavigator.kt @@ -0,0 +1,28 @@ +/* + * 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 im.vector.app.features.settings.devices.v2.rename + +import androidx.fragment.app.FragmentActivity +import javax.inject.Inject + +// TODO add unit tests +class RenameSessionViewNavigator @Inject constructor() { + + fun navigateBack(activity: FragmentActivity) { + activity.finish() + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewState.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewState.kt new file mode 100644 index 0000000000..18abba9c8d --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewState.kt @@ -0,0 +1,28 @@ +/* + * 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 im.vector.app.features.settings.devices.v2.rename + +import com.airbnb.mvrx.MavericksState + +data class RenameSessionViewState( + val deviceId: String, + val deviceName: String = "", +) : MavericksState { + constructor(args: RenameSessionArgs) : this( + deviceId = args.deviceId + ) +} diff --git a/vector/src/main/res/layout/fragment_session_rename.xml b/vector/src/main/res/layout/fragment_session_rename.xml new file mode 100644 index 0000000000..7911f36b00 --- /dev/null +++ b/vector/src/main/res/layout/fragment_session_rename.xml @@ -0,0 +1,8 @@ + + + + From 3de96a3a0cd72bc8d5e781dd94947187e3658570 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 19 Sep 2022 14:03:10 +0200 Subject: [PATCH 03/19] Adding new method into navigator --- .../v2/overview/SessionOverviewFragment.kt | 2 +- .../overview/SessionOverviewViewNavigator.kt | 7 +++++- .../SessionOverviewViewNavigatorTest.kt | 25 ++++++++++++++++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt index 73991c5f20..af19de4ce0 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt @@ -118,7 +118,7 @@ class SessionOverviewFragment : private fun updateEntryDetails(deviceId: String) { views.sessionOverviewEntryDetails.setOnClickListener { - viewNavigator.navigateToSessionDetails(requireContext(), deviceId) + viewNavigator.goToSessionDetails(requireContext(), deviceId) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewNavigator.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewNavigator.kt index ef61856255..8c4d0345dc 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewNavigator.kt @@ -18,11 +18,16 @@ package im.vector.app.features.settings.devices.v2.overview import android.content.Context import im.vector.app.features.settings.devices.v2.details.SessionDetailsActivity +import im.vector.app.features.settings.devices.v2.rename.RenameSessionActivity import javax.inject.Inject class SessionOverviewViewNavigator @Inject constructor() { - fun navigateToSessionDetails(context: Context, deviceId: String) { + fun goToSessionDetails(context: Context, deviceId: String) { context.startActivity(SessionDetailsActivity.newIntent(context, deviceId)) } + + fun goToRenameSession(context: Context, deviceId: String) { + context.startActivity(RenameSessionActivity.newIntent(context, deviceId)) + } } diff --git a/vector/src/test/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewNavigatorTest.kt b/vector/src/test/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewNavigatorTest.kt index 56f1e5920d..3d38f3b3bf 100644 --- a/vector/src/test/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewNavigatorTest.kt +++ b/vector/src/test/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewNavigatorTest.kt @@ -18,6 +18,7 @@ package im.vector.app.features.settings.devices.v2.overview import android.content.Intent import im.vector.app.features.settings.devices.v2.details.SessionDetailsActivity +import im.vector.app.features.settings.devices.v2.rename.RenameSessionActivity import im.vector.app.test.fakes.FakeContext import io.mockk.every import io.mockk.mockk @@ -38,6 +39,7 @@ class SessionOverviewViewNavigatorTest { @Before fun setUp() { mockkObject(SessionDetailsActivity) + mockkObject(RenameSessionActivity) } @After @@ -52,7 +54,22 @@ class SessionOverviewViewNavigatorTest { context.givenStartActivity(intent) // When - sessionOverviewViewNavigator.navigateToSessionDetails(context.instance, A_SESSION_ID) + sessionOverviewViewNavigator.goToSessionDetails(context.instance, A_SESSION_ID) + + // Then + verify { + context.instance.startActivity(intent) + } + } + + @Test + fun `given a session id when navigating to rename screen then it starts the correct activity`() { + // Given + val intent = givenIntentForRenameSession(A_SESSION_ID) + context.givenStartActivity(intent) + + // When + sessionOverviewViewNavigator.goToRenameSession(context.instance, A_SESSION_ID) // Then verify { @@ -65,4 +82,10 @@ class SessionOverviewViewNavigatorTest { every { SessionDetailsActivity.newIntent(context.instance, sessionId) } returns intent return intent } + + private fun givenIntentForRenameSession(sessionId: String): Intent { + val intent = mockk() + every { RenameSessionActivity.newIntent(context.instance, sessionId) } returns intent + return intent + } } From 82fabf4a85efa23a7abea15de51bc9a1503ff28a Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 19 Sep 2022 14:28:37 +0200 Subject: [PATCH 04/19] Adding menu with rename action in session overview screen --- .../src/main/res/values/strings.xml | 1 + .../app/core/di/MavericksViewModelModule.kt | 6 ++++++ .../v2/overview/SessionOverviewFragment.kt | 21 ++++++++++++++++++- .../v2/rename/RenameSessionFragment.kt | 9 ++++++++ .../main/res/menu/menu_session_overview.xml | 11 ++++++++++ 5 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 vector/src/main/res/menu/menu_session_overview.xml diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml index d8f6222acf..8fd7d2e811 100644 --- a/library/ui-strings/src/main/res/values/strings.xml +++ b/library/ui-strings/src/main/res/values/strings.xml @@ -3295,6 +3295,7 @@ Session ID Last activity IP address + Rename session %s\nis looking a little empty. diff --git a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt index 6fb2505386..62e7140742 100644 --- a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt @@ -91,6 +91,7 @@ import im.vector.app.features.settings.devices.DevicesViewModel import im.vector.app.features.settings.devices.v2.details.SessionDetailsViewModel import im.vector.app.features.settings.devices.v2.othersessions.OtherSessionsViewModel import im.vector.app.features.settings.devices.v2.overview.SessionOverviewViewModel +import im.vector.app.features.settings.devices.v2.rename.RenameSessionViewModel import im.vector.app.features.settings.devtools.AccountDataViewModel import im.vector.app.features.settings.devtools.GossipingEventsPaperTrailViewModel import im.vector.app.features.settings.devtools.KeyRequestListViewModel @@ -653,4 +654,9 @@ interface MavericksViewModelModule { @IntoMap @MavericksViewModelKey(SessionDetailsViewModel::class) fun sessionDetailsViewModelFactory(factory: SessionDetailsViewModel.Factory): MavericksAssistedViewModelFactory<*, *> + + @Binds + @IntoMap + @MavericksViewModelKey(RenameSessionViewModel::class) + fun renameSessionViewModelFactory(factory: RenameSessionViewModel.Factory): MavericksAssistedViewModelFactory<*, *> } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt index af19de4ce0..0bf6e1d14f 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt @@ -18,6 +18,7 @@ package im.vector.app.features.settings.devices.v2.overview import android.os.Bundle import android.view.LayoutInflater +import android.view.MenuItem import android.view.View import android.view.ViewGroup import android.widget.Toast @@ -31,6 +32,7 @@ import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R import im.vector.app.core.date.VectorDateFormatter import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.DrawableProvider import im.vector.app.databinding.FragmentSessionOverviewBinding @@ -43,7 +45,8 @@ import javax.inject.Inject */ @AndroidEntryPoint class SessionOverviewFragment : - VectorBaseFragment() { + VectorBaseFragment(), + VectorMenuProvider { @Inject lateinit var viewNavigator: SessionOverviewViewNavigator @@ -103,6 +106,22 @@ class SessionOverviewFragment : views.sessionOverviewInfo.onLearnMoreClickListener = null } + override fun getMenuRes() = R.menu.menu_session_overview + + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.sessionOverviewRename -> { + goToRenameSession() + true + } + else -> false + } + } + + private fun goToRenameSession() = withState(viewModel) { state -> + viewNavigator.goToRenameSession(requireContext(), state.deviceId) + } + override fun invalidate() = withState(viewModel) { state -> updateToolbar(state.isCurrentSession) updateEntryDetails(state.deviceId) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt index 2b071e524d..c8757f64c5 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt @@ -20,9 +20,11 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.appcompat.app.AppCompatActivity import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint +import im.vector.app.R import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentSessionRenameBinding import javax.inject.Inject @@ -45,6 +47,13 @@ class RenameSessionFragment : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) observeViewEvents() + initToolbar() + } + + private fun initToolbar() { + (activity as? AppCompatActivity) + ?.supportActionBar + ?.setTitle(R.string.device_manager_session_rename) } private fun observeViewEvents() { diff --git a/vector/src/main/res/menu/menu_session_overview.xml b/vector/src/main/res/menu/menu_session_overview.xml new file mode 100644 index 0000000000..7de3953dcc --- /dev/null +++ b/vector/src/main/res/menu/menu_session_overview.xml @@ -0,0 +1,11 @@ + + + + + From 54aec63f6ceb07102252be656075e5ad2ab1218a Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 19 Sep 2022 14:31:54 +0200 Subject: [PATCH 05/19] Small improvement in code readability --- .../devices/v2/overview/SessionOverviewFragment.kt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt index 0bf6e1d14f..ccf68a18bc 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt @@ -23,7 +23,6 @@ import android.view.View import android.view.ViewGroup import android.widget.Toast import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.isGone import androidx.core.view.isVisible import com.airbnb.mvrx.Success import com.airbnb.mvrx.fragmentViewModel @@ -155,11 +154,7 @@ class SessionOverviewFragment : ) views.sessionOverviewInfo.render(infoViewState, dateFormatter, drawableProvider, colorProvider) } else { - hideSessionInfo() + views.sessionOverviewInfo.isVisible = false } } - - private fun hideSessionInfo() { - views.sessionOverviewInfo.isGone = true - } } From c3d359e58f363a67aae5bcd5d9b728b03bebb552 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 19 Sep 2022 15:57:08 +0200 Subject: [PATCH 06/19] Adding edit text into the screen --- .../src/main/res/values/strings.xml | 3 ++ .../v2/rename/RenameSessionFragment.kt | 9 +++-- .../res/layout/fragment_session_rename.xml | 33 ++++++++++++++++++- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml index 8fd7d2e811..fdb04a6e76 100644 --- a/library/ui-strings/src/main/res/values/strings.xml +++ b/library/ui-strings/src/main/res/values/strings.xml @@ -3296,6 +3296,9 @@ Last activity IP address Rename session + Session name + Custom session names can help you recognize your devices more easily. + Please be aware that session names are also visible to people you communicate with. %s\nis looking a little empty. diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt index c8757f64c5..7bb4eaaed7 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt @@ -40,6 +40,8 @@ class RenameSessionFragment : @Inject lateinit var viewNavigator: RenameSessionViewNavigator + private var renameEditTextInitialized = false + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSessionRenameBinding { return FragmentSessionRenameBinding.inflate(inflater, container, false) } @@ -66,7 +68,10 @@ class RenameSessionFragment : } } - override fun invalidate() = withState(viewModel) { _ -> - // TODO + override fun invalidate() = withState(viewModel) { state -> + if(renameEditTextInitialized.not()) { + views.renameSessionEditText.setText(state.deviceName) + renameEditTextInitialized = true + } } } diff --git a/vector/src/main/res/layout/fragment_session_rename.xml b/vector/src/main/res/layout/fragment_session_rename.xml index 7911f36b00..cd0a47ae82 100644 --- a/vector/src/main/res/layout/fragment_session_rename.xml +++ b/vector/src/main/res/layout/fragment_session_rename.xml @@ -1,8 +1,39 @@ + + + + + + + + From 7eab37e9d1a97215b11bef28efff50fe3f971d46 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 19 Sep 2022 16:06:02 +0200 Subject: [PATCH 07/19] Small renaming of navigator method --- .../settings/devices/v2/rename/RenameSessionFragment.kt | 2 +- .../settings/devices/v2/rename/RenameSessionViewNavigator.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt index 7bb4eaaed7..49b2ee2cdf 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt @@ -62,7 +62,7 @@ class RenameSessionFragment : viewModel.observeViewEvents { when (it) { is RenameSessionViewEvent.SessionRenamed -> { - viewNavigator.navigateBack(requireActivity()) + viewNavigator.goBack(requireActivity()) } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewNavigator.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewNavigator.kt index 229d0bc70c..d26733635b 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewNavigator.kt @@ -22,7 +22,7 @@ import javax.inject.Inject // TODO add unit tests class RenameSessionViewNavigator @Inject constructor() { - fun navigateBack(activity: FragmentActivity) { + fun goBack(activity: FragmentActivity) { activity.finish() } } From 33cf3d3032947bc1d3b5f99a758e5c58abb617bf Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 19 Sep 2022 16:20:05 +0200 Subject: [PATCH 08/19] Setup a custom toolbar --- .../devices/v2/rename/RenameSessionActivity.kt | 9 ++++++--- .../devices/v2/rename/RenameSessionFragment.kt | 5 ++--- .../main/res/layout/fragment_session_rename.xml | 16 +++++++++++++++- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionActivity.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionActivity.kt index 36161610cd..11b3d5aebc 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionActivity.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionActivity.kt @@ -22,20 +22,23 @@ import android.os.Bundle import com.airbnb.mvrx.Mavericks import dagger.hilt.android.AndroidEntryPoint import im.vector.app.core.extensions.addFragment -import im.vector.app.core.platform.SimpleFragmentActivity +import im.vector.app.core.platform.VectorBaseActivity +import im.vector.app.databinding.ActivitySimpleBinding /** * Display the screen to rename a Session. */ @AndroidEntryPoint -class RenameSessionActivity : SimpleFragmentActivity() { +class RenameSessionActivity : VectorBaseActivity() { + + override fun getBinding() = ActivitySimpleBinding.inflate(layoutInflater) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (isFirstCreation()) { addFragment( - container = views.container, + container = views.simpleFragmentContainer, fragmentClass = RenameSessionFragment::class.java, params = intent.getParcelableExtra(Mavericks.KEY_ARG) ) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt index 49b2ee2cdf..ade23b5ee2 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt @@ -53,9 +53,8 @@ class RenameSessionFragment : } private fun initToolbar() { - (activity as? AppCompatActivity) - ?.supportActionBar - ?.setTitle(R.string.device_manager_session_rename) + setupToolbar(views.renameSessionToolbar) + .allowBack(useCross = true) } private fun observeViewEvents() { diff --git a/vector/src/main/res/layout/fragment_session_rename.xml b/vector/src/main/res/layout/fragment_session_rename.xml index cd0a47ae82..8ce1cbc453 100644 --- a/vector/src/main/res/layout/fragment_session_rename.xml +++ b/vector/src/main/res/layout/fragment_session_rename.xml @@ -4,6 +4,20 @@ android:layout_width="match_parent" android:layout_height="match_parent"> + + + + + + + app:layout_constraintTop_toBottomOf="@id/appBarLayout"> Date: Mon, 19 Sep 2022 17:27:06 +0200 Subject: [PATCH 09/19] Adding save button and view actions --- .../devices/v2/rename/RenameSessionAction.kt | 24 +++++++++++++++++++ .../v2/rename/RenameSessionFragment.kt | 20 +++++++++++++--- .../v2/rename/RenameSessionViewModel.kt | 19 +++++++++++---- .../res/layout/fragment_session_rename.xml | 11 ++++++++- 4 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionAction.kt diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionAction.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionAction.kt new file mode 100644 index 0000000000..d175d1ea4a --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionAction.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020 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.settings.devices.v2.rename + +import im.vector.app.core.platform.VectorViewModelAction + +sealed class RenameSessionAction : VectorViewModelAction { + object SaveModifications : RenameSessionAction() + data class EditLocally(val editedName: String) : RenameSessionAction() +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt index ade23b5ee2..964fef1a99 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionFragment.kt @@ -20,11 +20,10 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.appcompat.app.AppCompatActivity +import androidx.core.widget.doOnTextChanged import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint -import im.vector.app.R import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentSessionRenameBinding import javax.inject.Inject @@ -50,6 +49,8 @@ class RenameSessionFragment : super.onViewCreated(view, savedInstanceState) observeViewEvents() initToolbar() + initEditText() + initSaveButton() } private fun initToolbar() { @@ -57,6 +58,18 @@ class RenameSessionFragment : .allowBack(useCross = true) } + private fun initEditText() { + views.renameSessionEditText.doOnTextChanged { text, _, _, _ -> + viewModel.handle(RenameSessionAction.EditLocally(text.toString())) + } + } + + private fun initSaveButton() { + views.renameSessionSave.debouncedClicks { + viewModel.handle(RenameSessionAction.SaveModifications) + } + } + private fun observeViewEvents() { viewModel.observeViewEvents { when (it) { @@ -68,9 +81,10 @@ class RenameSessionFragment : } override fun invalidate() = withState(viewModel) { state -> - if(renameEditTextInitialized.not()) { + if (renameEditTextInitialized.not()) { views.renameSessionEditText.setText(state.deviceName) renameEditTextInitialized = true } + views.renameSessionSave.isEnabled = state.deviceName.isNotEmpty() } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewModel.kt index ebd30b7ef6..7e50ecce34 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/rename/RenameSessionViewModel.kt @@ -22,7 +22,6 @@ import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory -import im.vector.app.core.platform.EmptyAction import im.vector.app.core.platform.VectorViewModel import im.vector.app.features.settings.devices.v2.overview.GetDeviceFullInfoUseCase import kotlinx.coroutines.flow.launchIn @@ -32,7 +31,7 @@ import kotlinx.coroutines.flow.onEach class RenameSessionViewModel @AssistedInject constructor( @Assisted val initialState: RenameSessionViewState, private val getDeviceFullInfoUseCase: GetDeviceFullInfoUseCase, -) : VectorViewModel(initialState) { +) : VectorViewModel(initialState) { companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() @@ -51,7 +50,19 @@ class RenameSessionViewModel @AssistedInject constructor( .launchIn(viewModelScope) } - override fun handle(action: EmptyAction) { - // do nothing + override fun handle(action: RenameSessionAction) { + when (action) { + is RenameSessionAction.EditLocally -> handleEditLocally(action.editedName) + is RenameSessionAction.SaveModifications -> handleSaveModifications() + } + } + + private fun handleEditLocally(editedName: String) { + setState { copy(deviceName = editedName) } + } + + private fun handleSaveModifications() { + // TODO call use case to save the modifications + _viewEvents.post(RenameSessionViewEvent.SessionRenamed) } } diff --git a/vector/src/main/res/layout/fragment_session_rename.xml b/vector/src/main/res/layout/fragment_session_rename.xml index 8ce1cbc453..93b36566b1 100644 --- a/vector/src/main/res/layout/fragment_session_rename.xml +++ b/vector/src/main/res/layout/fragment_session_rename.xml @@ -14,8 +14,17 @@ android:id="@+id/renameSessionToolbar" android:layout_width="match_parent" android:layout_height="?actionBarSize" - app:title="@string/device_manager_session_rename"/> + app:title="@string/device_manager_session_rename"> +