From ebf707dca9a26346450e28c6ba5470916a232224 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 29 Aug 2022 18:29:12 +0200 Subject: [PATCH] Navigation from current session --- .../src/main/res/values/strings.xml | 2 + vector/src/main/AndroidManifest.xml | 1 + .../app/core/di/MavericksViewModelModule.kt | 6 +++ .../v2/VectorSettingsDevicesFragment.kt | 26 ++++++++- .../v2/VectorSettingsDevicesViewNavigator.kt | 29 ++++++++++ .../devices/v2/list/CurrentSessionView.kt | 2 + .../v2/overview/SessionOverviewAction.kt | 21 ++++++++ .../v2/overview/SessionOverviewActivity.kt | 52 ++++++++++++++++++ .../v2/overview/SessionOverviewArgs.kt | 25 +++++++++ .../v2/overview/SessionOverviewFragment.kt | 52 ++++++++++++++++++ .../v2/overview/SessionOverviewState.kt | 28 ++++++++++ .../v2/overview/SessionOverviewViewModel.kt | 53 +++++++++++++++++++ .../res/layout/fragment_settings_devices.xml | 2 +- .../fragment_settings_session_overview.xml | 6 +++ 14 files changed, 302 insertions(+), 3 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesViewNavigator.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewAction.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewActivity.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewArgs.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewState.kt create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt create mode 100644 vector/src/main/res/layout/fragment_settings_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 8c2af01e52..823a26df74 100644 --- a/library/ui-strings/src/main/res/values/strings.xml +++ b/library/ui-strings/src/main/res/values/strings.xml @@ -3248,6 +3248,8 @@ Consider signing out from old sessions (%1$d day or more) that you don’t use anymore. Consider signing out from old sessions (%1$d days or more) that you don’t use anymore. + Current Session + Session %s\nis looking a little empty. diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index c4022576c3..cd2fd52b32 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -339,6 +339,7 @@ + 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 a40aeaaa15..40484f57e8 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 @@ -88,6 +88,7 @@ import im.vector.app.features.settings.account.deactivation.DeactivateAccountVie import im.vector.app.features.settings.crosssigning.CrossSigningSettingsViewModel import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheetViewModel import im.vector.app.features.settings.devices.DevicesViewModel +import im.vector.app.features.settings.devices.v2.overview.SessionOverviewViewModel import im.vector.app.features.settings.devtools.AccountDataViewModel import im.vector.app.features.settings.devtools.GossipingEventsPaperTrailViewModel import im.vector.app.features.settings.devtools.KeyRequestListViewModel @@ -630,4 +631,9 @@ interface MavericksViewModelModule { @IntoMap @MavericksViewModelKey(ReleaseNotesViewModel::class) fun releaseNotesViewModel(factory: ReleaseNotesViewModel.Factory): MavericksAssistedViewModelFactory<*, *> + + @Binds + @IntoMap + @MavericksViewModelKey(SessionOverviewViewModel::class) + fun sessionOverviewViewModelFactory(factory: SessionOverviewViewModel.Factory): MavericksAssistedViewModelFactory<*, *> } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt index 78b8c66f9c..2adf7969bf 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt @@ -42,6 +42,7 @@ import im.vector.app.features.settings.devices.DevicesViewEvents import im.vector.app.features.settings.devices.DevicesViewModel import im.vector.app.features.settings.devices.v2.list.SESSION_IS_MARKED_AS_INACTIVE_AFTER_DAYS import im.vector.app.features.settings.devices.v2.list.SecurityRecommendationViewState +import javax.inject.Inject /** * Display the list of the user's devices and sessions. @@ -50,6 +51,8 @@ import im.vector.app.features.settings.devices.v2.list.SecurityRecommendationVie class VectorSettingsDevicesFragment : VectorBaseFragment() { + @Inject lateinit var viewNavigator: VectorSettingsDevicesViewNavigator + private val viewModel: DevicesViewModel by fragmentViewModel() override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSettingsDevicesBinding { @@ -72,10 +75,10 @@ class VectorSettingsDevicesFragment : initLearnMoreButtons() initWaitingView() - observerViewEvents() + observeViewEvents() } - private fun observerViewEvents() { + private fun observeViewEvents() { viewModel.observeViewEvents { when (it) { is DevicesViewEvents.Loading -> showLoading(it.message) @@ -197,15 +200,34 @@ class VectorSettingsDevicesFragment : views.deviceListHeaderCurrentSession.isVisible = true views.deviceListCurrentSession.isVisible = true views.deviceListCurrentSession.render(it) + views.deviceListCurrentSession.debouncedClicks { + currentDeviceInfo.deviceInfo.deviceId?.let { deviceId -> navigateToSessionOverview(deviceId) } + } + views.deviceListCurrentSession.viewDetailsButton.debouncedClicks { + currentDeviceInfo.deviceInfo.deviceId?.let { deviceId -> navigateToSessionOverview(deviceId) } + } } ?: run { hideCurrentSessionView() } } + private fun navigateToSessionOverview(sessionId: String) { + viewNavigator.navigateToSessionOverview( + context = requireActivity(), + sessionId = sessionId + ) + } + private fun hideCurrentSessionView() { views.deviceListHeaderCurrentSession.isVisible = false views.deviceListCurrentSession.isVisible = false views.deviceListDividerCurrentSession.isVisible = false + views.deviceListCurrentSession.debouncedClicks { + // do nothing + } + views.deviceListCurrentSession.viewDetailsButton.debouncedClicks { + // do nothing + } } private fun handleRequestStatus(unIgnoreRequest: Async) { diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesViewNavigator.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesViewNavigator.kt new file mode 100644 index 0000000000..0e5cb87d7b --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesViewNavigator.kt @@ -0,0 +1,29 @@ +/* + * 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 + +import android.content.Context +import im.vector.app.features.settings.devices.v2.overview.SessionOverviewActivity +import javax.inject.Inject + +// TODO add unit tests +class VectorSettingsDevicesViewNavigator @Inject constructor() { + + fun navigateToSessionOverview(context: Context, sessionId: String) { + context.startActivity(SessionOverviewActivity.newIntent(context, sessionId)) + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/CurrentSessionView.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/CurrentSessionView.kt index d6f81f4f79..1ce035931f 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/CurrentSessionView.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/list/CurrentSessionView.kt @@ -39,6 +39,8 @@ class CurrentSessionView @JvmOverloads constructor( views = ViewCurrentSessionBinding.bind(this) } + val viewDetailsButton = views.currentSessionViewDetailsButton + fun render(currentDeviceInfo: DeviceFullInfo) { renderDeviceInfo(currentDeviceInfo.deviceInfo.displayName.orEmpty()) renderVerificationStatus(currentDeviceInfo.trustLevelForShield) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewAction.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewAction.kt new file mode 100644 index 0000000000..c028c08ec4 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewAction.kt @@ -0,0 +1,21 @@ +/* + * 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.overview + +import im.vector.app.core.platform.VectorViewModelAction + +sealed class SessionOverviewAction : VectorViewModelAction diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewActivity.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewActivity.kt new file mode 100644 index 0000000000..a663c0ff2a --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewActivity.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.overview + +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 overview info about a Session. + */ +@AndroidEntryPoint +class SessionOverviewActivity : SimpleFragmentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + if (isFirstCreation()) { + addFragment( + container = views.container, + fragmentClass = SessionOverviewFragment::class.java, + params = intent.getParcelableExtra(Mavericks.KEY_ARG) + ) + } + } + + companion object { + fun newIntent(context: Context, sessionId: String): Intent { + return Intent(context, SessionOverviewActivity::class.java).apply { + putExtra(Mavericks.KEY_ARG, SessionOverviewArgs(sessionId)) + } + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewArgs.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewArgs.kt new file mode 100644 index 0000000000..87ea883362 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewArgs.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.overview + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class SessionOverviewArgs( + val sessionId: String +) : Parcelable 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 new file mode 100644 index 0000000000..1b8b231a5c --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt @@ -0,0 +1,52 @@ +/* + * 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.overview + +import android.view.LayoutInflater +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.FragmentSettingsSessionOverviewBinding + +/** + * Display the overview info about a Session. + */ +@AndroidEntryPoint +class SessionOverviewFragment : + VectorBaseFragment() { + + private val viewModel: SessionOverviewViewModel by fragmentViewModel() + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSettingsSessionOverviewBinding { + return FragmentSettingsSessionOverviewBinding.inflate(inflater, container, false) + } + + override fun invalidate() = withState(viewModel) { state -> + updateToolbar(state.isCurrentSession) + } + + private fun updateToolbar(isCurrentSession: Boolean) { + val titleResId = if (isCurrentSession) R.string.device_manager_current_session_title else R.string.device_manager_session_title + (activity as? AppCompatActivity) + ?.supportActionBar + ?.setTitle(titleResId) + } +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewState.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewState.kt new file mode 100644 index 0000000000..d91d6a82ce --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewState.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.overview + +import com.airbnb.mvrx.MavericksState + +data class SessionOverviewState( + val sessionId: String, + val isCurrentSession: Boolean = false, +) : MavericksState { + constructor(args: SessionOverviewArgs) : this( + sessionId = args.sessionId + ) +} diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt new file mode 100644 index 0000000000..a95cc1a49b --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt @@ -0,0 +1,53 @@ +/* + * 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.overview + +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.EmptyViewEvents +import im.vector.app.core.platform.VectorViewModel +import org.matrix.android.sdk.api.session.Session + +class SessionOverviewViewModel @AssistedInject constructor( + @Assisted val initialState: SessionOverviewState, + session: Session, +) : VectorViewModel(initialState) { + + companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() + + @AssistedFactory + interface Factory : MavericksAssistedViewModelFactory { + override fun create(initialState: SessionOverviewState): SessionOverviewViewModel + } + + init { + val currentSessionId = session.sessionParams.deviceId.orEmpty() + setState { + copy( + isCurrentSession = sessionId.isNotEmpty() && sessionId == currentSessionId + ) + } + } + + override fun handle(action: SessionOverviewAction) { + TODO("Implement when adding the first action") + } +} diff --git a/vector/src/main/res/layout/fragment_settings_devices.xml b/vector/src/main/res/layout/fragment_settings_devices.xml index a289bda735..b4f47302e1 100644 --- a/vector/src/main/res/layout/fragment_settings_devices.xml +++ b/vector/src/main/res/layout/fragment_settings_devices.xml @@ -61,7 +61,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" app:devicesListHeaderDescription="" - app:devicesListHeaderTitle="@string/device_manager_header_section_current_session" + app:devicesListHeaderTitle="@string/device_manager_current_session_title" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/deviceListSecurityRecommendationsDivider" /> diff --git a/vector/src/main/res/layout/fragment_settings_session_overview.xml b/vector/src/main/res/layout/fragment_settings_session_overview.xml new file mode 100644 index 0000000000..1354408486 --- /dev/null +++ b/vector/src/main/res/layout/fragment_settings_session_overview.xml @@ -0,0 +1,6 @@ + + + +