Timeline permalink : start updating tests

This commit is contained in:
ganfra 2024-04-24 21:33:20 +02:00
parent fed1733cb5
commit bf87b975fc
19 changed files with 410 additions and 295 deletions

View file

@ -288,7 +288,7 @@ class MessagesPresenter @AssistedInject constructor(
emoji: String,
eventId: EventId,
) = launch(dispatchers.io) {
timelineController.invokeOnTimeline {
timelineController.invokeOnCurrentTimeline {
toggleReaction(emoji, eventId)
.onFailure { Timber.e(it) }
}

View file

@ -30,6 +30,7 @@ import io.element.android.libraries.architecture.Presenter
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.room.MatrixRoom
import io.element.android.libraries.matrix.api.timeline.TimelineProvider
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.CoroutineScope
@ -37,8 +38,8 @@ import kotlinx.coroutines.launch
class ForwardMessagesPresenter @AssistedInject constructor(
@Assisted eventId: String,
private val room: MatrixRoom,
private val matrixCoroutineScope: CoroutineScope,
private val timelineProvider: TimelineProvider,
) : Presenter<ForwardMessagesState> {
private val eventId: EventId = EventId(eventId)
@ -79,7 +80,7 @@ class ForwardMessagesPresenter @AssistedInject constructor(
isForwardMessagesState: MutableState<AsyncData<ImmutableList<RoomId>>>,
) = launch {
isForwardMessagesState.value = AsyncData.Loading()
room.forwardEvent(eventId, roomIds).fold(
timelineProvider.getActiveTimeline().forwardEvent(eventId, roomIds).fold(
{ isForwardMessagesState.value = AsyncData.Success(roomIds) },
{ isForwardMessagesState.value = AsyncData.Failure(it) }
)

View file

@ -266,7 +266,7 @@ class MessageComposerPresenter @Inject constructor(
is MessageComposerMode.Quote -> null
}.let { relatedEventId ->
appCoroutineScope.launch {
timelineController.invokeOnTimeline {
timelineController.invokeOnCurrentTimeline {
enterSpecialMode(relatedEventId)
}
}
@ -390,14 +390,14 @@ class MessageComposerPresenter @Inject constructor(
is MessageComposerMode.Edit -> {
val eventId = capturedMode.eventId
val transactionId = capturedMode.transactionId
timelineController.invokeOnTimeline {
timelineController.invokeOnCurrentTimeline {
editMessage(eventId, transactionId, message.markdown, message.html, mentions)
}
}
is MessageComposerMode.Quote -> TODO()
is MessageComposerMode.Reply -> {
timelineController.invokeOnTimeline {
timelineController.invokeOnCurrentTimeline {
replyMessage(capturedMode.eventId, message.markdown, message.html, mentions)
}
}

View file

@ -16,9 +16,7 @@
package io.element.android.features.messages.impl.timeline
import androidx.compose.runtime.MutableState
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.matrix.api.core.EventId
@ -26,9 +24,7 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.timeline.LiveTimelineProvider
import io.element.android.libraries.matrix.api.timeline.TimelineProvider
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.ReceiptType
import io.element.android.libraries.matrix.api.timeline.Timeline
import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@ -65,7 +61,7 @@ class TimelineController @Inject constructor(
return detachedTimeline.map { !it.isPresent }
}
suspend fun invokeOnTimeline(block: suspend (Timeline.() -> Any)) {
suspend fun invokeOnCurrentTimeline(block: suspend (Timeline.() -> Any)) {
currentTimelineFlow().first().run {
block(this)
}
@ -124,37 +120,6 @@ class TimelineController @Inject constructor(
}
}
suspend fun sendReadReceiptIfNeeded(
firstVisibleIndex: Int,
timelineItems: ImmutableList<TimelineItem>,
lastReadReceiptId: MutableState<EventId?>,
readReceiptType: ReceiptType,
) {
// If we are at the bottom of timeline, we mark the room as read.
if (firstVisibleIndex == 0) {
room.markAsRead(receiptType = readReceiptType)
} else {
// Get last valid EventId seen by the user, as the first index might refer to a Virtual item
val eventId = getLastEventIdBeforeOrAt(firstVisibleIndex, timelineItems)
if (eventId != null && eventId != lastReadReceiptId.value) {
lastReadReceiptId.value = eventId
currentTimelineFlow()
.first()
.sendReadReceipt(eventId = eventId, receiptType = readReceiptType)
}
}
}
private fun getLastEventIdBeforeOrAt(index: Int, items: ImmutableList<TimelineItem>): EventId? {
for (i in index until items.count()) {
val item = items[i]
if (item is TimelineItem.Event) {
return item.eventId
}
}
return null
}
override suspend fun getActiveTimeline(): Timeline {
return currentTimelineFlow().first()
}

View file

@ -111,6 +111,7 @@ class TimelinePresenter @AssistedInject constructor(
if (event.firstIndex == 0) {
newEventState.value = NewEventState.None
}
println("## sendReadReceiptIfNeeded firstVisibleIndex: ${event.firstIndex}")
appScope.sendReadReceiptIfNeeded(
firstVisibleIndex = event.firstIndex,
timelineItems = timelineItems,
@ -256,7 +257,7 @@ class TimelinePresenter @AssistedInject constructor(
val eventId = getLastEventIdBeforeOrAt(firstVisibleIndex, timelineItems)
if (eventId != null && eventId != lastReadReceiptId.value) {
lastReadReceiptId.value = eventId
//timeline.sendReadReceipt(eventId = eventId, receiptType = readReceiptType)
room.liveTimeline.sendReadReceipt(eventId = eventId, receiptType = readReceiptType)
}
}
}

View file

@ -116,10 +116,6 @@ fun TimelineView(
// TODO implement this logic once we have support to 'jump to event X' in sliding sync
}
LaunchedEffect(key1 = state.timelineItems) {
Timber.d("TimelineView - timelineItem identifiers: ${state.timelineItems.joinToString(", ") { it.identifier() }}")
}
// Animate alpha when timeline is first displayed, to avoid flashes or glitching when viewing rooms
AnimatedVisibility(visible = true, enter = fadeIn()) {
Box(modifier) {

View file

@ -62,10 +62,6 @@ class TimelineItemsFactory @Inject constructor(
}
}
fun items(): StateFlow<ImmutableList<TimelineItem>> {
return timelineItems
}
@Composable
fun collectItemsAsState(): State<ImmutableList<TimelineItem>> {
return timelineItems.collectAsState()