Pills : handle avatar

This commit is contained in:
ganfra 2019-02-27 17:17:47 +01:00
parent 63bf4355b9
commit adc51529f2
4 changed files with 46 additions and 44 deletions

View file

@ -60,6 +60,7 @@ dependencies {
def epoxy_version = "3.0.0"
def arrow_version = "0.8.2"
def coroutines_version = "1.0.1"
def markwon_version = '3.0.0-SNAPSHOT'
implementation project(":matrix-sdk-android")
@ -67,6 +68,8 @@ dependencies {
implementation 'com.android.support:multidex:1.0.3'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

View file

@ -22,8 +22,6 @@ import android.widget.ImageView
import androidx.core.content.ContextCompat
import com.amulyakhare.textdrawable.TextDrawable
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.transition.Transition
import im.vector.matrix.android.api.Matrix
import im.vector.matrix.android.api.MatrixPatterns
import im.vector.matrix.android.api.session.room.model.RoomMember
@ -31,6 +29,8 @@ import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.riotredesign.R
import im.vector.riotredesign.core.glide.GlideApp
import im.vector.riotredesign.core.glide.GlideRequest
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
object AvatarRenderer {
@ -46,53 +46,47 @@ object AvatarRenderer {
if (name.isNullOrEmpty()) {
return
}
buildGlideRequest(imageView.context, name, avatarUrl).into(imageView)
val placeholder = buildPlaceholderDrawable(imageView.context, name)
buildGlideRequest(imageView.context, avatarUrl)
.placeholder(placeholder)
.into(imageView)
}
fun load(context: Context, avatarUrl: String?, name: String?, callback: Callback) {
fun load(context: Context, avatarUrl: String?, name: String?, size: Int, callback: Callback) {
if (name.isNullOrEmpty()) {
return
}
buildGlideRequest(context, name, avatarUrl).into(CallbackTarget(callback))
val request = buildGlideRequest(context, avatarUrl)
GlobalScope.launch {
val placeholder = buildPlaceholderDrawable(context, name)
callback.onDrawableUpdated(placeholder)
try {
val drawable = request.submit(size, size).get()
callback.onDrawableUpdated(drawable)
} catch (exception: Exception) {
callback.onDrawableUpdated(placeholder)
}
}
}
private fun buildGlideRequest(context: Context, name: String, avatarUrl: String?): GlideRequest<Drawable> {
private fun buildGlideRequest(context: Context, avatarUrl: String?): GlideRequest<Drawable> {
val resolvedUrl = Matrix.getInstance().currentSession.contentUrlResolver().resolveFullSize(avatarUrl)
return GlideApp
.with(context)
.load(resolvedUrl)
.apply(RequestOptions.circleCropTransform())
}
private fun buildPlaceholderDrawable(context: Context, name: String): Drawable {
val avatarColor = ContextCompat.getColor(context, R.color.pale_teal)
val isNameUserId = MatrixPatterns.isUserId(name)
val firstLetterIndex = if (isNameUserId) 1 else 0
val firstLetter = name[firstLetterIndex].toString().toUpperCase()
val fallbackDrawable = TextDrawable.builder().buildRound(firstLetter, avatarColor)
return GlideApp
.with(context)
.load(resolvedUrl)
.placeholder(fallbackDrawable)
.apply(RequestOptions.circleCropTransform())
return TextDrawable.builder().buildRound(firstLetter, avatarColor)
}
interface Callback {
fun onDrawableUpdated(drawable: Drawable?)
fun onDestroy()
}
private class CallbackTarget(private val callback: Callback) : SimpleTarget<Drawable>() {
override fun onDestroy() {
callback.onDestroy()
}
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
callback.onDrawableUpdated(resource)
}
override fun onLoadStarted(placeholder: Drawable?) {
callback.onDrawableUpdated(placeholder)
}
override fun onLoadFailed(errorDrawable: Drawable?) {
callback.onDrawableUpdated(errorDrawable)
}
}
}

View file

@ -27,15 +27,18 @@ import java.lang.ref.WeakReference
object PillDrawableFactory {
fun create(context: Context, userId: String, user: User?): Drawable {
val textPadding = context.resources.getDimension(R.dimen.pill_text_padding)
val chipDrawable = ChipDrawable.createFromResource(context, R.xml.pill_view).apply {
setText(user?.displayName ?: userId)
textEndPadding = 8f
textStartPadding = 8f
setBounds(0, 0, intrinsicWidth, (intrinsicHeight / 1.5f).toInt())
textEndPadding = textPadding
textStartPadding = textPadding
setChipMinHeightResource(R.dimen.pill_min_height)
setChipIconSizeResource(R.dimen.pill_avatar_size)
setBounds(0, 0, intrinsicWidth, intrinsicHeight)
}
val avatarRendererCallback = AvatarRendererChipCallback(chipDrawable)
// TODO: need to work on getting drawable async
//AvatarRenderer.load(context, user?.avatarUrl, user?.displayName, avatarRendererCallback)
AvatarRenderer.load(context, user?.avatarUrl, user?.displayName, 80, avatarRendererCallback)
return chipDrawable
}
@ -43,19 +46,14 @@ object PillDrawableFactory {
private val weakChipDrawable = WeakReference<ChipDrawable>(chipDrawable)
override fun onDestroy() {
weakChipDrawable.clear()
}
override fun onDrawableUpdated(drawable: Drawable?) {
weakChipDrawable.get()?.apply {
chipIcon = drawable
setBounds(0, 0, intrinsicWidth, (intrinsicHeight / 1.5f).toInt())
setBounds(0, 0, intrinsicWidth, intrinsicHeight)
}
}
}
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="pill_avatar_size">16dp</dimen>
<dimen name="pill_min_height">20dp</dimen>
<dimen name="pill_text_padding">4dp</dimen>
</resources>