forked from GitHub-Mirror/riotX-android
Use addLinks method on message. Next step is to proceed the url to navigate.
This commit is contained in:
parent
58f60eaab4
commit
fdd4642cbb
@ -23,8 +23,9 @@ import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventCo
|
||||
import kotlinx.android.synthetic.main.fragment_room_detail.*
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.core.parameter.parametersOf
|
||||
import timber.log.Timber
|
||||
|
||||
class RoomDetailFragment : RiotFragment() {
|
||||
class RoomDetailFragment : RiotFragment(), TimelineEventController.Callback {
|
||||
|
||||
companion object {
|
||||
|
||||
@ -80,6 +81,7 @@ class RoomDetailFragment : RiotFragment() {
|
||||
recyclerView.layoutManager = layoutManager
|
||||
timelineEventController.addModelBuildListener { it.dispatchTo(scrollOnNewMessageCallback) }
|
||||
recyclerView.setController(timelineEventController)
|
||||
timelineEventController.callback = this
|
||||
}
|
||||
|
||||
private fun renderRoomSummary(roomSummary: RoomSummary?) {
|
||||
@ -100,4 +102,10 @@ class RoomDetailFragment : RiotFragment() {
|
||||
timelineEventController.timeline = events
|
||||
}
|
||||
|
||||
// TimelineEventController.Callback ************************************************************
|
||||
|
||||
override fun onUrlClicked(url: String) {
|
||||
Timber.v("Url clicked: $url")
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package im.vector.riotredesign.features.home.room.detail.timeline
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import im.vector.matrix.android.api.permalinks.MatrixURLSpan
|
||||
import im.vector.matrix.android.api.permalinks.MatrixUrlLinkify
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.epoxy.KotlinModel
|
||||
import im.vector.riotredesign.features.home.AvatarRenderer
|
||||
@ -12,7 +14,8 @@ data class MessageItem(
|
||||
val time: CharSequence? = null,
|
||||
val avatarUrl: String?,
|
||||
val memberName: CharSequence? = null,
|
||||
val showInformation: Boolean = true
|
||||
val showInformation: Boolean = true,
|
||||
val onUrlClickedListener: ((url: String) -> Unit)? = null
|
||||
) : KotlinModel(R.layout.item_event_message) {
|
||||
|
||||
private val avatarImageView by bind<ImageView>(R.id.messageAvatarImageView)
|
||||
@ -22,6 +25,11 @@ data class MessageItem(
|
||||
|
||||
override fun bind() {
|
||||
messageView.text = message
|
||||
MatrixUrlLinkify.addLinks(messageView, object : MatrixURLSpan.Callback {
|
||||
override fun onUrlClicked(url: String) {
|
||||
onUrlClickedListener?.invoke(url)
|
||||
}
|
||||
})
|
||||
if (showInformation) {
|
||||
avatarImageView.visibility = View.VISIBLE
|
||||
memberNameView.visibility = View.VISIBLE
|
||||
|
@ -9,7 +9,13 @@ class MessageItemFactory(private val timelineDateFormatter: TimelineDateFormatte
|
||||
|
||||
private val messagesDisplayedWithInformation = HashSet<String?>()
|
||||
|
||||
fun create(event: EnrichedEvent, nextEvent: EnrichedEvent?, addDaySeparator: Boolean, date: LocalDateTime): MessageItem? {
|
||||
fun create(event: EnrichedEvent,
|
||||
nextEvent: EnrichedEvent?,
|
||||
addDaySeparator: Boolean,
|
||||
date: LocalDateTime,
|
||||
callback: TimelineEventController.Callback?
|
||||
): MessageItem? {
|
||||
|
||||
val messageContent: MessageContent? = event.root.content.toModel()
|
||||
val roomMember = event.roomMember
|
||||
if (messageContent == null || roomMember == null) {
|
||||
@ -20,13 +26,13 @@ class MessageItemFactory(private val timelineDateFormatter: TimelineDateFormatte
|
||||
messagesDisplayedWithInformation.add(event.root.eventId)
|
||||
}
|
||||
val showInformation = messagesDisplayedWithInformation.contains(event.root.eventId)
|
||||
|
||||
return MessageItem(
|
||||
message = messageContent.body,
|
||||
avatarUrl = roomMember.avatarUrl,
|
||||
showInformation = showInformation,
|
||||
time = timelineDateFormatter.formatMessageHour(date),
|
||||
memberName = roomMember.displayName ?: event.root.sender
|
||||
memberName = roomMember.displayName ?: event.root.sender,
|
||||
onUrlClickedListener = { callback?.onUrlClicked(it) }
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,8 @@ class TimelineEventController(private val roomId: String,
|
||||
buildSnapshotList()
|
||||
}
|
||||
|
||||
var callback: Callback? = null
|
||||
|
||||
override fun buildModels() {
|
||||
buildModels(snapshotList)
|
||||
}
|
||||
@ -61,8 +63,8 @@ class TimelineEventController(private val roomId: String,
|
||||
val addDaySeparator = date.toLocalDate() != nextDate?.toLocalDate()
|
||||
|
||||
val item = when (event.root.type) {
|
||||
EventType.MESSAGE -> messageItemFactory.create(event, nextEvent, addDaySeparator, date)
|
||||
else -> textItemFactory.create(event)
|
||||
EventType.MESSAGE -> messageItemFactory.create(event, nextEvent, addDaySeparator, date, callback)
|
||||
else -> textItemFactory.create(event)
|
||||
}
|
||||
item
|
||||
?.onBind { timeline?.loadAround(index) }
|
||||
@ -87,4 +89,8 @@ class TimelineEventController(private val roomId: String,
|
||||
requestModelBuild()
|
||||
}
|
||||
|
||||
interface Callback {
|
||||
fun onUrlClicked(url: String)
|
||||
}
|
||||
|
||||
}
|
@ -1,34 +1,69 @@
|
||||
package im.vector.matrix.android.api.permalinks
|
||||
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.SpannableString
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.widget.TextView
|
||||
|
||||
object MatrixUrlLinkify {
|
||||
|
||||
/**
|
||||
* Find the matrix spans i.e matrix id , user id ... to display them as URL.
|
||||
*
|
||||
* @param spannableStringBuilder the text in which the matrix items has to be clickable.
|
||||
* @param spannable the text in which the matrix items has to be clickable.
|
||||
*/
|
||||
fun addLinks(spannableStringBuilder: SpannableStringBuilder, callback: MatrixURLSpan.Callback?) {
|
||||
fun addLinks(spannable: Spannable?, callback: MatrixURLSpan.Callback?): Boolean {
|
||||
// sanity checks
|
||||
if (spannableStringBuilder.isEmpty()) {
|
||||
return
|
||||
if (spannable.isNullOrEmpty()) {
|
||||
return false
|
||||
}
|
||||
val text = spannableStringBuilder.toString()
|
||||
val text = spannable.toString()
|
||||
var hasMatch = false
|
||||
for (index in MatrixPatterns.MATRIX_PATTERNS.indices) {
|
||||
val pattern = MatrixPatterns.MATRIX_PATTERNS[index]
|
||||
val matcher = pattern.matcher(spannableStringBuilder)
|
||||
val matcher = pattern.matcher(spannable)
|
||||
while (matcher.find()) {
|
||||
hasMatch = true
|
||||
val startPos = matcher.start(0)
|
||||
if (startPos == 0 || text[startPos - 1] != '/') {
|
||||
val endPos = matcher.end(0)
|
||||
val url = text.substring(matcher.start(0), matcher.end(0))
|
||||
val span = MatrixURLSpan(url, callback)
|
||||
spannableStringBuilder.setSpan(span, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
spannable.setSpan(span, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
}
|
||||
}
|
||||
return hasMatch
|
||||
}
|
||||
|
||||
fun addLinks(textView: TextView, callback: MatrixURLSpan.Callback?): Boolean {
|
||||
val text = textView.text
|
||||
if (text is Spannable) {
|
||||
if (addLinks(text, callback)) {
|
||||
addLinkMovementMethod(textView)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
} else {
|
||||
val spannableString = SpannableString.valueOf(text)
|
||||
if (addLinks(spannableString, callback)) {
|
||||
addLinkMovementMethod(textView)
|
||||
textView.text = spannableString
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun addLinkMovementMethod(textView: TextView) {
|
||||
val movementMethod = textView.movementMethod
|
||||
if (movementMethod == null || movementMethod !is LinkMovementMethod) {
|
||||
if (textView.linksClickable) {
|
||||
textView.movementMethod = LinkMovementMethod.getInstance()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user