Browse Source

Timeline : introduce loadReplyDetails api

pull/3099/head
ganfra 3 months ago
parent
commit
f24e87faf1
  1. 3
      libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt
  2. 15
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt
  3. 30
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt
  4. 54
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/reply/InReplyToMapper.kt
  5. 7
      libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt

3
libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/Timeline.kt

@ -28,6 +28,7 @@ import io.element.android.libraries.matrix.api.media.VideoInfo @@ -28,6 +28,7 @@ import io.element.android.libraries.matrix.api.media.VideoInfo
import io.element.android.libraries.matrix.api.poll.PollKind
import io.element.android.libraries.matrix.api.room.Mention
import io.element.android.libraries.matrix.api.room.location.AssetType
import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import java.io.File
@ -168,4 +169,6 @@ interface Timeline : AutoCloseable { @@ -168,4 +169,6 @@ interface Timeline : AutoCloseable {
waveform: List<Float>,
progressCallback: ProgressCallback?
): Result<MediaUploadHandler>
suspend fun loadReplyDetails(eventId: EventId): Result<InReplyTo>
}

15
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt

@ -33,6 +33,7 @@ import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem @@ -33,6 +33,7 @@ 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 io.element.android.libraries.matrix.api.timeline.TimelineException
import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo
import io.element.android.libraries.matrix.impl.core.toProgressWatcher
import io.element.android.libraries.matrix.impl.media.MediaUploadHandlerImpl
import io.element.android.libraries.matrix.impl.media.map
@ -41,7 +42,6 @@ import io.element.android.libraries.matrix.impl.poll.toInner @@ -41,7 +42,6 @@ import io.element.android.libraries.matrix.impl.poll.toInner
import io.element.android.libraries.matrix.impl.room.RoomContentForwarder
import io.element.android.libraries.matrix.impl.room.location.toInner
import io.element.android.libraries.matrix.impl.room.map
import io.element.android.libraries.matrix.impl.timeline.item.event.EventMessageMapper
import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper
import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper
import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper
@ -49,6 +49,7 @@ import io.element.android.libraries.matrix.impl.timeline.postprocessor.LastForwa @@ -49,6 +49,7 @@ import io.element.android.libraries.matrix.impl.timeline.postprocessor.LastForwa
import io.element.android.libraries.matrix.impl.timeline.postprocessor.LoadingIndicatorsPostProcessor
import io.element.android.libraries.matrix.impl.timeline.postprocessor.RoomBeginningPostProcessor
import io.element.android.libraries.matrix.impl.timeline.postprocessor.TimelineEncryptedHistoryPostProcessor
import io.element.android.libraries.matrix.impl.timeline.reply.InReplyToMapper
import io.element.android.services.toolbox.api.systemclock.SystemClock
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineDispatcher
@ -118,14 +119,14 @@ class RustTimeline( @@ -118,14 +119,14 @@ class RustTimeline(
private val loadingIndicatorsPostProcessor = LoadingIndicatorsPostProcessor(systemClock)
private val lastForwardIndicatorsPostProcessor = LastForwardIndicatorsPostProcessor(isLive)
private val timelineEventContentMapper = TimelineEventContentMapper()
private val inReplyToMapper = InReplyToMapper(timelineEventContentMapper)
private val timelineItemFactory = MatrixTimelineItemMapper(
fetchDetailsForEvent = this::fetchDetailsForEvent,
roomCoroutineScope = roomCoroutineScope,
virtualTimelineItemMapper = VirtualTimelineItemMapper(),
eventTimelineItemMapper = EventTimelineItemMapper(
contentMapper = TimelineEventContentMapper(
eventMessageMapper = EventMessageMapper()
)
contentMapper = timelineEventContentMapper
)
)
@ -580,4 +581,10 @@ class RustTimeline( @@ -580,4 +581,10 @@ class RustTimeline(
inner.fetchDetailsForEvent(eventId.value)
}
}
override suspend fun loadReplyDetails(eventId: EventId): Result<InReplyTo> {
return runCatching {
inner.loadReplyDetails(eventId.value).use(inReplyToMapper::map)
}
}
}

30
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventMessageMapper.kt

@ -16,8 +16,6 @@ @@ -16,8 +16,6 @@
package io.element.android.libraries.matrix.impl.timeline.item.event
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType
@ -33,42 +31,20 @@ import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageTy @@ -33,42 +31,20 @@ import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageTy
import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.VoiceMessageType
import io.element.android.libraries.matrix.impl.media.map
import io.element.android.libraries.matrix.impl.timeline.reply.InReplyToMapper
import org.matrix.rustcomponents.sdk.Message
import org.matrix.rustcomponents.sdk.MessageType
import org.matrix.rustcomponents.sdk.RepliedToEventDetails
import org.matrix.rustcomponents.sdk.use
import org.matrix.rustcomponents.sdk.FormattedBody as RustFormattedBody
import org.matrix.rustcomponents.sdk.MessageFormat as RustMessageFormat
import org.matrix.rustcomponents.sdk.MessageType as RustMessageType
class EventMessageMapper {
private val timelineEventContentMapper by lazy { TimelineEventContentMapper() }
private val inReplyToMapper by lazy { InReplyToMapper(TimelineEventContentMapper()) }
fun map(message: Message): MessageContent = message.use {
val type = it.msgtype().use(this::mapMessageType)
val inReplyToEvent: InReplyTo? = it.inReplyTo()?.use { details ->
val inReplyToId = EventId(details.eventId)
when (val event = details.event) {
is RepliedToEventDetails.Ready -> {
InReplyTo.Ready(
eventId = inReplyToId,
content = timelineEventContentMapper.map(event.content),
senderId = UserId(event.sender),
senderProfile = event.senderProfile.map(),
)
}
is RepliedToEventDetails.Error -> InReplyTo.Error(
eventId = inReplyToId,
message = event.message,
)
RepliedToEventDetails.Pending -> InReplyTo.Pending(
eventId = inReplyToId,
)
is RepliedToEventDetails.Unavailable -> InReplyTo.NotLoaded(
eventId = inReplyToId
)
}
}
val inReplyToEvent: InReplyTo? = it.inReplyTo()?.use(inReplyToMapper::map)
MessageContent(
body = it.body(),
inReplyTo = inReplyToEvent,

54
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/reply/InReplyToMapper.kt

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.matrix.impl.timeline.reply
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo
import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper
import io.element.android.libraries.matrix.impl.timeline.item.event.map
import org.matrix.rustcomponents.sdk.InReplyToDetails
import org.matrix.rustcomponents.sdk.RepliedToEventDetails
class InReplyToMapper(
private val timelineEventContentMapper: TimelineEventContentMapper,
) {
fun map(inReplyToDetails: InReplyToDetails): InReplyTo {
val inReplyToId = EventId(inReplyToDetails.eventId)
return when (val event = inReplyToDetails.event) {
is RepliedToEventDetails.Ready -> {
InReplyTo.Ready(
eventId = inReplyToId,
content = timelineEventContentMapper.map(event.content),
senderId = UserId(event.sender),
senderProfile = event.senderProfile.map(),
)
}
is RepliedToEventDetails.Error -> InReplyTo.Error(
eventId = inReplyToId,
message = event.message,
)
RepliedToEventDetails.Pending -> InReplyTo.Pending(
eventId = inReplyToId,
)
is RepliedToEventDetails.Unavailable -> InReplyTo.NotLoaded(
eventId = inReplyToId
)
}
}
}

7
libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeTimeline.kt

@ -31,6 +31,7 @@ import io.element.android.libraries.matrix.api.room.location.AssetType @@ -31,6 +31,7 @@ import io.element.android.libraries.matrix.api.room.location.AssetType
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 io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo
import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
@ -370,6 +371,12 @@ class FakeTimeline( @@ -370,6 +371,12 @@ class FakeTimeline(
}
}
var loadReplyDetailsLambda: (eventId: EventId) -> Result<InReplyTo> = {
Result.success(InReplyTo.NotLoaded(it))
}
override suspend fun loadReplyDetails(eventId: EventId) = loadReplyDetailsLambda(eventId)
var closeCounter = 0
private set

Loading…
Cancel
Save