diff --git a/CHANGES.md b/CHANGES.md index ee7bc25530..6b02cc2102 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,7 +8,7 @@ Improvements 🙌: - Other changes: - - + - Use same default room colors than Riot-Web Bugfix 🐛: - Scroll breadcrumbs to top when opened diff --git a/build.gradle b/build.gradle index 714152370e..6f0874dc81 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:3.5.1' + classpath 'com.android.tools.build:gradle:3.5.3' classpath 'com.google.gms:google-services:4.3.2' classpath "com.airbnb.okreplay:gradle-plugin:1.5.0" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/send/UserMentionSpan.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/send/UserMentionSpan.kt index 4cd8080dc3..71a422bac8 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/send/UserMentionSpan.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/send/UserMentionSpan.kt @@ -16,11 +16,12 @@ package im.vector.matrix.android.api.session.room.send +import im.vector.matrix.android.api.util.MatrixItem + /** * Tag class for spans that should mention a user. * These Spans will be transformed into pills when detected in message to send */ interface UserMentionSpan { - val displayName: String - val userId: String + val matrixItem: MatrixItem } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/util/MatrixItem.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/util/MatrixItem.kt new file mode 100644 index 0000000000..b94335e526 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/util/MatrixItem.kt @@ -0,0 +1,75 @@ +/* + * 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.matrix.android.api.util + +import im.vector.matrix.android.api.session.group.model.GroupSummary +import im.vector.matrix.android.api.session.room.model.RoomSummary +import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom +import im.vector.matrix.android.api.session.user.model.User + +sealed class MatrixItem( + open val id: String, + open val displayName: String?, + open val avatarUrl: String? +) { + data class UserItem(override val id: String, + override val displayName: String? = null, + override val avatarUrl: String? = null + ) : MatrixItem(id, displayName, avatarUrl) + + data class EventItem(override val id: String, + override val displayName: String? = null, + override val avatarUrl: String? = null) + : MatrixItem(id, displayName, avatarUrl) + + data class RoomItem(override val id: String, + override val displayName: String? = null, + override val avatarUrl: String? = null) + : MatrixItem(id, displayName, avatarUrl) + + data class RoomAliasItem(override val id: String, + override val displayName: String? = null, + override val avatarUrl: String? = null) + : MatrixItem(id, displayName, avatarUrl) + + data class GroupItem(override val id: String, + override val displayName: String? = null, + override val avatarUrl: String? = null) + : MatrixItem(id, displayName, avatarUrl) + + fun getBestName(): String { + return displayName?.takeIf { it.isNotBlank() } ?: id + } + + /** + * Return the prefix as defined in the matrix spec (and not extracted from the id) + */ + fun getPrefix() = when (this) { + is UserItem -> '@' + is EventItem -> '$' + is RoomItem -> '!' + is RoomAliasItem -> '#' + is GroupItem -> '+' + } + + companion object { + fun from(user: User) = UserItem(user.userId, user.displayName, user.avatarUrl) + fun from(groupSummary: GroupSummary) = GroupItem(groupSummary.groupId, groupSummary.displayName, groupSummary.avatarUrl) + fun from(roomSummary: RoomSummary) = RoomItem(roomSummary.roomId, roomSummary.displayName, roomSummary.avatarUrl) + fun from(publicRoom: PublicRoom) = RoomItem(publicRoom.roomId, publicRoom.name, publicRoom.avatarUrl) + } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/pills/TextPillsUtils.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/pills/TextPillsUtils.kt index 580e49b2ce..c079e456c0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/pills/TextPillsUtils.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/pills/TextPillsUtils.kt @@ -65,7 +65,7 @@ internal class TextPillsUtils @Inject constructor( // append text before pill append(text, currIndex, start) // append the pill - append(String.format(template, urlSpan.userId, urlSpan.displayName)) + append(String.format(template, urlSpan.matrixItem.id, urlSpan.matrixItem.displayName)) currIndex = end } // append text after the last pill diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringUtils.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringUtils.kt index 31da372bbe..c27d66efed 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringUtils.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringUtils.kt @@ -52,6 +52,7 @@ fun convertFromUTF8(s: String): String { } } +// TODO Improve this fun String?.firstLetterOfDisplayName(): String { if (this.isNullOrEmpty()) return "" val isUserId = MatrixPatterns.isUserId(this) diff --git a/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt index 8105d7a7c0..7b79ce8549 100644 --- a/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt +++ b/vector/src/main/java/im/vector/riotx/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt @@ -21,6 +21,7 @@ import android.widget.ImageView import android.widget.TextView import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.core.epoxy.VectorEpoxyModel @@ -37,11 +38,7 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel>() { +class AutocompleteUserController @Inject constructor() : TypedEpoxyController>() { var listener: AutocompleteClickListener? = null @@ -35,9 +36,7 @@ class AutocompleteUserController @Inject constructor(): TypedEpoxyController autocompleteUserItem { id(user.userId) - userId(user.userId) - name(user.displayName) - avatarUrl(user.avatarUrl) + matrixItem(MatrixItem.from(user)) avatarRenderer(avatarRenderer) clickListener { _ -> listener?.onItemClick(user) diff --git a/vector/src/main/java/im/vector/riotx/features/autocomplete/user/AutocompleteUserItem.kt b/vector/src/main/java/im/vector/riotx/features/autocomplete/user/AutocompleteUserItem.kt index b32562d8e6..8581ba8e2c 100644 --- a/vector/src/main/java/im/vector/riotx/features/autocomplete/user/AutocompleteUserItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/autocomplete/user/AutocompleteUserItem.kt @@ -21,6 +21,7 @@ import android.widget.ImageView import android.widget.TextView import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.core.epoxy.VectorEpoxyModel @@ -30,15 +31,13 @@ import im.vector.riotx.features.home.AvatarRenderer abstract class AutocompleteUserItem : VectorEpoxyModel() { @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer - @EpoxyAttribute var name: String? = null - @EpoxyAttribute var userId: String = "" - @EpoxyAttribute var avatarUrl: String? = null + @EpoxyAttribute lateinit var matrixItem: MatrixItem @EpoxyAttribute var clickListener: View.OnClickListener? = null override fun bind(holder: Holder) { holder.view.setOnClickListener(clickListener) - holder.nameView.text = name - avatarRenderer.render(avatarUrl, userId, name, holder.avatarImageView) + holder.nameView.text = matrixItem.getBestName() + avatarRenderer.render(matrixItem, holder.avatarImageView) } class Holder : VectorEpoxyHolder() { diff --git a/vector/src/main/java/im/vector/riotx/features/crypto/verification/SASVerificationIncomingFragment.kt b/vector/src/main/java/im/vector/riotx/features/crypto/verification/SASVerificationIncomingFragment.kt index 88df53d0f3..47d7e783b4 100644 --- a/vector/src/main/java/im/vector/riotx/features/crypto/verification/SASVerificationIncomingFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/crypto/verification/SASVerificationIncomingFragment.kt @@ -22,6 +22,7 @@ import androidx.lifecycle.Observer import butterknife.BindView import butterknife.OnClick import im.vector.matrix.android.api.session.crypto.sas.IncomingSasVerificationTransaction +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.platform.VectorBaseFragment import im.vector.riotx.features.home.AvatarRenderer @@ -57,10 +58,10 @@ class SASVerificationIncomingFragment @Inject constructor( otherDeviceTextView.text = viewModel.otherDeviceId viewModel.otherUser?.let { - avatarRenderer.render(it, avatarImageView) + avatarRenderer.render(MatrixItem.from(it), avatarImageView) } ?: run { // Fallback to what we know - avatarRenderer.render(null, viewModel.otherUserId ?: "", viewModel.otherUserId, avatarImageView) + avatarRenderer.render(MatrixItem.UserItem(viewModel.otherUserId ?: "", viewModel.otherUserId), avatarImageView) } viewModel.transactionState.observe(viewLifecycleOwner, Observer { diff --git a/vector/src/main/java/im/vector/riotx/features/home/AvatarRenderer.kt b/vector/src/main/java/im/vector/riotx/features/home/AvatarRenderer.kt index 9975ee91cd..736cb6e4ff 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/AvatarRenderer.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/AvatarRenderer.kt @@ -27,10 +27,8 @@ import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.target.DrawableImageViewTarget import com.bumptech.glide.request.target.Target import im.vector.matrix.android.api.session.content.ContentUrlResolver -import im.vector.matrix.android.api.session.room.model.RoomSummary -import im.vector.matrix.android.api.session.user.model.User +import im.vector.matrix.android.api.util.MatrixItem import im.vector.matrix.android.internal.util.firstLetterOfDisplayName -import im.vector.riotx.R import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.glide.GlideApp import im.vector.riotx.core.glide.GlideRequest @@ -45,54 +43,37 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active companion object { private const val THUMBNAIL_SIZE = 250 - - private val AVATAR_COLOR_LIST = listOf( - R.color.riotx_avatar_fill_1, - R.color.riotx_avatar_fill_2, - R.color.riotx_avatar_fill_3 - ) } @UiThread - fun render(roomSummary: RoomSummary, imageView: ImageView) { - render(roomSummary.avatarUrl, roomSummary.roomId, roomSummary.displayName, imageView) - } - - @UiThread - fun render(user: User, imageView: ImageView) { - render(imageView.context, GlideApp.with(imageView), user.avatarUrl, user.userId, user.displayName, DrawableImageViewTarget(imageView)) - } - - @UiThread - fun render(avatarUrl: String?, identifier: String, name: String?, imageView: ImageView) { - render(imageView.context, GlideApp.with(imageView), avatarUrl, identifier, name, DrawableImageViewTarget(imageView)) + fun render(matrixItem: MatrixItem, imageView: ImageView) { + render(imageView.context, + GlideApp.with(imageView), + matrixItem, + DrawableImageViewTarget(imageView)) } @UiThread fun render(context: Context, glideRequest: GlideRequests, - avatarUrl: String?, - identifier: String, - name: String?, + matrixItem: MatrixItem, target: Target) { - val displayName = if (name.isNullOrBlank()) { - identifier - } else { - name - } - val placeholder = getPlaceholderDrawable(context, identifier, displayName) - buildGlideRequest(glideRequest, avatarUrl) + val placeholder = getPlaceholderDrawable(context, matrixItem) + buildGlideRequest(glideRequest, matrixItem.avatarUrl) .placeholder(placeholder) .into(target) } @AnyThread - fun getPlaceholderDrawable(context: Context, identifier: String, text: String): Drawable { - val avatarColor = ContextCompat.getColor(context, getColorFromUserId(identifier)) - return if (text.isEmpty()) { + fun getPlaceholderDrawable(context: Context, matrixItem: MatrixItem): Drawable { + val avatarColor = when (matrixItem) { + is MatrixItem.UserItem -> ContextCompat.getColor(context, getColorFromUserId(matrixItem.id)) + else -> ContextCompat.getColor(context, getColorFromRoomId(matrixItem.id)) + } + return if (matrixItem.displayName.isNullOrBlank()) { TextDrawable.builder().buildRound("", avatarColor) } else { - val firstLetter = text.firstLetterOfDisplayName() + val firstLetter = matrixItem.displayName.firstLetterOfDisplayName() TextDrawable.builder() .beginConfig() .bold() @@ -103,18 +84,6 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active // PRIVATE API ********************************************************************************* -// private fun getAvatarColor(text: String? = null): Int { -// var colorIndex: Long = 0 -// if (!text.isNullOrEmpty()) { -// var sum: Long = 0 -// for (i in 0 until text.length) { -// sum += text[i].toLong() -// } -// colorIndex = sum % AVATAR_COLOR_LIST.size -// } -// return AVATAR_COLOR_LIST[colorIndex.toInt()] -// } - private fun buildGlideRequest(glideRequest: GlideRequests, avatarUrl: String?): GlideRequest { val resolvedUrl = activeSessionHolder.getActiveSession().contentUrlResolver() .resolveThumbnail(avatarUrl, THUMBNAIL_SIZE, THUMBNAIL_SIZE, ContentUrlResolver.ThumbnailMethod.SCALE) diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeDetailFragment.kt index ac8d429cb1..d844d0a2f0 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeDetailFragment.kt @@ -27,6 +27,7 @@ import com.google.android.material.bottomnavigation.BottomNavigationItemView import com.google.android.material.bottomnavigation.BottomNavigationMenuView import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupState import im.vector.matrix.android.api.session.group.model.GroupSummary +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.extensions.commitTransactionNow import im.vector.riotx.core.platform.ToolbarConfigurable @@ -74,12 +75,7 @@ class HomeDetailFragment @Inject constructor( private fun onGroupChange(groupSummary: GroupSummary?) { groupSummary?.let { - avatarRenderer.render( - it.avatarUrl, - it.groupId, - it.displayName, - groupToolbarAvatarImageView - ) + avatarRenderer.render(MatrixItem.from(it), groupToolbarAvatarImageView) } } @@ -155,7 +151,7 @@ class HomeDetailFragment @Inject constructor( bottomNavigationView.selectedItemId = when (displayMode) { RoomListDisplayMode.PEOPLE -> R.id.bottom_action_people RoomListDisplayMode.ROOMS -> R.id.bottom_action_rooms - else -> R.id.bottom_action_home + else -> R.id.bottom_action_home } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeDrawerFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeDrawerFragment.kt index 422b59671e..32344db2df 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeDrawerFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeDrawerFragment.kt @@ -19,6 +19,7 @@ package im.vector.riotx.features.home import android.os.Bundle import android.view.View import im.vector.matrix.android.api.session.Session +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.extensions.observeK import im.vector.riotx.core.extensions.replaceChildFragment @@ -42,7 +43,7 @@ class HomeDrawerFragment @Inject constructor( session.liveUser(session.myUserId).observeK(this) { optionalUser -> val user = optionalUser?.getOrNull() if (user != null) { - avatarRenderer.render(user.avatarUrl, user.userId, user.displayName, homeDrawerHeaderAvatarView) + avatarRenderer.render(MatrixItem.from(user), homeDrawerHeaderAvatarView) homeDrawerUsernameView.text = user.displayName homeDrawerUserIdView.text = user.userId } diff --git a/vector/src/main/java/im/vector/riotx/features/home/RoomColor.kt b/vector/src/main/java/im/vector/riotx/features/home/RoomColor.kt new file mode 100644 index 0000000000..48f2e22b6d --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/RoomColor.kt @@ -0,0 +1,29 @@ +/* + * 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.riotx.features.home + +import androidx.annotation.ColorRes +import im.vector.riotx.R + +@ColorRes +fun getColorFromRoomId(roomId: String? = null): Int { + return when ((roomId?.toList()?.sumBy { it.toInt() } ?: 0) % 3) { + 1 -> R.color.riotx_avatar_fill_2 + 2 -> R.color.riotx_avatar_fill_3 + else -> R.color.riotx_avatar_fill_1 + } +} diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomUserItem.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomUserItem.kt index 0ff4c5baf8..401d4445fe 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomUserItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomUserItem.kt @@ -25,6 +25,7 @@ import androidx.core.content.ContextCompat import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import com.amulyakhare.textdrawable.TextDrawable +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.core.epoxy.VectorEpoxyModel @@ -34,22 +35,20 @@ import im.vector.riotx.features.home.AvatarRenderer abstract class CreateDirectRoomUserItem : VectorEpoxyModel() { @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer - @EpoxyAttribute var name: String? = null - @EpoxyAttribute var userId: String = "" - @EpoxyAttribute var avatarUrl: String? = null + @EpoxyAttribute lateinit var matrixItem: MatrixItem @EpoxyAttribute var clickListener: View.OnClickListener? = null @EpoxyAttribute var selected: Boolean = false override fun bind(holder: Holder) { holder.view.setOnClickListener(clickListener) // If name is empty, use userId as name and force it being centered - if (name.isNullOrEmpty()) { + if (matrixItem.displayName.isNullOrEmpty()) { holder.userIdView.visibility = View.GONE - holder.nameView.text = userId + holder.nameView.text = matrixItem.id } else { holder.userIdView.visibility = View.VISIBLE - holder.nameView.text = name - holder.userIdView.text = userId + holder.nameView.text = matrixItem.displayName + holder.userIdView.text = matrixItem.id } renderSelection(holder, selected) } @@ -62,7 +61,7 @@ abstract class CreateDirectRoomUserItem : VectorEpoxyModel callback?.onItemClick(user) diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/KnownUsersController.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/KnownUsersController.kt index 3d1ee84254..6a4fdd553b 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/createdirect/KnownUsersController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/KnownUsersController.kt @@ -23,6 +23,7 @@ import com.airbnb.mvrx.Incomplete import com.airbnb.mvrx.Uninitialized import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.user.model.User +import im.vector.matrix.android.api.util.MatrixItem import im.vector.matrix.android.internal.util.firstLetterOfDisplayName import im.vector.riotx.R import im.vector.riotx.core.epoxy.EmptyItem_ @@ -68,9 +69,7 @@ class KnownUsersController @Inject constructor(private val session: Session, CreateDirectRoomUserItem_() .id(item.userId) .selected(isSelected) - .userId(item.userId) - .name(item.displayName) - .avatarUrl(item.avatarUrl) + .matrixItem(MatrixItem.from(item)) .avatarRenderer(avatarRenderer) .clickListener { _ -> callback?.onItemClick(item) @@ -87,8 +86,8 @@ class KnownUsersController @Inject constructor(private val session: Session, var lastFirstLetter: String? = null for (model in models) { if (model is CreateDirectRoomUserItem) { - if (model.userId == session.myUserId) continue - val currentFirstLetter = model.name.firstLetterOfDisplayName() + if (model.matrixItem.id == session.myUserId) continue + val currentFirstLetter = model.matrixItem.displayName.firstLetterOfDisplayName() val showLetter = !isFiltering && currentFirstLetter.isNotEmpty() && lastFirstLetter != currentFirstLetter lastFirstLetter = currentFirstLetter diff --git a/vector/src/main/java/im/vector/riotx/features/home/group/GroupSummaryController.kt b/vector/src/main/java/im/vector/riotx/features/home/group/GroupSummaryController.kt index 7c3cfd2a94..4e98ddb412 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/group/GroupSummaryController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/group/GroupSummaryController.kt @@ -18,6 +18,7 @@ package im.vector.riotx.features.home.group import com.airbnb.epoxy.EpoxyController import im.vector.matrix.android.api.session.group.model.GroupSummary +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.features.home.AvatarRenderer import javax.inject.Inject @@ -49,10 +50,8 @@ class GroupSummaryController @Inject constructor(private val avatarRenderer: Ava groupSummaryItem { avatarRenderer(avatarRenderer) id(groupSummary.groupId) - groupId(groupSummary.groupId) - groupName(groupSummary.displayName) + matrixItem(MatrixItem.from(groupSummary)) selected(isSelected) - avatarUrl(groupSummary.avatarUrl) listener { callback?.onGroupSelected(groupSummary) } } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/group/GroupSummaryItem.kt b/vector/src/main/java/im/vector/riotx/features/home/group/GroupSummaryItem.kt index 30c1852f1d..61c589cc00 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/group/GroupSummaryItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/group/GroupSummaryItem.kt @@ -20,6 +20,7 @@ import android.widget.ImageView import android.widget.TextView import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.core.epoxy.VectorEpoxyModel @@ -30,18 +31,16 @@ import im.vector.riotx.features.home.AvatarRenderer abstract class GroupSummaryItem : VectorEpoxyModel() { @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer - @EpoxyAttribute lateinit var groupName: CharSequence - @EpoxyAttribute lateinit var groupId: String - @EpoxyAttribute var avatarUrl: String? = null + @EpoxyAttribute lateinit var matrixItem: MatrixItem @EpoxyAttribute var selected: Boolean = false @EpoxyAttribute var listener: (() -> Unit)? = null override fun bind(holder: Holder) { super.bind(holder) holder.rootView.setOnClickListener { listener?.invoke() } - holder.groupNameView.text = groupName + holder.groupNameView.text = matrixItem.displayName holder.rootView.isChecked = selected - avatarRenderer.render(avatarUrl, groupId, groupName.toString(), holder.avatarImageView) + avatarRenderer.render(matrixItem, holder.avatarImageView) } class Holder : VectorEpoxyHolder() { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/breadcrumbs/BreadcrumbsController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/breadcrumbs/BreadcrumbsController.kt index 3e400b37ea..a3e46d3197 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/breadcrumbs/BreadcrumbsController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/breadcrumbs/BreadcrumbsController.kt @@ -18,6 +18,7 @@ package im.vector.riotx.features.home.room.breadcrumbs import android.view.View import com.airbnb.epoxy.EpoxyController +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.core.utils.DebouncedClickListener import im.vector.riotx.features.home.AvatarRenderer import javax.inject.Inject @@ -52,9 +53,7 @@ class BreadcrumbsController @Inject constructor( breadcrumbsItem { id(it.roomId) avatarRenderer(avatarRenderer) - roomId(it.roomId) - roomName(it.displayName) - avatarUrl(it.avatarUrl) + matrixItem(MatrixItem.from(it)) unreadNotificationCount(it.notificationCount) showHighlighted(it.highlightCount > 0) hasUnreadMessage(it.hasUnreadMessages) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/breadcrumbs/BreadcrumbsItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/breadcrumbs/BreadcrumbsItem.kt index 074c35af00..6d18a85b75 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/breadcrumbs/BreadcrumbsItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/breadcrumbs/BreadcrumbsItem.kt @@ -22,6 +22,7 @@ import android.widget.ImageView import androidx.core.view.isVisible import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.core.epoxy.VectorEpoxyModel @@ -32,9 +33,7 @@ import im.vector.riotx.features.home.room.list.UnreadCounterBadgeView abstract class BreadcrumbsItem : VectorEpoxyModel() { @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer - @EpoxyAttribute lateinit var roomId: String - @EpoxyAttribute lateinit var roomName: CharSequence - @EpoxyAttribute var avatarUrl: String? = null + @EpoxyAttribute lateinit var matrixItem: MatrixItem @EpoxyAttribute var unreadNotificationCount: Int = 0 @EpoxyAttribute var showHighlighted: Boolean = false @EpoxyAttribute var hasUnreadMessage: Boolean = false @@ -45,7 +44,7 @@ abstract class BreadcrumbsItem : VectorEpoxyModel() { super.bind(holder) holder.rootView.setOnClickListener(itemClickListener) holder.unreadIndentIndicator.isVisible = hasUnreadMessage - avatarRenderer.render(avatarUrl, roomId, roomName.toString(), holder.avatarImageView) + avatarRenderer.render(matrixItem, holder.avatarImageView) holder.unreadCounterBadgeView.render(UnreadCounterBadgeView.State(unreadNotificationCount, showHighlighted)) holder.draftIndentIndicator.isVisible = hasDraft } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt index 80f54a9c1f..fd72e85199 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt @@ -66,6 +66,7 @@ import im.vector.matrix.android.api.session.room.timeline.Timeline import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent import im.vector.matrix.android.api.session.user.model.User +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.dialogs.withColoredButton import im.vector.riotx.core.epoxy.LayoutManagerStateRestorer @@ -410,9 +411,7 @@ class RoomDetailFragment @Inject constructor( composerLayout.sendButton.setContentDescription(getString(descriptionRes)) avatarRenderer.render( - event.senderAvatar, - event.root.senderId ?: "", - event.getDisambiguatedDisplayName(), + MatrixItem.UserItem(event.root.senderId ?: "", event.getDisambiguatedDisplayName(), event.senderAvatar), composerLayout.composerRelatedMessageAvatar ) composerLayout.expand { @@ -601,20 +600,19 @@ class RoomDetailFragment @Inject constructor( } // Replace the word by its completion - val displayName = item.displayName ?: item.userId + val matrixItem = MatrixItem.from(item) + val displayName = matrixItem.getBestName() // with a trailing space editable.replace(startIndex, endIndex, "$displayName ") // Add the span - val user = session.getUser(item.userId) val span = PillImageSpan( glideRequests, avatarRenderer, requireContext(), - item.userId, - user?.displayName ?: item.userId, - user?.avatarUrl) + matrixItem + ) span.bind(composerLayout.composerEditText) editable.setSpan(span, startIndex, startIndex + displayName.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) @@ -686,7 +684,7 @@ class RoomDetailFragment @Inject constructor( inviteView.visibility = View.GONE val uid = session.myUserId val meMember = session.getRoom(state.roomId)?.getRoomMember(uid) - avatarRenderer.render(meMember?.avatarUrl, uid, meMember?.displayName, composerLayout.composerAvatarImageView) + avatarRenderer.render(MatrixItem.UserItem(uid, meMember?.displayName, meMember?.avatarUrl), composerLayout.composerAvatarImageView) } else if (summary?.membership == Membership.INVITE && inviter != null) { inviteView.visibility = View.VISIBLE inviteView.render(inviter, VectorInviteView.Mode.LARGE) @@ -713,7 +711,7 @@ class RoomDetailFragment @Inject constructor( activity?.finish() } else { roomToolbarTitleView.text = it.displayName - avatarRenderer.render(it, roomToolbarAvatarImageView) + avatarRenderer.render(MatrixItem.from(it), roomToolbarAvatarImageView) roomToolbarSubtitleView.setTextOrHide(it.topic) } jumpToBottomView.count = it.notificationCount @@ -1197,9 +1195,8 @@ class RoomDetailFragment @Inject constructor( glideRequests, avatarRenderer, requireContext(), - userId, - displayName, - roomMember?.avatarUrl) + MatrixItem.UserItem(userId, displayName, roomMember?.avatarUrl) + ) .also { it.bind(composerLayout.composerEditText) }, 0, displayName.length, diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt index 2b7d64a80e..6bc93f28dc 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/readreceipts/DisplayReadReceiptItem.kt @@ -22,6 +22,7 @@ import androidx.core.view.isVisible import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import com.airbnb.epoxy.EpoxyModelWithHolder +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.features.home.AvatarRenderer @@ -29,15 +30,13 @@ import im.vector.riotx.features.home.AvatarRenderer @EpoxyModelClass(layout = R.layout.item_display_read_receipt) abstract class DisplayReadReceiptItem : EpoxyModelWithHolder() { - @EpoxyAttribute var name: String? = null - @EpoxyAttribute var userId: String = "" - @EpoxyAttribute var avatarUrl: String? = null + @EpoxyAttribute lateinit var matrixItem: MatrixItem @EpoxyAttribute var timestamp: CharSequence? = null @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer override fun bind(holder: Holder) { - avatarRenderer.render(avatarUrl, userId, name, holder.avatarView) - holder.displayNameView.text = name ?: userId + avatarRenderer.render(matrixItem, holder.avatarView) + holder.displayNameView.text = matrixItem.getBestName() timestamp?.let { holder.timestampView.text = it holder.timestampView.isVisible = true diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/readreceipts/DisplayReadReceiptsController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/readreceipts/DisplayReadReceiptsController.kt index 6affa582bc..ef7dba5caf 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/readreceipts/DisplayReadReceiptsController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/readreceipts/DisplayReadReceiptsController.kt @@ -18,6 +18,7 @@ package im.vector.riotx.features.home.room.detail.readreceipts import com.airbnb.epoxy.TypedEpoxyController import im.vector.matrix.android.api.session.Session +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.core.date.VectorDateFormatter import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.home.room.detail.timeline.item.ReadReceiptData @@ -36,9 +37,7 @@ class DisplayReadReceiptsController @Inject constructor(private val dateFormatte val timestamp = dateFormatter.formatRelativeDateTime(it.timestamp) DisplayReadReceiptItem_() .id(it.userId) - .userId(it.userId) - .avatarUrl(it.avatarUrl) - .name(it.displayName) + .matrixItem(MatrixItem.UserItem(it.userId, it.displayName, it.avatarUrl)) .avatarRenderer(avatarRender) .timestamp(timestamp) .addIf(session.myUserId != it.userId, this) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt index efbfd3434c..939564e780 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt @@ -44,9 +44,7 @@ class MessageActionsEpoxyController @Inject constructor(private val stringProvid bottomSheetMessagePreviewItem { id("preview") avatarRenderer(avatarRenderer) - avatarUrl(state.informationData.avatarUrl ?: "") - senderId(state.informationData.senderId) - senderName(state.senderName()) + matrixItem(state.informationData.matrixItem) movementMethod(createLinkMovementMethod(listener)) body(body.linkify(listener)) time(state.time()) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsMessageItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsMessageItem.kt index 713b60d4d8..af4c55e742 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsMessageItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/AbsMessageItem.kt @@ -77,12 +77,7 @@ abstract class AbsMessageItem : BaseEventItem() { holder.timeView.visibility = View.VISIBLE holder.timeView.text = attributes.informationData.time holder.memberNameView.text = attributes.informationData.memberName - attributes.avatarRenderer.render( - attributes.informationData.avatarUrl, - attributes.informationData.senderId, - attributes.informationData.memberName?.toString(), - holder.avatarImageView - ) + attributes.avatarRenderer.render(attributes.informationData.matrixItem, holder.avatarImageView) holder.avatarImageView.setOnLongClickListener(attributes.itemLongClickListener) holder.memberNameView.setOnLongClickListener(attributes.itemLongClickListener) } else { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedHeaderItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedHeaderItem.kt index a2a3c9ad3b..728c8cd740 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedHeaderItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MergedHeaderItem.kt @@ -24,6 +24,7 @@ import androidx.core.view.children import androidx.core.view.isVisible import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.features.home.AvatarRenderer import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController @@ -54,7 +55,7 @@ abstract class MergedHeaderItem : BaseEventItem() { val data = distinctMergeData.getOrNull(index) if (data != null && view is ImageView) { view.visibility = View.VISIBLE - attributes.avatarRenderer.render(data.avatarUrl, data.userId, data.memberName, view) + attributes.avatarRenderer.render(MatrixItem.UserItem(data.userId, data.memberName, data.avatarUrl), view) } else { view.visibility = View.GONE } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MessageInformationData.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MessageInformationData.kt index 2dd581ce6f..ffaec7dd48 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MessageInformationData.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/MessageInformationData.kt @@ -18,6 +18,7 @@ package im.vector.riotx.features.home.room.detail.timeline.item import android.os.Parcelable import im.vector.matrix.android.api.session.room.send.SendState +import im.vector.matrix.android.api.util.MatrixItem import kotlinx.android.parcel.Parcelize @Parcelize @@ -34,7 +35,11 @@ data class MessageInformationData( val hasBeenEdited: Boolean = false, val hasPendingEdits: Boolean = false, val readReceipts: List = emptyList() -) : Parcelable +) : Parcelable { + + val matrixItem: MatrixItem + get() = MatrixItem.UserItem(senderId, memberName?.toString(), avatarUrl) +} @Parcelize data class ReactionInfoData( diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/NoticeItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/NoticeItem.kt index 05dedcfa22..189c358b48 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/NoticeItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/item/NoticeItem.kt @@ -39,13 +39,7 @@ abstract class NoticeItem : BaseEventItem() { override fun bind(holder: Holder) { super.bind(holder) holder.noticeTextView.text = attributes.noticeText - attributes.avatarRenderer.render( - attributes.informationData.avatarUrl, - attributes.informationData.senderId, - attributes.informationData.memberName?.toString() - ?: attributes.informationData.senderId, - holder.avatarImageView - ) + attributes.avatarRenderer.render(attributes.informationData.matrixItem, holder.avatarImageView) holder.view.setOnLongClickListener(attributes.itemLongClickListener) holder.readReceiptsView.render(attributes.informationData.readReceipts, attributes.avatarRenderer, _readReceiptsClickListener) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomInvitationItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomInvitationItem.kt index 3bd097d67b..4e4e758aa2 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomInvitationItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomInvitationItem.kt @@ -22,6 +22,7 @@ import android.widget.TextView import androidx.core.view.isVisible import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.core.epoxy.VectorEpoxyModel @@ -33,10 +34,8 @@ import im.vector.riotx.features.home.AvatarRenderer abstract class RoomInvitationItem : VectorEpoxyModel() { @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer - @EpoxyAttribute lateinit var roomName: CharSequence - @EpoxyAttribute lateinit var roomId: String + @EpoxyAttribute lateinit var matrixItem: MatrixItem @EpoxyAttribute var secondLine: CharSequence? = null - @EpoxyAttribute var avatarUrl: String? = null @EpoxyAttribute var listener: (() -> Unit)? = null @EpoxyAttribute var invitationAcceptInProgress: Boolean = false @EpoxyAttribute var invitationAcceptInError: Boolean = false @@ -85,9 +84,9 @@ abstract class RoomInvitationItem : VectorEpoxyModel( rejectListener?.invoke() } } - holder.titleView.text = roomName + holder.titleView.text = matrixItem.getBestName() holder.subtitleView.setTextOrHide(secondLine) - avatarRenderer.render(avatarUrl, roomId, roomName.toString(), holder.avatarImageView) + avatarRenderer.render(matrixItem, holder.avatarImageView) } class Holder : VectorEpoxyHolder() { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItem.kt index fe208a3085..23a0fd60a2 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItem.kt @@ -23,6 +23,7 @@ import android.widget.TextView import androidx.core.view.isVisible import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.core.epoxy.VectorEpoxyModel @@ -32,11 +33,9 @@ import im.vector.riotx.features.home.AvatarRenderer abstract class RoomSummaryItem : VectorEpoxyModel() { @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer - @EpoxyAttribute lateinit var roomName: CharSequence - @EpoxyAttribute lateinit var roomId: String + @EpoxyAttribute lateinit var matrixItem: MatrixItem @EpoxyAttribute lateinit var lastFormattedEvent: CharSequence @EpoxyAttribute lateinit var lastEventTime: CharSequence - @EpoxyAttribute var avatarUrl: String? = null @EpoxyAttribute var unreadNotificationCount: Int = 0 @EpoxyAttribute var hasUnreadMessage: Boolean = false @EpoxyAttribute var hasDraft: Boolean = false @@ -48,13 +47,13 @@ abstract class RoomSummaryItem : VectorEpoxyModel() { super.bind(holder) holder.rootView.setOnClickListener(itemClickListener) holder.rootView.setOnLongClickListener(itemLongClickListener) - holder.titleView.text = roomName + holder.titleView.text = matrixItem.getBestName() holder.lastEventTimeView.text = lastEventTime holder.lastEventView.text = lastFormattedEvent holder.unreadCounterBadgeView.render(UnreadCounterBadgeView.State(unreadNotificationCount, showHighlighted)) holder.unreadIndentIndicator.isVisible = hasUnreadMessage holder.draftView.isVisible = hasDraft - avatarRenderer.render(avatarUrl, roomId, roomName.toString(), holder.avatarImageView) + avatarRenderer.render(matrixItem, holder.avatarImageView) } class Holder : VectorEpoxyHolder() { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItemFactory.kt index 85652c4139..96c8673ca7 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomSummaryItemFactory.kt @@ -21,6 +21,7 @@ import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.room.model.Membership import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.date.VectorDateFormatter import im.vector.riotx.core.epoxy.VectorEpoxyModel @@ -69,7 +70,7 @@ class RoomSummaryItemFactory @Inject constructor(private val noticeEventFormatte return RoomInvitationItem_() .id(roomSummary.roomId) .avatarRenderer(avatarRenderer) - .roomId(roomSummary.roomId) + .matrixItem(MatrixItem.from(roomSummary)) .secondLine(secondLine) .invitationAcceptInProgress(joiningRoomsIds.contains(roomSummary.roomId)) .invitationAcceptInError(joiningErrorRoomsIds.contains(roomSummary.roomId)) @@ -77,8 +78,6 @@ class RoomSummaryItemFactory @Inject constructor(private val noticeEventFormatte .invitationRejectInError(rejectingErrorRoomsIds.contains(roomSummary.roomId)) .acceptListener { listener?.onAcceptRoomInvitation(roomSummary) } .rejectListener { listener?.onRejectRoomInvitation(roomSummary) } - .roomName(roomSummary.displayName) - .avatarUrl(roomSummary.avatarUrl) .listener { listener?.onRoomClicked(roomSummary) } } @@ -125,11 +124,9 @@ class RoomSummaryItemFactory @Inject constructor(private val noticeEventFormatte return RoomSummaryItem_() .id(roomSummary.roomId) .avatarRenderer(avatarRenderer) - .roomId(roomSummary.roomId) + .matrixItem(MatrixItem.from(roomSummary)) .lastEventTime(latestEventTime) .lastFormattedEvent(latestFormattedEvent) - .roomName(roomSummary.displayName) - .avatarUrl(roomSummary.avatarUrl) .showHighlighted(showHighlighted) .unreadNotificationCount(unreadCount) .hasUnreadMessage(roomSummary.hasUnreadMessages) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt index 84fd5bc6f2..559dfd7301 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/actions/RoomListQuickActionsEpoxyController.kt @@ -18,6 +18,7 @@ package im.vector.riotx.features.home.room.list.actions import android.view.View import com.airbnb.epoxy.TypedEpoxyController import im.vector.matrix.android.api.session.room.notification.RoomNotificationState +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.core.epoxy.bottomsheet.bottomSheetActionItem import im.vector.riotx.core.epoxy.bottomsheet.bottomSheetRoomPreviewItem import im.vector.riotx.core.epoxy.bottomsheet.bottomSheetSeparatorItem @@ -39,9 +40,7 @@ class RoomListQuickActionsEpoxyController @Inject constructor(private val avatar bottomSheetRoomPreviewItem { id("preview") avatarRenderer(avatarRenderer) - roomName(roomSummary.displayName) - avatarUrl(roomSummary.avatarUrl) - roomId(roomSummary.roomId) + matrixItem(MatrixItem.from(roomSummary)) settingsClickListener(View.OnClickListener { listener?.didSelectMenuAction(RoomListQuickActionsSharedAction.Settings(roomSummary.roomId)) }) } diff --git a/vector/src/main/java/im/vector/riotx/features/html/MxLinkTagHandler.kt b/vector/src/main/java/im/vector/riotx/features/html/MxLinkTagHandler.kt index ecbf0da415..3f16666221 100644 --- a/vector/src/main/java/im/vector/riotx/features/html/MxLinkTagHandler.kt +++ b/vector/src/main/java/im/vector/riotx/features/html/MxLinkTagHandler.kt @@ -20,6 +20,7 @@ import android.content.Context import android.text.style.URLSpan import im.vector.matrix.android.api.permalinks.PermalinkData import im.vector.matrix.android.api.permalinks.PermalinkParser +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.glide.GlideRequests import im.vector.riotx.features.home.AvatarRenderer @@ -41,8 +42,8 @@ class MxLinkTagHandler(private val glideRequests: GlideRequests, when (permalinkData) { is PermalinkData.UserLink -> { val user = sessionHolder.getSafeActiveSession()?.getUser(permalinkData.userId) - val span = PillImageSpan(glideRequests, avatarRenderer, context, permalinkData.userId, user?.displayName - ?: permalinkData.userId, user?.avatarUrl) + val span = PillImageSpan(glideRequests, avatarRenderer, context, MatrixItem.UserItem(permalinkData.userId, user?.displayName + ?: permalinkData.userId, user?.avatarUrl)) SpannableBuilder.setSpans( visitor.builder(), span, diff --git a/vector/src/main/java/im/vector/riotx/features/html/PillImageSpan.kt b/vector/src/main/java/im/vector/riotx/features/html/PillImageSpan.kt index a192c71961..8b57006439 100644 --- a/vector/src/main/java/im/vector/riotx/features/html/PillImageSpan.kt +++ b/vector/src/main/java/im/vector/riotx/features/html/PillImageSpan.kt @@ -29,6 +29,7 @@ import com.bumptech.glide.request.target.SimpleTarget import com.bumptech.glide.request.transition.Transition import com.google.android.material.chip.ChipDrawable import im.vector.matrix.android.api.session.room.send.UserMentionSpan +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.glide.GlideRequests import im.vector.riotx.features.home.AvatarRenderer @@ -42,9 +43,8 @@ import java.lang.ref.WeakReference class PillImageSpan(private val glideRequests: GlideRequests, private val avatarRenderer: AvatarRenderer, private val context: Context, - override val userId: String, - override val displayName: String, - private val avatarUrl: String?) : ReplacementSpan(), UserMentionSpan { + override val matrixItem: MatrixItem +) : ReplacementSpan(), UserMentionSpan { private val pillDrawable = createChipDrawable() private val target = PillImageSpanTarget(this) @@ -53,7 +53,7 @@ class PillImageSpan(private val glideRequests: GlideRequests, @UiThread fun bind(textView: TextView) { tv = WeakReference(textView) - avatarRenderer.render(context, glideRequests, avatarUrl, userId, displayName, target) + avatarRenderer.render(context, glideRequests, matrixItem, target) } // ReplacementSpan ***************************************************************************** @@ -101,12 +101,12 @@ class PillImageSpan(private val glideRequests: GlideRequests, private fun createChipDrawable(): ChipDrawable { val textPadding = context.resources.getDimension(R.dimen.pill_text_padding) return ChipDrawable.createFromResource(context, R.xml.pill_view).apply { - text = displayName + text = matrixItem.getBestName() textEndPadding = textPadding textStartPadding = textPadding setChipMinHeightResource(R.dimen.pill_min_height) setChipIconSizeResource(R.dimen.pill_avatar_size) - chipIcon = avatarRenderer.getPlaceholderDrawable(context, userId, displayName) + chipIcon = avatarRenderer.getPlaceholderDrawable(context, matrixItem) setBounds(0, 0, intrinsicWidth, intrinsicHeight) } } diff --git a/vector/src/main/java/im/vector/riotx/features/invite/VectorInviteView.kt b/vector/src/main/java/im/vector/riotx/features/invite/VectorInviteView.kt index 71420448f4..56217d9980 100644 --- a/vector/src/main/java/im/vector/riotx/features/invite/VectorInviteView.kt +++ b/vector/src/main/java/im/vector/riotx/features/invite/VectorInviteView.kt @@ -22,6 +22,7 @@ import android.view.View import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.updateLayoutParams import im.vector.matrix.android.api.session.user.model.User +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.di.HasScreenInjector import im.vector.riotx.features.home.AvatarRenderer @@ -56,7 +57,7 @@ class VectorInviteView @JvmOverloads constructor(context: Context, attrs: Attrib fun render(sender: User, mode: Mode = Mode.LARGE) { if (mode == Mode.LARGE) { updateLayoutParams { height = LayoutParams.MATCH_CONSTRAINT } - avatarRenderer.render(sender.avatarUrl, sender.userId, sender.displayName, inviteAvatarView) + avatarRenderer.render(MatrixItem.from(sender), inviteAvatarView) inviteIdentifierView.text = sender.userId inviteNameView.text = sender.displayName inviteLabelView.text = context.getString(R.string.send_you_invite) diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomItem.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomItem.kt index 5e5c4fc5f1..108627e3f8 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomItem.kt @@ -21,6 +21,7 @@ import android.widget.ImageView import android.widget.TextView import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.core.epoxy.VectorEpoxyModel @@ -35,13 +36,7 @@ abstract class PublicRoomItem : VectorEpoxyModel() { lateinit var avatarRenderer: AvatarRenderer @EpoxyAttribute - var avatarUrl: String? = null - - @EpoxyAttribute - var roomId: String? = null - - @EpoxyAttribute - var roomName: String? = null + lateinit var matrixItem: MatrixItem @EpoxyAttribute var roomAlias: String? = null @@ -64,8 +59,8 @@ abstract class PublicRoomItem : VectorEpoxyModel() { override fun bind(holder: Holder) { holder.rootView.setOnClickListener { globalListener?.invoke() } - avatarRenderer.render(avatarUrl, roomId!!, roomName, holder.avatarView) - holder.nameView.text = roomName + avatarRenderer.render(matrixItem, holder.avatarView) + holder.nameView.text = matrixItem.displayName holder.aliasView.setTextOrHide(roomAlias) holder.topicView.setTextOrHide(roomTopic) // TODO Use formatter for big numbers? diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomsController.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomsController.kt index 183256a53e..97952059ce 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomsController.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/PublicRoomsController.kt @@ -22,6 +22,7 @@ import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Incomplete import com.airbnb.mvrx.Success import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.epoxy.errorWithRetryItem import im.vector.riotx.core.epoxy.loadingItem @@ -83,9 +84,7 @@ class PublicRoomsController @Inject constructor(private val stringProvider: Stri publicRoomItem { avatarRenderer(avatarRenderer) id(publicRoom.roomId) - roomId(publicRoom.roomId) - avatarUrl(publicRoom.avatarUrl) - roomName(publicRoom.name) + matrixItem(MatrixItem.from(publicRoom)) roomAlias(publicRoom.canonicalAlias) roomTopic(publicRoom.topic) nbOfMembers(publicRoom.numJoinedMembers) diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt index 9003421dc7..e3a1830965 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewNoPreviewFragment.kt @@ -23,6 +23,7 @@ import androidx.transition.TransitionManager import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.error.ErrorFormatter import im.vector.riotx.core.extensions.setTextOrHide @@ -51,11 +52,11 @@ class RoomPreviewNoPreviewFragment @Inject constructor( super.onViewCreated(view, savedInstanceState) setupToolbar(roomPreviewNoPreviewToolbar) // Toolbar - avatarRenderer.render(roomPreviewData.avatarUrl, roomPreviewData.roomId, roomPreviewData.roomName, roomPreviewNoPreviewToolbarAvatar) + avatarRenderer.render(MatrixItem.RoomItem(roomPreviewData.roomId, roomPreviewData.roomName, roomPreviewData.avatarUrl), roomPreviewNoPreviewToolbarAvatar) roomPreviewNoPreviewToolbarTitle.text = roomPreviewData.roomName // Screen - avatarRenderer.render(roomPreviewData.avatarUrl, roomPreviewData.roomId, roomPreviewData.roomName, roomPreviewNoPreviewAvatar) + avatarRenderer.render(MatrixItem.RoomItem(roomPreviewData.roomId, roomPreviewData.roomName, roomPreviewData.avatarUrl), roomPreviewNoPreviewAvatar) roomPreviewNoPreviewName.text = roomPreviewData.roomName roomPreviewNoPreviewTopic.setTextOrHide(roomPreviewData.topic) diff --git a/vector/src/main/java/im/vector/riotx/features/settings/ignored/IgnoredUsersController.kt b/vector/src/main/java/im/vector/riotx/features/settings/ignored/IgnoredUsersController.kt index 120781874d..18f256a207 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/ignored/IgnoredUsersController.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/ignored/IgnoredUsersController.kt @@ -18,6 +18,7 @@ package im.vector.riotx.features.settings.ignored import com.airbnb.epoxy.EpoxyController import im.vector.matrix.android.api.session.user.model.User +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.epoxy.noResultItem import im.vector.riotx.core.resources.StringProvider @@ -44,19 +45,19 @@ class IgnoredUsersController @Inject constructor(private val stringProvider: Str buildIgnoredUserModels(nonNullViewState.ignoredUsers) } - private fun buildIgnoredUserModels(userIds: List) { - if (userIds.isEmpty()) { + private fun buildIgnoredUserModels(users: List) { + if (users.isEmpty()) { noResultItem { id("empty") text(stringProvider.getString(R.string.no_ignored_users)) } } else { - userIds.forEach { userId -> + users.forEach { user -> userItem { - id(userId.userId) + id(user.userId) avatarRenderer(avatarRenderer) - user(userId) - itemClickAction { callback?.onUserIdClicked(userId.userId) } + matrixItem(MatrixItem.from(user)) + itemClickAction { callback?.onUserIdClicked(user.userId) } } } } diff --git a/vector/src/main/java/im/vector/riotx/features/settings/ignored/UserItem.kt b/vector/src/main/java/im/vector/riotx/features/settings/ignored/UserItem.kt index a9c1b98915..23fb03d59a 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/ignored/UserItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/ignored/UserItem.kt @@ -20,7 +20,7 @@ import android.widget.ImageView import android.widget.TextView import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass -import im.vector.matrix.android.api.session.user.model.User +import im.vector.matrix.android.api.util.MatrixItem import im.vector.riotx.R import im.vector.riotx.core.epoxy.VectorEpoxyHolder import im.vector.riotx.core.epoxy.VectorEpoxyModel @@ -37,7 +37,7 @@ abstract class UserItem : VectorEpoxyModel() { lateinit var avatarRenderer: AvatarRenderer @EpoxyAttribute - lateinit var user: User + lateinit var matrixItem: MatrixItem @EpoxyAttribute var itemClickAction: (() -> Unit)? = null @@ -45,9 +45,9 @@ abstract class UserItem : VectorEpoxyModel() { override fun bind(holder: Holder) { holder.root.setOnClickListener { itemClickAction?.invoke() } - avatarRenderer.render(user, holder.avatarImage) - holder.userIdText.setTextOrHide(user.userId) - holder.displayNameText.setTextOrHide(user.displayName) + avatarRenderer.render(matrixItem, holder.avatarImage) + holder.userIdText.setTextOrHide(matrixItem.id) + holder.displayNameText.setTextOrHide(matrixItem.displayName) } class Holder : VectorEpoxyHolder() {