forked from GitHub-Mirror/riotX-android
Html : continue work on Pills. Still need to find how to handle avatar drawable.
This commit is contained in:
parent
41b06bca60
commit
63bf4355b9
@ -16,16 +16,21 @@
|
||||
|
||||
package im.vector.riotredesign.features.home
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
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
|
||||
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
|
||||
|
||||
object AvatarRenderer {
|
||||
|
||||
@ -41,19 +46,52 @@ object AvatarRenderer {
|
||||
if (name.isNullOrEmpty()) {
|
||||
return
|
||||
}
|
||||
buildGlideRequest(imageView.context, name, avatarUrl).into(imageView)
|
||||
}
|
||||
|
||||
fun load(context: Context, avatarUrl: String?, name: String?, callback: Callback) {
|
||||
if (name.isNullOrEmpty()) {
|
||||
return
|
||||
}
|
||||
buildGlideRequest(context, name, avatarUrl).into(CallbackTarget(callback))
|
||||
}
|
||||
|
||||
private fun buildGlideRequest(context: Context, name: String, avatarUrl: String?): GlideRequest<Drawable> {
|
||||
val resolvedUrl = Matrix.getInstance().currentSession.contentUrlResolver().resolveFullSize(avatarUrl)
|
||||
val avatarColor = ContextCompat.getColor(imageView.context, R.color.pale_teal)
|
||||
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)
|
||||
|
||||
GlideApp
|
||||
.with(imageView)
|
||||
return GlideApp
|
||||
.with(context)
|
||||
.load(resolvedUrl)
|
||||
.placeholder(fallbackDrawable)
|
||||
.apply(RequestOptions.circleCropTransform())
|
||||
.into(imageView)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,25 +16,39 @@
|
||||
|
||||
package im.vector.riotredesign.features.home
|
||||
|
||||
import im.vector.matrix.android.api.Matrix
|
||||
import im.vector.riotredesign.features.home.group.SelectedGroupStore
|
||||
import im.vector.riotredesign.features.home.room.VisibleRoomStore
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.*
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.CallItemFactory
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.DefaultItemFactory
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.MessageItemFactory
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.RoomHistoryVisibilityItemFactory
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.RoomMemberItemFactory
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.RoomNameItemFactory
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.RoomTopicItemFactory
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.TimelineDateFormatter
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.TimelineItemFactory
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
|
||||
import im.vector.riotredesign.features.home.room.list.RoomSummaryComparator
|
||||
import im.vector.riotredesign.features.home.room.list.RoomSummaryController
|
||||
import im.vector.riotredesign.features.markdown.EventHtmlRenderer
|
||||
import im.vector.riotredesign.features.html.EventHtmlRenderer
|
||||
import org.koin.dsl.module.module
|
||||
|
||||
class HomeModule(homeActivity: HomeActivity) {
|
||||
|
||||
val definition = module(override = true) {
|
||||
|
||||
single {
|
||||
Matrix.getInstance().currentSession
|
||||
}
|
||||
|
||||
single {
|
||||
TimelineDateFormatter(get())
|
||||
}
|
||||
|
||||
single {
|
||||
EventHtmlRenderer(homeActivity)
|
||||
EventHtmlRenderer(homeActivity, get())
|
||||
}
|
||||
|
||||
single {
|
||||
|
@ -29,7 +29,7 @@ import im.vector.riotredesign.core.epoxy.RiotEpoxyModel
|
||||
import im.vector.riotredesign.core.extensions.localDateTime
|
||||
import im.vector.riotredesign.core.resources.ColorProvider
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
|
||||
import im.vector.riotredesign.features.markdown.EventHtmlRenderer
|
||||
import im.vector.riotredesign.features.html.EventHtmlRenderer
|
||||
import im.vector.riotredesign.features.media.MediaContentRenderer
|
||||
import me.gujun.android.span.span
|
||||
|
||||
|
@ -16,14 +16,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package im.vector.riotredesign.features.markdown
|
||||
package im.vector.riotredesign.features.html
|
||||
|
||||
import android.content.Context
|
||||
import android.text.style.ImageSpan
|
||||
import com.google.android.material.chip.ChipDrawable
|
||||
import im.vector.matrix.android.api.permalinks.PermalinkData
|
||||
import im.vector.matrix.android.api.permalinks.PermalinkParser
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import org.commonmark.node.BlockQuote
|
||||
import org.commonmark.node.HtmlBlock
|
||||
import org.commonmark.node.HtmlInline
|
||||
@ -50,10 +49,11 @@ import ru.noties.markwon.html.tag.SuperScriptHandler
|
||||
import ru.noties.markwon.html.tag.UnderlineHandler
|
||||
import java.util.Arrays.asList
|
||||
|
||||
class EventHtmlRenderer(private val context: Context) {
|
||||
class EventHtmlRenderer(private val context: Context,
|
||||
private val session: Session) {
|
||||
|
||||
private val markwon = Markwon.builder(context)
|
||||
.usePlugin(MatrixPlugin.create(context))
|
||||
.usePlugin(MatrixPlugin.create(context, session))
|
||||
.build()
|
||||
|
||||
fun render(text: String): CharSequence {
|
||||
@ -62,7 +62,8 @@ class EventHtmlRenderer(private val context: Context) {
|
||||
|
||||
}
|
||||
|
||||
private class MatrixPlugin private constructor(private val context: Context) : AbstractMarkwonPlugin() {
|
||||
private class MatrixPlugin private constructor(private val context: Context,
|
||||
private val session: Session) : AbstractMarkwonPlugin() {
|
||||
|
||||
override fun configureConfiguration(builder: MarkwonConfiguration.Builder) {
|
||||
builder.htmlParser(MarkwonHtmlParserImpl.create())
|
||||
@ -75,7 +76,7 @@ private class MatrixPlugin private constructor(private val context: Context) : A
|
||||
ImageHandler.create())
|
||||
.addHandler(
|
||||
"a",
|
||||
MxLinkHandler(context))
|
||||
MxLinkHandler(context, session))
|
||||
.addHandler(
|
||||
"blockquote",
|
||||
BlockquoteHandler())
|
||||
@ -127,13 +128,13 @@ private class MatrixPlugin private constructor(private val context: Context) : A
|
||||
|
||||
companion object {
|
||||
|
||||
fun create(context: Context): MatrixPlugin {
|
||||
return MatrixPlugin(context)
|
||||
fun create(context: Context, session: Session): MatrixPlugin {
|
||||
return MatrixPlugin(context, session)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MxLinkHandler(private val context: Context) : TagHandler() {
|
||||
private class MxLinkHandler(private val context: Context, private val session: Session) : TagHandler() {
|
||||
|
||||
private val linkHandler = LinkHandler()
|
||||
|
||||
@ -143,12 +144,9 @@ private class MxLinkHandler(private val context: Context) : TagHandler() {
|
||||
val permalinkData = PermalinkParser.parse(link)
|
||||
when (permalinkData) {
|
||||
is PermalinkData.UserLink -> {
|
||||
val chipDrawable = ChipDrawable.createFromResource(context, R.xml.pill_view)
|
||||
chipDrawable.setText(permalinkData.userId)
|
||||
chipDrawable.textEndPadding = 8f
|
||||
chipDrawable.textStartPadding = 8f
|
||||
chipDrawable.setBounds(0, 0, chipDrawable.intrinsicWidth, (chipDrawable.intrinsicHeight / 1.5f).toInt())
|
||||
val span = ImageSpan(chipDrawable)
|
||||
val user = session.getUser(permalinkData.userId) ?: return
|
||||
val drawable = PillDrawableFactory.create(context, permalinkData.userId, user)
|
||||
val span = ImageSpan(drawable)
|
||||
SpannableBuilder.setSpans(
|
||||
visitor.builder(),
|
||||
span,
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.riotredesign.features.html
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import com.google.android.material.chip.ChipDrawable
|
||||
import im.vector.matrix.android.api.session.user.model.User
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.features.home.AvatarRenderer
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
object PillDrawableFactory {
|
||||
|
||||
fun create(context: Context, userId: String, user: User?): Drawable {
|
||||
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())
|
||||
}
|
||||
val avatarRendererCallback = AvatarRendererChipCallback(chipDrawable)
|
||||
// TODO: need to work on getting drawable async
|
||||
//AvatarRenderer.load(context, user?.avatarUrl, user?.displayName, avatarRendererCallback)
|
||||
return chipDrawable
|
||||
}
|
||||
|
||||
private class AvatarRendererChipCallback(chipDrawable: ChipDrawable) : AvatarRenderer.Callback {
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user