[MatrixSDK] start mapping all the timeline objects
This commit is contained in:
parent
98911a12ad
commit
fb85f35525
37 changed files with 1054 additions and 49 deletions
|
|
@ -47,7 +47,7 @@ class TimelineItemContentMessageFactory @Inject constructor() {
|
|||
TimelineItemImageContent(
|
||||
body = messageType.content.body,
|
||||
imageMeta = MediaResolver.Meta(
|
||||
source = messageType.content.source,
|
||||
url = messageType.content.source,
|
||||
kind = MediaResolver.Kind.Content
|
||||
),
|
||||
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.TimelineItemVirtualModel
|
||||
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
|
||||
|
||||
class TimelineItemDaySeparatorFactory @Inject constructor(private val daySeparatorFormatter: DaySeparatorFormatter) {
|
||||
|
||||
fun create(virtualItem: VirtualTimelineItem.DayDivider): TimelineItemVirtualModel {
|
||||
val formattedDate = daySeparatorFormatter.format(virtualItem.ts.toLong())
|
||||
val formattedDate = daySeparatorFormatter.format(virtualItem.timestamp)
|
||||
return TimelineItemDaySeparatorModel(
|
||||
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.TimelineItemVirtualModel
|
||||
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 javax.inject.Inject
|
||||
|
||||
|
|
@ -42,10 +43,10 @@ class TimelineItemVirtualFactory @Inject constructor(
|
|||
|
||||
private fun MatrixTimelineItem.Virtual.computeModel(index: Int): TimelineItemVirtualModel {
|
||||
return when (val inner = virtual) {
|
||||
is VirtualTimelineItem.DayDivider -> daySeparatorFactory.create(inner)
|
||||
is VirtualTimelineItem.ReadMarker -> TimelineItemReadMarkerModel
|
||||
is VirtualTimelineItem.LoadingIndicator -> TimelineItemLoadingModel
|
||||
is VirtualTimelineItem.TimelineStart -> TimelineItemReadMarkerModel
|
||||
is io.element.android.libraries.matrix.api.timeline.item.virtual.TimelineItemVirtual.VirtualTimelineItem.DayDivider -> daySeparatorFactory.create(inner)
|
||||
is io.element.android.libraries.matrix.api.timeline.item.virtual.TimelineItemVirtual.VirtualTimelineItem.ReadMarker -> TimelineItemReadMarkerModel
|
||||
is io.element.android.libraries.matrix.api.timeline.item.virtual.TimelineItemVirtual.VirtualTimelineItem.LoadingIndicator -> TimelineItemLoadingModel
|
||||
is io.element.android.libraries.matrix.api.timeline.item.virtual.TimelineItemVirtual.VirtualTimelineItem.TimelineStart -> TimelineItemReadMarkerModel
|
||||
else -> TimelineItemUnknownVirtualModel
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ open class TimelineItemImageContentProvider : PreviewParameterProvider<TimelineI
|
|||
|
||||
fun aTimelineItemImageContent() = TimelineItemImageContent(
|
||||
body = "a body",
|
||||
imageMeta = MediaResolver.Meta(source = null, kind = MediaResolver.Kind.Content),
|
||||
imageMeta = MediaResolver.Meta(url = null, kind = MediaResolver.Kind.Content),
|
||||
blurhash = null,
|
||||
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
|
||||
|
||||
import org.matrix.rustcomponents.sdk.MediaSource
|
||||
|
||||
interface MediaResolver {
|
||||
|
||||
sealed interface Kind {
|
||||
|
|
@ -29,11 +27,10 @@ interface MediaResolver {
|
|||
}
|
||||
|
||||
data class Meta(
|
||||
val source: MediaSource?,
|
||||
val url: String?,
|
||||
val kind: Kind
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import org.matrix.rustcomponents.sdk.EventTimelineItem
|
||||
import org.matrix.rustcomponents.sdk.VirtualTimelineItem
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
|
||||
import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
|
||||
|
||||
sealed interface MatrixTimelineItem {
|
||||
data class Event(val event: EventTimelineItem) : MatrixTimelineItem {
|
||||
val uniqueId: String = event.uniqueIdentifier()
|
||||
val eventId: EventId? = event.eventId()?.let { EventId(it) }
|
||||
val uniqueId: String = event.uniqueIdentifier
|
||||
val eventId: EventId? = event.eventId
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
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
|
||||
import org.matrix.rustcomponents.sdk.TimelineItem
|
||||
interface MediaResolver {
|
||||
|
||||
fun TimelineItem.asMatrixTimelineItem(): MatrixTimelineItem {
|
||||
val asEvent = asEvent()
|
||||
if (asEvent != null) {
|
||||
return MatrixTimelineItem.Event(asEvent)
|
||||
sealed interface Kind {
|
||||
data class Thumbnail(val width: Int, val height: Int) : Kind {
|
||||
constructor(size: Int) : this(size, size)
|
||||
}
|
||||
|
||||
object Content : Kind
|
||||
}
|
||||
val asVirtual = asVirtual()
|
||||
if (asVirtual != null) {
|
||||
return MatrixTimelineItem.Virtual(asVirtual)
|
||||
}
|
||||
return MatrixTimelineItem.Other
|
||||
|
||||
data class Meta(
|
||||
val url: String?,
|
||||
val kind: Kind
|
||||
)
|
||||
|
||||
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.media.MediaResolver
|
||||
import org.matrix.rustcomponents.sdk.MediaSource
|
||||
import org.matrix.rustcomponents.sdk.mediaSourceFromUrl
|
||||
|
||||
internal class RustMediaResolver(private val client: MatrixClient) : MediaResolver {
|
||||
|
||||
override suspend fun resolve(url: String?, kind: MediaResolver.Kind): ByteArray? {
|
||||
if (url.isNullOrEmpty()) return null
|
||||
val mediaSource = mediaSourceFromUrl(url)
|
||||
return resolve(MediaResolver.Meta(mediaSource, kind))
|
||||
return mediaSourceFromUrl(url).use { mediaSource ->
|
||||
resolve(mediaSource, kind)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun resolve(meta: MediaResolver.Meta): ByteArray? {
|
||||
val source = meta.source ?: return null
|
||||
val kind = meta.kind
|
||||
private suspend fun resolve(mediaSource: MediaSource, kind: MediaResolver.Kind): ByteArray? {
|
||||
return when (kind) {
|
||||
is MediaResolver.Kind.Content -> client.loadMediaContentForSource(source)
|
||||
is MediaResolver.Kind.Content -> client.loadMediaContentForSource(mediaSource)
|
||||
is MediaResolver.Kind.Thumbnail -> client.loadMediaThumbnailForSource(
|
||||
source,
|
||||
mediaSource,
|
||||
kind.width.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.MatrixTimelineItem
|
||||
import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -25,14 +26,15 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.rustcomponents.sdk.TimelineChange
|
||||
import org.matrix.rustcomponents.sdk.TimelineDiff
|
||||
import org.matrix.rustcomponents.sdk.TimelineItem
|
||||
import org.matrix.rustcomponents.sdk.TimelineListener
|
||||
import org.matrix.rustcomponents.sdk.VirtualTimelineItem
|
||||
|
||||
internal class MatrixTimelineDiffProcessor(
|
||||
private val paginationState: MutableStateFlow<MatrixTimeline.PaginationState>,
|
||||
private val timelineItems: MutableStateFlow<List<MatrixTimelineItem>>,
|
||||
private val coroutineScope: CoroutineScope,
|
||||
private val diffDispatcher: CoroutineDispatcher,
|
||||
private val timelineItemFactory: MatrixTimelineItemMapper,
|
||||
) : TimelineListener {
|
||||
|
||||
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
|
||||
|
||||
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.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
|
||||
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.FlowPreview
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
|
@ -52,11 +56,21 @@ class RustMatrixTimeline(
|
|||
MatrixTimeline.PaginationState(canBackPaginate = true, isBackPaginating = false)
|
||||
)
|
||||
|
||||
private val timelineItemFactory = MatrixTimelineItemMapper(
|
||||
virtualTimelineItemMapper = VirtualTimelineItemMapper(),
|
||||
eventTimelineItemMapper = EventTimelineItemMapper(
|
||||
contentMapper = TimelineEventContentMapper(
|
||||
eventMessageMapper = EventMessageMapper()
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
private val innerTimelineListener = MatrixTimelineDiffProcessor(
|
||||
paginationState = paginationState,
|
||||
timelineItems = timelineItems,
|
||||
coroutineScope = coroutineScope,
|
||||
diffDispatcher = coroutineDispatchers.diffUpdateDispatcher
|
||||
diffDispatcher = coroutineDispatchers.diffUpdateDispatcher,
|
||||
timelineItemFactory = timelineItemFactory,
|
||||
)
|
||||
|
||||
private val listenerTokens = TaskHandleBag()
|
||||
|
|
@ -83,7 +97,7 @@ class RustMatrixTimeline(
|
|||
val result = addListener(innerTimelineListener)
|
||||
result
|
||||
.onSuccess { timelineItems ->
|
||||
val matrixTimelineItems = timelineItems.map { it.asMatrixTimelineItem() }
|
||||
val matrixTimelineItems = timelineItems.map(timelineItemFactory::map)
|
||||
withContext(coroutineDispatchers.diffUpdateDispatcher) {
|
||||
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() {
|
||||
tokens.forEach { it.cancel() }
|
||||
tokens.forEach {
|
||||
it.cancel()
|
||||
it.destroy()
|
||||
}
|
||||
tokens.clear()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,4 @@ class FakeMediaResolver : MediaResolver {
|
|||
override suspend fun resolve(url: String?, kind: MediaResolver.Kind): ByteArray? {
|
||||
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.matrix.api.media.MediaResolver
|
||||
import org.matrix.rustcomponents.sdk.mediaSourceFromUrl
|
||||
|
||||
fun AvatarData.toMetadata(): MediaResolver.Meta {
|
||||
val mediaSource = url?.let { mediaSourceFromUrl(it) }
|
||||
return MediaResolver.Meta(source = mediaSource, kind = MediaResolver.Kind.Thumbnail(size.value))
|
||||
return MediaResolver.Meta(url = url, kind = MediaResolver.Kind.Thumbnail(size.value))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ internal class MediaFetcher(
|
|||
) : Fetcher {
|
||||
|
||||
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)
|
||||
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