Merge pull request #1802 from vector-im/feature/fix_reply_tag
Feature/fix reply tag
This commit is contained in:
commit
0d0308d584
|
@ -18,6 +18,7 @@ Bugfix 🐛:
|
||||||
- Fix 404 on EMS (#1761)
|
- Fix 404 on EMS (#1761)
|
||||||
- Fix Infinite loop at startup when migrating account from Riot (#1699)
|
- Fix Infinite loop at startup when migrating account from Riot (#1699)
|
||||||
- Fix Element crashes in loop after initial sync (#1709)
|
- Fix Element crashes in loop after initial sync (#1709)
|
||||||
|
- Remove inner mx-reply tags before replying
|
||||||
- Fix timeline items not loading when there are only filtered events
|
- Fix timeline items not loading when there are only filtered events
|
||||||
- Fix "Voice & Video" grayed out in Settings (#1733)
|
- Fix "Voice & Video" grayed out in Settings (#1733)
|
||||||
- Fix Allow VOIP call in all rooms with 2 participants (even if not DM)
|
- Fix Allow VOIP call in all rooms with 2 participants (even if not DM)
|
||||||
|
|
|
@ -21,9 +21,11 @@ import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.session.crypto.MXCryptoError
|
import im.vector.matrix.android.api.session.crypto.MXCryptoError
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
||||||
|
import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent
|
||||||
import im.vector.matrix.android.api.session.room.send.SendState
|
import im.vector.matrix.android.api.session.room.send.SendState
|
||||||
import im.vector.matrix.android.api.util.JsonDict
|
import im.vector.matrix.android.api.util.JsonDict
|
||||||
import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult
|
import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult
|
||||||
|
import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent
|
||||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
@ -240,6 +242,18 @@ fun Event.isFileMessage(): Boolean {
|
||||||
return getClearType() == EventType.MESSAGE
|
return getClearType() == EventType.MESSAGE
|
||||||
&& when (getClearContent()?.toModel<MessageContent>()?.msgType) {
|
&& when (getClearContent()?.toModel<MessageContent>()?.msgType) {
|
||||||
MessageType.MSGTYPE_FILE -> true
|
MessageType.MSGTYPE_FILE -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Event.getRelationContent(): RelationDefaultContent? {
|
||||||
|
return if (isEncrypted()) {
|
||||||
|
content.toModel<EncryptedEventContent>()?.relatesTo
|
||||||
|
} else {
|
||||||
|
content.toModel<MessageContent>()?.relatesTo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Event.isReply(): Boolean {
|
||||||
|
return getRelationContent()?.inReplyTo?.eventId != null
|
||||||
|
}
|
||||||
|
|
|
@ -25,7 +25,3 @@ interface MessageContent {
|
||||||
val relatesTo: RelationDefaultContent?
|
val relatesTo: RelationDefaultContent?
|
||||||
val newContent: Content?
|
val newContent: Content?
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MessageContent?.isReply(): Boolean {
|
|
||||||
return this?.relatesTo?.inReplyTo?.eventId != null
|
|
||||||
}
|
|
||||||
|
|
|
@ -20,15 +20,16 @@ import im.vector.matrix.android.BuildConfig
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.session.events.model.RelationType
|
import im.vector.matrix.android.api.session.events.model.RelationType
|
||||||
|
import im.vector.matrix.android.api.session.events.model.getRelationContent
|
||||||
|
import im.vector.matrix.android.api.session.events.model.isReply
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
|
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.ReadReceipt
|
import im.vector.matrix.android.api.session.room.model.ReadReceipt
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageStickerContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageStickerContent
|
||||||
import im.vector.matrix.android.api.session.room.model.message.isReply
|
import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent
|
||||||
import im.vector.matrix.android.api.session.room.sender.SenderInfo
|
import im.vector.matrix.android.api.session.room.sender.SenderInfo
|
||||||
import im.vector.matrix.android.api.util.ContentUtils.extractUsefulTextFromReply
|
import im.vector.matrix.android.api.util.ContentUtils.extractUsefulTextFromReply
|
||||||
import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This data class is a wrapper around an Event. It allows to get useful data in the context of a timeline.
|
* This data class is a wrapper around an Event. It allows to get useful data in the context of a timeline.
|
||||||
|
@ -88,11 +89,18 @@ data class TimelineEvent(
|
||||||
*/
|
*/
|
||||||
fun TimelineEvent.hasBeenEdited() = annotations?.editSummary != null
|
fun TimelineEvent.hasBeenEdited() = annotations?.editSummary != null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the relation content if any
|
||||||
|
*/
|
||||||
|
fun TimelineEvent.getRelationContent(): RelationDefaultContent? {
|
||||||
|
return root.getRelationContent()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the eventId which was edited by this event if any
|
* Get the eventId which was edited by this event if any
|
||||||
*/
|
*/
|
||||||
fun TimelineEvent.getEditedEventId(): String? {
|
fun TimelineEvent.getEditedEventId(): String? {
|
||||||
return root.getClearContent().toModel<MessageContent>()?.relatesTo?.takeIf { it.type == RelationType.REPLACE }?.eventId
|
return getRelationContent()?.takeIf { it.type == RelationType.REPLACE }?.eventId
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -121,11 +129,16 @@ fun TimelineEvent.getLastMessageBody(): String? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if it's a reply
|
||||||
|
*/
|
||||||
|
fun TimelineEvent.isReply(): Boolean {
|
||||||
|
return root.isReply()
|
||||||
|
}
|
||||||
|
|
||||||
fun TimelineEvent.getTextEditableContent(): String? {
|
fun TimelineEvent.getTextEditableContent(): String? {
|
||||||
val originalContent = root.getClearContent().toModel<MessageContent>() ?: return null
|
|
||||||
val isReply = originalContent.isReply() || root.content.toModel<EncryptedEventContent>()?.relatesTo?.inReplyTo?.eventId != null
|
|
||||||
val lastContent = getLastMessageContent()
|
val lastContent = getLastMessageContent()
|
||||||
return if (isReply) {
|
return if (isReply()) {
|
||||||
return extractUsefulTextFromReply(lastContent?.body ?: "")
|
return extractUsefulTextFromReply(lastContent?.body ?: "")
|
||||||
} else {
|
} else {
|
||||||
lastContent?.body ?: ""
|
lastContent?.body ?: ""
|
||||||
|
|
|
@ -30,7 +30,6 @@ import im.vector.matrix.android.api.session.events.model.LocalEcho
|
||||||
import im.vector.matrix.android.api.session.events.model.RelationType
|
import im.vector.matrix.android.api.session.events.model.RelationType
|
||||||
import im.vector.matrix.android.api.session.events.model.UnsignedData
|
import im.vector.matrix.android.api.session.events.model.UnsignedData
|
||||||
import im.vector.matrix.android.api.session.events.model.toContent
|
import im.vector.matrix.android.api.session.events.model.toContent
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
|
||||||
import im.vector.matrix.android.api.session.room.model.message.AudioInfo
|
import im.vector.matrix.android.api.session.room.model.message.AudioInfo
|
||||||
import im.vector.matrix.android.api.session.room.model.message.FileInfo
|
import im.vector.matrix.android.api.session.room.model.message.FileInfo
|
||||||
import im.vector.matrix.android.api.session.room.model.message.ImageInfo
|
import im.vector.matrix.android.api.session.room.model.message.ImageInfo
|
||||||
|
@ -50,13 +49,13 @@ import im.vector.matrix.android.api.session.room.model.message.OPTION_TYPE_POLL
|
||||||
import im.vector.matrix.android.api.session.room.model.message.OptionItem
|
import im.vector.matrix.android.api.session.room.model.message.OptionItem
|
||||||
import im.vector.matrix.android.api.session.room.model.message.ThumbnailInfo
|
import im.vector.matrix.android.api.session.room.model.message.ThumbnailInfo
|
||||||
import im.vector.matrix.android.api.session.room.model.message.VideoInfo
|
import im.vector.matrix.android.api.session.room.model.message.VideoInfo
|
||||||
import im.vector.matrix.android.api.session.room.model.message.isReply
|
|
||||||
import im.vector.matrix.android.api.session.room.model.relation.ReactionContent
|
import im.vector.matrix.android.api.session.room.model.relation.ReactionContent
|
||||||
import im.vector.matrix.android.api.session.room.model.relation.ReactionInfo
|
import im.vector.matrix.android.api.session.room.model.relation.ReactionInfo
|
||||||
import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent
|
import im.vector.matrix.android.api.session.room.model.relation.RelationDefaultContent
|
||||||
import im.vector.matrix.android.api.session.room.model.relation.ReplyToContent
|
import im.vector.matrix.android.api.session.room.model.relation.ReplyToContent
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent
|
import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent
|
||||||
|
import im.vector.matrix.android.api.session.room.timeline.isReply
|
||||||
import im.vector.matrix.android.internal.di.UserId
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.session.content.ThumbnailExtractor
|
import im.vector.matrix.android.internal.session.content.ThumbnailExtractor
|
||||||
import im.vector.matrix.android.internal.session.room.send.pills.TextPillsUtils
|
import im.vector.matrix.android.internal.session.room.send.pills.TextPillsUtils
|
||||||
|
@ -173,12 +172,13 @@ internal class LocalEchoEventFactory @Inject constructor(
|
||||||
val userLink = originalEvent.root.senderId?.let { PermalinkFactory.createPermalink(it) }
|
val userLink = originalEvent.root.senderId?.let { PermalinkFactory.createPermalink(it) }
|
||||||
?: ""
|
?: ""
|
||||||
|
|
||||||
val body = bodyForReply(originalEvent.getLastMessageContent(), originalEvent.root.getClearContent().toModel())
|
val body = bodyForReply(originalEvent.getLastMessageContent(), originalEvent.isReply())
|
||||||
val replyFormatted = REPLY_PATTERN.format(
|
val replyFormatted = REPLY_PATTERN.format(
|
||||||
permalink,
|
permalink,
|
||||||
userLink,
|
userLink,
|
||||||
originalEvent.senderInfo.disambiguatedDisplayName,
|
originalEvent.senderInfo.disambiguatedDisplayName,
|
||||||
body.takeFormatted(),
|
// Remove inner mx_reply tags if any
|
||||||
|
body.takeFormatted().replace(MX_REPLY_REGEX, ""),
|
||||||
createTextContent(newBodyText, newBodyAutoMarkdown).takeFormatted()
|
createTextContent(newBodyText, newBodyAutoMarkdown).takeFormatted()
|
||||||
)
|
)
|
||||||
//
|
//
|
||||||
|
@ -367,12 +367,13 @@ internal class LocalEchoEventFactory @Inject constructor(
|
||||||
val userId = eventReplied.root.senderId ?: return null
|
val userId = eventReplied.root.senderId ?: return null
|
||||||
val userLink = PermalinkFactory.createPermalink(userId) ?: return null
|
val userLink = PermalinkFactory.createPermalink(userId) ?: return null
|
||||||
|
|
||||||
val body = bodyForReply(eventReplied.getLastMessageContent(), eventReplied.root.getClearContent().toModel())
|
val body = bodyForReply(eventReplied.getLastMessageContent(), eventReplied.isReply())
|
||||||
val replyFormatted = REPLY_PATTERN.format(
|
val replyFormatted = REPLY_PATTERN.format(
|
||||||
permalink,
|
permalink,
|
||||||
userLink,
|
userLink,
|
||||||
userId,
|
userId,
|
||||||
body.takeFormatted(),
|
// Remove inner mx_reply tags if any
|
||||||
|
body.takeFormatted().replace(MX_REPLY_REGEX, ""),
|
||||||
createTextContent(replyText, autoMarkdown).takeFormatted()
|
createTextContent(replyText, autoMarkdown).takeFormatted()
|
||||||
)
|
)
|
||||||
//
|
//
|
||||||
|
@ -412,10 +413,10 @@ internal class LocalEchoEventFactory @Inject constructor(
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a TextContent used for the fallback event representation in a reply message.
|
* Returns a TextContent used for the fallback event representation in a reply message.
|
||||||
* We also pass the original content, because in case of an edit of a reply the last content is not
|
* In case of an edit of a reply the last content is not
|
||||||
* himself a reply, but it will contain the fallbacks, so we have to trim them.
|
* himself a reply, but it will contain the fallbacks, so we have to trim them.
|
||||||
*/
|
*/
|
||||||
private fun bodyForReply(content: MessageContent?, originalContent: MessageContent?): TextContent {
|
private fun bodyForReply(content: MessageContent?, isReply: Boolean): TextContent {
|
||||||
when (content?.msgType) {
|
when (content?.msgType) {
|
||||||
MessageType.MSGTYPE_EMOTE,
|
MessageType.MSGTYPE_EMOTE,
|
||||||
MessageType.MSGTYPE_TEXT,
|
MessageType.MSGTYPE_TEXT,
|
||||||
|
@ -424,7 +425,6 @@ internal class LocalEchoEventFactory @Inject constructor(
|
||||||
if (content is MessageContentWithFormattedBody) {
|
if (content is MessageContentWithFormattedBody) {
|
||||||
formattedText = content.matrixFormattedBody
|
formattedText = content.matrixFormattedBody
|
||||||
}
|
}
|
||||||
val isReply = content.isReply() || originalContent.isReply()
|
|
||||||
return if (isReply) {
|
return if (isReply) {
|
||||||
TextContent(content.body, formattedText).removeInReplyFallbacks()
|
TextContent(content.body, formattedText).removeInReplyFallbacks()
|
||||||
} else {
|
} else {
|
||||||
|
@ -485,5 +485,8 @@ internal class LocalEchoEventFactory @Inject constructor(
|
||||||
// </mx-reply>
|
// </mx-reply>
|
||||||
// No whitespace because currently breaks temporary formatted text to Span
|
// No whitespace because currently breaks temporary formatted text to Span
|
||||||
const val REPLY_PATTERN = """<mx-reply><blockquote><a href="%s">In reply to</a> <a href="%s">%s</a><br />%s</blockquote></mx-reply>%s"""
|
const val REPLY_PATTERN = """<mx-reply><blockquote><a href="%s">In reply to</a> <a href="%s">%s</a><br />%s</blockquote></mx-reply>%s"""
|
||||||
|
|
||||||
|
// This is used to replace inner mx-reply tags
|
||||||
|
val MX_REPLY_REGEX = "<mx-reply>.*</mx-reply>".toRegex()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,7 @@ import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.api.session.crypto.MXCryptoError
|
import im.vector.matrix.android.api.session.crypto.MXCryptoError
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.isReply
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
|
||||||
import im.vector.matrix.android.api.session.room.model.message.isReply
|
|
||||||
import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult
|
import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult
|
||||||
import im.vector.riotx.core.date.VectorDateFormatter
|
import im.vector.riotx.core.date.VectorDateFormatter
|
||||||
import im.vector.riotx.core.platform.EmptyAction
|
import im.vector.riotx.core.platform.EmptyAction
|
||||||
|
@ -113,7 +111,7 @@ class ViewEditHistoryViewModel @AssistedInject constructor(@Assisted
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.eventId == it.eventId) {
|
if (event.eventId == it.eventId) {
|
||||||
originalIsReply = it.getClearContent().toModel<MessageContent>().isReply()
|
originalIsReply = it.isReply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -354,16 +354,22 @@ class MessageItemFactory @Inject constructor(
|
||||||
when (codeVisitor.codeKind) {
|
when (codeVisitor.codeKind) {
|
||||||
CodeVisitor.Kind.BLOCK -> {
|
CodeVisitor.Kind.BLOCK -> {
|
||||||
val codeFormattedBlock = htmlRenderer.get().render(localFormattedBody)
|
val codeFormattedBlock = htmlRenderer.get().render(localFormattedBody)
|
||||||
buildCodeBlockItem(codeFormattedBlock, informationData, highlight, callback, attributes)
|
if (codeFormattedBlock == null) {
|
||||||
|
buildFormattedTextItem(messageContent, informationData, highlight, callback, attributes)
|
||||||
|
} else {
|
||||||
|
buildCodeBlockItem(codeFormattedBlock, informationData, highlight, callback, attributes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CodeVisitor.Kind.INLINE -> {
|
CodeVisitor.Kind.INLINE -> {
|
||||||
val codeFormatted = htmlRenderer.get().render(localFormattedBody)
|
val codeFormatted = htmlRenderer.get().render(localFormattedBody)
|
||||||
buildMessageTextItem(codeFormatted, false, informationData, highlight, callback, attributes)
|
if (codeFormatted == null) {
|
||||||
|
buildFormattedTextItem(messageContent, informationData, highlight, callback, attributes)
|
||||||
|
} else {
|
||||||
|
buildMessageTextItem(codeFormatted, false, informationData, highlight, callback, attributes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CodeVisitor.Kind.NONE -> {
|
CodeVisitor.Kind.NONE -> {
|
||||||
val compressed = htmlCompressor.compress(messageContent.formattedBody!!)
|
buildFormattedTextItem(messageContent, informationData, highlight, callback, attributes)
|
||||||
val formattedBody = htmlRenderer.get().render(compressed)
|
|
||||||
buildMessageTextItem(formattedBody, true, informationData, highlight, callback, attributes)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -371,6 +377,16 @@ class MessageItemFactory @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun buildFormattedTextItem(messageContent: MessageTextContent,
|
||||||
|
informationData: MessageInformationData,
|
||||||
|
highlight: Boolean,
|
||||||
|
callback: TimelineEventController.Callback?,
|
||||||
|
attributes: AbsMessageItem.Attributes): MessageTextItem? {
|
||||||
|
val compressed = htmlCompressor.compress(messageContent.formattedBody!!)
|
||||||
|
val formattedBody = htmlRenderer.get().render(compressed)
|
||||||
|
return buildMessageTextItem(formattedBody, true, informationData, highlight, callback, attributes)
|
||||||
|
}
|
||||||
|
|
||||||
private fun buildMessageTextItem(body: CharSequence,
|
private fun buildMessageTextItem(body: CharSequence,
|
||||||
isFormatted: Boolean,
|
isFormatted: Boolean,
|
||||||
informationData: MessageInformationData,
|
informationData: MessageInformationData,
|
||||||
|
|
|
@ -19,11 +19,11 @@ package im.vector.riotx.features.home.room.detail.timeline.format
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
||||||
import im.vector.matrix.android.api.session.room.model.message.isReply
|
|
||||||
import im.vector.matrix.android.api.session.room.model.relation.ReactionContent
|
import im.vector.matrix.android.api.session.room.model.relation.ReactionContent
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent
|
import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent
|
||||||
import im.vector.matrix.android.api.session.room.timeline.getTextEditableContent
|
import im.vector.matrix.android.api.session.room.timeline.getTextEditableContent
|
||||||
|
import im.vector.matrix.android.api.session.room.timeline.isReply
|
||||||
import im.vector.riotx.EmojiCompatWrapper
|
import im.vector.riotx.EmojiCompatWrapper
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.resources.ColorProvider
|
import im.vector.riotx.core.resources.ColorProvider
|
||||||
|
@ -79,13 +79,13 @@ class DisplayableEventFormatter @Inject constructor(
|
||||||
return simpleFormat(senderName, stringProvider.getString(R.string.sent_a_file), appendAuthor)
|
return simpleFormat(senderName, stringProvider.getString(R.string.sent_a_file), appendAuthor)
|
||||||
}
|
}
|
||||||
MessageType.MSGTYPE_TEXT -> {
|
MessageType.MSGTYPE_TEXT -> {
|
||||||
if (messageContent.isReply()) {
|
return if (timelineEvent.isReply()) {
|
||||||
// Skip reply prefix, and show important
|
// Skip reply prefix, and show important
|
||||||
// TODO add a reply image span ?
|
// TODO add a reply image span ?
|
||||||
return simpleFormat(senderName, timelineEvent.getTextEditableContent()
|
simpleFormat(senderName, timelineEvent.getTextEditableContent()
|
||||||
?: messageContent.body, appendAuthor)
|
?: messageContent.body, appendAuthor)
|
||||||
} else {
|
} else {
|
||||||
return simpleFormat(senderName, messageContent.body, appendAuthor)
|
simpleFormat(senderName, messageContent.body, appendAuthor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import io.noties.markwon.Markwon
|
||||||
import io.noties.markwon.html.HtmlPlugin
|
import io.noties.markwon.html.HtmlPlugin
|
||||||
import io.noties.markwon.html.TagHandlerNoOp
|
import io.noties.markwon.html.TagHandlerNoOp
|
||||||
import org.commonmark.node.Node
|
import org.commonmark.node.Node
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@ -41,11 +42,21 @@ class EventHtmlRenderer @Inject constructor(context: Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
fun render(text: String): CharSequence {
|
fun render(text: String): CharSequence {
|
||||||
return markwon.toMarkdown(text)
|
return try {
|
||||||
|
markwon.toMarkdown(text)
|
||||||
|
} catch (failure: Throwable) {
|
||||||
|
Timber.v("Fail to render $text to html")
|
||||||
|
text
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun render(node: Node): CharSequence {
|
fun render(node: Node): CharSequence? {
|
||||||
return markwon.render(node)
|
return try {
|
||||||
|
markwon.render(node)
|
||||||
|
} catch (failure: Throwable) {
|
||||||
|
Timber.v("Fail to render $node to html")
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue