diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt index abcfe0d5d8..5452b03992 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt @@ -19,7 +19,6 @@ package im.vector.app.features.home.room.list import android.view.HapticFeedbackConstants import android.view.View import android.widget.ImageView -import android.widget.Space import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.isInvisible @@ -141,11 +140,6 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { private fun renderForFilteredDisplayMode(holder: Holder) { holder.subtitleView.text = subtitle - holder.centerTitle(shouldCenter = subtitle.isEmpty()) - } - - private fun Holder.centerTitle(shouldCenter: Boolean) { - centerTitleSpace.isVisible = shouldCenter } override fun unbind(holder: Holder) { @@ -182,6 +176,5 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { val roomAvatarFailSendingImageView by bind(R.id.roomAvatarFailSendingImageView) val roomAvatarPresenceImageView by bind(R.id.roomAvatarPresenceImageView) val rootView by bind(R.id.itemRoomLayout) - val centerTitleSpace by bind(R.id.centerTitleSpace) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemCentered.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemCentered.kt new file mode 100644 index 0000000000..8f2d949178 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemCentered.kt @@ -0,0 +1,134 @@ +/* + * Copyright 2019 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.home.room.list + +import android.view.HapticFeedbackConstants +import android.view.View +import android.widget.ImageView +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.view.isVisible +import com.airbnb.epoxy.EpoxyAttribute +import com.airbnb.epoxy.EpoxyModelClass +import com.amulyakhare.textdrawable.TextDrawable +import im.vector.app.R +import im.vector.app.core.epoxy.ClickListener +import im.vector.app.core.epoxy.VectorEpoxyHolder +import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.app.core.epoxy.onClick +import im.vector.app.core.ui.views.PresenceStateImageView +import im.vector.app.core.ui.views.ShieldImageView +import im.vector.app.features.displayname.getBestName +import im.vector.app.features.home.AvatarRenderer +import im.vector.app.features.home.RoomListDisplayMode +import im.vector.app.features.themes.ThemeUtils +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel +import org.matrix.android.sdk.api.session.presence.model.UserPresence +import org.matrix.android.sdk.api.util.MatrixItem + +@EpoxyModelClass(layout = R.layout.item_room_centered) +abstract class RoomSummaryItemCentered : VectorEpoxyModel() { + + @EpoxyAttribute + lateinit var avatarRenderer: AvatarRenderer + + @EpoxyAttribute + lateinit var matrixItem: MatrixItem + + @EpoxyAttribute + var displayMode: RoomListDisplayMode = RoomListDisplayMode.PEOPLE + + @EpoxyAttribute + var encryptionTrustLevel: RoomEncryptionTrustLevel? = null + + @EpoxyAttribute + var userPresence: UserPresence? = null + + @EpoxyAttribute + var showPresence: Boolean = false + + @EpoxyAttribute @JvmField + var isPublic: Boolean = false + + @EpoxyAttribute + var unreadNotificationCount: Int = 0 + + @EpoxyAttribute + var hasUnreadMessage: Boolean = false + + @EpoxyAttribute + var hasDraft: Boolean = false + + @EpoxyAttribute + var hasFailedSending: Boolean = false + + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) + var itemLongClickListener: View.OnLongClickListener? = null + + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) + var itemClickListener: ClickListener? = null + + @EpoxyAttribute + var showSelected: Boolean = false + + override fun bind(holder: Holder) { + super.bind(holder) + + holder.rootView.onClick(itemClickListener) + holder.rootView.setOnLongClickListener { + it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) + itemLongClickListener?.onLongClick(it) ?: false + } + holder.titleView.text = matrixItem.getBestName() + avatarRenderer.render(matrixItem, holder.avatarImageView) + holder.roomAvatarDecorationImageView.render(encryptionTrustLevel) + holder.roomAvatarPublicDecorationImageView.isVisible = isPublic + holder.roomAvatarFailSendingImageView.isVisible = hasFailedSending + renderSelection(holder, showSelected) + holder.roomAvatarPresenceImageView.render(showPresence, userPresence) + } + + override fun unbind(holder: Holder) { + holder.rootView.setOnClickListener(null) + holder.rootView.setOnLongClickListener(null) + avatarRenderer.clear(holder.avatarImageView) + super.unbind(holder) + } + + private fun renderSelection(holder: Holder, isSelected: Boolean) { + if (isSelected) { + holder.avatarCheckedImageView.visibility = View.VISIBLE + val backgroundColor = ThemeUtils.getColor(holder.view.context, R.attr.colorPrimary) + val backgroundDrawable = TextDrawable.builder().buildRound("", backgroundColor) + holder.avatarImageView.setImageDrawable(backgroundDrawable) + } else { + holder.avatarCheckedImageView.visibility = View.GONE + avatarRenderer.render(matrixItem, holder.avatarImageView) + } + } + + class Holder : VectorEpoxyHolder() { + val titleView by bind(R.id.roomNameView) + val avatarCheckedImageView by bind(R.id.roomAvatarCheckedImageView) + val avatarImageView by bind(R.id.roomAvatarImageView) + val roomAvatarDecorationImageView by bind(R.id.roomAvatarDecorationImageView) + val roomAvatarPublicDecorationImageView by bind(R.id.roomAvatarPublicDecorationImageView) + val roomAvatarFailSendingImageView by bind(R.id.roomAvatarFailSendingImageView) + val roomAvatarPresenceImageView by bind(R.id.roomAvatarPresenceImageView) + val rootView by bind(R.id.itemRoomLayout) + } +} diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt index 05701b908f..792303eaf6 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt @@ -126,31 +126,74 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor } val typingMessage = typingHelper.getTypingMessage(roomSummary.typingUsers) - return RoomSummaryItem_() - .id(roomSummary.roomId) - .avatarRenderer(avatarRenderer) - // We do not display shield in the room list anymore - // .encryptionTrustLevel(roomSummary.roomEncryptionTrustLevel) - .displayMode(displayMode) - .subtitle(subtitle) - .isPublic(roomSummary.isPublic) - .showPresence(roomSummary.isDirect) - .userPresence(roomSummary.directUserPresence) - .matrixItem(roomSummary.toMatrixItem()) - .lastEventTime(latestEventTime) - .typingMessage(typingMessage) - .lastFormattedEvent(latestFormattedEvent.toEpoxyCharSequence()) - .showHighlighted(showHighlighted) - .showSelected(showSelected) - .hasFailedSending(roomSummary.hasFailedSending) - .unreadNotificationCount(unreadCount) - .hasUnreadMessage(roomSummary.hasUnreadMessages) - .hasDraft(roomSummary.userDrafts.isNotEmpty()) - .itemLongClickListener { _ -> - onLongClick?.invoke(roomSummary) ?: false - } - .itemClickListener { onClick?.invoke(roomSummary) } + + return if (subtitle.isBlank() && displayMode == RoomListDisplayMode.FILTERED) { + createCenteredRoomSummaryItem(roomSummary, displayMode, showSelected, unreadCount, onClick, onLongClick) + } else { + createRoomSummaryItem(roomSummary, displayMode, subtitle, latestEventTime, typingMessage, + latestFormattedEvent, showHighlighted, showSelected, unreadCount, onClick, onLongClick) + } } + + private fun createRoomSummaryItem( + roomSummary: RoomSummary, + displayMode: RoomListDisplayMode, + subtitle: String, + latestEventTime: String, + typingMessage: String, + latestFormattedEvent: CharSequence, + showHighlighted: Boolean, + showSelected: Boolean, + unreadCount: Int, + onClick: ((RoomSummary) -> Unit)?, + onLongClick: ((RoomSummary) -> Boolean)? + ) = RoomSummaryItem_() + .id(roomSummary.roomId) + .avatarRenderer(avatarRenderer) + // We do not display shield in the room list anymore + // .encryptionTrustLevel(roomSummary.roomEncryptionTrustLevel) + .displayMode(displayMode) + .subtitle(subtitle) + .isPublic(roomSummary.isPublic) + .showPresence(roomSummary.isDirect) + .userPresence(roomSummary.directUserPresence) + .matrixItem(roomSummary.toMatrixItem()) + .lastEventTime(latestEventTime) + .typingMessage(typingMessage) + .lastFormattedEvent(latestFormattedEvent.toEpoxyCharSequence()) + .showHighlighted(showHighlighted) + .showSelected(showSelected) + .hasFailedSending(roomSummary.hasFailedSending) + .unreadNotificationCount(unreadCount) + .hasUnreadMessage(roomSummary.hasUnreadMessages) + .hasDraft(roomSummary.userDrafts.isNotEmpty()) + .itemLongClickListener { _ -> onLongClick?.invoke(roomSummary) ?: false } + .itemClickListener { onClick?.invoke(roomSummary) } + + private fun createCenteredRoomSummaryItem( + roomSummary: RoomSummary, + displayMode: RoomListDisplayMode, + showSelected: Boolean, + unreadCount: Int, + onClick: ((RoomSummary) -> Unit)?, + onLongClick: ((RoomSummary) -> Boolean)? + ) = RoomSummaryItemCentered_() + .id(roomSummary.roomId) + .avatarRenderer(avatarRenderer) + // We do not display shield in the room list anymore + // .encryptionTrustLevel(roomSummary.roomEncryptionTrustLevel) + .displayMode(displayMode) + .isPublic(roomSummary.isPublic) + .showPresence(roomSummary.isDirect) + .userPresence(roomSummary.directUserPresence) + .matrixItem(roomSummary.toMatrixItem()) + .showSelected(showSelected) + .hasFailedSending(roomSummary.hasFailedSending) + .unreadNotificationCount(unreadCount) + .hasUnreadMessage(roomSummary.hasUnreadMessages) + .hasDraft(roomSummary.userDrafts.isNotEmpty()) + .itemLongClickListener { _ -> onLongClick?.invoke(roomSummary) ?: false } + .itemClickListener { onClick?.invoke(roomSummary) } private fun getSearchResultSubtitle(roomSummary: RoomSummary): String { val userId = roomSummary.directUserId diff --git a/vector/src/main/res/layout/item_room.xml b/vector/src/main/res/layout/item_room.xml index ac028ccb08..ab0af18acb 100644 --- a/vector/src/main/res/layout/item_room.xml +++ b/vector/src/main/res/layout/item_room.xml @@ -112,27 +112,13 @@ app:layout_constraintTop_toBottomOf="@id/roomAvatarContainer" tools:layout_marginStart="20dp" /> - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +