mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-26 19:36:08 +03:00
Reply with formatted content
This commit is contained in:
parent
92e3a02389
commit
1918302297
5 changed files with 35 additions and 26 deletions
|
@ -77,8 +77,9 @@ interface RelationService {
|
||||||
* https://matrix.org/docs/spec/client_server/r0.4.0.html#id350
|
* https://matrix.org/docs/spec/client_server/r0.4.0.html#id350
|
||||||
* @param eventReplied the event referenced by the reply
|
* @param eventReplied the event referenced by the reply
|
||||||
* @param replyText the reply text
|
* @param replyText the reply text
|
||||||
|
* @param autoMarkdown If true, the SDK will generate a formatted HTML message from the body text if markdown syntax is present
|
||||||
*/
|
*/
|
||||||
fun replyToMessage(eventReplied: Event, replyText: String): Cancelable?
|
fun replyToMessage(eventReplied: Event, replyText: String, autoMarkdown: Boolean = false): Cancelable?
|
||||||
|
|
||||||
fun getEventSummaryLive(eventId: String): LiveData<EventAnnotationsSummary>
|
fun getEventSummaryLive(eventId: String): LiveData<EventAnnotationsSummary>
|
||||||
}
|
}
|
|
@ -127,8 +127,8 @@ internal class DefaultRelationService @Inject constructor(private val context: C
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun replyToMessage(eventReplied: Event, replyText: String): Cancelable? {
|
override fun replyToMessage(eventReplied: Event, replyText: String, autoMarkdown: Boolean): Cancelable? {
|
||||||
val event = eventFactory.createReplyTextEvent(roomId, eventReplied, replyText)?.also {
|
val event = eventFactory.createReplyTextEvent(roomId, eventReplied, replyText, autoMarkdown)?.also {
|
||||||
saveLocalEcho(it)
|
saveLocalEcho(it)
|
||||||
} ?: return null
|
} ?: return null
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ internal class DefaultSendService @Inject constructor(private val context: Conte
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sendFormattedTextMessage(text: String, formattedText: String): Cancelable {
|
override fun sendFormattedTextMessage(text: String, formattedText: String): Cancelable {
|
||||||
val event = localEchoEventFactory.createFormattedTextEvent(roomId, text, formattedText).also {
|
val event = localEchoEventFactory.createFormattedTextEvent(roomId, TextContent(text, formattedText)).also {
|
||||||
saveLocalEcho(it)
|
saveLocalEcho(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,30 +52,41 @@ import javax.inject.Inject
|
||||||
internal class LocalEchoEventFactory @Inject constructor(private val credentials: Credentials,
|
internal class LocalEchoEventFactory @Inject constructor(private val credentials: Credentials,
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val roomSummaryUpdater: RoomSummaryUpdater) {
|
private val roomSummaryUpdater: RoomSummaryUpdater) {
|
||||||
|
// TODO Inject
|
||||||
|
private val parser = Parser.builder().build()
|
||||||
|
// TODO Inject
|
||||||
|
private val renderer = HtmlRenderer.builder().build()
|
||||||
|
|
||||||
fun createTextEvent(roomId: String, msgType: String, text: String, autoMarkdown: Boolean): Event {
|
fun createTextEvent(roomId: String, msgType: String, text: String, autoMarkdown: Boolean): Event {
|
||||||
if (autoMarkdown && msgType == MessageType.MSGTYPE_TEXT) {
|
if (msgType == MessageType.MSGTYPE_TEXT) {
|
||||||
val parser = Parser.builder().build()
|
return createFormattedTextEvent(roomId, createTextContent(text, autoMarkdown))
|
||||||
val document = parser.parse(text)
|
|
||||||
val renderer = HtmlRenderer.builder().build()
|
|
||||||
val htmlText = renderer.render(document)
|
|
||||||
if (isFormattedTextPertinent(text, htmlText)) { //FIXME
|
|
||||||
return createFormattedTextEvent(roomId, text, htmlText)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
val content = MessageTextContent(type = msgType, body = text)
|
val content = MessageTextContent(type = msgType, body = text)
|
||||||
return createEvent(roomId, content)
|
return createEvent(roomId, content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createTextContent(text: String, autoMarkdown: Boolean): TextContent {
|
||||||
|
if (autoMarkdown) {
|
||||||
|
val document = parser.parse(text)
|
||||||
|
val htmlText = renderer.render(document)
|
||||||
|
|
||||||
|
if (isFormattedTextPertinent(text, htmlText)) {
|
||||||
|
return TextContent(text, htmlText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TextContent(text)
|
||||||
|
}
|
||||||
|
|
||||||
private fun isFormattedTextPertinent(text: String, htmlText: String?) =
|
private fun isFormattedTextPertinent(text: String, htmlText: String?) =
|
||||||
text != htmlText && htmlText != "<p>${text.trim()}</p>\n"
|
text != htmlText && htmlText != "<p>${text.trim()}</p>\n"
|
||||||
|
|
||||||
fun createFormattedTextEvent(roomId: String, text: String, formattedText: String): Event {
|
fun createFormattedTextEvent(roomId: String, textContent: TextContent): Event {
|
||||||
val content = MessageTextContent(
|
val content = MessageTextContent(
|
||||||
type = MessageType.MSGTYPE_TEXT,
|
type = MessageType.MSGTYPE_TEXT,
|
||||||
format = MessageType.FORMAT_MATRIX_HTML,
|
format = if (textContent.formattedText == null) MessageType.FORMAT_MATRIX_HTML else null,
|
||||||
body = text,
|
body = textContent.text,
|
||||||
formattedBody = formattedText
|
formattedBody = textContent.formattedText
|
||||||
)
|
)
|
||||||
return createEvent(roomId, content)
|
return createEvent(roomId, content)
|
||||||
}
|
}
|
||||||
|
@ -87,7 +98,7 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials
|
||||||
newBodyAutoMarkdown: Boolean,
|
newBodyAutoMarkdown: Boolean,
|
||||||
msgType: String,
|
msgType: String,
|
||||||
compatibilityText: String): Event {
|
compatibilityText: String): Event {
|
||||||
|
// TODO Format newBodyText
|
||||||
var newContent = MessageTextContent(
|
var newContent = MessageTextContent(
|
||||||
type = MessageType.MSGTYPE_TEXT,
|
type = MessageType.MSGTYPE_TEXT,
|
||||||
body = newBodyText
|
body = newBodyText
|
||||||
|
@ -202,7 +213,7 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials
|
||||||
type = MessageType.MSGTYPE_AUDIO,
|
type = MessageType.MSGTYPE_AUDIO,
|
||||||
body = attachment.name ?: "audio",
|
body = attachment.name ?: "audio",
|
||||||
audioInfo = AudioInfo(
|
audioInfo = AudioInfo(
|
||||||
mimeType = attachment.mimeType ?: "audio/mpeg",
|
mimeType = attachment.mimeType.takeIf { it.isNotBlank() } ?: "audio/mpeg",
|
||||||
size = attachment.size
|
size = attachment.size
|
||||||
),
|
),
|
||||||
url = attachment.path
|
url = attachment.path
|
||||||
|
@ -215,7 +226,7 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials
|
||||||
type = MessageType.MSGTYPE_FILE,
|
type = MessageType.MSGTYPE_FILE,
|
||||||
body = attachment.name ?: "file",
|
body = attachment.name ?: "file",
|
||||||
info = FileInfo(
|
info = FileInfo(
|
||||||
mimeType = attachment.mimeType ?: "application/octet-stream",
|
mimeType = attachment.mimeType.takeIf { it.isNotBlank() } ?: "application/octet-stream",
|
||||||
size = attachment.size
|
size = attachment.size
|
||||||
),
|
),
|
||||||
url = attachment.path
|
url = attachment.path
|
||||||
|
@ -244,7 +255,7 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials
|
||||||
return "$LOCAL_ID_PREFIX${UUID.randomUUID()}"
|
return "$LOCAL_ID_PREFIX${UUID.randomUUID()}"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createReplyTextEvent(roomId: String, eventReplied: Event, replyText: String): Event? {
|
fun createReplyTextEvent(roomId: String, eventReplied: Event, replyText: String, autoMarkdown: Boolean): Event? {
|
||||||
//Fallbacks and event representation
|
//Fallbacks and event representation
|
||||||
//TODO Add error/warning logs when any of this is null
|
//TODO Add error/warning logs when any of this is null
|
||||||
val permalink = PermalinkFactory.createPermalink(eventReplied) ?: return null
|
val permalink = PermalinkFactory.createPermalink(eventReplied) ?: return null
|
||||||
|
@ -266,7 +277,7 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials
|
||||||
userLink,
|
userLink,
|
||||||
userId,
|
userId,
|
||||||
body.takeFormatted(),
|
body.takeFormatted(),
|
||||||
replyText
|
createTextContent(replyText, autoMarkdown).takeFormatted()
|
||||||
)
|
)
|
||||||
//
|
//
|
||||||
// > <@alice:example.org> This is the original body
|
// > <@alice:example.org> This is the original body
|
||||||
|
@ -294,8 +305,7 @@ internal class LocalEchoEventFactory @Inject constructor(private val credentials
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a pair of <Plain Text, Formatted Text?> used for the fallback event representation
|
* Returns a TextContent used for the fallback event representation in a reply message.
|
||||||
* in a reply message.
|
|
||||||
*/
|
*/
|
||||||
private fun bodyForReply(content: MessageContent?): TextContent {
|
private fun bodyForReply(content: MessageContent?): TextContent {
|
||||||
when (content?.type) {
|
when (content?.type) {
|
||||||
|
|
|
@ -47,8 +47,6 @@ import im.vector.riotx.core.utils.LiveEvent
|
||||||
import im.vector.riotx.features.command.CommandParser
|
import im.vector.riotx.features.command.CommandParser
|
||||||
import im.vector.riotx.features.command.ParsedCommand
|
import im.vector.riotx.features.command.ParsedCommand
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineDisplayableEvents
|
import im.vector.riotx.features.home.room.detail.timeline.helper.TimelineDisplayableEvents
|
||||||
import io.reactivex.Observable
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
|
||||||
import io.reactivex.rxkotlin.subscribeBy
|
import io.reactivex.rxkotlin.subscribeBy
|
||||||
import org.commonmark.parser.Parser
|
import org.commonmark.parser.Parser
|
||||||
import org.commonmark.renderer.html.HtmlRenderer
|
import org.commonmark.renderer.html.HtmlRenderer
|
||||||
|
@ -272,7 +270,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
||||||
}
|
}
|
||||||
SendMode.REPLY -> {
|
SendMode.REPLY -> {
|
||||||
state.selectedEvent?.let {
|
state.selectedEvent?.let {
|
||||||
room.replyToMessage(it.root, action.text)
|
room.replyToMessage(it.root, action.text, action.autoMarkdown)
|
||||||
setState {
|
setState {
|
||||||
copy(
|
copy(
|
||||||
sendMode = SendMode.REGULAR,
|
sendMode = SendMode.REGULAR,
|
||||||
|
|
Loading…
Reference in a new issue