Merge branch 'develop' into feature/fga/update-rust-sdk-0.1.29-again

This commit is contained in:
ganfra 2023-07-10 15:41:42 +02:00
commit 9e5a3d14e5
225 changed files with 1635 additions and 815 deletions

View file

@ -28,19 +28,19 @@ class NotificationMapper {
private val timelineEventMapper = TimelineEventMapper()
fun map(notificationItem: NotificationItem): NotificationData {
return notificationItem.use {
return notificationItem.use { item ->
NotificationData(
senderId = UserId(it.event.senderId()),
eventId = EventId(it.event.eventId()),
roomId = RoomId(it.roomInfo.id),
senderAvatarUrl = it.senderInfo.avatarUrl,
senderDisplayName = it.senderInfo.displayName,
roomAvatarUrl = it.roomInfo.avatarUrl,
roomDisplayName = it.roomInfo.displayName,
isDirect = it.roomInfo.isDirect,
isEncrypted = it.roomInfo.isEncrypted.orFalse(),
isNoisy = it.isNoisy,
event = it.event.use { event -> timelineEventMapper.map(event) }
senderId = UserId(item.event.senderId()),
eventId = EventId(item.event.eventId()),
roomId = RoomId(item.roomInfo.id),
senderAvatarUrl = item.senderInfo.avatarUrl,
senderDisplayName = item.senderInfo.displayName,
roomAvatarUrl = item.roomInfo.avatarUrl ?: item.senderInfo.avatarUrl.takeIf { item.roomInfo.isDirect },
roomDisplayName = item.roomInfo.displayName,
isDirect = item.roomInfo.isDirect,
isEncrypted = item.roomInfo.isEncrypted.orFalse(),
isNoisy = item.isNoisy,
event = item.event.use { event -> timelineEventMapper.map(event) }
)
}
}

View file

@ -36,7 +36,8 @@ class RustNotificationService(
filterByPushRules: Boolean,
): Result<NotificationData?> {
return runCatching {
client.getNotificationItem(roomId.value, eventId.value, filterByPushRules)?.use(notificationMapper::map)
val item = client.getNotificationItem(roomId.value, eventId.value, filterByPushRules)
item?.use(notificationMapper::map)
}
}
}

View file

@ -16,9 +16,11 @@
package io.element.android.libraries.matrix.impl.notification
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
import org.matrix.rustcomponents.sdk.MessageType
import org.matrix.rustcomponents.sdk.StateEventContent
import org.matrix.rustcomponents.sdk.TimelineEvent
import org.matrix.rustcomponents.sdk.TimelineEventType
@ -38,71 +40,62 @@ class TimelineEventMapper @Inject constructor() {
}
}
private fun TimelineEventType.toContent(): String {
private fun TimelineEventType.toContent(): NotificationContent {
return when (this) {
is TimelineEventType.MessageLike -> content.toContent()
is TimelineEventType.State -> content.toContent()
}
}
private fun StateEventContent.toContent(): String {
private fun StateEventContent.toContent(): NotificationContent.StateEvent {
return when (this) {
StateEventContent.PolicyRuleRoom -> "PolicyRuleRoom"
StateEventContent.PolicyRuleServer -> "PolicyRuleServer"
StateEventContent.PolicyRuleUser -> "PolicyRuleUser"
StateEventContent.RoomAliases -> "RoomAliases"
StateEventContent.RoomAvatar -> "RoomAvatar"
StateEventContent.RoomCanonicalAlias -> "RoomCanonicalAlias"
StateEventContent.RoomCreate -> "RoomCreate"
StateEventContent.RoomEncryption -> "RoomEncryption"
StateEventContent.RoomGuestAccess -> "RoomGuestAccess"
StateEventContent.RoomHistoryVisibility -> "RoomHistoryVisibility"
StateEventContent.RoomJoinRules -> "RoomJoinRules"
is StateEventContent.RoomMemberContent -> "$userId is now $membershipState"
StateEventContent.RoomName -> "RoomName"
StateEventContent.RoomPinnedEvents -> "RoomPinnedEvents"
StateEventContent.RoomPowerLevels -> "RoomPowerLevels"
StateEventContent.RoomServerAcl -> "RoomServerAcl"
StateEventContent.RoomThirdPartyInvite -> "RoomThirdPartyInvite"
StateEventContent.RoomTombstone -> "RoomTombstone"
StateEventContent.RoomTopic -> "RoomTopic"
StateEventContent.SpaceChild -> "SpaceChild"
StateEventContent.SpaceParent -> "SpaceParent"
StateEventContent.PolicyRuleRoom -> NotificationContent.StateEvent.PolicyRuleRoom
StateEventContent.PolicyRuleServer -> NotificationContent.StateEvent.PolicyRuleServer
StateEventContent.PolicyRuleUser -> NotificationContent.StateEvent.PolicyRuleUser
StateEventContent.RoomAliases -> NotificationContent.StateEvent.RoomAliases
StateEventContent.RoomAvatar -> NotificationContent.StateEvent.RoomAvatar
StateEventContent.RoomCanonicalAlias -> NotificationContent.StateEvent.RoomCanonicalAlias
StateEventContent.RoomCreate -> NotificationContent.StateEvent.RoomCreate
StateEventContent.RoomEncryption -> NotificationContent.StateEvent.RoomEncryption
StateEventContent.RoomGuestAccess -> NotificationContent.StateEvent.RoomGuestAccess
StateEventContent.RoomHistoryVisibility -> NotificationContent.StateEvent.RoomHistoryVisibility
StateEventContent.RoomJoinRules -> NotificationContent.StateEvent.RoomJoinRules
is StateEventContent.RoomMemberContent -> {
NotificationContent.StateEvent.RoomMemberContent(userId, RoomMemberMapper.mapMembership(membershipState))
}
StateEventContent.RoomName -> NotificationContent.StateEvent.RoomName
StateEventContent.RoomPinnedEvents -> NotificationContent.StateEvent.RoomPinnedEvents
StateEventContent.RoomPowerLevels -> NotificationContent.StateEvent.RoomPowerLevels
StateEventContent.RoomServerAcl -> NotificationContent.StateEvent.RoomServerAcl
StateEventContent.RoomThirdPartyInvite -> NotificationContent.StateEvent.RoomThirdPartyInvite
StateEventContent.RoomTombstone -> NotificationContent.StateEvent.RoomTombstone
StateEventContent.RoomTopic -> NotificationContent.StateEvent.RoomTopic
StateEventContent.SpaceChild -> NotificationContent.StateEvent.SpaceChild
StateEventContent.SpaceParent -> NotificationContent.StateEvent.SpaceParent
}
}
private fun MessageLikeEventContent.toContent(): String {
private fun MessageLikeEventContent.toContent(): NotificationContent.MessageLike {
return use {
when (it) {
MessageLikeEventContent.CallAnswer -> "CallAnswer"
MessageLikeEventContent.CallCandidates -> "CallCandidates"
MessageLikeEventContent.CallHangup -> "CallHangup"
MessageLikeEventContent.CallInvite -> "CallInvite"
MessageLikeEventContent.KeyVerificationAccept -> "KeyVerificationAccept"
MessageLikeEventContent.KeyVerificationCancel -> "KeyVerificationCancel"
MessageLikeEventContent.KeyVerificationDone -> "KeyVerificationDone"
MessageLikeEventContent.KeyVerificationKey -> "KeyVerificationKey"
MessageLikeEventContent.KeyVerificationMac -> "KeyVerificationMac"
MessageLikeEventContent.KeyVerificationReady -> "KeyVerificationReady"
MessageLikeEventContent.KeyVerificationStart -> "KeyVerificationStart"
is MessageLikeEventContent.ReactionContent -> "Reacted to ${it.relatedEventId.take(8)}"
MessageLikeEventContent.RoomEncrypted -> "RoomEncrypted"
is MessageLikeEventContent.RoomMessage -> it.messageType.toContent()
MessageLikeEventContent.RoomRedaction -> "RoomRedaction"
MessageLikeEventContent.Sticker -> "Sticker"
MessageLikeEventContent.CallAnswer -> NotificationContent.MessageLike.CallAnswer
MessageLikeEventContent.CallCandidates -> NotificationContent.MessageLike.CallCandidates
MessageLikeEventContent.CallHangup -> NotificationContent.MessageLike.CallHangup
MessageLikeEventContent.CallInvite -> NotificationContent.MessageLike.CallInvite
MessageLikeEventContent.KeyVerificationAccept -> NotificationContent.MessageLike.KeyVerificationAccept
MessageLikeEventContent.KeyVerificationCancel -> NotificationContent.MessageLike.KeyVerificationCancel
MessageLikeEventContent.KeyVerificationDone -> NotificationContent.MessageLike.KeyVerificationDone
MessageLikeEventContent.KeyVerificationKey -> NotificationContent.MessageLike.KeyVerificationKey
MessageLikeEventContent.KeyVerificationMac -> NotificationContent.MessageLike.KeyVerificationMac
MessageLikeEventContent.KeyVerificationReady -> NotificationContent.MessageLike.KeyVerificationReady
MessageLikeEventContent.KeyVerificationStart -> NotificationContent.MessageLike.KeyVerificationStart
is MessageLikeEventContent.ReactionContent -> NotificationContent.MessageLike.ReactionContent(it.relatedEventId)
MessageLikeEventContent.RoomEncrypted -> NotificationContent.MessageLike.RoomEncrypted
is MessageLikeEventContent.RoomMessage -> {
NotificationContent.MessageLike.RoomMessage(EventMessageMapper().mapMessageType(it.messageType))
}
MessageLikeEventContent.RoomRedaction -> NotificationContent.MessageLike.RoomRedaction
MessageLikeEventContent.Sticker -> NotificationContent.MessageLike.Sticker
}
}
}
private fun MessageType.toContent(): String {
return when (this) {
is MessageType.Audio -> content.use { it.body }
is MessageType.Emote -> content.body
is MessageType.File -> content.use { it.body }
is MessageType.Image -> content.use { it.body }
is MessageType.Location -> content.body
is MessageType.Notice -> content.body
is MessageType.Text -> content.body
is MessageType.Video -> content.use { it.body }
}
}

View file

@ -24,23 +24,30 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import org.matrix.rustcomponents.sdk.RoomListService
import org.matrix.rustcomponents.sdk.RoomListServiceState
import timber.log.Timber
import java.util.concurrent.atomic.AtomicBoolean
class RustSyncService(
private val roomListService: RoomListService,
sessionCoroutineScope: CoroutineScope
) : SyncService {
private val isSyncing = AtomicBoolean(false)
override fun startSync() = runCatching {
if (!roomListService.isSyncing()) {
if (isSyncing.compareAndSet(false, true)) {
Timber.v("Start sync")
roomListService.sync()
}
}
override fun stopSync() = runCatching {
if (roomListService.isSyncing()) {
if (isSyncing.compareAndSet(true, false)) {
Timber.v("Stop sync")
roomListService.stopSync()
}
}
@ -49,6 +56,10 @@ class RustSyncService(
roomListService
.stateFlow()
.map(RoomListServiceState::toSyncState)
.onEach { state ->
Timber.v("Sync state=$state")
isSyncing.set(state == SyncState.Syncing)
}
.distinctUntilChanged()
.stateIn(sessionCoroutineScope, SharingStarted.WhileSubscribed(), SyncState.Idle)
.stateIn(sessionCoroutineScope, SharingStarted.Eagerly, SyncState.Idle)
}

View file

@ -33,48 +33,17 @@ import io.element.android.libraries.matrix.api.timeline.item.event.UnknownMessag
import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType
import io.element.android.libraries.matrix.impl.media.map
import org.matrix.rustcomponents.sdk.Message
import org.matrix.rustcomponents.sdk.MessageType
import org.matrix.rustcomponents.sdk.ProfileDetails
import org.matrix.rustcomponents.sdk.RepliedToEventDetails
import org.matrix.rustcomponents.sdk.use
import org.matrix.rustcomponents.sdk.FormattedBody as RustFormattedBody
import org.matrix.rustcomponents.sdk.MessageFormat as RustMessageFormat
import org.matrix.rustcomponents.sdk.MessageType as RustMessageType
class EventMessageMapper {
fun map(message: Message): MessageContent = message.use {
val type = it.msgtype().use { type ->
when (type) {
is MessageType.Audio -> {
AudioMessageType(type.content.body, type.content.source.map(), type.content.info?.map())
}
is MessageType.File -> {
FileMessageType(type.content.body, type.content.source.map(), type.content.info?.map())
}
is MessageType.Image -> {
ImageMessageType(type.content.body, type.content.source.map(), type.content.info?.map())
}
is MessageType.Location -> {
LocationMessageType(type.content.body, type.content.geoUri, type.content.description)
}
is MessageType.Notice -> {
NoticeMessageType(type.content.body, type.content.formatted?.map())
}
is MessageType.Text -> {
TextMessageType(type.content.body, type.content.formatted?.map())
}
is MessageType.Emote -> {
EmoteMessageType(type.content.body, type.content.formatted?.map())
}
is MessageType.Video -> {
VideoMessageType(type.content.body, type.content.source.map(), type.content.info?.map())
}
null -> {
UnknownMessageType
}
}
}
val type = it.msgtype().use(this::mapMessageType)
val inReplyToId = it.inReplyTo()?.eventId?.let(::EventId)
val inReplyToEvent: InReplyTo? = (it.inReplyTo()?.event)?.use { details ->
when (details) {
@ -99,6 +68,34 @@ class EventMessageMapper {
type = type
)
}
fun mapMessageType(type: RustMessageType?) = when (type) {
is RustMessageType.Audio -> {
AudioMessageType(type.content.body, type.content.source.map(), type.content.info?.map())
}
is RustMessageType.File -> {
FileMessageType(type.content.body, type.content.source.map(), type.content.info?.map())
}
is RustMessageType.Image -> {
ImageMessageType(type.content.body, type.content.source.map(), type.content.info?.map())
}
is RustMessageType.Notice -> {
NoticeMessageType(type.content.body, type.content.formatted?.map())
}
is RustMessageType.Text -> {
TextMessageType(type.content.body, type.content.formatted?.map())
}
is RustMessageType.Emote -> {
EmoteMessageType(type.content.body, type.content.formatted?.map())
}
is RustMessageType.Video -> {
VideoMessageType(type.content.body, type.content.source.map(), type.content.info?.map())
}
is RustMessageType.Location -> {
LocationMessageType(type.content.body, type.content.geoUri, type.content.description)
}
null -> UnknownMessageType
}
}
private fun RustFormattedBody.map(): FormattedBody = FormattedBody(