diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt index 88a90f6c7d..40d62313ec 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt @@ -87,6 +87,7 @@ import io.element.android.libraries.matrix.api.room.alias.matches import io.element.android.libraries.matrix.api.room.joinedRoomMembers import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.api.timeline.TimelineProvider import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.ui.messages.RoomMemberProfilesCache import io.element.android.libraries.matrix.ui.messages.RoomNamesCache @@ -104,6 +105,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.withContext +import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize import kotlin.time.Duration.Companion.milliseconds @@ -180,7 +182,8 @@ class MessagesFlowNode( @Parcelize data class ForwardEvent( val eventId: EventId, - val fromPinnedEvents: Boolean, + @IgnoredOnParcel + val timelineProvider: TimelineProvider? = null, ) : NavTarget @Parcelize @@ -303,8 +306,8 @@ class MessagesFlowNode( backstack.push(NavTarget.EventDebugInfo(eventId, debugInfo)) } - override fun forwardEvent(eventId: EventId) { - backstack.push(NavTarget.ForwardEvent(eventId, fromPinnedEvents = false)) + override fun forwardEvent(eventId: EventId, timelineProvider: TimelineProvider) { + backstack.push(NavTarget.ForwardEvent(eventId, timelineProvider)) } override fun navigateToReportMessage(eventId: EventId, senderId: UserId) { @@ -459,11 +462,8 @@ class MessagesFlowNode( createNode(buildContext, listOf(inputs)) } is NavTarget.ForwardEvent -> { - val timelineProvider = if (navTarget.fromPinnedEvents) { - pinnedEventsTimelineProvider - } else { - timelineController - } + // If no timeline provider is received, assume the live timeline should be used + val timelineProvider = navTarget.timelineProvider ?: timelineController val params = ForwardEntryPoint.Params(navTarget.eventId, timelineProvider) val callback = object : ForwardEntryPoint.Callback { override fun onDone(roomIds: List) { @@ -550,8 +550,8 @@ class MessagesFlowNode( backstack.push(NavTarget.EventDebugInfo(eventId, debugInfo)) } - override fun handleForwardEventClick(eventId: EventId) { - backstack.push(NavTarget.ForwardEvent(eventId = eventId, fromPinnedEvents = true)) + override fun handleForwardEventClick(eventId: EventId, timelineProvider: TimelineProvider) { + backstack.push(NavTarget.ForwardEvent(eventId = eventId, timelineProvider = timelineProvider)) } override fun navigateToThread(threadRootId: ThreadId) { @@ -617,8 +617,8 @@ class MessagesFlowNode( backstack.push(NavTarget.EventDebugInfo(eventId, debugInfo)) } - override fun handleForwardEventClick(eventId: EventId) { - backstack.push(NavTarget.ForwardEvent(eventId, fromPinnedEvents = false)) + override fun handleForwardEventClick(eventId: EventId, timelineProvider: TimelineProvider) { + backstack.push(NavTarget.ForwardEvent(eventId, timelineProvider)) } override fun navigateToReportMessage(eventId: EventId, senderId: UserId) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt index 6113b68aab..424d8bcd21 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt @@ -13,12 +13,13 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId 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.timeline.TimelineProvider import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import kotlinx.collections.immutable.ImmutableList interface MessagesNavigator { fun navigateToEventDebugInfo(eventId: EventId?, debugInfo: TimelineItemDebugInfo) - fun forwardEvent(eventId: EventId) + fun forwardEvent(eventId: EventId, timelineProvider: TimelineProvider) fun navigateToReportMessage(eventId: EventId, senderId: UserId) fun navigateToEditPoll(eventId: EventId) fun navigateToPreviewAttachments(attachments: ImmutableList, inReplyToEventId: EventId?) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt index e0213f2fb5..62830ef1ba 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt @@ -68,6 +68,7 @@ import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.alias.matches import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.api.timeline.TimelineProvider import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.ui.media.contentvalidation.EventContentValidationCache import io.element.android.libraries.matrix.ui.media.contentvalidation.LocalEventContentValidationState @@ -137,7 +138,7 @@ class MessagesNode( fun navigateToRoomMemberDetails(userId: UserId) fun handlePermalinkClick(data: PermalinkData) fun navigateToEventDebugInfo(eventId: EventId?, debugInfo: TimelineItemDebugInfo) - fun forwardEvent(eventId: EventId) + fun forwardEvent(eventId: EventId, timelineProvider: TimelineProvider) fun navigateToReportMessage(eventId: EventId, senderId: UserId) fun navigateToSendLocation() fun navigateToCreatePoll() @@ -220,8 +221,8 @@ class MessagesNode( callback.navigateToEventDebugInfo(eventId, debugInfo) } - override fun forwardEvent(eventId: EventId) { - callback.forwardEvent(eventId) + override fun forwardEvent(eventId: EventId, timelineProvider: TimelineProvider) { + callback.forwardEvent(eventId, timelineProvider) } override fun navigateToReportMessage(eventId: EventId, senderId: UserId) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 812ec704f0..92574c7c1a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -615,7 +615,7 @@ class MessagesPresenter( private fun handleForwardAction(event: TimelineItem.Event) { if (event.eventId == null) return - navigator.forwardEvent(event.eventId) + navigator.forwardEvent(eventId = event.eventId, timelineProvider = timelineController) } private fun handleReportAction(event: TimelineItem.Event) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNavigator.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNavigator.kt index 9633802f77..02c2bf7fa9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNavigator.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNavigator.kt @@ -10,11 +10,12 @@ package io.element.android.features.messages.impl.pinned.list 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.timeline.TimelineProvider import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo interface PinnedMessagesListNavigator { fun viewInTimeline(eventId: EventId) fun navigateToEventDebugInfo(eventId: EventId?, debugInfo: TimelineItemDebugInfo) - fun forwardEvent(eventId: EventId) + fun forwardEvent(eventId: EventId, timelineProvider: TimelineProvider) fun navigateToThread(threadRootId: ThreadId) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt index 36ae68de9b..5c6980c8bb 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListNode.kt @@ -37,6 +37,7 @@ import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.permalink.PermalinkData import io.element.android.libraries.matrix.api.permalink.PermalinkParser import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.api.timeline.TimelineProvider import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.utils.a11y.hasExternalKeyboard @@ -60,7 +61,7 @@ class PinnedMessagesListNode( fun viewInTimeline(eventId: EventId) fun handlePermalinkClick(data: PermalinkData.RoomLink) fun navigateToEventDebugInfo(eventId: EventId?, debugInfo: TimelineItemDebugInfo) - fun handleForwardEventClick(eventId: EventId) + fun handleForwardEventClick(eventId: EventId, timelineProvider: TimelineProvider) fun navigateToThread(threadRootId: ThreadId) } @@ -98,8 +99,8 @@ class PinnedMessagesListNode( callback.navigateToEventDebugInfo(eventId, debugInfo) } - override fun forwardEvent(eventId: EventId) { - callback.handleForwardEventClick(eventId) + override fun forwardEvent(eventId: EventId, timelineProvider: TimelineProvider) { + callback.handleForwardEventClick(eventId, timelineProvider) } override fun navigateToThread(threadRootId: ThreadId) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt index 8983342cd7..2ee4705838 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt @@ -181,7 +181,7 @@ class PinnedMessagesListPresenter( } TimelineItemAction.Forward -> { targetEvent.eventId?.let { eventId -> - navigator.forwardEvent(eventId) + navigator.forwardEvent(eventId, timelineProvider) } } TimelineItemAction.Unpin -> handleUnpinAction(targetEvent) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt index b5542ec4be..34f2b1fc74 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt @@ -70,6 +70,7 @@ import io.element.android.libraries.matrix.api.room.CreateTimelineParams import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.alias.matches import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.api.timeline.TimelineProvider import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.ui.model.getBestName import io.element.android.libraries.ui.utils.a11y.hasExternalKeyboard @@ -142,7 +143,7 @@ class ThreadedMessagesNode( fun navigateToRoomMemberDetails(userId: UserId) fun handlePermalinkClick(data: PermalinkData) fun navigateToEventDebugInfo(eventId: EventId?, debugInfo: TimelineItemDebugInfo) - fun handleForwardEventClick(eventId: EventId) + fun handleForwardEventClick(eventId: EventId, timelineProvider: TimelineProvider) fun navigateToReportMessage(eventId: EventId, senderId: UserId) fun navigateToSendLocation() fun navigateToCreatePoll() @@ -226,8 +227,8 @@ class ThreadedMessagesNode( callback.navigateToEventDebugInfo(eventId, debugInfo) } - override fun forwardEvent(eventId: EventId) { - callback.handleForwardEventClick(eventId) + override fun forwardEvent(eventId: EventId, timelineProvider: TimelineProvider) { + callback.handleForwardEventClick(eventId, timelineProvider) } override fun navigateToReportMessage(eventId: EventId, senderId: UserId) { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt index 68f9a8d17a..31f6e4604e 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt @@ -13,13 +13,14 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId 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.timeline.TimelineProvider import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.tests.testutils.lambda.lambdaError import kotlinx.collections.immutable.ImmutableList class FakeMessagesNavigator( private val onShowEventDebugInfoClickLambda: (eventId: EventId?, debugInfo: TimelineItemDebugInfo) -> Unit = { _, _ -> lambdaError() }, - private val onForwardEventClickLambda: (eventId: EventId) -> Unit = { _ -> lambdaError() }, + private val onForwardEventClickLambda: (eventId: EventId, timelineProvider: TimelineProvider) -> Unit = { _, _ -> lambdaError() }, private val onReportContentClickLambda: (eventId: EventId, senderId: UserId) -> Unit = { _, _ -> lambdaError() }, private val onEditPollClickLambda: (eventId: EventId) -> Unit = { _ -> lambdaError() }, private val onPreviewAttachmentLambda: (attachments: ImmutableList, inReplyToEventId: EventId?) -> Unit = { _, _ -> lambdaError() }, @@ -34,8 +35,8 @@ class FakeMessagesNavigator( onShowEventDebugInfoClickLambda(eventId, debugInfo) } - override fun forwardEvent(eventId: EventId) { - onForwardEventClickLambda(eventId) + override fun forwardEvent(eventId: EventId, timelineProvider: TimelineProvider) { + onForwardEventClickLambda(eventId, timelineProvider) } override fun navigateToReportMessage(eventId: EventId, senderId: UserId) { diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt index bddca0178b..ee87d743db 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt @@ -71,6 +71,7 @@ import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.api.timeline.TimelineProvider import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState @@ -109,6 +110,7 @@ import io.element.android.tests.testutils.FakeLifecycleOwner import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.consumeItemsUntilPredicate import io.element.android.tests.testutils.consumeItemsUntilTimeout +import io.element.android.tests.testutils.lambda.any import io.element.android.tests.testutils.lambda.assert import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder @@ -288,7 +290,7 @@ class MessagesPresenterTest { @Test fun `present - handle action forward`() = runTest { - val onForwardEventClickLambda = lambdaRecorder { } + val onForwardEventClickLambda = lambdaRecorder { _, _ -> } val navigator = FakeMessagesNavigator( onForwardEventClickLambda = onForwardEventClickLambda, ) @@ -297,7 +299,7 @@ class MessagesPresenterTest { val initialState = awaitItem() initialState.eventSink(MessagesEvent.HandleAction(TimelineItemAction.Forward, aMessageEvent())) assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None) - onForwardEventClickLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID)) + onForwardEventClickLambda.assertions().isCalledOnce().with(value(AN_EVENT_ID), any()) } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/FakePinnedMessagesListNavigator.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/FakePinnedMessagesListNavigator.kt index 69eaae3699..377ed0dc52 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/FakePinnedMessagesListNavigator.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/FakePinnedMessagesListNavigator.kt @@ -10,6 +10,7 @@ package io.element.android.features.messages.impl.pinned.list 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.timeline.TimelineProvider import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo class FakePinnedMessagesListNavigator : PinnedMessagesListNavigator { @@ -23,9 +24,9 @@ class FakePinnedMessagesListNavigator : PinnedMessagesListNavigator { onShowEventDebugInfoClickLambda?.invoke(eventId, debugInfo) } - var onForwardEventClickLambda: ((EventId) -> Unit)? = null - override fun forwardEvent(eventId: EventId) { - onForwardEventClickLambda?.invoke(eventId) + var onForwardEventClickLambda: ((EventId, TimelineProvider) -> Unit)? = null + override fun forwardEvent(eventId: EventId, timelineProvider: TimelineProvider) { + onForwardEventClickLambda?.invoke(eventId, timelineProvider) } var onOpenThreadLambda: ((ThreadId) -> Unit)? = null diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt index cafb16c41f..fc00b2f12b 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenterTest.kt @@ -27,6 +27,7 @@ import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.sync.SyncService import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.api.timeline.TimelineProvider import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent import io.element.android.libraries.matrix.api.timeline.item.event.UnknownContent @@ -47,6 +48,7 @@ import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.consumeItemsUntilPredicate +import io.element.android.tests.testutils.lambda.any import io.element.android.tests.testutils.lambda.assert import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value @@ -329,7 +331,7 @@ class PinnedMessagesListPresenterTest { @Test fun `present - forward event`() = runTest { - val onForwardEventClickLambda = lambdaRecorder { _: EventId -> } + val onForwardEventClickLambda = lambdaRecorder { _: EventId, _: TimelineProvider -> } val navigator = FakePinnedMessagesListNavigator().apply { this.onForwardEventClickLambda = onForwardEventClickLambda } @@ -352,7 +354,7 @@ class PinnedMessagesListPresenterTest { cancelAndIgnoreRemainingEvents() assert(onForwardEventClickLambda) .isCalledOnce() - .with(value(AN_EVENT_ID)) + .with(value(AN_EVENT_ID), any()) } }