mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-16 02:05:06 +08:00
Select devices with basic UI for tests
This commit is contained in:
parent
ab2e91ae80
commit
5b1bf8a68e
@ -30,4 +30,5 @@ data class DeviceFullInfo(
|
||||
val isCurrentDevice: Boolean,
|
||||
val deviceExtendedInfo: DeviceExtendedInfo,
|
||||
val matrixClientInfo: MatrixClientInfoContent?,
|
||||
val isSelected: Boolean = false,
|
||||
)
|
||||
|
@ -17,10 +17,12 @@
|
||||
package im.vector.app.features.settings.devices.v2.list
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.View
|
||||
import android.view.View.OnLongClickListener
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.app.R
|
||||
@ -57,6 +59,9 @@ abstract class OtherSessionItem : VectorEpoxyModel<OtherSessionItem.Holder>(R.la
|
||||
@EpoxyAttribute
|
||||
lateinit var stringProvider: StringProvider
|
||||
|
||||
@EpoxyAttribute
|
||||
var selected: Boolean = false
|
||||
|
||||
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
|
||||
var clickListener: ClickListener? = null
|
||||
|
||||
@ -81,6 +86,9 @@ abstract class OtherSessionItem : VectorEpoxyModel<OtherSessionItem.Holder>(R.la
|
||||
holder.otherSessionDescriptionTextView.setTextColor(it)
|
||||
}
|
||||
holder.otherSessionDescriptionTextView.setCompoundDrawablesWithIntrinsicBounds(sessionDescriptionDrawable, null, null, null)
|
||||
// TODO set drawable with correct color and corners
|
||||
val color = if (selected) R.color.alert_default_error_background else android.R.color.transparent
|
||||
holder.otherSessionItemBackgroundView.setBackgroundColor(ContextCompat.getColor(holder.view.context, color))
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
@ -88,5 +96,6 @@ abstract class OtherSessionItem : VectorEpoxyModel<OtherSessionItem.Holder>(R.la
|
||||
val otherSessionVerificationStatusImageView by bind<ShieldImageView>(R.id.otherSessionVerificationStatusImageView)
|
||||
val otherSessionNameTextView by bind<TextView>(R.id.otherSessionNameTextView)
|
||||
val otherSessionDescriptionTextView by bind<TextView>(R.id.otherSessionDescriptionTextView)
|
||||
val otherSessionItemBackgroundView by bind<View>(R.id.otherSessionItemBackground)
|
||||
}
|
||||
}
|
||||
|
@ -73,6 +73,7 @@ class OtherSessionsController @Inject constructor(
|
||||
sessionDescriptionDrawable(descriptionDrawable)
|
||||
sessionDescriptionColor(descriptionColor)
|
||||
stringProvider(this@OtherSessionsController.stringProvider)
|
||||
selected(device.isSelected)
|
||||
clickListener { device.deviceInfo.deviceId?.let { host.callback?.onItemClicked(it) } }
|
||||
onLongClickListener(View.OnLongClickListener {
|
||||
device.deviceInfo.deviceId?.let { host.callback?.onItemLongClicked(it) }
|
||||
|
@ -21,6 +21,7 @@ import im.vector.app.features.settings.devices.v2.filter.DeviceManagerFilterType
|
||||
|
||||
sealed class OtherSessionsAction : VectorViewModelAction {
|
||||
data class FilterDevices(val filterType: DeviceManagerFilterType) : OtherSessionsAction()
|
||||
object EnableSelectMode : OtherSessionsAction()
|
||||
data class EnableSelectMode(val deviceId: String?) : OtherSessionsAction()
|
||||
object DisableSelectMode : OtherSessionsAction()
|
||||
data class ToggleSelectionForDevice(val deviceId: String) : OtherSessionsAction()
|
||||
}
|
||||
|
@ -89,8 +89,8 @@ class OtherSessionsFragment :
|
||||
}
|
||||
}
|
||||
|
||||
private fun enableSelectMode(isEnabled: Boolean) {
|
||||
val action = if (isEnabled) OtherSessionsAction.EnableSelectMode else OtherSessionsAction.DisableSelectMode
|
||||
private fun enableSelectMode(isEnabled: Boolean, deviceId: String? = null) {
|
||||
val action = if (isEnabled) OtherSessionsAction.EnableSelectMode(deviceId) else OtherSessionsAction.DisableSelectMode
|
||||
viewModel.handle(action)
|
||||
}
|
||||
|
||||
@ -153,23 +153,25 @@ class OtherSessionsFragment :
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(viewModel) { state ->
|
||||
updateToolbar(state.isSelectModeEnabled)
|
||||
if (state.devices is Success) {
|
||||
renderDevices(state.devices(), state.currentFilter)
|
||||
val devices = state.devices().orEmpty()
|
||||
renderDevices(devices, state.currentFilter)
|
||||
updateToolbar(devices, state.isSelectModeEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateToolbar(isSelectModeEnabled: Boolean) {
|
||||
private fun updateToolbar(devices: List<DeviceFullInfo>, isSelectModeEnabled: Boolean) {
|
||||
invalidateOptionsMenu()
|
||||
val title = if (isSelectModeEnabled) {
|
||||
stringProvider.getQuantityString(R.plurals.device_manager_other_sessions_selected, 0, 0)
|
||||
val selection = devices.count { it.isSelected }
|
||||
stringProvider.getQuantityString(R.plurals.device_manager_other_sessions_selected, selection, selection)
|
||||
} else {
|
||||
getString(args.titleResourceId)
|
||||
}
|
||||
toolbar?.title = title
|
||||
}
|
||||
|
||||
private fun renderDevices(devices: List<DeviceFullInfo>?, currentFilter: DeviceManagerFilterType) {
|
||||
private fun renderDevices(devices: List<DeviceFullInfo>, currentFilter: DeviceManagerFilterType) {
|
||||
views.otherSessionsFilterBadgeImageView.isVisible = currentFilter != DeviceManagerFilterType.ALL_SESSIONS
|
||||
views.otherSessionsSecurityRecommendationView.isVisible = currentFilter != DeviceManagerFilterType.ALL_SESSIONS
|
||||
views.deviceListHeaderOtherSessions.isVisible = currentFilter == DeviceManagerFilterType.ALL_SESSIONS
|
||||
@ -222,7 +224,7 @@ class OtherSessionsFragment :
|
||||
}
|
||||
}
|
||||
|
||||
if (devices.isNullOrEmpty()) {
|
||||
if (devices.isEmpty()) {
|
||||
views.deviceListOtherSessions.isVisible = false
|
||||
views.otherSessionsNotFoundLayout.isVisible = true
|
||||
} else {
|
||||
@ -254,15 +256,19 @@ class OtherSessionsFragment :
|
||||
|
||||
override fun onOtherSessionLongClicked(deviceId: String) = withState(viewModel) { state ->
|
||||
if (!state.isSelectModeEnabled) {
|
||||
enableSelectMode(true)
|
||||
enableSelectMode(true, deviceId)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOtherSessionClicked(deviceId: String) {
|
||||
viewNavigator.navigateToSessionOverview(
|
||||
context = requireActivity(),
|
||||
deviceId = deviceId
|
||||
)
|
||||
override fun onOtherSessionClicked(deviceId: String) = withState(viewModel) { state ->
|
||||
if (state.isSelectModeEnabled) {
|
||||
viewModel.handle(OtherSessionsAction.ToggleSelectionForDevice(deviceId))
|
||||
} else {
|
||||
viewNavigator.navigateToSessionOverview(
|
||||
context = requireActivity(),
|
||||
deviceId = deviceId
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewAllOtherSessionsClicked() {
|
||||
|
@ -17,6 +17,7 @@
|
||||
package im.vector.app.features.settings.devices.v2.othersessions
|
||||
|
||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||
import com.airbnb.mvrx.Success
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
@ -69,7 +70,8 @@ class OtherSessionsViewModel @AssistedInject constructor(
|
||||
when (action) {
|
||||
is OtherSessionsAction.FilterDevices -> handleFilterDevices(action)
|
||||
OtherSessionsAction.DisableSelectMode -> handleDisableSelectMode()
|
||||
OtherSessionsAction.EnableSelectMode -> handleEnableSelectMode()
|
||||
is OtherSessionsAction.EnableSelectMode -> handleEnableSelectMode(action.deviceId)
|
||||
is OtherSessionsAction.ToggleSelectionForDevice -> handleToggleSelectionForDevice(action.deviceId)
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,10 +85,37 @@ class OtherSessionsViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleDisableSelectMode() {
|
||||
// TODO deselect all selected sessions
|
||||
setState { copy(isSelectModeEnabled = false) }
|
||||
}
|
||||
|
||||
private fun handleEnableSelectMode() {
|
||||
setState { copy(isSelectModeEnabled = true) }
|
||||
private fun handleEnableSelectMode(deviceId: String?) {
|
||||
toggleSelectionForDevice(deviceId, true)
|
||||
}
|
||||
|
||||
private fun handleToggleSelectionForDevice(deviceId: String) = withState { state ->
|
||||
toggleSelectionForDevice(deviceId, state.isSelectModeEnabled)
|
||||
}
|
||||
|
||||
private fun toggleSelectionForDevice(deviceId: String?, enableSelectMode: Boolean) = withState { state ->
|
||||
val updatedDevices = if (state.devices is Success) {
|
||||
val devices = state.devices.invoke().toMutableList()
|
||||
val indexToUpdate = devices.indexOfFirst { it.deviceInfo.deviceId == deviceId }
|
||||
if (indexToUpdate >= 0) {
|
||||
val currentInfo = devices[indexToUpdate]
|
||||
val updatedInfo = currentInfo.copy(isSelected = !currentInfo.isSelected)
|
||||
devices[indexToUpdate] = updatedInfo
|
||||
}
|
||||
Success(devices)
|
||||
} else {
|
||||
state.devices
|
||||
}
|
||||
|
||||
setState {
|
||||
copy(
|
||||
devices = updatedDevices,
|
||||
isSelectModeEnabled = enableSelectMode
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,30 +5,44 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:foreground="?selectableItemBackground"
|
||||
android:paddingTop="16dp">
|
||||
android:paddingTop="8dp"
|
||||
android:paddingHorizontal="8dp">
|
||||
|
||||
<View
|
||||
android:id="@+id/otherSessionItemBackground"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/otherSessionVerificationStatusImageView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/otherSessionDeviceTypeImageView"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="11dp"
|
||||
android:background="@drawable/bg_device_type"
|
||||
android:contentDescription="@string/a11y_device_manager_device_type_mobile"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/otherSessionItemBackground"
|
||||
app:layout_constraintStart_toStartOf="@+id/otherSessionItemBackground"
|
||||
app:layout_constraintTop_toTopOf="@+id/otherSessionItemBackground"
|
||||
tools:src="@drawable/ic_device_type_mobile" />
|
||||
|
||||
<im.vector.app.core.ui.views.ShieldImageView
|
||||
android:id="@+id/otherSessionVerificationStatusImageView"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginStart="26dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:background="@drawable/circle_with_border"
|
||||
android:importantForAccessibility="no"
|
||||
android:padding="6dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@+id/otherSessionDeviceTypeImageView"
|
||||
app:layout_constraintTop_toTopOf="@id/otherSessionDeviceTypeImageView"
|
||||
tools:src="@drawable/ic_shield_trusted" />
|
||||
|
||||
<TextView
|
||||
@ -37,21 +51,23 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/otherSessionDeviceTypeImageView"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/otherSessionDeviceTypeImageView"
|
||||
tools:text="Element Mobile: Android" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/otherSessionDescriptionTextView"
|
||||
style="@style/TextAppearance.Vector.Body.DevicesManagement"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:drawablePadding="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/otherSessionDeviceTypeImageView"
|
||||
app:layout_constraintEnd_toEndOf="@id/otherSessionNameTextView"
|
||||
app:layout_constraintStart_toStartOf="@id/otherSessionNameTextView"
|
||||
app:layout_constraintTop_toBottomOf="@id/otherSessionNameTextView"
|
||||
tools:text="@string/device_manager_verification_status_verified" />
|
||||
@ -59,10 +75,10 @@
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="?vctr_content_quinary"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/otherSessionNameTextView"
|
||||
app:layout_constraintTop_toBottomOf="@id/otherSessionDescriptionTextView" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/otherSessionItemBackground" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -9,7 +9,6 @@
|
||||
android:id="@+id/otherSessionsRecyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
@ -21,6 +20,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="0dp"
|
||||
android:layout_marginStart="16dp"
|
||||
app:layout_constraintStart_toStartOf="@id/otherSessionsRecyclerView"
|
||||
app:layout_constraintTop_toBottomOf="@id/otherSessionsRecyclerView"
|
||||
tools:text="@string/device_manager_other_sessions_view_all" />
|
||||
|
Loading…
Reference in New Issue
Block a user