Timeline : introduce loadReplyDetails api
This commit is contained in:
parent
f821fa5862
commit
5724c62c67
5 changed files with 78 additions and 31 deletions
|
|
@ -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.poll.PollKind
|
||||||
import io.element.android.libraries.matrix.api.room.Mention
|
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.room.location.AssetType
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
@ -168,4 +169,6 @@ interface Timeline : AutoCloseable {
|
||||||
waveform: List<Float>,
|
waveform: List<Float>,
|
||||||
progressCallback: ProgressCallback?
|
progressCallback: ProgressCallback?
|
||||||
): Result<MediaUploadHandler>
|
): Result<MediaUploadHandler>
|
||||||
|
|
||||||
|
suspend fun loadReplyDetails(eventId: EventId): Result<InReplyTo>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.ReceiptType
|
||||||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
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.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.core.toProgressWatcher
|
||||||
import io.element.android.libraries.matrix.impl.media.MediaUploadHandlerImpl
|
import io.element.android.libraries.matrix.impl.media.MediaUploadHandlerImpl
|
||||||
import io.element.android.libraries.matrix.impl.media.map
|
import io.element.android.libraries.matrix.impl.media.map
|
||||||
|
|
@ -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.RoomContentForwarder
|
||||||
import io.element.android.libraries.matrix.impl.room.location.toInner
|
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.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.EventTimelineItemMapper
|
||||||
import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper
|
import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper
|
||||||
import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper
|
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
|
||||||
import io.element.android.libraries.matrix.impl.timeline.postprocessor.LoadingIndicatorsPostProcessor
|
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.RoomBeginningPostProcessor
|
||||||
import io.element.android.libraries.matrix.impl.timeline.postprocessor.TimelineEncryptedHistoryPostProcessor
|
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 io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||||
import kotlinx.coroutines.CompletableDeferred
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
|
@ -118,14 +119,14 @@ class RustTimeline(
|
||||||
private val loadingIndicatorsPostProcessor = LoadingIndicatorsPostProcessor(systemClock)
|
private val loadingIndicatorsPostProcessor = LoadingIndicatorsPostProcessor(systemClock)
|
||||||
private val lastForwardIndicatorsPostProcessor = LastForwardIndicatorsPostProcessor(isLive)
|
private val lastForwardIndicatorsPostProcessor = LastForwardIndicatorsPostProcessor(isLive)
|
||||||
|
|
||||||
|
private val timelineEventContentMapper = TimelineEventContentMapper()
|
||||||
|
private val inReplyToMapper = InReplyToMapper(timelineEventContentMapper)
|
||||||
private val timelineItemFactory = MatrixTimelineItemMapper(
|
private val timelineItemFactory = MatrixTimelineItemMapper(
|
||||||
fetchDetailsForEvent = this::fetchDetailsForEvent,
|
fetchDetailsForEvent = this::fetchDetailsForEvent,
|
||||||
roomCoroutineScope = roomCoroutineScope,
|
roomCoroutineScope = roomCoroutineScope,
|
||||||
virtualTimelineItemMapper = VirtualTimelineItemMapper(),
|
virtualTimelineItemMapper = VirtualTimelineItemMapper(),
|
||||||
eventTimelineItemMapper = EventTimelineItemMapper(
|
eventTimelineItemMapper = EventTimelineItemMapper(
|
||||||
contentMapper = TimelineEventContentMapper(
|
contentMapper = timelineEventContentMapper
|
||||||
eventMessageMapper = EventMessageMapper()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -580,4 +581,10 @@ class RustTimeline(
|
||||||
inner.fetchDetailsForEvent(eventId.value)
|
inner.fetchDetailsForEvent(eventId.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun loadReplyDetails(eventId: EventId): Result<InReplyTo> {
|
||||||
|
return runCatching {
|
||||||
|
inner.loadReplyDetails(eventId.value).use(inReplyToMapper::map)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
package io.element.android.libraries.matrix.impl.timeline.item.event
|
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.AudioMessageType
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType
|
import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType
|
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
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType
|
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.api.timeline.item.event.VoiceMessageType
|
||||||
import io.element.android.libraries.matrix.impl.media.map
|
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.Message
|
||||||
import org.matrix.rustcomponents.sdk.MessageType
|
import org.matrix.rustcomponents.sdk.MessageType
|
||||||
import org.matrix.rustcomponents.sdk.RepliedToEventDetails
|
|
||||||
import org.matrix.rustcomponents.sdk.use
|
import org.matrix.rustcomponents.sdk.use
|
||||||
import org.matrix.rustcomponents.sdk.FormattedBody as RustFormattedBody
|
import org.matrix.rustcomponents.sdk.FormattedBody as RustFormattedBody
|
||||||
import org.matrix.rustcomponents.sdk.MessageFormat as RustMessageFormat
|
import org.matrix.rustcomponents.sdk.MessageFormat as RustMessageFormat
|
||||||
import org.matrix.rustcomponents.sdk.MessageType as RustMessageType
|
import org.matrix.rustcomponents.sdk.MessageType as RustMessageType
|
||||||
|
|
||||||
class EventMessageMapper {
|
class EventMessageMapper {
|
||||||
private val timelineEventContentMapper by lazy { TimelineEventContentMapper() }
|
private val inReplyToMapper by lazy { InReplyToMapper(TimelineEventContentMapper()) }
|
||||||
|
|
||||||
fun map(message: Message): MessageContent = message.use {
|
fun map(message: Message): MessageContent = message.use {
|
||||||
val type = it.msgtype().use(this::mapMessageType)
|
val type = it.msgtype().use(this::mapMessageType)
|
||||||
val inReplyToEvent: InReplyTo? = it.inReplyTo()?.use { details ->
|
val inReplyToEvent: InReplyTo? = it.inReplyTo()?.use(inReplyToMapper::map)
|
||||||
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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MessageContent(
|
MessageContent(
|
||||||
body = it.body(),
|
body = it.body(),
|
||||||
inReplyTo = inReplyToEvent,
|
inReplyTo = inReplyToEvent,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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.MatrixTimelineItem
|
||||||
import io.element.android.libraries.matrix.api.timeline.ReceiptType
|
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.Timeline
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo
|
||||||
import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler
|
import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
|
|
@ -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
|
var closeCounter = 0
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue