Prepare update to Rust SDK 0.1.36 (#966)
* Update to Rust SDK 0.1.36 * Cancel fetching members when the we exit the room
This commit is contained in:
committed by
GitHub
parent
c620e64ca6
commit
a9d1a299f5
@@ -517,42 +517,46 @@ private fun ReplyToContent(
|
||||
}
|
||||
}
|
||||
|
||||
private fun attachmentThumbnailInfoForInReplyTo(inReplyTo: InReplyTo.Ready) =
|
||||
when (val type = inReplyTo.content.type) {
|
||||
private fun attachmentThumbnailInfoForInReplyTo(inReplyTo: InReplyTo.Ready): AttachmentThumbnailInfo? {
|
||||
val messageContent = inReplyTo.content as? MessageContent ?: return null
|
||||
return when (val type = messageContent.type) {
|
||||
is ImageMessageType -> AttachmentThumbnailInfo(
|
||||
thumbnailSource = type.info?.thumbnailSource,
|
||||
textContent = inReplyTo.content.body,
|
||||
textContent = messageContent.body,
|
||||
type = AttachmentThumbnailType.Image,
|
||||
blurHash = type.info?.blurhash,
|
||||
)
|
||||
is VideoMessageType -> AttachmentThumbnailInfo(
|
||||
thumbnailSource = type.info?.thumbnailSource,
|
||||
textContent = inReplyTo.content.body,
|
||||
textContent = messageContent.body,
|
||||
type = AttachmentThumbnailType.Video,
|
||||
blurHash = type.info?.blurhash,
|
||||
)
|
||||
is FileMessageType -> AttachmentThumbnailInfo(
|
||||
thumbnailSource = type.info?.thumbnailSource,
|
||||
textContent = inReplyTo.content.body,
|
||||
textContent = messageContent.body,
|
||||
type = AttachmentThumbnailType.File,
|
||||
)
|
||||
is LocationMessageType -> AttachmentThumbnailInfo(
|
||||
textContent = inReplyTo.content.body,
|
||||
textContent = messageContent.body,
|
||||
type = AttachmentThumbnailType.Location,
|
||||
)
|
||||
is AudioMessageType -> AttachmentThumbnailInfo(
|
||||
textContent = inReplyTo.content.body,
|
||||
textContent = messageContent.body,
|
||||
type = AttachmentThumbnailType.Audio,
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun textForInReplyTo(inReplyTo: InReplyTo.Ready) =
|
||||
when (inReplyTo.content.type) {
|
||||
private fun textForInReplyTo(inReplyTo: InReplyTo.Ready): String {
|
||||
val messageContent = inReplyTo.content as? MessageContent ?: return ""
|
||||
return when (messageContent.type) {
|
||||
is LocationMessageType -> stringResource(CommonStrings.common_shared_location)
|
||||
else -> inReplyTo.content.body
|
||||
else -> messageContent.body
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
|
||||
@@ -145,7 +145,7 @@ jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
|
||||
appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" }
|
||||
molecule-runtime = { module = "app.cash.molecule:molecule-runtime", version.ref = "molecule" }
|
||||
timber = "com.jakewharton.timber:timber:5.0.1"
|
||||
matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.34"
|
||||
matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.36"
|
||||
sqldelight-driver-android = { module = "com.squareup.sqldelight:android-driver", version.ref = "sqldelight" }
|
||||
sqldelight-driver-jvm = { module = "com.squareup.sqldelight:sqlite-driver", version.ref = "sqldelight" }
|
||||
sqldelight-coroutines = { module = "com.squareup.sqldelight:coroutines-extensions", version.ref = "sqldelight" }
|
||||
|
||||
@@ -23,7 +23,6 @@ import io.element.android.libraries.matrix.api.room.RoomMembershipState
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.MessageType
|
||||
|
||||
data class NotificationData(
|
||||
val senderId: UserId,
|
||||
val eventId: EventId,
|
||||
val roomId: RoomId,
|
||||
val senderAvatarUrl: String?,
|
||||
@@ -33,14 +32,10 @@ data class NotificationData(
|
||||
val isDirect: Boolean,
|
||||
val isEncrypted: Boolean,
|
||||
val isNoisy: Boolean,
|
||||
val event: NotificationEvent,
|
||||
)
|
||||
|
||||
data class NotificationEvent(
|
||||
val timestamp: Long,
|
||||
val content: NotificationContent,
|
||||
// For images for instance
|
||||
val contentUrl: String?
|
||||
val contentUrl: String?,
|
||||
)
|
||||
|
||||
sealed interface NotificationContent {
|
||||
@@ -61,6 +56,7 @@ sealed interface NotificationContent {
|
||||
) : MessageLike
|
||||
object RoomEncrypted : MessageLike
|
||||
data class RoomMessage(
|
||||
val senderId: UserId,
|
||||
val messageType: MessageType
|
||||
) : MessageLike
|
||||
object RoomRedaction : MessageLike
|
||||
|
||||
@@ -44,7 +44,7 @@ sealed interface InReplyTo {
|
||||
/** The event details are available. */
|
||||
data class Ready(
|
||||
val eventId: EventId,
|
||||
val content: MessageContent,
|
||||
val content: EventContent,
|
||||
val senderId: UserId,
|
||||
val senderDisplayName: String?,
|
||||
val senderAvatarUrl: String?,
|
||||
|
||||
@@ -29,7 +29,7 @@ anvil {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// api(projects.libraries.rustsdk)
|
||||
// api(projects.libraries.rustsdk)
|
||||
implementation(libs.matrix.sdk)
|
||||
implementation(projects.libraries.di)
|
||||
implementation(projects.libraries.androidutils)
|
||||
|
||||
@@ -103,7 +103,7 @@ class RustMatrixClient constructor(
|
||||
builder.finish()
|
||||
}
|
||||
|
||||
private val notificationService = RustNotificationService(notificationClient)
|
||||
private val notificationService = RustNotificationService(sessionId, notificationClient, clock)
|
||||
|
||||
private val isLoggingOut = AtomicBoolean(false)
|
||||
|
||||
|
||||
@@ -19,19 +19,29 @@ package io.element.android.libraries.matrix.impl.notification
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.notification.NotificationContent
|
||||
import io.element.android.libraries.matrix.api.notification.NotificationData
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipState
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
import org.matrix.rustcomponents.sdk.NotificationEvent
|
||||
import org.matrix.rustcomponents.sdk.NotificationItem
|
||||
import org.matrix.rustcomponents.sdk.use
|
||||
|
||||
class NotificationMapper {
|
||||
private val timelineEventMapper = TimelineEventMapper()
|
||||
class NotificationMapper(
|
||||
private val sessionId: SessionId,
|
||||
private val clock: SystemClock,
|
||||
) {
|
||||
private val notificationContentMapper = NotificationContentMapper(sessionId)
|
||||
|
||||
fun map(roomId: RoomId, notificationItem: NotificationItem): NotificationData {
|
||||
fun map(
|
||||
eventId: EventId,
|
||||
roomId: RoomId,
|
||||
notificationItem: NotificationItem
|
||||
): NotificationData {
|
||||
return notificationItem.use { item ->
|
||||
NotificationData(
|
||||
senderId = UserId(item.event.senderId()),
|
||||
eventId = EventId(item.event.eventId()),
|
||||
eventId = eventId,
|
||||
roomId = roomId,
|
||||
senderAvatarUrl = item.senderInfo.avatarUrl,
|
||||
senderDisplayName = item.senderInfo.displayName,
|
||||
@@ -39,9 +49,30 @@ class NotificationMapper {
|
||||
roomDisplayName = item.roomInfo.displayName,
|
||||
isDirect = item.roomInfo.isDirect,
|
||||
isEncrypted = item.roomInfo.isEncrypted.orFalse(),
|
||||
isNoisy = item.isNoisy,
|
||||
event = item.event.use { event -> timelineEventMapper.map(event) }
|
||||
isNoisy = item.isNoisy.orFalse(),
|
||||
timestamp = item.timestamp() ?: clock.epochMillis(),
|
||||
content = item.event.use(notificationContentMapper::map),
|
||||
contentUrl = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NotificationContentMapper(
|
||||
private val sessionId: SessionId,
|
||||
) {
|
||||
private val timelineEventToNotificationContentMapper = TimelineEventToNotificationContentMapper()
|
||||
|
||||
fun map(notificationEvent: NotificationEvent): NotificationContent =
|
||||
when (notificationEvent) {
|
||||
is NotificationEvent.Timeline -> timelineEventToNotificationContentMapper.map(notificationEvent.event)
|
||||
is NotificationEvent.Invite -> NotificationContent.StateEvent.RoomMemberContent(
|
||||
userId = sessionId.value,
|
||||
membershipState = RoomMembershipState.INVITE,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun NotificationItem.timestamp(): Long? {
|
||||
return (this.event as? NotificationEvent.Timeline)?.event?.timestamp()?.toLong()
|
||||
}
|
||||
|
||||
@@ -21,13 +21,16 @@ import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.notification.NotificationData
|
||||
import io.element.android.libraries.matrix.api.notification.NotificationService
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
import org.matrix.rustcomponents.sdk.NotificationClient
|
||||
import org.matrix.rustcomponents.sdk.use
|
||||
|
||||
class RustNotificationService(
|
||||
sessionId: SessionId,
|
||||
private val notificationClient: NotificationClient,
|
||||
clock: SystemClock,
|
||||
) : NotificationService {
|
||||
private val notificationMapper: NotificationMapper = NotificationMapper()
|
||||
private val notificationMapper: NotificationMapper = NotificationMapper(sessionId, clock)
|
||||
|
||||
override fun getNotification(
|
||||
userId: SessionId,
|
||||
@@ -36,9 +39,9 @@ class RustNotificationService(
|
||||
filterByPushRules: Boolean,
|
||||
): Result<NotificationData?> {
|
||||
return runCatching {
|
||||
val item = notificationClient.getNotification(roomId.value, eventId.value)
|
||||
val item = notificationClient.getNotificationWithSlidingSync(roomId.value, eventId.value)
|
||||
item?.use {
|
||||
notificationMapper.map(roomId, it)
|
||||
notificationMapper.map(eventId, roomId, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
package io.element.android.libraries.matrix.impl.notification
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.notification.NotificationContent
|
||||
import io.element.android.libraries.matrix.api.notification.NotificationEvent
|
||||
import io.element.android.libraries.matrix.impl.room.RoomMemberMapper
|
||||
import io.element.android.libraries.matrix.impl.timeline.item.event.EventMessageMapper
|
||||
import org.matrix.rustcomponents.sdk.MessageLikeEventContent
|
||||
@@ -27,22 +27,18 @@ import org.matrix.rustcomponents.sdk.TimelineEventType
|
||||
import org.matrix.rustcomponents.sdk.use
|
||||
import javax.inject.Inject
|
||||
|
||||
class TimelineEventMapper @Inject constructor() {
|
||||
class TimelineEventToNotificationContentMapper @Inject constructor() {
|
||||
|
||||
fun map(timelineEvent: TimelineEvent): NotificationEvent {
|
||||
fun map(timelineEvent: TimelineEvent): NotificationContent {
|
||||
return timelineEvent.use {
|
||||
NotificationEvent(
|
||||
timestamp = it.timestamp().toLong(),
|
||||
content = it.eventType().toContent(),
|
||||
contentUrl = null // TODO it.eventType().toContentUrl(),
|
||||
)
|
||||
it.eventType().toContent(senderId = UserId(timelineEvent.senderId()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun TimelineEventType.toContent(): NotificationContent {
|
||||
private fun TimelineEventType.toContent(senderId: UserId): NotificationContent {
|
||||
return when (this) {
|
||||
is TimelineEventType.MessageLike -> content.toContent()
|
||||
is TimelineEventType.MessageLike -> content.toContent(senderId)
|
||||
is TimelineEventType.State -> content.toContent()
|
||||
}
|
||||
}
|
||||
@@ -75,7 +71,7 @@ private fun StateEventContent.toContent(): NotificationContent.StateEvent {
|
||||
}
|
||||
}
|
||||
|
||||
private fun MessageLikeEventContent.toContent(): NotificationContent.MessageLike {
|
||||
private fun MessageLikeEventContent.toContent(senderId: UserId): NotificationContent.MessageLike {
|
||||
return use {
|
||||
when (it) {
|
||||
MessageLikeEventContent.CallAnswer -> NotificationContent.MessageLike.CallAnswer
|
||||
@@ -92,7 +88,7 @@ private fun MessageLikeEventContent.toContent(): NotificationContent.MessageLike
|
||||
is MessageLikeEventContent.ReactionContent -> NotificationContent.MessageLike.ReactionContent(it.relatedEventId)
|
||||
MessageLikeEventContent.RoomEncrypted -> NotificationContent.MessageLike.RoomEncrypted
|
||||
is MessageLikeEventContent.RoomMessage -> {
|
||||
NotificationContent.MessageLike.RoomMessage(EventMessageMapper().mapMessageType(it.messageType))
|
||||
NotificationContent.MessageLike.RoomMessage(senderId, EventMessageMapper().mapMessageType(it.messageType))
|
||||
}
|
||||
MessageLikeEventContent.RoomRedaction -> NotificationContent.MessageLike.RoomRedaction
|
||||
MessageLikeEventContent.Sticker -> NotificationContent.MessageLike.Sticker
|
||||
@@ -27,6 +27,7 @@ import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelin
|
||||
import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper
|
||||
import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper
|
||||
import io.element.android.libraries.matrix.impl.timeline.postprocessor.TimelineEncryptedHistoryPostProcessor
|
||||
import io.element.android.libraries.matrix.impl.util.TaskHandleBag
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -102,6 +103,8 @@ class RustMatrixTimeline(
|
||||
|
||||
init {
|
||||
Timber.d("Initialize timeline for room ${matrixRoom.roomId}")
|
||||
|
||||
val taskHandleBag = TaskHandleBag()
|
||||
roomCoroutineScope.launch(dispatcher) {
|
||||
innerRoom.timelineDiffFlow { initialList ->
|
||||
postItems(initialList)
|
||||
@@ -117,7 +120,9 @@ class RustMatrixTimeline(
|
||||
postPaginationStatus(it)
|
||||
}.launchIn(this)
|
||||
|
||||
fetchMembers()
|
||||
taskHandleBag += fetchMembers().getOrNull()
|
||||
}.invokeOnCompletion {
|
||||
taskHandleBag.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ import org.matrix.rustcomponents.sdk.MessageType as RustMessageType
|
||||
|
||||
class EventMessageMapper {
|
||||
|
||||
private val timelineEventContentMapper by lazy { TimelineEventContentMapper() }
|
||||
|
||||
fun map(message: Message): MessageContent = message.use {
|
||||
val type = it.msgtype().use(this::mapMessageType)
|
||||
val inReplyToId = it.inReplyTo()?.eventId?.let(::EventId)
|
||||
@@ -51,7 +53,7 @@ class EventMessageMapper {
|
||||
val senderProfile = details.senderProfile as? ProfileDetails.Ready
|
||||
InReplyTo.Ready(
|
||||
eventId = inReplyToId!!,
|
||||
content = map(details.message),
|
||||
content = timelineEventContentMapper.map(details.content),
|
||||
senderId = UserId(details.sender),
|
||||
senderDisplayName = senderProfile?.displayName,
|
||||
senderAvatarUrl = senderProfile?.avatarUrl,
|
||||
|
||||
@@ -22,6 +22,7 @@ import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.notification.NotificationContent
|
||||
import io.element.android.libraries.matrix.api.notification.NotificationData
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipState
|
||||
@@ -81,18 +82,18 @@ class NotifiableEventResolver @Inject constructor(
|
||||
}
|
||||
|
||||
private fun NotificationData.asNotifiableEvent(userId: SessionId): NotifiableEvent? {
|
||||
return when (val content = this.event.content) {
|
||||
return when (val content = this.content) {
|
||||
is NotificationContent.MessageLike.RoomMessage -> {
|
||||
buildNotifiableMessageEvent(
|
||||
sessionId = userId,
|
||||
senderId = content.senderId,
|
||||
roomId = roomId,
|
||||
eventId = eventId,
|
||||
noisy = isNoisy,
|
||||
timestamp = event.timestamp,
|
||||
timestamp = this.timestamp,
|
||||
senderName = senderDisplayName,
|
||||
senderId = senderId.value,
|
||||
body = descriptionFromMessageContent(content),
|
||||
imageUriString = event.contentUrl,
|
||||
imageUriString = this.contentUrl,
|
||||
roomName = roomDisplayName,
|
||||
roomIsDirect = isDirect,
|
||||
roomAvatarPath = roomAvatarUrl,
|
||||
@@ -109,7 +110,7 @@ class NotifiableEventResolver @Inject constructor(
|
||||
canBeReplaced = true,
|
||||
roomName = roomDisplayName,
|
||||
noisy = isNoisy,
|
||||
timestamp = event.timestamp,
|
||||
timestamp = this.timestamp,
|
||||
soundName = null,
|
||||
isRedacted = false,
|
||||
isUpdated = false,
|
||||
@@ -177,6 +178,7 @@ class NotifiableEventResolver @Inject constructor(
|
||||
@Suppress("LongParameterList")
|
||||
private fun buildNotifiableMessageEvent(
|
||||
sessionId: SessionId,
|
||||
senderId: UserId,
|
||||
roomId: RoomId,
|
||||
eventId: EventId,
|
||||
editedEventId: EventId? = null,
|
||||
@@ -184,7 +186,6 @@ private fun buildNotifiableMessageEvent(
|
||||
noisy: Boolean,
|
||||
timestamp: Long,
|
||||
senderName: String?,
|
||||
senderId: String?,
|
||||
body: String?,
|
||||
// We cannot use Uri? type here, as that could trigger a
|
||||
// NotSerializableException when persisting this to storage
|
||||
@@ -202,6 +203,7 @@ private fun buildNotifiableMessageEvent(
|
||||
isUpdated: Boolean = false
|
||||
) = NotifiableMessageEvent(
|
||||
sessionId = sessionId,
|
||||
senderId = senderId,
|
||||
roomId = roomId,
|
||||
eventId = eventId,
|
||||
editedEventId = editedEventId,
|
||||
@@ -209,7 +211,6 @@ private fun buildNotifiableMessageEvent(
|
||||
noisy = noisy,
|
||||
timestamp = timestamp,
|
||||
senderName = senderName,
|
||||
senderId = senderId,
|
||||
body = body,
|
||||
imageUriString = imageUriString,
|
||||
threadId = threadId,
|
||||
|
||||
@@ -108,7 +108,7 @@ class RoomGroupMessageCreator @Inject constructor(
|
||||
Person.Builder()
|
||||
.setName(event.senderName?.annotateForDebug(70))
|
||||
.setIcon(bitmapLoader.getUserIcon(event.senderAvatarPath))
|
||||
.setKey(event.senderId)
|
||||
.setKey(event.senderId.value)
|
||||
.build()
|
||||
}
|
||||
when {
|
||||
|
||||
@@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.EventType
|
||||
import io.element.android.services.appnavstate.api.AppNavigationState
|
||||
import io.element.android.services.appnavstate.api.currentRoomId
|
||||
@@ -32,10 +33,10 @@ data class NotifiableMessageEvent(
|
||||
override val eventId: EventId,
|
||||
override val editedEventId: EventId?,
|
||||
override val canBeReplaced: Boolean,
|
||||
val senderId: UserId,
|
||||
val noisy: Boolean,
|
||||
val timestamp: Long,
|
||||
val senderName: String?,
|
||||
val senderId: String?,
|
||||
val body: String?,
|
||||
// We cannot use Uri? type here, as that could trigger a
|
||||
// NotSerializableException when persisting this to storage
|
||||
|
||||
@@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
@@ -84,7 +85,7 @@ fun aNotifiableMessageEvent(
|
||||
noisy = false,
|
||||
timestamp = 0,
|
||||
senderName = "sender-name",
|
||||
senderId = "sending-id",
|
||||
senderId = UserId("@sending-id:domain.com"),
|
||||
body = "message-body",
|
||||
roomId = roomId,
|
||||
threadId = threadId,
|
||||
|
||||
@@ -29,6 +29,10 @@ dependencyResolutionManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
// To have immediate access to Rust SDK versions
|
||||
maven {
|
||||
url = URI("https://s01.oss.sonatype.org/content/repositories/releases")
|
||||
}
|
||||
maven {
|
||||
url = URI("https://www.jitpack.io")
|
||||
content {
|
||||
|
||||
Reference in New Issue
Block a user