@@ -19,7 +19,7 @@ package im.vector.app.features.home.room.detail.timeline.helper
19
19
import android.content.Context
20
20
import android.graphics.drawable.Drawable
21
21
import android.graphics.drawable.LayerDrawable
22
- import androidx.annotation.ColorInt
22
+ import android.util.LruCache
23
23
import androidx.core.content.ContextCompat
24
24
import androidx.core.graphics.drawable.DrawableCompat
25
25
import com.bumptech.glide.request.target.CustomTarget
@@ -30,11 +30,17 @@ import im.vector.app.core.glide.GlideApp
30
30
import im.vector.app.core.utils.DimensionConverter
31
31
import im.vector.app.features.home.AvatarRenderer
32
32
import org.matrix.android.sdk.api.session.getUserOrDefault
33
+ import org.matrix.android.sdk.api.util.MatrixItem
33
34
import org.matrix.android.sdk.api.util.toMatrixItem
34
35
import timber.log.Timber
35
36
import javax.inject.Inject
36
37
import javax.inject.Singleton
37
38
39
+ private data class CachedDrawable (
40
+ val drawable : Drawable ,
41
+ val isError : Boolean ,
42
+ )
43
+
38
44
@Singleton
39
45
class LocationPinProvider @Inject constructor(
40
46
private val context : Context ,
@@ -43,7 +49,7 @@ class LocationPinProvider @Inject constructor(
43
49
private val avatarRenderer : AvatarRenderer ,
44
50
private val matrixItemColorProvider : MatrixItemColorProvider
45
51
) {
46
- private val cache = mutableMapOf< String , Drawable >( )
52
+ private val cache = LruCache < MatrixItem . UserItem , CachedDrawable >( 32 )
47
53
48
54
private val glideRequests by lazy {
49
55
GlideApp .with (context)
@@ -60,23 +66,16 @@ class LocationPinProvider @Inject constructor(
60
66
return
61
67
}
62
68
63
- if (cache.contains(userId)) {
64
- callback(cache[userId]!! )
65
- return
66
- }
67
-
68
69
activeSessionHolder
69
70
.getActiveSession()
70
71
.getUserOrDefault(userId)
71
72
.toMatrixItem()
72
73
.let { userItem ->
73
74
val size = dimensionConverter.dpToPx(44 )
74
- val bgTintColor = matrixItemColorProvider.getColor(userItem)
75
75
avatarRenderer.render(glideRequests, userItem, object : CustomTarget <Drawable >(size, size) {
76
76
override fun onResourceReady (resource : Drawable , transition : Transition <in Drawable >? ) {
77
77
Timber .d(" ## Location: onResourceReady" )
78
- val pinDrawable = createPinDrawable(resource, bgTintColor)
79
- cache[userId] = pinDrawable
78
+ val pinDrawable = createPinDrawable(userItem, resource, isError = false )
80
79
callback(pinDrawable)
81
80
}
82
81
@@ -87,17 +86,29 @@ class LocationPinProvider @Inject constructor(
87
86
}
88
87
89
88
override fun onLoadFailed (errorDrawable : Drawable ? ) {
89
+ // Note: `onLoadFailed` is also called when the user has no avatarUrl
90
+ // and the errorDrawable is actually the placeholder.
90
91
Timber .w(" ## Location: onLoadFailed" )
91
92
errorDrawable ? : return
92
- val pinDrawable = createPinDrawable(errorDrawable, bgTintColor)
93
- cache[userId] = pinDrawable
93
+ val pinDrawable = createPinDrawable(userItem, errorDrawable, isError = true )
94
94
callback(pinDrawable)
95
95
}
96
96
})
97
97
}
98
98
}
99
99
100
- private fun createPinDrawable (drawable : Drawable , @ColorInt bgTintColor : Int ): Drawable {
100
+ private fun createPinDrawable (
101
+ userItem : MatrixItem .UserItem ,
102
+ drawable : Drawable ,
103
+ isError : Boolean ,
104
+ ): Drawable {
105
+ val fromCache = cache.get(userItem)
106
+ // Return the cached drawable only if it is valid, or the new drawable is again an error
107
+ if (fromCache != null && (! fromCache.isError || isError)) {
108
+ return fromCache.drawable
109
+ }
110
+
111
+ val bgTintColor = matrixItemColorProvider.getColor(userItem)
101
112
val bgUserPin = ContextCompat .getDrawable(context, R .drawable.bg_map_user_pin)!!
102
113
// use mutate on drawable to avoid sharing the color when we have multiple different user pins
103
114
DrawableCompat .setTint(bgUserPin.mutate(), bgTintColor)
@@ -106,6 +117,7 @@ class LocationPinProvider @Inject constructor(
106
117
val topInset = dimensionConverter.dpToPx(4 )
107
118
val bottomInset = dimensionConverter.dpToPx(8 )
108
119
layerDrawable.setLayerInset(1 , horizontalInset, topInset, horizontalInset, bottomInset)
120
+ cache.put(userItem, CachedDrawable (layerDrawable, isError))
109
121
return layerDrawable
110
122
}
111
123
}
0 commit comments