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 @@
+
+