[MatrixSDK] start mapping all the timeline objects
This commit is contained in:
parent
b1c116b883
commit
8ccd21d856
37 changed files with 1054 additions and 49 deletions
|
|
@ -47,7 +47,7 @@ class TimelineItemContentMessageFactory @Inject constructor() {
|
||||||
TimelineItemImageContent(
|
TimelineItemImageContent(
|
||||||
body = messageType.content.body,
|
body = messageType.content.body,
|
||||||
imageMeta = MediaResolver.Meta(
|
imageMeta = MediaResolver.Meta(
|
||||||
source = messageType.content.source,
|
url = messageType.content.source,
|
||||||
kind = MediaResolver.Kind.Content
|
kind = MediaResolver.Kind.Content
|
||||||
),
|
),
|
||||||
blurhash = messageType.content.info?.blurhash,
|
blurhash = messageType.content.info?.blurhash,
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,13 @@ package io.element.android.features.messages.impl.timeline.factories.virtual
|
||||||
import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemDaySeparatorModel
|
import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemDaySeparatorModel
|
||||||
import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemVirtualModel
|
import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemVirtualModel
|
||||||
import io.element.android.libraries.dateformatter.api.DaySeparatorFormatter
|
import io.element.android.libraries.dateformatter.api.DaySeparatorFormatter
|
||||||
import org.matrix.rustcomponents.sdk.VirtualTimelineItem
|
import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class TimelineItemDaySeparatorFactory @Inject constructor(private val daySeparatorFormatter: DaySeparatorFormatter) {
|
class TimelineItemDaySeparatorFactory @Inject constructor(private val daySeparatorFormatter: DaySeparatorFormatter) {
|
||||||
|
|
||||||
fun create(virtualItem: VirtualTimelineItem.DayDivider): TimelineItemVirtualModel {
|
fun create(virtualItem: VirtualTimelineItem.DayDivider): TimelineItemVirtualModel {
|
||||||
val formattedDate = daySeparatorFormatter.format(virtualItem.ts.toLong())
|
val formattedDate = daySeparatorFormatter.format(virtualItem.timestamp)
|
||||||
return TimelineItemDaySeparatorModel(
|
return TimelineItemDaySeparatorModel(
|
||||||
formattedDate = formattedDate
|
formattedDate = formattedDate
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import io.element.android.features.messages.impl.timeline.model.virtual.Timeline
|
||||||
import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemUnknownVirtualModel
|
import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemUnknownVirtualModel
|
||||||
import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemVirtualModel
|
import io.element.android.features.messages.impl.timeline.model.virtual.TimelineItemVirtualModel
|
||||||
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.item.virtual.VirtualTimelineItem
|
||||||
import org.matrix.rustcomponents.sdk.VirtualTimelineItem
|
import org.matrix.rustcomponents.sdk.VirtualTimelineItem
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -42,10 +43,10 @@ class TimelineItemVirtualFactory @Inject constructor(
|
||||||
|
|
||||||
private fun MatrixTimelineItem.Virtual.computeModel(index: Int): TimelineItemVirtualModel {
|
private fun MatrixTimelineItem.Virtual.computeModel(index: Int): TimelineItemVirtualModel {
|
||||||
return when (val inner = virtual) {
|
return when (val inner = virtual) {
|
||||||
is VirtualTimelineItem.DayDivider -> daySeparatorFactory.create(inner)
|
is io.element.android.libraries.matrix.api.timeline.item.virtual.TimelineItemVirtual.VirtualTimelineItem.DayDivider -> daySeparatorFactory.create(inner)
|
||||||
is VirtualTimelineItem.ReadMarker -> TimelineItemReadMarkerModel
|
is io.element.android.libraries.matrix.api.timeline.item.virtual.TimelineItemVirtual.VirtualTimelineItem.ReadMarker -> TimelineItemReadMarkerModel
|
||||||
is VirtualTimelineItem.LoadingIndicator -> TimelineItemLoadingModel
|
is io.element.android.libraries.matrix.api.timeline.item.virtual.TimelineItemVirtual.VirtualTimelineItem.LoadingIndicator -> TimelineItemLoadingModel
|
||||||
is VirtualTimelineItem.TimelineStart -> TimelineItemReadMarkerModel
|
is io.element.android.libraries.matrix.api.timeline.item.virtual.TimelineItemVirtual.VirtualTimelineItem.TimelineStart -> TimelineItemReadMarkerModel
|
||||||
else -> TimelineItemUnknownVirtualModel
|
else -> TimelineItemUnknownVirtualModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ open class TimelineItemImageContentProvider : PreviewParameterProvider<TimelineI
|
||||||
|
|
||||||
fun aTimelineItemImageContent() = TimelineItemImageContent(
|
fun aTimelineItemImageContent() = TimelineItemImageContent(
|
||||||
body = "a body",
|
body = "a body",
|
||||||
imageMeta = MediaResolver.Meta(source = null, kind = MediaResolver.Kind.Content),
|
imageMeta = MediaResolver.Meta(url = null, kind = MediaResolver.Kind.Content),
|
||||||
blurhash = null,
|
blurhash = null,
|
||||||
aspectRatio = 0.5f,
|
aspectRatio = 0.5f,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.api.media
|
||||||
|
|
||||||
|
data class AudioInfo(
|
||||||
|
val duration: Long?,
|
||||||
|
val size: Long?
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.api.media
|
||||||
|
|
||||||
|
data class FileInfo(
|
||||||
|
val mimetype: String?,
|
||||||
|
val size: Long?,
|
||||||
|
val thumbnailInfo: ThumbnailInfo?,
|
||||||
|
val thumbnailUrl: String?
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.api.media
|
||||||
|
|
||||||
|
data class ImageInfo(
|
||||||
|
val height: Long?,
|
||||||
|
val width: Long?,
|
||||||
|
val mimetype: String?,
|
||||||
|
val size: Long?,
|
||||||
|
val thumbnailInfo: ThumbnailInfo?,
|
||||||
|
val thumbnailUrl: String?,
|
||||||
|
val blurhash: String?
|
||||||
|
)
|
||||||
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
package io.element.android.libraries.matrix.api.media
|
package io.element.android.libraries.matrix.api.media
|
||||||
|
|
||||||
import org.matrix.rustcomponents.sdk.MediaSource
|
|
||||||
|
|
||||||
interface MediaResolver {
|
interface MediaResolver {
|
||||||
|
|
||||||
sealed interface Kind {
|
sealed interface Kind {
|
||||||
|
|
@ -29,11 +27,10 @@ interface MediaResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Meta(
|
data class Meta(
|
||||||
val source: MediaSource?,
|
val url: String?,
|
||||||
val kind: Kind
|
val kind: Kind
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun resolve(url: String?, kind: Kind): ByteArray?
|
suspend fun resolve(url: String?, kind: Kind): ByteArray?
|
||||||
|
|
||||||
suspend fun resolve(meta: Meta): ByteArray?
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.api.media
|
||||||
|
|
||||||
|
data class ThumbnailInfo(
|
||||||
|
val height: Long?,
|
||||||
|
val width: Long?,
|
||||||
|
val mimetype: String?,
|
||||||
|
val size: Long?
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.api.media
|
||||||
|
|
||||||
|
data class VideoInfo(
|
||||||
|
val duration: Long?,
|
||||||
|
val height: Long?,
|
||||||
|
val width: Long?,
|
||||||
|
val mimetype: String?,
|
||||||
|
val size: Long?,
|
||||||
|
val thumbnailInfo: ThumbnailInfo?,
|
||||||
|
val thumbnailUrl: String?,
|
||||||
|
val blurhash: String?
|
||||||
|
)
|
||||||
|
|
@ -17,13 +17,13 @@
|
||||||
package io.element.android.libraries.matrix.api.timeline
|
package io.element.android.libraries.matrix.api.timeline
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
import org.matrix.rustcomponents.sdk.EventTimelineItem
|
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
|
||||||
import org.matrix.rustcomponents.sdk.VirtualTimelineItem
|
import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
|
||||||
|
|
||||||
sealed interface MatrixTimelineItem {
|
sealed interface MatrixTimelineItem {
|
||||||
data class Event(val event: EventTimelineItem) : MatrixTimelineItem {
|
data class Event(val event: EventTimelineItem) : MatrixTimelineItem {
|
||||||
val uniqueId: String = event.uniqueIdentifier()
|
val uniqueId: String = event.uniqueIdentifier
|
||||||
val eventId: EventId? = event.eventId()?.let { EventId(it) }
|
val eventId: EventId? = event.eventId
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Virtual(val virtual: VirtualTimelineItem) : MatrixTimelineItem
|
data class Virtual(val virtual: VirtualTimelineItem) : MatrixTimelineItem
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.api.timeline.item.event
|
||||||
|
|
||||||
|
data class EventReaction(
|
||||||
|
val key: String,
|
||||||
|
val count: Long
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.api.timeline.item.event
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
|
|
||||||
|
sealed interface EventSendState {
|
||||||
|
object NotSendYet : EventSendState
|
||||||
|
|
||||||
|
data class SendingFailed(
|
||||||
|
val error: String
|
||||||
|
) : EventSendState
|
||||||
|
|
||||||
|
data class Sent(
|
||||||
|
val eventId: EventId
|
||||||
|
) : EventSendState
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.api.timeline.item.event
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
|
import io.element.android.libraries.matrix.api.core.UserId
|
||||||
|
|
||||||
|
data class EventTimelineItem(
|
||||||
|
val uniqueIdentifier: String,
|
||||||
|
val eventId: EventId?,
|
||||||
|
val isEditable: Boolean,
|
||||||
|
val isLocal: Boolean,
|
||||||
|
val isOwn: Boolean,
|
||||||
|
val isRemote: Boolean,
|
||||||
|
val localSendState: EventSendState?,
|
||||||
|
val reactions: List<EventReaction>,
|
||||||
|
val sender: UserId,
|
||||||
|
val senderProfile: ProfileTimelineDetails,
|
||||||
|
val timestamp: Long,
|
||||||
|
val content: TimelineEventContent
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.api.timeline.item.event
|
||||||
|
|
||||||
|
sealed interface ProfileTimelineDetails {
|
||||||
|
object Unavailable : ProfileTimelineDetails
|
||||||
|
|
||||||
|
object Pending : ProfileTimelineDetails
|
||||||
|
|
||||||
|
data class Ready(
|
||||||
|
val displayName: String?,
|
||||||
|
val displayNameAmbiguous: Boolean,
|
||||||
|
val avatarUrl: String?
|
||||||
|
) : ProfileTimelineDetails
|
||||||
|
|
||||||
|
data class Error(
|
||||||
|
val message: String
|
||||||
|
) : ProfileTimelineDetails
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,212 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.api.timeline.item.event
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.core.UserId
|
||||||
|
import io.element.android.libraries.matrix.api.media.AudioInfo
|
||||||
|
import io.element.android.libraries.matrix.api.media.FileInfo
|
||||||
|
import io.element.android.libraries.matrix.api.media.ImageInfo
|
||||||
|
import io.element.android.libraries.matrix.api.media.VideoInfo
|
||||||
|
|
||||||
|
sealed interface TimelineEventContent
|
||||||
|
|
||||||
|
data class TimelineEventMessageContent(
|
||||||
|
val body: String,
|
||||||
|
val inReplyTo: UserId?,
|
||||||
|
val isEdited: Boolean,
|
||||||
|
val content: MessageContent?
|
||||||
|
) : TimelineEventContent
|
||||||
|
|
||||||
|
object RedactedContent : TimelineEventContent
|
||||||
|
|
||||||
|
data class StickerContent(
|
||||||
|
val body: String,
|
||||||
|
val info: ImageInfo,
|
||||||
|
val url: String
|
||||||
|
) : TimelineEventContent
|
||||||
|
|
||||||
|
sealed interface EncryptedMessage {
|
||||||
|
data class OlmV1Curve25519AesSha2(
|
||||||
|
val senderKey: String
|
||||||
|
) : EncryptedMessage
|
||||||
|
|
||||||
|
data class MegolmV1AesSha2(
|
||||||
|
val sessionId: String
|
||||||
|
) : EncryptedMessage
|
||||||
|
|
||||||
|
object Unknown : EncryptedMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
data class UnableToDecryptContent(
|
||||||
|
val message: EncryptedMessage
|
||||||
|
) : TimelineEventContent
|
||||||
|
|
||||||
|
data class RoomMembership(
|
||||||
|
val userId: UserId,
|
||||||
|
val change: MembershipChange?
|
||||||
|
) : TimelineEventContent
|
||||||
|
|
||||||
|
data class ProfileChange(
|
||||||
|
val displayName: String?,
|
||||||
|
val prevDisplayName: String?,
|
||||||
|
val avatarUrl: String?,
|
||||||
|
val prevAvatarUrl: String?
|
||||||
|
) : TimelineEventContent
|
||||||
|
|
||||||
|
data class State(
|
||||||
|
val stateKey: String,
|
||||||
|
val content: OtherState
|
||||||
|
) : TimelineEventContent
|
||||||
|
|
||||||
|
data class FailedToParseMessageLike(
|
||||||
|
val eventType: String,
|
||||||
|
val error: String
|
||||||
|
) : TimelineEventContent
|
||||||
|
|
||||||
|
data class FailedToParseState(
|
||||||
|
val eventType: String,
|
||||||
|
val stateKey: String,
|
||||||
|
val error: String
|
||||||
|
) : TimelineEventContent
|
||||||
|
|
||||||
|
object UnknownContent : TimelineEventContent
|
||||||
|
|
||||||
|
sealed interface MessageContent
|
||||||
|
|
||||||
|
object UnknownMessageContent : MessageContent
|
||||||
|
|
||||||
|
enum class MessageFormat {
|
||||||
|
HTML, UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
data class FormattedBody(
|
||||||
|
val format: MessageFormat,
|
||||||
|
val body: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class EmoteMessageContent(
|
||||||
|
val body: String,
|
||||||
|
val formatted: FormattedBody?
|
||||||
|
) : MessageContent
|
||||||
|
|
||||||
|
data class ImageMessageContent(
|
||||||
|
val body: String,
|
||||||
|
val url: String,
|
||||||
|
val info: ImageInfo?
|
||||||
|
) : MessageContent
|
||||||
|
|
||||||
|
data class AudioMessageContent(
|
||||||
|
var body: String,
|
||||||
|
var url: String,
|
||||||
|
var info: AudioInfo?
|
||||||
|
) : MessageContent
|
||||||
|
|
||||||
|
data class VideoMessageContent(
|
||||||
|
val body: String,
|
||||||
|
val url: String,
|
||||||
|
val info: VideoInfo?
|
||||||
|
) : MessageContent
|
||||||
|
|
||||||
|
data class FileMessageContent(
|
||||||
|
val body: String,
|
||||||
|
val url: String,
|
||||||
|
val info: FileInfo?
|
||||||
|
) : MessageContent
|
||||||
|
|
||||||
|
data class NoticeMessageContent(
|
||||||
|
val body: String,
|
||||||
|
val formatted: FormattedBody?
|
||||||
|
) : MessageContent
|
||||||
|
|
||||||
|
data class TextMessageContent(
|
||||||
|
val body: String,
|
||||||
|
val formatted: FormattedBody?
|
||||||
|
) : MessageContent
|
||||||
|
|
||||||
|
enum class MembershipChange {
|
||||||
|
NONE,
|
||||||
|
ERROR,
|
||||||
|
JOINED,
|
||||||
|
LEFT,
|
||||||
|
BANNED,
|
||||||
|
UNBANNED,
|
||||||
|
KICKED,
|
||||||
|
INVITED,
|
||||||
|
KICKED_AND_BANNED,
|
||||||
|
INVITATION_ACCEPTED,
|
||||||
|
INVITATION_REJECTED,
|
||||||
|
INVITATION_REVOKED,
|
||||||
|
KNOCKED,
|
||||||
|
KNOCK_ACCEPTED,
|
||||||
|
KNOCK_RETRACTED,
|
||||||
|
KNOCK_DENIED,
|
||||||
|
NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed interface OtherState {
|
||||||
|
object PolicyRuleRoom : OtherState
|
||||||
|
|
||||||
|
object PolicyRuleServer : OtherState
|
||||||
|
|
||||||
|
object PolicyRuleUser : OtherState
|
||||||
|
|
||||||
|
object RoomAliases : OtherState
|
||||||
|
|
||||||
|
data class RoomAvatar(
|
||||||
|
val url: String?
|
||||||
|
) : OtherState
|
||||||
|
|
||||||
|
object RoomCanonicalAlias : OtherState
|
||||||
|
|
||||||
|
object RoomCreate : OtherState
|
||||||
|
|
||||||
|
object RoomEncryption : OtherState
|
||||||
|
|
||||||
|
object RoomGuestAccess : OtherState
|
||||||
|
|
||||||
|
object RoomHistoryVisibility : OtherState
|
||||||
|
|
||||||
|
object RoomJoinRules : OtherState
|
||||||
|
|
||||||
|
data class RoomName(
|
||||||
|
val name: String?
|
||||||
|
) : OtherState
|
||||||
|
|
||||||
|
object RoomPinnedEvents : OtherState
|
||||||
|
|
||||||
|
object RoomPowerLevels : OtherState
|
||||||
|
|
||||||
|
object RoomServerAcl : OtherState
|
||||||
|
|
||||||
|
data class RoomThirdPartyInvite(
|
||||||
|
val displayName: String?
|
||||||
|
) : OtherState
|
||||||
|
|
||||||
|
object RoomTombstone : OtherState
|
||||||
|
|
||||||
|
data class RoomTopic(
|
||||||
|
val `topic`: String?
|
||||||
|
) : OtherState
|
||||||
|
|
||||||
|
object SpaceChild : OtherState
|
||||||
|
|
||||||
|
object SpaceParent : OtherState
|
||||||
|
|
||||||
|
data class Custom(
|
||||||
|
val eventType: String
|
||||||
|
) : OtherState
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.api.timeline.item.virtual
|
||||||
|
|
||||||
|
sealed interface VirtualTimelineItem {
|
||||||
|
|
||||||
|
data class DayDivider(
|
||||||
|
val timestamp: Long
|
||||||
|
) : VirtualTimelineItem
|
||||||
|
|
||||||
|
object ReadMarker : VirtualTimelineItem
|
||||||
|
|
||||||
|
object LoadingIndicator : VirtualTimelineItem
|
||||||
|
|
||||||
|
object TimelineStart : VirtualTimelineItem
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.media
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.media.AudioInfo
|
||||||
|
import org.matrix.rustcomponents.sdk.AudioInfo as RustAudioInfo
|
||||||
|
|
||||||
|
fun RustAudioInfo.map(): AudioInfo = AudioInfo(
|
||||||
|
duration = duration?.toLong(),
|
||||||
|
size = size?.toLong()
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.media
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.media.FileInfo
|
||||||
|
import io.element.android.libraries.matrix.api.media.ThumbnailInfo
|
||||||
|
import org.matrix.rustcomponents.sdk.FileInfo as RustFileInfo
|
||||||
|
import org.matrix.rustcomponents.sdk.ThumbnailInfo as RustThumbnailInfo
|
||||||
|
|
||||||
|
fun RustFileInfo.map(): FileInfo = FileInfo(
|
||||||
|
mimetype = mimetype,
|
||||||
|
size = size?.toLong(),
|
||||||
|
thumbnailInfo = thumbnailInfo?.map(),
|
||||||
|
thumbnailUrl = thumbnailSource?.useUrl()
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.media
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.media.ImageInfo
|
||||||
|
import org.matrix.rustcomponents.sdk.ImageInfo as RustImageInfo
|
||||||
|
|
||||||
|
fun RustImageInfo.map(): ImageInfo = ImageInfo(
|
||||||
|
height = height?.toLong(),
|
||||||
|
width = width?.toLong(),
|
||||||
|
mimetype = mimetype,
|
||||||
|
size = size?.toLong(),
|
||||||
|
thumbnailInfo = thumbnailInfo?.map(),
|
||||||
|
thumbnailUrl = thumbnailSource?.useUrl(),
|
||||||
|
blurhash = blurhash
|
||||||
|
)
|
||||||
|
|
@ -14,19 +14,23 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.matrix.impl.timeline
|
package io.element.android.libraries.matrix.impl.media
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
interface MediaResolver {
|
||||||
import org.matrix.rustcomponents.sdk.TimelineItem
|
|
||||||
|
|
||||||
fun TimelineItem.asMatrixTimelineItem(): MatrixTimelineItem {
|
sealed interface Kind {
|
||||||
val asEvent = asEvent()
|
data class Thumbnail(val width: Int, val height: Int) : Kind {
|
||||||
if (asEvent != null) {
|
constructor(size: Int) : this(size, size)
|
||||||
return MatrixTimelineItem.Event(asEvent)
|
}
|
||||||
|
|
||||||
|
object Content : Kind
|
||||||
}
|
}
|
||||||
val asVirtual = asVirtual()
|
|
||||||
if (asVirtual != null) {
|
data class Meta(
|
||||||
return MatrixTimelineItem.Virtual(asVirtual)
|
val url: String?,
|
||||||
}
|
val kind: Kind
|
||||||
return MatrixTimelineItem.Other
|
)
|
||||||
|
|
||||||
|
suspend fun resolve(url: String?, kind: Kind): ByteArray?
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.media
|
||||||
|
|
||||||
|
import org.matrix.rustcomponents.sdk.MediaSource
|
||||||
|
import org.matrix.rustcomponents.sdk.use
|
||||||
|
|
||||||
|
fun MediaSource.useUrl(): String = use { it.url() }
|
||||||
|
|
@ -18,23 +18,23 @@ package io.element.android.libraries.matrix.impl.media
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.media.MediaResolver
|
import io.element.android.libraries.matrix.api.media.MediaResolver
|
||||||
|
import org.matrix.rustcomponents.sdk.MediaSource
|
||||||
import org.matrix.rustcomponents.sdk.mediaSourceFromUrl
|
import org.matrix.rustcomponents.sdk.mediaSourceFromUrl
|
||||||
|
|
||||||
internal class RustMediaResolver(private val client: MatrixClient) : MediaResolver {
|
internal class RustMediaResolver(private val client: MatrixClient) : MediaResolver {
|
||||||
|
|
||||||
override suspend fun resolve(url: String?, kind: MediaResolver.Kind): ByteArray? {
|
override suspend fun resolve(url: String?, kind: MediaResolver.Kind): ByteArray? {
|
||||||
if (url.isNullOrEmpty()) return null
|
if (url.isNullOrEmpty()) return null
|
||||||
val mediaSource = mediaSourceFromUrl(url)
|
return mediaSourceFromUrl(url).use { mediaSource ->
|
||||||
return resolve(MediaResolver.Meta(mediaSource, kind))
|
resolve(mediaSource, kind)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun resolve(meta: MediaResolver.Meta): ByteArray? {
|
private suspend fun resolve(mediaSource: MediaSource, kind: MediaResolver.Kind): ByteArray? {
|
||||||
val source = meta.source ?: return null
|
|
||||||
val kind = meta.kind
|
|
||||||
return when (kind) {
|
return when (kind) {
|
||||||
is MediaResolver.Kind.Content -> client.loadMediaContentForSource(source)
|
is MediaResolver.Kind.Content -> client.loadMediaContentForSource(mediaSource)
|
||||||
is MediaResolver.Kind.Thumbnail -> client.loadMediaThumbnailForSource(
|
is MediaResolver.Kind.Thumbnail -> client.loadMediaThumbnailForSource(
|
||||||
source,
|
mediaSource,
|
||||||
kind.width.toLong(),
|
kind.width.toLong(),
|
||||||
kind.height.toLong()
|
kind.height.toLong()
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.media
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.media.ThumbnailInfo
|
||||||
|
import org.matrix.rustcomponents.sdk.ThumbnailInfo as RustThumbnailInfo
|
||||||
|
|
||||||
|
fun RustThumbnailInfo.map(): ThumbnailInfo = ThumbnailInfo(
|
||||||
|
height = height?.toLong(),
|
||||||
|
width = width?.toLong(),
|
||||||
|
mimetype = mimetype,
|
||||||
|
size = size?.toLong()
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.media
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.media.VideoInfo
|
||||||
|
import org.matrix.rustcomponents.sdk.VideoInfo as RustVideoInfo
|
||||||
|
|
||||||
|
fun RustVideoInfo.map(): VideoInfo = VideoInfo(
|
||||||
|
duration = duration?.toLong(),
|
||||||
|
height = height?.toLong(),
|
||||||
|
width = width?.toLong(),
|
||||||
|
mimetype = mimetype,
|
||||||
|
size = size?.toLong(),
|
||||||
|
thumbnailInfo = thumbnailInfo?.map(),
|
||||||
|
thumbnailUrl = thumbnailSource?.useUrl(),
|
||||||
|
blurhash = blurhash
|
||||||
|
)
|
||||||
|
|
@ -18,6 +18,7 @@ package io.element.android.libraries.matrix.impl.timeline
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
|
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
|
||||||
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.item.virtual.VirtualTimelineItem
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -25,14 +26,15 @@ import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.matrix.rustcomponents.sdk.TimelineChange
|
import org.matrix.rustcomponents.sdk.TimelineChange
|
||||||
import org.matrix.rustcomponents.sdk.TimelineDiff
|
import org.matrix.rustcomponents.sdk.TimelineDiff
|
||||||
|
import org.matrix.rustcomponents.sdk.TimelineItem
|
||||||
import org.matrix.rustcomponents.sdk.TimelineListener
|
import org.matrix.rustcomponents.sdk.TimelineListener
|
||||||
import org.matrix.rustcomponents.sdk.VirtualTimelineItem
|
|
||||||
|
|
||||||
internal class MatrixTimelineDiffProcessor(
|
internal class MatrixTimelineDiffProcessor(
|
||||||
private val paginationState: MutableStateFlow<MatrixTimeline.PaginationState>,
|
private val paginationState: MutableStateFlow<MatrixTimeline.PaginationState>,
|
||||||
private val timelineItems: MutableStateFlow<List<MatrixTimelineItem>>,
|
private val timelineItems: MutableStateFlow<List<MatrixTimelineItem>>,
|
||||||
private val coroutineScope: CoroutineScope,
|
private val coroutineScope: CoroutineScope,
|
||||||
private val diffDispatcher: CoroutineDispatcher,
|
private val diffDispatcher: CoroutineDispatcher,
|
||||||
|
private val timelineItemFactory: MatrixTimelineItemMapper,
|
||||||
) : TimelineListener {
|
) : TimelineListener {
|
||||||
|
|
||||||
override fun onUpdate(update: TimelineDiff) {
|
override fun onUpdate(update: TimelineDiff) {
|
||||||
|
|
@ -117,4 +119,9 @@ internal class MatrixTimelineDiffProcessor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun TimelineItem.asMatrixTimelineItem(): MatrixTimelineItem {
|
||||||
|
return timelineItemFactory.map(this)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
||||||
|
import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper
|
||||||
|
import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper
|
||||||
|
import org.matrix.rustcomponents.sdk.TimelineItem
|
||||||
|
|
||||||
|
class MatrixTimelineItemMapper(
|
||||||
|
private val virtualTimelineItemMapper: VirtualTimelineItemMapper = VirtualTimelineItemMapper(),
|
||||||
|
private val eventTimelineItemMapper: EventTimelineItemMapper= EventTimelineItemMapper(),
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun map(timelineItem: TimelineItem): MatrixTimelineItem = timelineItem.use {
|
||||||
|
val asEvent = timelineItem.asEvent()
|
||||||
|
if (asEvent != null) {
|
||||||
|
val eventTimelineItem = eventTimelineItemMapper.map(asEvent)
|
||||||
|
return MatrixTimelineItem.Event(eventTimelineItem)
|
||||||
|
}
|
||||||
|
val asVirtual = timelineItem.asVirtual()
|
||||||
|
if (asVirtual != null) {
|
||||||
|
val virtualTimelineItem = virtualTimelineItemMapper.map(asVirtual)
|
||||||
|
return MatrixTimelineItem.Virtual(virtualTimelineItem)
|
||||||
|
}
|
||||||
|
return MatrixTimelineItem.Other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -17,11 +17,15 @@
|
||||||
package io.element.android.libraries.matrix.impl.timeline
|
package io.element.android.libraries.matrix.impl.timeline
|
||||||
|
|
||||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||||
import io.element.android.libraries.matrix.impl.util.TaskHandleBag
|
|
||||||
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.room.MatrixRoom
|
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
|
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
|
||||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
||||||
|
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
|
||||||
|
import io.element.android.libraries.matrix.impl.util.TaskHandleBag
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.FlowPreview
|
import kotlinx.coroutines.FlowPreview
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
@ -52,11 +56,21 @@ class RustMatrixTimeline(
|
||||||
MatrixTimeline.PaginationState(canBackPaginate = true, isBackPaginating = false)
|
MatrixTimeline.PaginationState(canBackPaginate = true, isBackPaginating = false)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val timelineItemFactory = MatrixTimelineItemMapper(
|
||||||
|
virtualTimelineItemMapper = VirtualTimelineItemMapper(),
|
||||||
|
eventTimelineItemMapper = EventTimelineItemMapper(
|
||||||
|
contentMapper = TimelineEventContentMapper(
|
||||||
|
eventMessageMapper = EventMessageMapper()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
private val innerTimelineListener = MatrixTimelineDiffProcessor(
|
private val innerTimelineListener = MatrixTimelineDiffProcessor(
|
||||||
paginationState = paginationState,
|
paginationState = paginationState,
|
||||||
timelineItems = timelineItems,
|
timelineItems = timelineItems,
|
||||||
coroutineScope = coroutineScope,
|
coroutineScope = coroutineScope,
|
||||||
diffDispatcher = coroutineDispatchers.diffUpdateDispatcher
|
diffDispatcher = coroutineDispatchers.diffUpdateDispatcher,
|
||||||
|
timelineItemFactory = timelineItemFactory,
|
||||||
)
|
)
|
||||||
|
|
||||||
private val listenerTokens = TaskHandleBag()
|
private val listenerTokens = TaskHandleBag()
|
||||||
|
|
@ -83,7 +97,7 @@ class RustMatrixTimeline(
|
||||||
val result = addListener(innerTimelineListener)
|
val result = addListener(innerTimelineListener)
|
||||||
result
|
result
|
||||||
.onSuccess { timelineItems ->
|
.onSuccess { timelineItems ->
|
||||||
val matrixTimelineItems = timelineItems.map { it.asMatrixTimelineItem() }
|
val matrixTimelineItems = timelineItems.map(timelineItemFactory::map)
|
||||||
withContext(coroutineDispatchers.diffUpdateDispatcher) {
|
withContext(coroutineDispatchers.diffUpdateDispatcher) {
|
||||||
this@RustMatrixTimeline.timelineItems.value = matrixTimelineItems
|
this@RustMatrixTimeline.timelineItems.value = matrixTimelineItems
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.item.event
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.core.UserId
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.FormattedBody
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.ImageMessageContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.MessageFormat
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.NoticeMessageContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.TimelineEventMessageContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.UnknownMessageContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageContent
|
||||||
|
import io.element.android.libraries.matrix.impl.media.map
|
||||||
|
import io.element.android.libraries.matrix.impl.media.useUrl
|
||||||
|
import org.matrix.rustcomponents.sdk.Message
|
||||||
|
import org.matrix.rustcomponents.sdk.MessageType
|
||||||
|
import org.matrix.rustcomponents.sdk.use
|
||||||
|
import org.matrix.rustcomponents.sdk.FormattedBody as RustFormattedBody
|
||||||
|
import org.matrix.rustcomponents.sdk.MessageFormat as RustMessageFormat
|
||||||
|
|
||||||
|
class EventMessageMapper {
|
||||||
|
|
||||||
|
fun map(message: Message): TimelineEventMessageContent = message.use {
|
||||||
|
val content = message.msgtype().use { type ->
|
||||||
|
when (type) {
|
||||||
|
is MessageType.Audio -> {
|
||||||
|
AudioMessageContent(type.content.body, type.content.source.useUrl(), type.content.info?.map())
|
||||||
|
}
|
||||||
|
is MessageType.File -> {
|
||||||
|
FileMessageContent(type.content.body, type.content.source.useUrl(), type.content.info?.map())
|
||||||
|
}
|
||||||
|
is MessageType.Image -> {
|
||||||
|
ImageMessageContent(type.content.body, type.content.source.useUrl(), type.content.info?.map())
|
||||||
|
}
|
||||||
|
is MessageType.Notice -> {
|
||||||
|
NoticeMessageContent(type.content.body, type.content.formatted?.map())
|
||||||
|
}
|
||||||
|
is MessageType.Text -> {
|
||||||
|
TextMessageContent(type.content.body, type.content.formatted?.map())
|
||||||
|
}
|
||||||
|
is MessageType.Emote -> {
|
||||||
|
EmoteMessageContent(type.content.body, type.content.formatted?.map())
|
||||||
|
}
|
||||||
|
is MessageType.Video -> {
|
||||||
|
VideoMessageContent(type.content.body, type.content.source.useUrl(), type.content.info?.map())
|
||||||
|
}
|
||||||
|
null -> {
|
||||||
|
UnknownMessageContent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TimelineEventMessageContent(
|
||||||
|
body = message.body(),
|
||||||
|
inReplyTo = message.inReplyTo()?.let { UserId(it) },
|
||||||
|
isEdited = message.isEdited(),
|
||||||
|
content = content
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun RustFormattedBody.map(): FormattedBody = FormattedBody(
|
||||||
|
format = format.map(),
|
||||||
|
body = body
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun RustMessageFormat.map(): MessageFormat {
|
||||||
|
return when (this) {
|
||||||
|
RustMessageFormat.HTML -> MessageFormat.HTML
|
||||||
|
RustMessageFormat.UNKNOWN -> MessageFormat.UNKNOWN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.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.EventReaction
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.EventSendState
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.TimelineEventContent
|
||||||
|
import org.matrix.rustcomponents.sdk.Reaction
|
||||||
|
import org.matrix.rustcomponents.sdk.EventSendState as RustEventSendState
|
||||||
|
import org.matrix.rustcomponents.sdk.EventTimelineItem as RustEventTimelineItem
|
||||||
|
import org.matrix.rustcomponents.sdk.ProfileTimelineDetails as RustProfileTimelineDetails
|
||||||
|
|
||||||
|
class EventTimelineItemMapper(private val contentMapper: TimelineEventContentMapper = TimelineEventContentMapper()) {
|
||||||
|
|
||||||
|
fun map(eventTimelineItem: RustEventTimelineItem): EventTimelineItem = eventTimelineItem.use {
|
||||||
|
EventTimelineItem(
|
||||||
|
uniqueIdentifier = eventTimelineItem.uniqueIdentifier(),
|
||||||
|
eventId = eventTimelineItem.eventId()?.let { EventId(it) },
|
||||||
|
isEditable = eventTimelineItem.isEditable(),
|
||||||
|
isLocal = eventTimelineItem.isLocal(),
|
||||||
|
isOwn = eventTimelineItem.isOwn(),
|
||||||
|
isRemote = eventTimelineItem.isRemote(),
|
||||||
|
localSendState = eventTimelineItem.localSendState()?.map(),
|
||||||
|
reactions = eventTimelineItem.reactions().map(),
|
||||||
|
sender = UserId(eventTimelineItem.sender()),
|
||||||
|
senderProfile = eventTimelineItem.senderProfile().map(),
|
||||||
|
timestamp = eventTimelineItem.timestamp().toLong(),
|
||||||
|
content = contentMapper.map(eventTimelineItem.content())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun RustProfileTimelineDetails.map(): ProfileTimelineDetails {
|
||||||
|
return when (this) {
|
||||||
|
RustProfileTimelineDetails.Pending -> ProfileTimelineDetails.Pending
|
||||||
|
RustProfileTimelineDetails.Unavailable -> ProfileTimelineDetails.Unavailable
|
||||||
|
is RustProfileTimelineDetails.Error -> ProfileTimelineDetails.Error(message)
|
||||||
|
is RustProfileTimelineDetails.Ready -> ProfileTimelineDetails.Ready(
|
||||||
|
displayName = displayName,
|
||||||
|
displayNameAmbiguous = displayNameAmbiguous,
|
||||||
|
avatarUrl = avatarUrl
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun RustEventSendState?.map(): EventSendState? {
|
||||||
|
return when (this) {
|
||||||
|
null -> null
|
||||||
|
RustEventSendState.NotSendYet -> EventSendState.NotSendYet
|
||||||
|
is RustEventSendState.SendingFailed -> EventSendState.SendingFailed(error)
|
||||||
|
is RustEventSendState.Sent -> EventSendState.Sent(EventId(eventId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun List<Reaction>?.map(): List<EventReaction> {
|
||||||
|
return this?.map {
|
||||||
|
EventReaction(
|
||||||
|
key = it.key,
|
||||||
|
count = it.count.toLong()
|
||||||
|
)
|
||||||
|
} ?: emptyList()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.item.event
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.core.UserId
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLike
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseState
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChange
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembership
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.StickerContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.TimelineEventContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.UnknownContent
|
||||||
|
import io.element.android.libraries.matrix.impl.media.map
|
||||||
|
import org.matrix.rustcomponents.sdk.TimelineItemContent
|
||||||
|
import org.matrix.rustcomponents.sdk.TimelineItemContentKind
|
||||||
|
|
||||||
|
class TimelineEventContentMapper(private val eventMessageMapper: EventMessageMapper = EventMessageMapper()) {
|
||||||
|
|
||||||
|
fun map(content: TimelineItemContent): TimelineEventContent = content.use {
|
||||||
|
when (val kind = content.kind()) {
|
||||||
|
is TimelineItemContentKind.FailedToParseMessageLike -> {
|
||||||
|
FailedToParseMessageLike(
|
||||||
|
eventType = kind.eventType,
|
||||||
|
error = kind.error
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is TimelineItemContentKind.FailedToParseState -> {
|
||||||
|
FailedToParseState(
|
||||||
|
eventType = kind.eventType,
|
||||||
|
stateKey = kind.stateKey,
|
||||||
|
error = kind.error
|
||||||
|
)
|
||||||
|
}
|
||||||
|
TimelineItemContentKind.Message -> {
|
||||||
|
val message = content.asMessage()
|
||||||
|
if (message == null) {
|
||||||
|
UnknownContent
|
||||||
|
} else {
|
||||||
|
eventMessageMapper.map(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is TimelineItemContentKind.ProfileChange -> {
|
||||||
|
ProfileChange(
|
||||||
|
displayName = kind.displayName,
|
||||||
|
prevDisplayName = kind.prevDisplayName,
|
||||||
|
avatarUrl = kind.avatarUrl,
|
||||||
|
prevAvatarUrl = kind.prevAvatarUrl
|
||||||
|
)
|
||||||
|
}
|
||||||
|
TimelineItemContentKind.RedactedMessage -> {
|
||||||
|
RedactedContent
|
||||||
|
}
|
||||||
|
is TimelineItemContentKind.RoomMembership -> {
|
||||||
|
RoomMembership(
|
||||||
|
UserId(kind.userId),
|
||||||
|
MembershipChange.JOINED
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is TimelineItemContentKind.State -> {
|
||||||
|
UnknownContent
|
||||||
|
}
|
||||||
|
is TimelineItemContentKind.Sticker -> {
|
||||||
|
StickerContent(
|
||||||
|
body = kind.body,
|
||||||
|
info = kind.info.map(),
|
||||||
|
url = kind.url
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is TimelineItemContentKind.UnableToDecrypt -> {
|
||||||
|
UnknownContent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.item.virtual
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
|
||||||
|
import org.matrix.rustcomponents.sdk.VirtualTimelineItem as RustVirtualTimelineItem
|
||||||
|
|
||||||
|
class VirtualTimelineItemMapper {
|
||||||
|
|
||||||
|
fun map(virtualTimelineItem: RustVirtualTimelineItem): VirtualTimelineItem {
|
||||||
|
return when (virtualTimelineItem) {
|
||||||
|
is RustVirtualTimelineItem.DayDivider -> VirtualTimelineItem.DayDivider(virtualTimelineItem.ts.toLong())
|
||||||
|
RustVirtualTimelineItem.LoadingIndicator -> VirtualTimelineItem.LoadingIndicator
|
||||||
|
RustVirtualTimelineItem.ReadMarker -> VirtualTimelineItem.ReadMarker
|
||||||
|
RustVirtualTimelineItem.TimelineStart -> VirtualTimelineItem.TimelineStart
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -27,7 +27,10 @@ class TaskHandleBag(private val tokens: MutableSet<TaskHandle> = CopyOnWriteArra
|
||||||
}
|
}
|
||||||
|
|
||||||
fun dispose() {
|
fun dispose() {
|
||||||
tokens.forEach { it.cancel() }
|
tokens.forEach {
|
||||||
|
it.cancel()
|
||||||
|
it.destroy()
|
||||||
|
}
|
||||||
tokens.clear()
|
tokens.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,4 @@ class FakeMediaResolver : MediaResolver {
|
||||||
override suspend fun resolve(url: String?, kind: MediaResolver.Kind): ByteArray? {
|
override suspend fun resolve(url: String?, kind: MediaResolver.Kind): ByteArray? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun resolve(meta: MediaResolver.Meta): ByteArray? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,7 @@ package io.element.android.libraries.matrix.ui.media
|
||||||
|
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||||
import io.element.android.libraries.matrix.api.media.MediaResolver
|
import io.element.android.libraries.matrix.api.media.MediaResolver
|
||||||
import org.matrix.rustcomponents.sdk.mediaSourceFromUrl
|
|
||||||
|
|
||||||
fun AvatarData.toMetadata(): MediaResolver.Meta {
|
fun AvatarData.toMetadata(): MediaResolver.Meta {
|
||||||
val mediaSource = url?.let { mediaSourceFromUrl(it) }
|
return MediaResolver.Meta(url = url, kind = MediaResolver.Kind.Thumbnail(size.value))
|
||||||
return MediaResolver.Meta(source = mediaSource, kind = MediaResolver.Kind.Thumbnail(size.value))
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ internal class MediaFetcher(
|
||||||
) : Fetcher {
|
) : Fetcher {
|
||||||
|
|
||||||
override suspend fun fetch(): FetchResult? {
|
override suspend fun fetch(): FetchResult? {
|
||||||
val byteArray = mediaResolver?.resolve(meta) ?: return null
|
val byteArray = mediaResolver?.resolve(meta.url, meta.kind) ?: return null
|
||||||
val byteBuffer = ByteBuffer.wrap(byteArray)
|
val byteBuffer = ByteBuffer.wrap(byteArray)
|
||||||
return imageLoader.components.newFetcher(byteBuffer, options, imageLoader)?.first?.fetch()
|
return imageLoader.components.newFetcher(byteBuffer, options, imageLoader)?.first?.fetch()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,4 +33,4 @@ internal class MediaKeyer : Keyer<MediaResolver.Meta> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MediaResolver.Meta.toKey() = "${source?.url()}_${kind}"
|
private fun MediaResolver.Meta.toKey() = "${url}_${kind}"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue