Merge pull request #2288 from vector-im/feature/bma/low_priority

Toggle low priority tag of a room
This commit is contained in:
Benoit Marty 2020-10-28 13:53:28 +01:00 committed by GitHub
commit b9795786c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 113 additions and 17 deletions

View File

@ -7,6 +7,7 @@ Features ✨:
Improvements 🙌: Improvements 🙌:
- Rework sending Event management (#154) - Rework sending Event management (#154)
- New room creation screen: set topic and avatar in the room creation form (#2078) - New room creation screen: set topic and avatar in the room creation form (#2078)
- Toggle Low priority tag (#1490)
- Add option to send with enter (#1195) - Add option to send with enter (#1195)
- Use Hardware keyboard enter to send message (use shift-enter for new line) (#1881, #1440) - Use Hardware keyboard enter to send message (use shift-enter for new line) (#1881, #1440)
- Edit and remove icons are now visible on image attachment preview screen (#2294) - Edit and remove icons are now visible on image attachment preview screen (#2294)

View File

@ -63,8 +63,13 @@ data class RoomSummary constructor(
val hasNewMessages: Boolean val hasNewMessages: Boolean
get() = notificationCount != 0 get() = notificationCount != 0
val isLowPriority: Boolean
get() = hasTag(RoomTag.ROOM_TAG_LOW_PRIORITY)
val isFavorite: Boolean val isFavorite: Boolean
get() = tags.any { it.name == RoomTag.ROOM_TAG_FAVOURITE } get() = hasTag(RoomTag.ROOM_TAG_FAVOURITE)
fun hasTag(tag: String) = tags.any { it.name == tag }
val canStartCall: Boolean val canStartCall: Boolean
get() = joinedMembersCount == 2 get() = joinedMembersCount == 2

View File

@ -44,8 +44,10 @@ abstract class BottomSheetRoomPreviewItem : VectorEpoxyModel<BottomSheetRoomPrev
@EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer
@EpoxyAttribute lateinit var matrixItem: MatrixItem @EpoxyAttribute lateinit var matrixItem: MatrixItem
@EpoxyAttribute lateinit var stringProvider: StringProvider @EpoxyAttribute lateinit var stringProvider: StringProvider
@EpoxyAttribute var izLowPriority: Boolean = false
@EpoxyAttribute var izFavorite: Boolean = false @EpoxyAttribute var izFavorite: Boolean = false
@EpoxyAttribute var settingsClickListener: ClickListener? = null @EpoxyAttribute var settingsClickListener: ClickListener? = null
@EpoxyAttribute var lowPriorityClickListener: ClickListener? = null
@EpoxyAttribute var favoriteClickListener: ClickListener? = null @EpoxyAttribute var favoriteClickListener: ClickListener? = null
override fun bind(holder: Holder) { override fun bind(holder: Holder) {
@ -53,17 +55,44 @@ abstract class BottomSheetRoomPreviewItem : VectorEpoxyModel<BottomSheetRoomPrev
avatarRenderer.render(matrixItem, holder.avatar) avatarRenderer.render(matrixItem, holder.avatar)
holder.avatar.onClick(settingsClickListener) holder.avatar.onClick(settingsClickListener)
holder.roomName.setTextOrHide(matrixItem.displayName) holder.roomName.setTextOrHide(matrixItem.displayName)
setLowPriorityState(holder, izLowPriority)
setFavoriteState(holder, izFavorite) setFavoriteState(holder, izFavorite)
holder.roomLowPriority.setOnClickListener {
// Immediate echo
setLowPriorityState(holder, !izLowPriority)
if (!izLowPriority) {
// If we put the room in low priority, it will also remove the favorite tag
setFavoriteState(holder, false)
}
// And do the action
lowPriorityClickListener?.invoke()
}
holder.roomFavorite.setOnClickListener { holder.roomFavorite.setOnClickListener {
// Immediate echo // Immediate echo
setFavoriteState(holder, !izFavorite) setFavoriteState(holder, !izFavorite)
if (!izFavorite) {
// If we put the room in favorite, it will also remove the low priority tag
setLowPriorityState(holder, false)
}
// And do the action // And do the action
favoriteClickListener?.invoke() favoriteClickListener?.invoke()
} }
holder.roomSettings.onClick(settingsClickListener) holder.roomSettings.onClick(settingsClickListener)
} }
private fun setLowPriorityState(holder: Holder, isLowPriority: Boolean) {
val tintColor: Int
if (isLowPriority) {
holder.roomLowPriority.contentDescription = stringProvider.getString(R.string.room_list_quick_actions_low_priority_remove)
tintColor = ContextCompat.getColor(holder.view.context, R.color.riotx_accent)
} else {
holder.roomLowPriority.contentDescription = stringProvider.getString(R.string.room_list_quick_actions_low_priority_add)
tintColor = ThemeUtils.getColor(holder.view.context, R.attr.riotx_text_secondary)
}
ImageViewCompat.setImageTintList(holder.roomLowPriority, ColorStateList.valueOf(tintColor))
}
private fun setFavoriteState(holder: Holder, isFavorite: Boolean) { private fun setFavoriteState(holder: Holder, isFavorite: Boolean) {
val tintColor: Int val tintColor: Int
if (isFavorite) { if (isFavorite) {
@ -81,6 +110,7 @@ abstract class BottomSheetRoomPreviewItem : VectorEpoxyModel<BottomSheetRoomPrev
class Holder : VectorEpoxyHolder() { class Holder : VectorEpoxyHolder() {
val avatar by bind<ImageView>(R.id.bottomSheetRoomPreviewAvatar) val avatar by bind<ImageView>(R.id.bottomSheetRoomPreviewAvatar)
val roomName by bind<TextView>(R.id.bottomSheetRoomPreviewName) val roomName by bind<TextView>(R.id.bottomSheetRoomPreviewName)
val roomLowPriority by bind<ImageView>(R.id.bottomSheetRoomPreviewLowPriority)
val roomFavorite by bind<ImageView>(R.id.bottomSheetRoomPreviewFavorite) val roomFavorite by bind<ImageView>(R.id.bottomSheetRoomPreviewFavorite)
val roomSettings by bind<View>(R.id.bottomSheetRoomPreviewSettings) val roomSettings by bind<View>(R.id.bottomSheetRoomPreviewSettings)
} }

View File

@ -27,7 +27,7 @@ sealed class RoomListAction : VectorViewModelAction {
data class RejectInvitation(val roomSummary: RoomSummary) : RoomListAction() data class RejectInvitation(val roomSummary: RoomSummary) : RoomListAction()
data class FilterWith(val filter: String) : RoomListAction() data class FilterWith(val filter: String) : RoomListAction()
data class ChangeRoomNotificationState(val roomId: String, val notificationState: RoomNotificationState) : RoomListAction() data class ChangeRoomNotificationState(val roomId: String, val notificationState: RoomNotificationState) : RoomListAction()
data class ToggleFavorite(val roomId: String) : RoomListAction() data class ToggleTag(val roomId: String, val tag: String) : RoomListAction()
data class LeaveRoom(val roomId: String) : RoomListAction() data class LeaveRoom(val roomId: String) : RoomListAction()
object MarkAllRoomsRead : RoomListAction() object MarkAllRoomsRead : RoomListAction()
} }

View File

@ -52,6 +52,7 @@ import kotlinx.android.synthetic.main.fragment_room_list.*
import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.tag.RoomTag
import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
import javax.inject.Inject import javax.inject.Inject
@ -233,7 +234,10 @@ class RoomListFragment @Inject constructor(
navigator.openRoomProfile(requireActivity(), quickAction.roomId) navigator.openRoomProfile(requireActivity(), quickAction.roomId)
} }
is RoomListQuickActionsSharedAction.Favorite -> { is RoomListQuickActionsSharedAction.Favorite -> {
roomListViewModel.handle(RoomListAction.ToggleFavorite(quickAction.roomId)) roomListViewModel.handle(RoomListAction.ToggleTag(quickAction.roomId, RoomTag.ROOM_TAG_FAVOURITE))
}
is RoomListQuickActionsSharedAction.LowPriority -> {
roomListViewModel.handle(RoomListAction.ToggleTag(quickAction.roomId, RoomTag.ROOM_TAG_LOW_PRIORITY))
} }
is RoomListQuickActionsSharedAction.Leave -> { is RoomListQuickActionsSharedAction.Leave -> {
AlertDialog.Builder(requireContext()) AlertDialog.Builder(requireContext())

View File

@ -16,6 +16,7 @@
package im.vector.app.features.home.room.list package im.vector.app.features.home.room.list
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.ViewModelContext import com.airbnb.mvrx.ViewModelContext
@ -23,6 +24,8 @@ import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.utils.DataSource import im.vector.app.core.utils.DataSource
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.NoOpMatrixCallback import org.matrix.android.sdk.api.NoOpMatrixCallback
import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.orFalse
@ -30,6 +33,7 @@ import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.tag.RoomTag import org.matrix.android.sdk.api.session.room.model.tag.RoomTag
import org.matrix.android.sdk.internal.util.awaitCallback
import org.matrix.android.sdk.rx.rx import org.matrix.android.sdk.rx.rx
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -70,7 +74,7 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState,
is RoomListAction.MarkAllRoomsRead -> handleMarkAllRoomsRead() is RoomListAction.MarkAllRoomsRead -> handleMarkAllRoomsRead()
is RoomListAction.LeaveRoom -> handleLeaveRoom(action) is RoomListAction.LeaveRoom -> handleLeaveRoom(action)
is RoomListAction.ChangeRoomNotificationState -> handleChangeNotificationMode(action) is RoomListAction.ChangeRoomNotificationState -> handleChangeNotificationMode(action)
is RoomListAction.ToggleFavorite -> handleToggleFavorite(action) is RoomListAction.ToggleTag -> handleToggleTag(action)
}.exhaustive }.exhaustive
} }
@ -172,19 +176,39 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState,
}) })
} }
private fun handleToggleFavorite(action: RoomListAction.ToggleFavorite) { private fun handleToggleTag(action: RoomListAction.ToggleTag) {
session.getRoom(action.roomId)?.let { session.getRoom(action.roomId)?.let { room ->
val callback = object : MatrixCallback<Unit> { viewModelScope.launch(Dispatchers.IO) {
override fun onFailure(failure: Throwable) { try {
if (room.roomSummary()?.hasTag(action.tag) == false) {
// Favorite and low priority tags are exclusive, so maybe delete the other tag first
action.tag.otherTag()
?.takeIf { room.roomSummary()?.hasTag(it).orFalse() }
?.let { tagToRemove ->
awaitCallback<Unit> { room.deleteTag(tagToRemove, it) }
}
// Set the tag. We do not handle the order for the moment
awaitCallback<Unit> {
room.addTag(action.tag, 0.5, it)
}
} else {
awaitCallback<Unit> {
room.deleteTag(action.tag, it)
}
}
} catch (failure: Throwable) {
_viewEvents.post(RoomListViewEvents.Failure(failure)) _viewEvents.post(RoomListViewEvents.Failure(failure))
} }
} }
if (it.roomSummary()?.isFavorite == false) { }
// Set favorite tag. We do not handle the order for the moment }
it.addTag(RoomTag.ROOM_TAG_FAVOURITE, 0.5, callback)
} else { private fun String.otherTag(): String? {
it.deleteTag(RoomTag.ROOM_TAG_FAVOURITE, callback) return when (this) {
} RoomTag.ROOM_TAG_FAVOURITE -> RoomTag.ROOM_TAG_LOW_PRIORITY
RoomTag.ROOM_TAG_LOW_PRIORITY -> RoomTag.ROOM_TAG_FAVOURITE
else -> null
} }
} }

View File

@ -89,8 +89,9 @@ class RoomListQuickActionsBottomSheet : VectorBaseBottomSheetDialogFragment(), R
sharedActionViewModel.post(quickAction) sharedActionViewModel.post(quickAction)
// Do not dismiss for all the actions // Do not dismiss for all the actions
when (quickAction) { when (quickAction) {
is RoomListQuickActionsSharedAction.Favorite -> Unit is RoomListQuickActionsSharedAction.LowPriority -> Unit
else -> dismiss() is RoomListQuickActionsSharedAction.Favorite -> Unit
else -> dismiss()
} }
} }

View File

@ -47,9 +47,11 @@ class RoomListQuickActionsEpoxyController @Inject constructor(
avatarRenderer(avatarRenderer) avatarRenderer(avatarRenderer)
matrixItem(roomSummary.toMatrixItem()) matrixItem(roomSummary.toMatrixItem())
stringProvider(stringProvider) stringProvider(stringProvider)
izLowPriority(roomSummary.isLowPriority)
izFavorite(roomSummary.isFavorite) izFavorite(roomSummary.isFavorite)
settingsClickListener { listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.Settings(roomSummary.roomId)) } settingsClickListener { listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.Settings(roomSummary.roomId)) }
favoriteClickListener { listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.Favorite(roomSummary.roomId)) } favoriteClickListener { listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.Favorite(roomSummary.roomId)) }
lowPriorityClickListener { listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.LowPriority(roomSummary.roomId)) }
} }
// Notifications // Notifications

View File

@ -52,6 +52,10 @@ sealed class RoomListQuickActionsSharedAction(
R.drawable.ic_room_actions_settings R.drawable.ic_room_actions_settings
) )
data class LowPriority(val roomId: String) : RoomListQuickActionsSharedAction(
R.string.room_list_quick_actions_low_priority_add,
R.drawable.ic_low_priority_24)
data class Favorite(val roomId: String) : RoomListQuickActionsSharedAction( data class Favorite(val roomId: String) : RoomListQuickActionsSharedAction(
R.string.room_list_quick_actions_favorite_add, R.string.room_list_quick_actions_favorite_add,
R.drawable.ic_star_24dp) R.drawable.ic_star_24dp)

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M13.6185,0.6704C12.7246,-0.2235 11.2754,-0.2235 10.3815,0.6704L0.6704,10.3815C-0.2235,11.2754 -0.2235,12.7246 0.6704,13.6185L10.3815,23.3296C11.2754,24.2235 12.7246,24.2235 13.6185,23.3296L23.3296,13.6185C24.2235,12.7246 24.2235,11.2754 23.3296,10.3815L13.6185,0.6704ZM11.9999,5C12.5522,5 12.9999,5.4477 12.9999,6V15.5564L15.7781,12.7782C16.1686,12.3877 16.8018,12.3877 17.1923,12.7782C17.5829,13.1687 17.5829,13.8019 17.1923,14.1924L12.8362,18.5486C12.6574,18.8205 12.3496,19 11.9999,19C11.7189,19 11.465,18.8841 11.2833,18.6974L11.2782,18.6924L6.7782,14.1924C6.3877,13.8019 6.3877,13.1687 6.7782,12.7782C7.1688,12.3877 7.8019,12.3877 8.1925,12.7782L10.9999,15.5857V6C10.9999,5.4477 11.4477,5 11.9999,5Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</vector>

