diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml index d5223a0638..7c74162859 100644 --- a/library/ui-strings/src/main/res/values/strings.xml +++ b/library/ui-strings/src/main/res/values/strings.xml @@ -3328,6 +3328,13 @@ No unverified sessions found. No inactive sessions found. Clear Filter + Select sessions + Select all + Deselect all + + %1$d selected + %1$d selected + Sign out of this session Session details Application, device, and activity information. diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsAction.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsAction.kt index 7164ecc866..2d184ffeaa 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsAction.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsAction.kt @@ -21,4 +21,6 @@ import im.vector.app.features.settings.devices.v2.filter.DeviceManagerFilterType sealed class OtherSessionsAction : VectorViewModelAction { data class FilterDevices(val filterType: DeviceManagerFilterType) : OtherSessionsAction() + object EnableSelectMode : OtherSessionsAction() + object DisableSelectMode : OtherSessionsAction() } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsFragment.kt index 610776e22e..804344e00e 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsFragment.kt @@ -18,8 +18,12 @@ package im.vector.app.features.settings.devices.v2.othersessions import android.os.Bundle import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuItem import android.view.View import android.view.ViewGroup +import androidx.activity.OnBackPressedCallback +import androidx.activity.addCallback import androidx.annotation.StringRes import androidx.core.view.isVisible import com.airbnb.mvrx.Success @@ -31,7 +35,9 @@ import im.vector.app.R import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment.ResultListener.Companion.RESULT_OK 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.StringProvider import im.vector.app.databinding.FragmentOtherSessionsBinding import im.vector.app.features.settings.devices.v2.DeviceFullInfo import im.vector.app.features.settings.devices.v2.filter.DeviceManagerFilterBottomSheet @@ -46,19 +52,65 @@ import javax.inject.Inject class OtherSessionsFragment : VectorBaseFragment(), VectorBaseBottomSheetDialogFragment.ResultListener, - OtherSessionsView.Callback { + OtherSessionsView.Callback, + VectorMenuProvider { private val viewModel: OtherSessionsViewModel by fragmentViewModel() private val args: OtherSessionsArgs by args() @Inject lateinit var colorProvider: ColorProvider + @Inject lateinit var stringProvider: StringProvider + @Inject lateinit var viewNavigator: OtherSessionsViewNavigator override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentOtherSessionsBinding { return FragmentOtherSessionsBinding.inflate(layoutInflater, container, false) } + override fun getMenuRes() = R.menu.menu_other_sessions + + override fun handlePrepareMenu(menu: Menu) { + withState(viewModel) { state -> + val isSelectModeEnabled = state.isSelectModeEnabled + menu.findItem(R.id.otherSessionsSelectAll).isVisible = isSelectModeEnabled + menu.findItem(R.id.otherSessionsDeselectAll).isVisible = isSelectModeEnabled + menu.findItem(R.id.otherSessionsSelect).isVisible = !isSelectModeEnabled + } + } + + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.otherSessionsSelect -> { + enableSelectMode(true) + true + } + else -> false + } + } + + // TODO call enableSelectMode(true) on long press of an item when disabled + private fun enableSelectMode(isEnabled: Boolean) { + val action = if (isEnabled) OtherSessionsAction.EnableSelectMode else OtherSessionsAction.DisableSelectMode + viewModel.handle(action) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + activity?.onBackPressedDispatcher?.addCallback(owner = this) { + handleBackPress(this) + } + } + + private fun handleBackPress(onBackPressedCallback: OnBackPressedCallback) = withState(viewModel) { state -> + if (state.isSelectModeEnabled) { + enableSelectMode(false) + } else { + onBackPressedCallback.isEnabled = false + activity?.onBackPressedDispatcher?.onBackPressed() + } + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) setupToolbar(views.otherSessionsToolbar).setTitle(args.titleResourceId).allowBack() @@ -102,11 +154,22 @@ class OtherSessionsFragment : } override fun invalidate() = withState(viewModel) { state -> + updateToolbar(state.isSelectModeEnabled) if (state.devices is Success) { renderDevices(state.devices(), state.currentFilter) } } + private fun updateToolbar(isSelectModeEnabled: Boolean) { + invalidateOptionsMenu() + val title = if (isSelectModeEnabled) { + stringProvider.getQuantityString(R.plurals.device_manager_other_sessions_selected, 0, 0) + } else { + getString(args.titleResourceId) + } + toolbar?.title = title + } + private fun renderDevices(devices: List?, currentFilter: DeviceManagerFilterType) { views.otherSessionsFilterBadgeImageView.isVisible = currentFilter != DeviceManagerFilterType.ALL_SESSIONS views.otherSessionsSecurityRecommendationView.isVisible = currentFilter != DeviceManagerFilterType.ALL_SESSIONS diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewModel.kt index e52953e2b6..21291fc082 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewModel.kt @@ -64,9 +64,12 @@ class OtherSessionsViewModel @AssistedInject constructor( } } + // TODO update unit tests override fun handle(action: OtherSessionsAction) { when (action) { is OtherSessionsAction.FilterDevices -> handleFilterDevices(action) + OtherSessionsAction.DisableSelectMode -> handleDisableSelectMode() + OtherSessionsAction.EnableSelectMode -> handleEnableSelectMode() } } @@ -78,4 +81,12 @@ class OtherSessionsViewModel @AssistedInject constructor( } observeDevices(action.filterType) } + + private fun handleDisableSelectMode() { + setState { copy(isSelectModeEnabled = false) } + } + + private fun handleEnableSelectMode() { + setState { copy(isSelectModeEnabled = true) } + } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewState.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewState.kt index 5256a9b27a..0db3c8cd0e 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewState.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/othersessions/OtherSessionsViewState.kt @@ -26,6 +26,7 @@ data class OtherSessionsViewState( val devices: Async> = Uninitialized, val currentFilter: DeviceManagerFilterType = DeviceManagerFilterType.ALL_SESSIONS, val excludeCurrentDevice: Boolean = false, + val isSelectModeEnabled: Boolean = false, ) : MavericksState { constructor(args: OtherSessionsArgs) : this(excludeCurrentDevice = args.excludeCurrentDevice) diff --git a/vector/src/main/res/menu/menu_other_sessions.xml b/vector/src/main/res/menu/menu_other_sessions.xml new file mode 100644 index 0000000000..0edab99127 --- /dev/null +++ b/vector/src/main/res/menu/menu_other_sessions.xml @@ -0,0 +1,21 @@ + + + + + + + + +