When thread disabled add thread replies within threads ( to the users with threads enabled )

This commit is contained in:
ariskotsomitopoulos 2022-01-27 13:49:03 +02:00
parent 358a7d0ec4
commit f53b711e0d
6 changed files with 45 additions and 10 deletions

View file

@ -109,10 +109,15 @@ interface RelationService {
* @param eventReplied the event referenced by the reply
* @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
* @param showInThread If true, relation will be added to the reply in order to be visible from within threads
* @param rootThreadEventId If show in thread is true then we need the rootThreadEventId to generate the relation
*/
fun replyToMessage(eventReplied: TimelineEvent,
replyText: CharSequence,
autoMarkdown: Boolean = false): Cancelable?
autoMarkdown: Boolean = false,
showInThread: Boolean = false,
rootThreadEventId: String? = null
): Cancelable?
/**
* Get the current EventAnnotationsSummary

View file

@ -132,6 +132,9 @@ internal fun TimelineEventEntity.Companion.findAllThreadsForRoomId(realm: Realm,
.equalTo(TimelineEventEntityFields.ROOT.IS_ROOT_THREAD, true)
.sort("${TimelineEventEntityFields.ROOT.THREAD_SUMMARY_LATEST_MESSAGE}.${TimelineEventEntityFields.ROOT.ORIGIN_SERVER_TS}", Sort.DESCENDING)
/**
* Map each timelineEvent with the equivalent decrypted text edition/replacement for root threads
*/
internal fun List<TimelineEvent>.mapEventsWithEdition(realm: Realm, roomId: String): List<TimelineEvent> =
this.map {
EventAnnotationsSummaryEntity

View file

@ -137,12 +137,20 @@ internal class DefaultRelationService @AssistedInject constructor(
return fetchEditHistoryTask.execute(FetchEditHistoryTask.Params(roomId, eventId))
}
override fun replyToMessage(eventReplied: TimelineEvent, replyText: CharSequence, autoMarkdown: Boolean): Cancelable? {
override fun replyToMessage(
eventReplied: TimelineEvent,
replyText: CharSequence,
autoMarkdown: Boolean,
showInThread: Boolean,
rootThreadEventId: String?
): Cancelable? {
val event = eventFactory.createReplyTextEvent(
roomId = roomId,
eventReplied = eventReplied,
replyText = replyText,
autoMarkdown = autoMarkdown)
autoMarkdown = autoMarkdown,
rootThreadEventId = rootThreadEventId,
showInThread = showInThread)
?.also { saveLocalEcho(it) }
?: return null
@ -182,7 +190,9 @@ internal class DefaultRelationService @AssistedInject constructor(
eventReplied = eventReplied,
replyText = replyInThreadText,
autoMarkdown = autoMarkdown,
rootThreadEventId = rootThreadEventId)
rootThreadEventId = rootThreadEventId,
showInThread = false
)
?.also {
saveLocalEcho(it)
}

View file

@ -71,7 +71,9 @@ internal class EventEditor @Inject constructor(private val eventSenderProcessor:
roomId = roomId,
eventReplied = originalTimelineEvent,
replyText = newBodyText,
autoMarkdown = false)?.copy(
autoMarkdown = false,
showInThread = false
)?.copy(
eventId = replyToEdit.eventId
) ?: return NoOpCancellable
updateFailedEchoWithEvent(roomId, replyToEdit.eventId, editedEvent)

View file

@ -469,7 +469,8 @@ internal class LocalEchoEventFactory @Inject constructor(
eventReplied: TimelineEvent,
replyText: CharSequence,
autoMarkdown: Boolean,
rootThreadEventId: String? = null): Event? {
rootThreadEventId: String? = null,
showInThread: Boolean): Event? {
// Fallbacks and event representation
// TODO Add error/warning logs when any of this is null
val permalink = permalinkFactory.createPermalink(eventReplied.root, false) ?: return null
@ -500,7 +501,10 @@ internal class LocalEchoEventFactory @Inject constructor(
format = MessageFormat.FORMAT_MATRIX_HTML,
body = replyFallback,
formattedBody = replyFormatted,
relatesTo = generateReplyRelationContent(eventId = eventId, rootThreadEventId = rootThreadEventId))
relatesTo = generateReplyRelationContent(
eventId = eventId,
rootThreadEventId = rootThreadEventId,
showAsReply = showInThread ))
return createMessageEvent(roomId, content)
}
@ -516,12 +520,12 @@ internal class LocalEchoEventFactory @Inject constructor(
* }
* }
*/
private fun generateReplyRelationContent(eventId: String, rootThreadEventId: String? = null): RelationDefaultContent =
private fun generateReplyRelationContent(eventId: String, rootThreadEventId: String? = null, showAsReply: Boolean): RelationDefaultContent =
rootThreadEventId?.let {
RelationDefaultContent(
type = RelationType.IO_THREAD,
eventId = it,
inReplyTo = ReplyToContent(eventId = eventId, renderIn = arrayListOf("m.thread")))
inReplyTo = ReplyToContent(eventId = eventId, renderIn = if (showAsReply) arrayListOf("m.thread") else null))
} ?: RelationDefaultContent(null, null, ReplyToContent(eventId = eventId))
private fun buildFormattedReply(permalink: String, userLink: String, userId: String, bodyFormatted: String, newBodyFormatted: String): String {

View file

@ -26,6 +26,7 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.resources.UserPreferencesProvider
import im.vector.app.features.attachments.toContentAttachmentData
import im.vector.app.features.command.CommandParser
import im.vector.app.features.command.ParsedCommand
@ -44,6 +45,8 @@ import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.getRootThreadEventId
import org.matrix.android.sdk.api.session.events.model.isThread
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
@ -495,13 +498,21 @@ class MessageComposerViewModel @AssistedInject constructor(
}
is SendMode.Reply -> {
val timelineEvent = state.sendMode.timelineEvent
val showInThread = state.sendMode.timelineEvent.root.isThread() && state.rootThreadEventId == null
val rootThreadEventId = if(showInThread) timelineEvent.root.getRootThreadEventId() else null
state.rootThreadEventId?.let {
room.replyInThread(
rootThreadEventId = it,
replyInThreadText = action.text.toString(),
autoMarkdown = action.autoMarkdown,
eventReplied = timelineEvent)
} ?: room.replyToMessage(timelineEvent, action.text.toString(), action.autoMarkdown)
} ?: room.replyToMessage(
eventReplied = timelineEvent,
replyText = action.text.toString(),
autoMarkdown = action.autoMarkdown,
showInThread = showInThread,
rootThreadEventId = rootThreadEventId
)
_viewEvents.post(MessageComposerViewEvents.MessageSent)
popDraft()