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 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 * @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, fun replyToMessage(eventReplied: TimelineEvent,
replyText: CharSequence, replyText: CharSequence,
autoMarkdown: Boolean = false): Cancelable? autoMarkdown: Boolean = false,
showInThread: Boolean = false,
rootThreadEventId: String? = null
): Cancelable?
/** /**
* Get the current EventAnnotationsSummary * Get the current EventAnnotationsSummary

View file

@ -132,6 +132,9 @@ internal fun TimelineEventEntity.Companion.findAllThreadsForRoomId(realm: Realm,
.equalTo(TimelineEventEntityFields.ROOT.IS_ROOT_THREAD, true) .equalTo(TimelineEventEntityFields.ROOT.IS_ROOT_THREAD, true)
.sort("${TimelineEventEntityFields.ROOT.THREAD_SUMMARY_LATEST_MESSAGE}.${TimelineEventEntityFields.ROOT.ORIGIN_SERVER_TS}", Sort.DESCENDING) .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> = internal fun List<TimelineEvent>.mapEventsWithEdition(realm: Realm, roomId: String): List<TimelineEvent> =
this.map { this.map {
EventAnnotationsSummaryEntity EventAnnotationsSummaryEntity

View file

@ -137,12 +137,20 @@ internal class DefaultRelationService @AssistedInject constructor(
return fetchEditHistoryTask.execute(FetchEditHistoryTask.Params(roomId, eventId)) 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( val event = eventFactory.createReplyTextEvent(
roomId = roomId, roomId = roomId,
eventReplied = eventReplied, eventReplied = eventReplied,
replyText = replyText, replyText = replyText,
autoMarkdown = autoMarkdown) autoMarkdown = autoMarkdown,
rootThreadEventId = rootThreadEventId,
showInThread = showInThread)
?.also { saveLocalEcho(it) } ?.also { saveLocalEcho(it) }
?: return null ?: return null
@ -182,7 +190,9 @@ internal class DefaultRelationService @AssistedInject constructor(
eventReplied = eventReplied, eventReplied = eventReplied,
replyText = replyInThreadText, replyText = replyInThreadText,
autoMarkdown = autoMarkdown, autoMarkdown = autoMarkdown,
rootThreadEventId = rootThreadEventId) rootThreadEventId = rootThreadEventId,
showInThread = false
)
?.also { ?.also {
saveLocalEcho(it) saveLocalEcho(it)
} }

View file

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

View file

@ -469,7 +469,8 @@ internal class LocalEchoEventFactory @Inject constructor(
eventReplied: TimelineEvent, eventReplied: TimelineEvent,
replyText: CharSequence, replyText: CharSequence,
autoMarkdown: Boolean, autoMarkdown: Boolean,
rootThreadEventId: String? = null): Event? { rootThreadEventId: String? = null,
showInThread: 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.root, false) ?: return null val permalink = permalinkFactory.createPermalink(eventReplied.root, false) ?: return null
@ -500,7 +501,10 @@ internal class LocalEchoEventFactory @Inject constructor(
format = MessageFormat.FORMAT_MATRIX_HTML, format = MessageFormat.FORMAT_MATRIX_HTML,
body = replyFallback, body = replyFallback,
formattedBody = replyFormatted, formattedBody = replyFormatted,
relatesTo = generateReplyRelationContent(eventId = eventId, rootThreadEventId = rootThreadEventId)) relatesTo = generateReplyRelationContent(
eventId = eventId,
rootThreadEventId = rootThreadEventId,
showAsReply = showInThread ))
return createMessageEvent(roomId, content) 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 { rootThreadEventId?.let {
RelationDefaultContent( RelationDefaultContent(
type = RelationType.IO_THREAD, type = RelationType.IO_THREAD,
eventId = it, 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)) } ?: RelationDefaultContent(null, null, ReplyToContent(eventId = eventId))
private fun buildFormattedReply(permalink: String, userLink: String, userId: String, bodyFormatted: String, newBodyFormatted: String): String { 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.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider 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.attachments.toContentAttachmentData
import im.vector.app.features.command.CommandParser import im.vector.app.features.command.CommandParser
import im.vector.app.features.command.ParsedCommand 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.Session
import org.matrix.android.sdk.api.session.content.ContentAttachmentData 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.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.toContent
import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
@ -495,13 +498,21 @@ class MessageComposerViewModel @AssistedInject constructor(
} }
is SendMode.Reply -> { is SendMode.Reply -> {
val timelineEvent = state.sendMode.timelineEvent 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 { state.rootThreadEventId?.let {
room.replyInThread( room.replyInThread(
rootThreadEventId = it, rootThreadEventId = it,
replyInThreadText = action.text.toString(), replyInThreadText = action.text.toString(),
autoMarkdown = action.autoMarkdown, autoMarkdown = action.autoMarkdown,
eventReplied = timelineEvent) 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) _viewEvents.post(MessageComposerViewEvents.MessageSent)
popDraft() popDraft()