Merge pull request #2154 from vector-im/feature/bma_user_color_cache
Use cache for user color
This commit is contained in:
commit
5ab7ec0bc8
|
@ -7,6 +7,7 @@ Features ✨:
|
|||
Improvements 🙌:
|
||||
- Add "show password" in import Megolm keys dialog
|
||||
- Visually disable call buttons in menu and prohibit calling when permissions are insufficient (#2112)
|
||||
- Use cache for user color
|
||||
|
||||
Bugfix 🐛:
|
||||
- Long message cannot be sent/takes infinite time & blocks other messages #1397
|
||||
|
|
|
@ -36,6 +36,7 @@ import im.vector.app.features.crypto.verification.IncomingVerificationRequestHan
|
|||
import im.vector.app.features.grouplist.SelectedGroupDataSource
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.home.HomeRoomListDataSource
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
|
||||
import im.vector.app.features.html.EventHtmlRenderer
|
||||
import im.vector.app.features.html.VectorHtmlCompressor
|
||||
import im.vector.app.features.login.ReAuthHelper
|
||||
|
@ -71,6 +72,8 @@ interface VectorComponent {
|
|||
|
||||
fun matrix(): Matrix
|
||||
|
||||
fun matrixItemColorProvider(): MatrixItemColorProvider
|
||||
|
||||
fun sessionListener(): SessionListener
|
||||
|
||||
fun currentSession(): Session
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* 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.core.utils
|
||||
|
||||
import androidx.annotation.ColorRes
|
||||
import im.vector.app.R
|
||||
import kotlin.math.abs
|
||||
|
||||
@ColorRes
|
||||
fun getColorFromUserId(userId: String?): Int {
|
||||
var hash = 0
|
||||
|
||||
userId?.toList()?.map { chr -> hash = (hash shl 5) - hash + chr.toInt() }
|
||||
|
||||
return when (abs(hash) % 8) {
|
||||
1 -> R.color.riotx_username_2
|
||||
2 -> R.color.riotx_username_3
|
||||
3 -> R.color.riotx_username_4
|
||||
4 -> R.color.riotx_username_5
|
||||
5 -> R.color.riotx_username_6
|
||||
6 -> R.color.riotx_username_7
|
||||
7 -> R.color.riotx_username_8
|
||||
else -> R.color.riotx_username_1
|
||||
}
|
||||
}
|
|
@ -16,13 +16,11 @@
|
|||
|
||||
package im.vector.app.features.home
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.widget.ImageView
|
||||
import androidx.annotation.AnyThread
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import com.amulyakhare.textdrawable.TextDrawable
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
|
@ -33,7 +31,7 @@ import im.vector.app.core.di.ActiveSessionHolder
|
|||
import im.vector.app.core.glide.GlideApp
|
||||
import im.vector.app.core.glide.GlideRequest
|
||||
import im.vector.app.core.glide.GlideRequests
|
||||
import im.vector.app.core.utils.getColorFromUserId
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.content.ContentUrlResolver
|
||||
import org.matrix.android.sdk.api.util.MatrixItem
|
||||
|
@ -43,7 +41,8 @@ import javax.inject.Inject
|
|||
* This helper centralise ways to retrieve avatar into ImageView or even generic Target<Drawable>
|
||||
*/
|
||||
|
||||
class AvatarRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder) {
|
||||
class AvatarRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder,
|
||||
private val matrixItemColorProvider: MatrixItemColorProvider) {
|
||||
|
||||
companion object {
|
||||
private const val THUMBNAIL_SIZE = 250
|
||||
|
@ -51,8 +50,7 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
|
|||
|
||||
@UiThread
|
||||
fun render(matrixItem: MatrixItem, imageView: ImageView) {
|
||||
render(imageView.context,
|
||||
GlideApp.with(imageView),
|
||||
render(GlideApp.with(imageView),
|
||||
matrixItem,
|
||||
DrawableImageViewTarget(imageView))
|
||||
}
|
||||
|
@ -64,8 +62,7 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
|
|||
|
||||
@UiThread
|
||||
fun render(matrixItem: MatrixItem, imageView: ImageView, glideRequests: GlideRequests) {
|
||||
render(imageView.context,
|
||||
glideRequests,
|
||||
render(glideRequests,
|
||||
matrixItem,
|
||||
DrawableImageViewTarget(imageView))
|
||||
}
|
||||
|
@ -79,7 +76,7 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
|
|||
displayName = mappedContact.displayName
|
||||
)
|
||||
|
||||
val placeholder = getPlaceholderDrawable(imageView.context, matrixItem)
|
||||
val placeholder = getPlaceholderDrawable(matrixItem)
|
||||
GlideApp.with(imageView)
|
||||
.load(mappedContact.photoURI)
|
||||
.apply(RequestOptions.circleCropTransform())
|
||||
|
@ -88,11 +85,10 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
|
|||
}
|
||||
|
||||
@UiThread
|
||||
fun render(context: Context,
|
||||
glideRequests: GlideRequests,
|
||||
fun render(glideRequests: GlideRequests,
|
||||
matrixItem: MatrixItem,
|
||||
target: Target<Drawable>) {
|
||||
val placeholder = getPlaceholderDrawable(context, matrixItem)
|
||||
val placeholder = getPlaceholderDrawable(matrixItem)
|
||||
buildGlideRequest(glideRequests, matrixItem.avatarUrl)
|
||||
.placeholder(placeholder)
|
||||
.into(target)
|
||||
|
@ -100,7 +96,7 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
|
|||
|
||||
@AnyThread
|
||||
@Throws
|
||||
fun shortcutDrawable(context: Context, glideRequests: GlideRequests, matrixItem: MatrixItem, iconSize: Int): Bitmap {
|
||||
fun shortcutDrawable(glideRequests: GlideRequests, matrixItem: MatrixItem, iconSize: Int): Bitmap {
|
||||
return glideRequests
|
||||
.asBitmap()
|
||||
.apply {
|
||||
|
@ -108,7 +104,7 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
|
|||
if (resolvedUrl != null) {
|
||||
load(resolvedUrl)
|
||||
} else {
|
||||
val avatarColor = avatarColor(matrixItem, context)
|
||||
val avatarColor = matrixItemColorProvider.getColor(matrixItem)
|
||||
load(TextDrawable.builder()
|
||||
.beginConfig()
|
||||
.bold()
|
||||
|
@ -130,8 +126,8 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
|
|||
}
|
||||
|
||||
@AnyThread
|
||||
fun getPlaceholderDrawable(context: Context, matrixItem: MatrixItem): Drawable {
|
||||
val avatarColor = avatarColor(matrixItem, context)
|
||||
fun getPlaceholderDrawable(matrixItem: MatrixItem): Drawable {
|
||||
val avatarColor = matrixItemColorProvider.getColor(matrixItem)
|
||||
return TextDrawable.builder()
|
||||
.beginConfig()
|
||||
.bold()
|
||||
|
@ -152,11 +148,4 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
|
|||
return activeSessionHolder.getSafeActiveSession()?.contentUrlResolver()
|
||||
?.resolveThumbnail(avatarUrl, THUMBNAIL_SIZE, THUMBNAIL_SIZE, ContentUrlResolver.ThumbnailMethod.SCALE)
|
||||
}
|
||||
|
||||
private fun avatarColor(matrixItem: MatrixItem, context: Context): Int {
|
||||
return when (matrixItem) {
|
||||
is MatrixItem.UserItem -> ContextCompat.getColor(context, getColorFromUserId(matrixItem.id))
|
||||
else -> ContextCompat.getColor(context, getColorFromRoomId(matrixItem.id))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
import androidx.annotation.ColorRes
|
||||
import im.vector.app.R
|
||||
|
||||
@ColorRes
|
||||
fun getColorFromRoomId(roomId: String?): 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
|
||||
}
|
||||
}
|
|
@ -70,7 +70,7 @@ class ShortcutsHandler @Inject constructor(
|
|||
.map { room ->
|
||||
val intent = RoomDetailActivity.shortcutIntent(context, room.roomId)
|
||||
val bitmap = try {
|
||||
avatarRenderer.shortcutDrawable(context, GlideApp.with(context), room.toMatrixItem(), iconSize)
|
||||
avatarRenderer.shortcutDrawable(GlideApp.with(context), room.toMatrixItem(), iconSize)
|
||||
} catch (failure: Throwable) {
|
||||
null
|
||||
}
|
||||
|
|
|
@ -97,7 +97,6 @@ import im.vector.app.core.utils.colorizeMatchingText
|
|||
import im.vector.app.core.utils.copyToClipboard
|
||||
import im.vector.app.core.utils.createJSonViewerStyleProvider
|
||||
import im.vector.app.core.utils.createUIHandler
|
||||
import im.vector.app.core.utils.getColorFromUserId
|
||||
import im.vector.app.core.utils.isValidUrl
|
||||
import im.vector.app.core.utils.onPermissionResultAudioIpCall
|
||||
import im.vector.app.core.utils.onPermissionResultVideoIpCall
|
||||
|
@ -127,6 +126,7 @@ import im.vector.app.features.home.room.detail.timeline.action.EventSharedAction
|
|||
import im.vector.app.features.home.room.detail.timeline.action.MessageActionsBottomSheet
|
||||
import im.vector.app.features.home.room.detail.timeline.action.MessageSharedActionViewModel
|
||||
import im.vector.app.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
|
||||
import im.vector.app.features.home.room.detail.timeline.item.AbsMessageItem
|
||||
import im.vector.app.features.home.room.detail.timeline.item.MessageFileItem
|
||||
import im.vector.app.features.home.room.detail.timeline.item.MessageImageVideoItem
|
||||
|
@ -217,7 +217,9 @@ class RoomDetailFragment @Inject constructor(
|
|||
private val vectorPreferences: VectorPreferences,
|
||||
private val colorProvider: ColorProvider,
|
||||
private val notificationUtils: NotificationUtils,
|
||||
private val webRtcPeerConnectionManager: WebRtcPeerConnectionManager) :
|
||||
private val webRtcPeerConnectionManager: WebRtcPeerConnectionManager,
|
||||
private val matrixItemColorProvider: MatrixItemColorProvider
|
||||
) :
|
||||
VectorBaseFragment(),
|
||||
TimelineEventController.Callback,
|
||||
VectorInviteView.Callback,
|
||||
|
@ -790,7 +792,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
// switch to expanded bar
|
||||
composerLayout.composerRelatedMessageTitle.apply {
|
||||
text = event.senderInfo.disambiguatedDisplayName
|
||||
setTextColor(ContextCompat.getColor(requireContext(), getColorFromUserId(event.root.senderId)))
|
||||
setTextColor(matrixItemColorProvider.getColor(MatrixItem.UserItem(event.root.senderId ?: "@")))
|
||||
}
|
||||
|
||||
val messageContent: MessageContent? = event.getLastMessageContent()
|
||||
|
|
|
@ -19,18 +19,20 @@ package im.vector.app.features.home.room.detail.timeline
|
|||
import androidx.annotation.ColorInt
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
import im.vector.app.core.utils.getColorFromUserId
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||
import org.matrix.android.sdk.api.util.MatrixItem
|
||||
import javax.inject.Inject
|
||||
|
||||
class MessageColorProvider @Inject constructor(
|
||||
private val colorProvider: ColorProvider,
|
||||
private val matrixItemColorProvider: MatrixItemColorProvider,
|
||||
private val vectorPreferences: VectorPreferences) {
|
||||
|
||||
@ColorInt
|
||||
fun getMemberNameTextColor(userId: String): Int {
|
||||
return colorProvider.getColor(getColorFromUserId(userId))
|
||||
fun getMemberNameTextColor(matrixItem: MatrixItem): Int {
|
||||
return matrixItemColorProvider.getColor(matrixItem)
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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.detail.timeline.helper
|
||||
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.ColorRes
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
import org.matrix.android.sdk.api.util.MatrixItem
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import kotlin.math.abs
|
||||
|
||||
@Singleton
|
||||
class MatrixItemColorProvider @Inject constructor(
|
||||
private val colorProvider: ColorProvider
|
||||
) {
|
||||
private val cache = mutableMapOf<String, Int>()
|
||||
|
||||
@ColorInt
|
||||
fun getColor(matrixItem: MatrixItem): Int {
|
||||
return cache.getOrPut(matrixItem.id) {
|
||||
colorProvider.getColor(
|
||||
when (matrixItem) {
|
||||
is MatrixItem.UserItem -> getColorFromUserId(matrixItem.id)
|
||||
else -> getColorFromRoomId(matrixItem.id)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ColorRes
|
||||
private fun getColorFromUserId(userId: String?): Int {
|
||||
var hash = 0
|
||||
|
||||
userId?.toList()?.map { chr -> hash = (hash shl 5) - hash + chr.toInt() }
|
||||
|
||||
return when (abs(hash) % 8) {
|
||||
1 -> R.color.riotx_username_2
|
||||
2 -> R.color.riotx_username_3
|
||||
3 -> R.color.riotx_username_4
|
||||
4 -> R.color.riotx_username_5
|
||||
5 -> R.color.riotx_username_6
|
||||
6 -> R.color.riotx_username_7
|
||||
7 -> R.color.riotx_username_8
|
||||
else -> R.color.riotx_username_1
|
||||
}
|
||||
}
|
||||
|
||||
@ColorRes
|
||||
private fun getColorFromRoomId(roomId: String?): 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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -85,7 +85,7 @@ abstract class AbsMessageItem<H : AbsMessageItem.Holder> : AbsBaseMessageItem<H>
|
|||
super.unbind(holder)
|
||||
}
|
||||
|
||||
private fun Attributes.getMemberNameColor() = messageColorProvider.getMemberNameTextColor(informationData.senderId)
|
||||
private fun Attributes.getMemberNameColor() = messageColorProvider.getMemberNameTextColor(informationData.matrixItem)
|
||||
|
||||
abstract class Holder(@IdRes stubId: Int) : AbsBaseMessageItem.Holder(stubId) {
|
||||
val avatarImageView by bind<ImageView>(R.id.messageAvatarImageView)
|
||||
|
|
|
@ -53,7 +53,7 @@ class PillImageSpan(private val glideRequests: GlideRequests,
|
|||
@UiThread
|
||||
fun bind(textView: TextView) {
|
||||
tv = WeakReference(textView)
|
||||
avatarRenderer.render(context, glideRequests, matrixItem, target)
|
||||
avatarRenderer.render(glideRequests, matrixItem, target)
|
||||
}
|
||||
|
||||
// ReplacementSpan *****************************************************************************
|
||||
|
@ -99,7 +99,7 @@ class PillImageSpan(private val glideRequests: GlideRequests,
|
|||
val icon = try {
|
||||
avatarRenderer.getCachedDrawable(glideRequests, matrixItem)
|
||||
} catch (exception: Exception) {
|
||||
avatarRenderer.getPlaceholderDrawable(context, matrixItem)
|
||||
avatarRenderer.getPlaceholderDrawable(matrixItem)
|
||||
}
|
||||
|
||||
return ChipDrawable.createFromResource(context, R.xml.pill_view).apply {
|
||||
|
|
Loading…
Reference in New Issue