Merge pull request #6984 from bxdxnn/fix/draft-threads

Fix message drafts not being saved in Threads
This commit is contained in:
Benoit Marty
2026-06-10 14:44:12 +02:00
committed by GitHub
5 changed files with 14 additions and 14 deletions
@@ -108,7 +108,7 @@ class MessagesNode(
private val timelineController = TimelineController(room, room.liveTimeline) private val timelineController = TimelineController(room, room.liveTimeline)
private val presenter = presenterFactory.create( private val presenter = presenterFactory.create(
navigator = this, navigator = this,
composerPresenter = messageComposerPresenterFactory.create(timelineController, this, isInThread = false), composerPresenter = messageComposerPresenterFactory.create(timelineController, this, threadRoot = null),
timelinePresenter = timelinePresenterFactory.create(timelineController = timelineController, this), timelinePresenter = timelinePresenterFactory.create(timelineController = timelineController, this),
actionListPresenter = actionListPresenterFactory.create( actionListPresenter = actionListPresenterFactory.create(
postProcessor = TimelineItemActionPostProcessor.Default, postProcessor = TimelineItemActionPostProcessor.Default,
@@ -49,6 +49,7 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatch
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.di.annotations.SessionCoroutineScope
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.ThreadId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder
import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.permalink.PermalinkParser
@@ -109,7 +110,7 @@ import io.element.android.libraries.core.mimetype.MimeTypes.Any as AnyMimeTypes
class MessageComposerPresenter( class MessageComposerPresenter(
@Assisted private val navigator: MessagesNavigator, @Assisted private val navigator: MessagesNavigator,
@Assisted private val timelineController: TimelineController, @Assisted private val timelineController: TimelineController,
@Assisted private val isInThread: Boolean, @Assisted private val threadRoot: ThreadId?,
@SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope,
private val room: JoinedRoom, private val room: JoinedRoom,
private val mediaPickerProvider: PickerProvider, private val mediaPickerProvider: PickerProvider,
@@ -138,10 +139,11 @@ class MessageComposerPresenter(
fun create( fun create(
timelineController: TimelineController, timelineController: TimelineController,
navigator: MessagesNavigator, navigator: MessagesNavigator,
isInThread: Boolean, threadRoot: ThreadId?,
): MessageComposerPresenter ): MessageComposerPresenter
} }
private val isInThread = threadRoot != null
private val mediaSender = mediaSenderFactory.create(timelineMode = timelineController.mainTimelineMode()) private val mediaSender = mediaSenderFactory.create(timelineMode = timelineController.mainTimelineMode())
private val cameraPermissionPresenter = permissionsPresenterFactory.create(Manifest.permission.CAMERA) private val cameraPermissionPresenter = permissionsPresenterFactory.create(Manifest.permission.CAMERA)
@@ -234,8 +236,7 @@ class MessageComposerPresenter(
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
val draft = draftService.loadDraft( val draft = draftService.loadDraft(
roomId = room.roomId, roomId = room.roomId,
// TODO support threads in composer threadRoot = threadRoot,
threadRoot = null,
isVolatile = false isVolatile = false
) )
if (draft != null) { if (draft != null) {
@@ -652,8 +653,7 @@ class MessageComposerPresenter(
roomId = room.roomId, roomId = room.roomId,
draft = draft, draft = draft,
isVolatile = isVolatile, isVolatile = isVolatile,
// TODO support threads in composer threadRoot = threadRoot,
threadRoot = null,
) )
} }
@@ -816,8 +816,7 @@ class MessageComposerPresenter(
// Use the volatile draft only when coming from edit mode otherwise. // Use the volatile draft only when coming from edit mode otherwise.
val draft = draftService.loadDraft( val draft = draftService.loadDraft(
roomId = room.roomId, roomId = room.roomId,
// TODO support threads in composer threadRoot = threadRoot,
threadRoot = null,
isVolatile = true isVolatile = true
).takeIf { fromEdit } ).takeIf { fromEdit }
if (draft != null) { if (draft != null) {
@@ -113,7 +113,7 @@ class ThreadedMessagesNode(
this.timelineController = timelineController this.timelineController = timelineController
return presenterFactory.create( return presenterFactory.create(
navigator = this, navigator = this,
composerPresenter = messageComposerPresenterFactory.create(timelineController, this, isInThread = true), composerPresenter = messageComposerPresenterFactory.create(timelineController, this, threadRoot = inputs.threadRootEventId),
timelinePresenter = timelinePresenterFactory.create(timelineController = timelineController, this), timelinePresenter = timelinePresenterFactory.create(timelineController = timelineController, this),
// TODO add special processor for threaded timeline // TODO add special processor for threaded timeline
actionListPresenter = actionListPresenterFactory.create( actionListPresenter = actionListPresenterFactory.create(
@@ -24,6 +24,7 @@ import io.element.android.features.messages.impl.utils.FakeMentionSpanFormatter
import io.element.android.features.messages.impl.utils.FakeTextPillificationHelper import io.element.android.features.messages.impl.utils.FakeTextPillificationHelper
import io.element.android.features.messages.impl.utils.TextPillificationHelper import io.element.android.features.messages.impl.utils.TextPillificationHelper
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.matrix.api.core.ThreadId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder
import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.permalink.PermalinkParser
@@ -271,12 +272,12 @@ class MessageComposerPresenterSlashCommandTest {
isRichTextEditorEnabled: Boolean = true, isRichTextEditorEnabled: Boolean = true,
draftService: ComposerDraftService = FakeComposerDraftService(), draftService: ComposerDraftService = FakeComposerDraftService(),
mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(),
isInThread: Boolean = false, threadRoot: ThreadId? = null,
slashCommandService: SlashCommandService = FakeSlashCommandService(), slashCommandService: SlashCommandService = FakeSlashCommandService(),
) = MessageComposerPresenter( ) = MessageComposerPresenter(
navigator = navigator, navigator = navigator,
sessionCoroutineScope = this, sessionCoroutineScope = this,
isInThread = isInThread, threadRoot = threadRoot,
room = room, room = room,
mediaPickerProvider = pickerProvider, mediaPickerProvider = pickerProvider,
sessionPreferencesStore = sessionPreferencesStore, sessionPreferencesStore = sessionPreferencesStore,
@@ -1534,12 +1534,12 @@ class MessageComposerPresenterTest {
isRichTextEditorEnabled: Boolean = true, isRichTextEditorEnabled: Boolean = true,
draftService: ComposerDraftService = FakeComposerDraftService(), draftService: ComposerDraftService = FakeComposerDraftService(),
mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(),
isInThread: Boolean = false, threadRoot: ThreadId? = null,
slashCommandService: SlashCommandService = FakeSlashCommandService(), slashCommandService: SlashCommandService = FakeSlashCommandService(),
) = MessageComposerPresenter( ) = MessageComposerPresenter(
navigator = navigator, navigator = navigator,
sessionCoroutineScope = this, sessionCoroutineScope = this,
isInThread = isInThread, threadRoot = threadRoot,
room = room, room = room,
mediaPickerProvider = pickerProvider, mediaPickerProvider = pickerProvider,
sessionPreferencesStore = sessionPreferencesStore, sessionPreferencesStore = sessionPreferencesStore,