View File

@ -38,11 +38,24 @@
android:textSize="14sp" android:textSize="14sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/bottomSheetRoomPreviewAvatar" app:layout_constraintBottom_toBottomOf="@+id/bottomSheetRoomPreviewAvatar"
app:layout_constraintEnd_toStartOf="@+id/bottomSheetRoomPreviewFavorite" app:layout_constraintEnd_toStartOf="@+id/bottomSheetRoomPreviewLowPriority"
app:layout_constraintStart_toEndOf="@id/bottomSheetRoomPreviewAvatar" app:layout_constraintStart_toEndOf="@id/bottomSheetRoomPreviewAvatar"
app:layout_constraintTop_toTopOf="@id/bottomSheetRoomPreviewAvatar" app:layout_constraintTop_toTopOf="@id/bottomSheetRoomPreviewAvatar"
tools:text="@tools:sample/full_names" /> tools:text="@tools:sample/full_names" />
<ImageView
android:id="@+id/bottomSheetRoomPreviewLowPriority"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?attr/selectableItemBackground"
android:scaleType="centerInside"
android:src="@drawable/ic_low_priority_24"
app:layout_constraintBottom_toBottomOf="@+id/bottomSheetRoomPreviewAvatar"
app:layout_constraintEnd_toStartOf="@+id/bottomSheetRoomPreviewFavorite"
app:layout_constraintTop_toTopOf="@id/bottomSheetRoomPreviewAvatar"
tools:contentDescription="@string/room_list_quick_actions_low_priority_add"
tools:tint="?riotx_text_secondary" />
<ImageView <ImageView
android:id="@+id/bottomSheetRoomPreviewFavorite" android:id="@+id/bottomSheetRoomPreviewFavorite"
android:layout_width="48dp" android:layout_width="48dp"

View File

@ -1883,6 +1883,8 @@
<string name="room_list_quick_actions_settings">"Settings"</string> <string name="room_list_quick_actions_settings">"Settings"</string>
<string name="room_list_quick_actions_favorite_add">"Add to favorites"</string> <string name="room_list_quick_actions_favorite_add">"Add to favorites"</string>
<string name="room_list_quick_actions_favorite_remove">"Remove from favorites"</string> <string name="room_list_quick_actions_favorite_remove">"Remove from favorites"</string>
<string name="room_list_quick_actions_low_priority_add">"Add to low priority"</string>
<string name="room_list_quick_actions_low_priority_remove">"Remove from low priority"</string>
<string name="room_list_quick_actions_leave">"Leave the room"</string> <string name="room_list_quick_actions_leave">"Leave the room"</string>
<string name="notice_member_no_changes">"%1$s made no changes"</string> <string name="notice_member_no_changes">"%1$s made no changes"</string>
<string name="notice_member_no_changes_by_you">"You made no changes"</string> <string name="notice_member_no_changes_by_you">"You made no changes"</string>