mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-24 10:25:51 +03:00
Fix rendering issue with HTML formatted body
This commit is contained in:
parent
08970ad8c1
commit
9d26ba3186
7 changed files with 63 additions and 3 deletions
|
@ -15,6 +15,7 @@ Bugfix 🐛:
|
|||
- Scroll breadcrumbs to top when opened
|
||||
- Render default room name when it starts with an emoji (#477)
|
||||
- Do not display " (IRC)" in display names https://github.com/vector-im/riot-android/issues/444
|
||||
- Fix rendering issue with HTML formatted body
|
||||
|
||||
Translations 🗣:
|
||||
-
|
||||
|
|
|
@ -293,6 +293,7 @@ dependencies {
|
|||
implementation 'me.gujun.android:span:1.7'
|
||||
implementation "io.noties.markwon:core:$markwon_version"
|
||||
implementation "io.noties.markwon:html:$markwon_version"
|
||||
implementation 'com.googlecode.htmlcompressor:htmlcompressor:1.4'
|
||||
implementation 'me.saket:better-link-movement-method:2.2.0'
|
||||
implementation 'com.google.android:flexbox:1.1.1'
|
||||
implementation "androidx.autofill:autofill:$autofill_version"
|
||||
|
|
|
@ -359,6 +359,11 @@ SOFTWARE.
|
|||
<br/>
|
||||
Copyright 2018 Kumar Bibek
|
||||
</li>
|
||||
<li>
|
||||
<b>htmlcompressor</b>
|
||||
<br/>
|
||||
Copyright 2017 Sergiy Kovalchuk
|
||||
</li>
|
||||
</ul>
|
||||
<pre>
|
||||
Apache License
|
||||
|
|
|
@ -38,6 +38,7 @@ import im.vector.riotx.features.home.AvatarRenderer
|
|||
import im.vector.riotx.features.home.HomeRoomListDataSource
|
||||
import im.vector.riotx.features.home.group.SelectedGroupDataSource
|
||||
import im.vector.riotx.features.html.EventHtmlRenderer
|
||||
import im.vector.riotx.features.html.VectorHtmlCompressor
|
||||
import im.vector.riotx.features.navigation.Navigator
|
||||
import im.vector.riotx.features.notifications.*
|
||||
import im.vector.riotx.features.rageshake.BugReporter
|
||||
|
@ -87,6 +88,8 @@ interface VectorComponent {
|
|||
|
||||
fun eventHtmlRenderer(): EventHtmlRenderer
|
||||
|
||||
fun vectorHtmlCompressor(): VectorHtmlCompressor
|
||||
|
||||
fun navigator(): Navigator
|
||||
|
||||
fun errorFormatter(): ErrorFormatter
|
||||
|
|
|
@ -41,6 +41,7 @@ import im.vector.riotx.core.resources.StringProvider
|
|||
import im.vector.riotx.features.home.room.detail.timeline.format.NoticeEventFormatter
|
||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
||||
import im.vector.riotx.features.html.EventHtmlRenderer
|
||||
import im.vector.riotx.features.html.VectorHtmlCompressor
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
|
@ -82,6 +83,7 @@ data class MessageActionState(
|
|||
class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
||||
initialState: MessageActionState,
|
||||
private val eventHtmlRenderer: Lazy<EventHtmlRenderer>,
|
||||
private val htmlCompressor: VectorHtmlCompressor,
|
||||
private val session: Session,
|
||||
private val noticeEventFormatter: NoticeEventFormatter,
|
||||
private val stringProvider: StringProvider
|
||||
|
@ -170,8 +172,12 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted
|
|||
EventType.MESSAGE -> {
|
||||
val messageContent: MessageContent? = timelineEvent()?.getLastMessageContent()
|
||||
if (messageContent is MessageTextContent && messageContent.format == MessageType.FORMAT_MATRIX_HTML) {
|
||||
eventHtmlRenderer.get().render(messageContent.formattedBody
|
||||
?: messageContent.body)
|
||||
val html = messageContent.formattedBody
|
||||
?.takeIf { it.isNotBlank() }
|
||||
?.let { htmlCompressor.compress(it) }
|
||||
?: messageContent.body
|
||||
|
||||
eventHtmlRenderer.get().render(html)
|
||||
} else {
|
||||
messageContent?.body
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ import im.vector.riotx.features.home.room.detail.timeline.tools.createLinkMoveme
|
|||
import im.vector.riotx.features.home.room.detail.timeline.tools.linkify
|
||||
import im.vector.riotx.features.html.CodeVisitor
|
||||
import im.vector.riotx.features.html.EventHtmlRenderer
|
||||
import im.vector.riotx.features.html.VectorHtmlCompressor
|
||||
import im.vector.riotx.features.media.ImageContentRenderer
|
||||
import im.vector.riotx.features.media.VideoContentRenderer
|
||||
import me.gujun.android.span.span
|
||||
|
@ -57,6 +58,7 @@ class MessageItemFactory @Inject constructor(
|
|||
private val dimensionConverter: DimensionConverter,
|
||||
private val timelineMediaSizeProvider: TimelineMediaSizeProvider,
|
||||
private val htmlRenderer: Lazy<EventHtmlRenderer>,
|
||||
private val htmlCompressor: VectorHtmlCompressor,
|
||||
private val stringProvider: StringProvider,
|
||||
private val imageContentRenderer: ImageContentRenderer,
|
||||
private val messageInformationDataFactory: MessageInformationDataFactory,
|
||||
|
@ -227,6 +229,7 @@ class MessageItemFactory @Inject constructor(
|
|||
attributes: AbsMessageItem.Attributes): VectorEpoxyModel<*>? {
|
||||
val isFormatted = messageContent.formattedBody.isNullOrBlank().not()
|
||||
return if (isFormatted) {
|
||||
// First detect if the message contains some code block(s) or inline code
|
||||
val localFormattedBody = htmlRenderer.get().parse(messageContent.body) as Document
|
||||
val codeVisitor = CodeVisitor()
|
||||
codeVisitor.visit(localFormattedBody)
|
||||
|
@ -240,7 +243,8 @@ class MessageItemFactory @Inject constructor(
|
|||
buildMessageTextItem(codeFormatted, false, informationData, highlight, callback, attributes)
|
||||
}
|
||||
CodeVisitor.Kind.NONE -> {
|
||||
val formattedBody = htmlRenderer.get().render(messageContent.formattedBody!!)
|
||||
val compressed = htmlCompressor.compress(messageContent.formattedBody!!)
|
||||
val formattedBody = htmlRenderer.get().render(compressed)
|
||||
buildMessageTextItem(formattedBody, true, informationData, highlight, callback, attributes)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.riotx.features.html
|
||||
|
||||
import com.googlecode.htmlcompressor.compressor.Compressor
|
||||
import com.googlecode.htmlcompressor.compressor.HtmlCompressor
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class VectorHtmlCompressor @Inject constructor() {
|
||||
|
||||
// All default options are suitable so far
|
||||
private val htmlCompressor: Compressor = HtmlCompressor()
|
||||
|
||||
fun compress(html: String): String {
|
||||
var result = htmlCompressor.compress(html)
|
||||
|
||||
// Trim space after <br> and <p>, unfortunately the method setRemoveSurroundingSpaces() from the doc does not exist
|
||||
result = result.replace("<br> ", "<br>")
|
||||
result = result.replace("<br/> ", "<br/>")
|
||||
result = result.replace("<p> ", "<p>")
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue