Merge branch 'develop' into feature/fga/user_detail_direct_chat
This commit is contained in:
commit
03a2e31d46
76 changed files with 329 additions and 148 deletions
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.encryption
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
@Immutable
|
||||
sealed interface BackupUploadState {
|
||||
data object Unknown : BackupUploadState
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.encryption
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
@Immutable
|
||||
sealed interface SteadyStateException {
|
||||
/**
|
||||
* The backup can be deleted.
|
||||
|
|
|
|||
|
|
@ -16,9 +16,10 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.media
|
||||
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlin.time.Duration
|
||||
|
||||
data class AudioDetails(
|
||||
val duration: Duration,
|
||||
val waveform: List<Float>,
|
||||
val waveform: ImmutableList<Float>,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -17,18 +17,21 @@
|
|||
package io.element.android.libraries.matrix.api.permalink
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.compose.runtime.Immutable
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
/**
|
||||
* This sealed class represents all the permalink cases.
|
||||
* You don't have to instantiate yourself but should use [PermalinkParser] instead.
|
||||
*/
|
||||
@Immutable
|
||||
sealed interface PermalinkData {
|
||||
|
||||
data class RoomLink(
|
||||
val roomIdOrAlias: String,
|
||||
val isRoomAlias: Boolean,
|
||||
val eventId: String?,
|
||||
val viaParameters: List<String>
|
||||
val viaParameters: ImmutableList<String>
|
||||
) : PermalinkData
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package io.element.android.libraries.matrix.api.permalink
|
|||
import android.net.Uri
|
||||
import android.net.UrlQuerySanitizer
|
||||
import io.element.android.libraries.matrix.api.core.MatrixPatterns
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import timber.log.Timber
|
||||
import java.net.URLDecoder
|
||||
|
||||
|
|
@ -80,7 +81,7 @@ object PermalinkParser {
|
|||
roomIdOrAlias = decodedIdentifier,
|
||||
isRoomAlias = true,
|
||||
eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) },
|
||||
viaParameters = viaQueryParameters
|
||||
viaParameters = viaQueryParameters.toImmutableList()
|
||||
)
|
||||
}
|
||||
else -> PermalinkData.FallbackLink(uri, MatrixPatterns.isGroupId(identifier))
|
||||
|
|
@ -119,7 +120,7 @@ object PermalinkParser {
|
|||
roomIdOrAlias = identifier,
|
||||
isRoomAlias = false,
|
||||
eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) },
|
||||
viaParameters = viaQueryParameters
|
||||
viaParameters = viaQueryParameters.toImmutableList()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,6 +132,8 @@ interface MatrixRoom : Closeable {
|
|||
|
||||
suspend fun canUserTriggerRoomNotification(userId: UserId): Result<Boolean>
|
||||
|
||||
suspend fun canUserJoinCall(userId: UserId): Result<Boolean>
|
||||
|
||||
suspend fun updateAvatar(mimeType: String, data: ByteArray): Result<Unit>
|
||||
|
||||
suspend fun removeAvatar(): Result<Unit>
|
||||
|
|
|
|||
|
|
@ -16,8 +16,11 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.room
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Immutable
|
||||
data class MatrixRoomInfo(
|
||||
val id: String,
|
||||
val name: String?,
|
||||
|
|
@ -28,7 +31,7 @@ data class MatrixRoomInfo(
|
|||
val isSpace: Boolean,
|
||||
val isTombstoned: Boolean,
|
||||
val canonicalAlias: String?,
|
||||
val alternativeAliases: List<String>,
|
||||
val alternativeAliases: ImmutableList<String>,
|
||||
val currentUserMembership: CurrentUserMembership,
|
||||
val latestEvent: EventTimelineItem?,
|
||||
val inviter: RoomMember?,
|
||||
|
|
@ -39,5 +42,5 @@ data class MatrixRoomInfo(
|
|||
val notificationCount: Long,
|
||||
val userDefinedNotificationMode: RoomNotificationMode?,
|
||||
val hasRoomCall: Boolean,
|
||||
val activeRoomCallParticipants: List<String>
|
||||
val activeRoomCallParticipants: ImmutableList<String>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -17,13 +17,14 @@
|
|||
package io.element.android.libraries.matrix.api.room
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Immutable
|
||||
sealed interface MatrixRoomMembersState {
|
||||
data object Unknown : MatrixRoomMembersState
|
||||
data class Pending(val prevRoomMembers: List<RoomMember>? = null) : MatrixRoomMembersState
|
||||
data class Error(val failure: Throwable, val prevRoomMembers: List<RoomMember>? = null) : MatrixRoomMembersState
|
||||
data class Ready(val roomMembers: List<RoomMember>) : MatrixRoomMembersState
|
||||
data class Pending(val prevRoomMembers: ImmutableList<RoomMember>? = null) : MatrixRoomMembersState
|
||||
data class Error(val failure: Throwable, val prevRoomMembers: ImmutableList<RoomMember>? = null) : MatrixRoomMembersState
|
||||
data class Ready(val roomMembers: ImmutableList<RoomMember>) : MatrixRoomMembersState
|
||||
}
|
||||
|
||||
fun MatrixRoomMembersState.roomMembers(): List<RoomMember>? {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.roomlist
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
/**
|
||||
|
|
@ -25,6 +26,7 @@ import kotlinx.coroutines.flow.StateFlow
|
|||
*/
|
||||
interface RoomListService {
|
||||
|
||||
@Immutable
|
||||
sealed interface State {
|
||||
data object Idle : State
|
||||
data object Running : State
|
||||
|
|
@ -32,6 +34,7 @@ interface RoomListService {
|
|||
data object Terminated : State
|
||||
}
|
||||
|
||||
@Immutable
|
||||
sealed interface SyncIndicator {
|
||||
data object Show : SyncIndicator
|
||||
data object Hide : SyncIndicator
|
||||
|
|
|
|||
|
|
@ -16,11 +16,15 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.timeline.item.event
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.media.ImageInfo
|
||||
import io.element.android.libraries.matrix.api.poll.PollAnswer
|
||||
import io.element.android.libraries.matrix.api.poll.PollKind
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.ImmutableMap
|
||||
|
||||
@Immutable
|
||||
sealed interface EventContent
|
||||
|
||||
data class MessageContent(
|
||||
|
|
@ -43,14 +47,16 @@ data class PollContent(
|
|||
val question: String,
|
||||
val kind: PollKind,
|
||||
val maxSelections: ULong,
|
||||
val answers: List<PollAnswer>,
|
||||
val votes: Map<String, List<UserId>>,
|
||||
val answers: ImmutableList<PollAnswer>,
|
||||
val votes: ImmutableMap<String, ImmutableList<UserId>>,
|
||||
val endTime: ULong?
|
||||
) : EventContent
|
||||
|
||||
data class UnableToDecryptContent(
|
||||
val data: Data
|
||||
) : EventContent {
|
||||
|
||||
@Immutable
|
||||
sealed interface Data {
|
||||
data class OlmV1Curve25519AesSha2(
|
||||
val senderKey: String
|
||||
|
|
|
|||
|
|
@ -16,7 +16,11 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.timeline.item.event
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Immutable
|
||||
data class EventReaction(
|
||||
val key: String,
|
||||
val senders: List<ReactionSender>
|
||||
val senders: ImmutableList<ReactionSender>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.core.EventId
|
|||
import io.element.android.libraries.matrix.api.core.TransactionId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
data class EventTimelineItem(
|
||||
val eventId: EventId?,
|
||||
|
|
@ -29,8 +30,8 @@ data class EventTimelineItem(
|
|||
val isOwn: Boolean,
|
||||
val isRemote: Boolean,
|
||||
val localSendState: LocalEventSendState?,
|
||||
val reactions: List<EventReaction>,
|
||||
val receipts: List<Receipt>,
|
||||
val reactions: ImmutableList<EventReaction>,
|
||||
val receipts: ImmutableList<Receipt>,
|
||||
val sender: UserId,
|
||||
val senderProfile: ProfileTimelineDetails,
|
||||
val timestamp: Long,
|
||||
|
|
|
|||
|
|
@ -16,9 +16,11 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.timeline.item.event
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
|
||||
@Immutable
|
||||
sealed interface InReplyTo {
|
||||
/** The event details are not loaded yet. We can fetch them. */
|
||||
data class NotLoaded(val eventId: EventId) : InReplyTo
|
||||
|
|
|
|||
|
|
@ -16,8 +16,10 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.timeline.item.event
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
|
||||
@Immutable
|
||||
sealed interface LocalEventSendState {
|
||||
data object NotSentYet : LocalEventSendState
|
||||
data object Canceled : LocalEventSendState
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.timeline.item.event
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import io.element.android.libraries.matrix.api.media.AudioDetails
|
||||
import io.element.android.libraries.matrix.api.media.AudioInfo
|
||||
import io.element.android.libraries.matrix.api.media.FileInfo
|
||||
|
|
@ -23,6 +24,7 @@ import io.element.android.libraries.matrix.api.media.ImageInfo
|
|||
import io.element.android.libraries.matrix.api.media.MediaSource
|
||||
import io.element.android.libraries.matrix.api.media.VideoInfo
|
||||
|
||||
@Immutable
|
||||
sealed interface MessageType
|
||||
|
||||
data class EmoteMessageType(
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.timeline.item.event
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
@Immutable
|
||||
sealed interface OtherState {
|
||||
data object PolicyRuleRoom : OtherState
|
||||
data object PolicyRuleServer : OtherState
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.timeline.item.event
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
@Immutable
|
||||
sealed interface ProfileTimelineDetails {
|
||||
data object Unavailable : ProfileTimelineDetails
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.user
|
||||
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
data class MatrixSearchUserResults(
|
||||
val results: List<MatrixUser>,
|
||||
val results: ImmutableList<MatrixUser>,
|
||||
val limited: Boolean,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.verification
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
|
|
@ -75,6 +77,7 @@ interface SessionVerificationService {
|
|||
}
|
||||
|
||||
/** Verification status of the current session. */
|
||||
@Immutable
|
||||
sealed interface SessionVerifiedStatus {
|
||||
/** Unknown status, we couldn't read the actual value from the SDK. */
|
||||
data object Unknown : SessionVerifiedStatus
|
||||
|
|
@ -87,6 +90,7 @@ sealed interface SessionVerifiedStatus {
|
|||
}
|
||||
|
||||
/** States produced by the [SessionVerificationService]. */
|
||||
@Immutable
|
||||
sealed interface VerificationFlowState {
|
||||
/** Initial state. */
|
||||
data object Initial : VerificationFlowState
|
||||
|
|
@ -98,7 +102,7 @@ sealed interface VerificationFlowState {
|
|||
data object StartedSasVerification : VerificationFlowState
|
||||
|
||||
/** Verification data for the SAS verification (emojis) received. */
|
||||
data class ReceivedVerificationData(val emoji: List<VerificationEmoji>) : VerificationFlowState
|
||||
data class ReceivedVerificationData(val emoji: ImmutableList<VerificationEmoji>) : VerificationFlowState
|
||||
|
||||
/** Verification completed successfully. */
|
||||
data object Finished : VerificationFlowState
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package io.element.android.libraries.matrix.api.permalink
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
|
|
@ -66,7 +67,7 @@ class PermalinkParserTest {
|
|||
roomIdOrAlias = "!aBCD1234:matrix.org",
|
||||
isRoomAlias = false,
|
||||
eventId = null,
|
||||
viaParameters = emptyList(),
|
||||
viaParameters = persistentListOf(),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -79,7 +80,7 @@ class PermalinkParserTest {
|
|||
roomIdOrAlias = "!aBCD1234:matrix.org",
|
||||
isRoomAlias = false,
|
||||
eventId = "\$1234567890abcdef:matrix.org",
|
||||
viaParameters = emptyList(),
|
||||
viaParameters = persistentListOf(),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -92,7 +93,7 @@ class PermalinkParserTest {
|
|||
roomIdOrAlias = "!aBCD1234:matrix.org",
|
||||
isRoomAlias = false,
|
||||
eventId = null,
|
||||
viaParameters = emptyList(),
|
||||
viaParameters = persistentListOf(),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -105,7 +106,7 @@ class PermalinkParserTest {
|
|||
roomIdOrAlias = "!aBCD1234:matrix.org",
|
||||
isRoomAlias = false,
|
||||
eventId = "\$1234567890abcdef:matrix.org",
|
||||
viaParameters = listOf("matrix.org", "matrix.com"),
|
||||
viaParameters = persistentListOf("matrix.org", "matrix.com"),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -118,7 +119,7 @@ class PermalinkParserTest {
|
|||
roomIdOrAlias = "#element-android:matrix.org",
|
||||
isRoomAlias = true,
|
||||
eventId = null,
|
||||
viaParameters = emptyList(),
|
||||
viaParameters = persistentListOf(),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ dependencies {
|
|||
implementation("net.java.dev.jna:jna:5.13.0@aar")
|
||||
implementation(libs.androidx.datastore.preferences)
|
||||
implementation(libs.serialization.json)
|
||||
implementation(libs.kotlinx.collections.immutable)
|
||||
|
||||
testImplementation(libs.test.junit)
|
||||
testImplementation(libs.test.truth)
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ import org.matrix.rustcomponents.sdk.BackupState
|
|||
import org.matrix.rustcomponents.sdk.Client
|
||||
import org.matrix.rustcomponents.sdk.ClientDelegate
|
||||
import org.matrix.rustcomponents.sdk.NotificationProcessSetup
|
||||
import org.matrix.rustcomponents.sdk.PowerLevels
|
||||
import org.matrix.rustcomponents.sdk.Room
|
||||
import org.matrix.rustcomponents.sdk.RoomListItem
|
||||
import org.matrix.rustcomponents.sdk.TaskHandle
|
||||
|
|
@ -274,6 +275,7 @@ class RustMatrixClient constructor(
|
|||
},
|
||||
invite = createRoomParams.invite?.map { it.value },
|
||||
avatar = createRoomParams.avatar,
|
||||
powerLevelContentOverride = defaultRoomCreationPowerLevels,
|
||||
)
|
||||
val roomId = RoomId(client.createRoom(rustParams))
|
||||
|
||||
|
|
@ -296,7 +298,7 @@ class RustMatrixClient constructor(
|
|||
isDirect = true,
|
||||
visibility = RoomVisibility.PRIVATE,
|
||||
preset = RoomPreset.TRUSTED_PRIVATE_CHAT,
|
||||
invite = listOf(userId)
|
||||
invite = listOf(userId),
|
||||
)
|
||||
return createRoom(createRoomParams)
|
||||
}
|
||||
|
|
@ -481,3 +483,18 @@ class RustMatrixClient constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private val defaultRoomCreationPowerLevels = PowerLevels(
|
||||
usersDefault = null,
|
||||
eventsDefault = null,
|
||||
stateDefault = null,
|
||||
ban = null,
|
||||
kick = null,
|
||||
redact = null,
|
||||
invite = null,
|
||||
notifications = null,
|
||||
users = mapOf(),
|
||||
events = mapOf(
|
||||
"m.call.member" to 0,
|
||||
"org.matrix.msc3401.call.member" to 0,
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -17,13 +17,14 @@
|
|||
package io.element.android.libraries.matrix.impl.media
|
||||
|
||||
import io.element.android.libraries.matrix.api.media.AudioDetails
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlin.time.toJavaDuration
|
||||
import kotlin.time.toKotlinDuration
|
||||
import org.matrix.rustcomponents.sdk.UnstableAudioDetailsContent as RustAudioDetails
|
||||
|
||||
fun RustAudioDetails.map(): AudioDetails = AudioDetails(
|
||||
duration = duration.toKotlinDuration(),
|
||||
waveform = waveform.fromMSC3246range(),
|
||||
waveform = waveform.fromMSC3246range().toImmutableList(),
|
||||
)
|
||||
|
||||
fun AudioDetails.map(): RustAudioDetails = RustAudioDetails(
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.room.CurrentUserMembership
|
|||
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
|
||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||
import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import org.matrix.rustcomponents.sdk.use
|
||||
import org.matrix.rustcomponents.sdk.Membership as RustMembership
|
||||
import org.matrix.rustcomponents.sdk.RoomInfo as RustRoomInfo
|
||||
|
|
@ -40,7 +41,7 @@ class MatrixRoomInfoMapper(
|
|||
isSpace = it.isSpace,
|
||||
isTombstoned = it.isTombstoned,
|
||||
canonicalAlias = it.canonicalAlias,
|
||||
alternativeAliases = it.alternativeAliases,
|
||||
alternativeAliases = it.alternativeAliases.toImmutableList(),
|
||||
currentUserMembership = it.membership.map(),
|
||||
latestEvent = it.latestEvent?.use (timelineItemMapper::map),
|
||||
inviter = it.inviter?.use(RoomMemberMapper::map),
|
||||
|
|
@ -51,7 +52,7 @@ class MatrixRoomInfoMapper(
|
|||
notificationCount = it.notificationCount.toLong(),
|
||||
userDefinedNotificationMode = it.userDefinedNotificationMode?.map(),
|
||||
hasRoomCall = it.hasRoomCall,
|
||||
activeRoomCallParticipants = it.activeRoomCallParticipants
|
||||
activeRoomCallParticipants = it.activeRoomCallParticipants.toImmutableList()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ import io.element.android.libraries.matrix.impl.widget.RustWidgetDriver
|
|||
import io.element.android.libraries.matrix.impl.widget.generateWidgetWebViewUrl
|
||||
import io.element.android.libraries.sessionstorage.api.SessionData
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
|
|
@ -198,7 +199,7 @@ class RustMatrixRoom(
|
|||
|
||||
override suspend fun updateMembers(): Result<Unit> = withContext(roomMembersDispatcher) {
|
||||
val currentState = _membersStateFlow.value
|
||||
val currentMembers = currentState.roomMembers()
|
||||
val currentMembers = currentState.roomMembers()?.toImmutableList()
|
||||
_membersStateFlow.value = MatrixRoomMembersState.Pending(prevRoomMembers = currentMembers)
|
||||
var rustMembers: List<RoomMember>? = null
|
||||
try {
|
||||
|
|
@ -213,7 +214,7 @@ class RustMatrixRoom(
|
|||
}
|
||||
}
|
||||
val mappedMembers = rustMembers.parallelMap(RoomMemberMapper::map)
|
||||
_membersStateFlow.value = MatrixRoomMembersState.Ready(mappedMembers)
|
||||
_membersStateFlow.value = MatrixRoomMembersState.Ready(mappedMembers.toImmutableList())
|
||||
Result.success(Unit)
|
||||
} catch (exception: CancellationException) {
|
||||
_membersStateFlow.value = MatrixRoomMembersState.Error(prevRoomMembers = currentMembers, failure = exception)
|
||||
|
|
@ -363,6 +364,12 @@ class RustMatrixRoom(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun canUserJoinCall(userId: UserId): Result<Boolean> {
|
||||
return runCatching {
|
||||
innerRoom.canUserSendState(userId.value, StateEventType.ROOM_MEMBER_EVENT.map())
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun sendImage(file: File, thumbnailFile: File, imageInfo: ImageInfo, progressCallback: ProgressCallback?): Result<MediaUploadHandler> {
|
||||
return sendAttachment(listOf(file, thumbnailFile)) {
|
||||
innerTimeline.sendImage(file.path, thumbnailFile.path, imageInfo.map(), progressCallback?.toProgressWatcher())
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimeli
|
|||
import io.element.android.libraries.matrix.api.timeline.item.event.ReactionSender
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.Receipt
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.TimelineItemEventOrigin
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import org.matrix.rustcomponents.sdk.Reaction
|
||||
import org.matrix.rustcomponents.sdk.EventItemOrigin as RustEventItemOrigin
|
||||
import org.matrix.rustcomponents.sdk.EventSendState as RustEventSendState
|
||||
|
|
@ -81,7 +84,7 @@ fun RustEventSendState?.map(): LocalEventSendState? {
|
|||
}
|
||||
}
|
||||
|
||||
private fun List<Reaction>?.map(): List<EventReaction> {
|
||||
private fun List<Reaction>?.map(): ImmutableList<EventReaction> {
|
||||
return this?.map {
|
||||
EventReaction(
|
||||
key = it.key,
|
||||
|
|
@ -90,18 +93,20 @@ private fun List<Reaction>?.map(): List<EventReaction> {
|
|||
senderId = UserId(sender.senderId),
|
||||
timestamp = sender.timestamp.toLong()
|
||||
)
|
||||
}
|
||||
}.toImmutableList()
|
||||
)
|
||||
} ?: emptyList()
|
||||
}?.toImmutableList() ?: persistentListOf()
|
||||
}
|
||||
|
||||
private fun Map<String, RustReceipt>.map(): List<Receipt> {
|
||||
private fun Map<String, RustReceipt>.map(): ImmutableList<Receipt> {
|
||||
return map {
|
||||
Receipt(
|
||||
userId = UserId(it.key),
|
||||
timestamp = it.value.timestamp?.toLong() ?: 0
|
||||
)
|
||||
}.sortedByDescending { it.timestamp }
|
||||
Receipt(
|
||||
userId = UserId(it.key),
|
||||
timestamp = it.value.timestamp?.toLong() ?: 0
|
||||
)
|
||||
}
|
||||
.sortedByDescending { it.timestamp }
|
||||
.toImmutableList()
|
||||
}
|
||||
|
||||
private fun RustEventTimelineItemDebugInfo.map(): TimelineItemDebugInfo {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecry
|
|||
import io.element.android.libraries.matrix.api.timeline.item.event.UnknownContent
|
||||
import io.element.android.libraries.matrix.impl.media.map
|
||||
import io.element.android.libraries.matrix.impl.poll.map
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableMap
|
||||
import org.matrix.rustcomponents.sdk.TimelineItemContent
|
||||
import org.matrix.rustcomponents.sdk.TimelineItemContentKind
|
||||
import org.matrix.rustcomponents.sdk.use
|
||||
|
|
@ -106,10 +108,10 @@ class TimelineEventContentMapper(private val eventMessageMapper: EventMessageMap
|
|||
question = kind.question,
|
||||
kind = kind.kind.map(),
|
||||
maxSelections = kind.maxSelections,
|
||||
answers = kind.answers.map { answer -> answer.map() },
|
||||
answers = kind.answers.map { answer -> answer.map() }.toImmutableList(),
|
||||
votes = kind.votes.mapValues { vote ->
|
||||
vote.value.map { userId -> UserId(userId) }
|
||||
},
|
||||
vote.value.map { userId -> UserId(userId) }.toImmutableList()
|
||||
}.toImmutableMap(),
|
||||
endTime = kind.endTime,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,13 +17,14 @@
|
|||
package io.element.android.libraries.matrix.impl.usersearch
|
||||
|
||||
import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import org.matrix.rustcomponents.sdk.SearchUsersResults
|
||||
|
||||
object UserSearchResultMapper {
|
||||
|
||||
fun map(result: SearchUsersResults): MatrixSearchUserResults {
|
||||
return MatrixSearchUserResults(
|
||||
results = result.results.map(UserProfileMapper::map),
|
||||
results = result.results.map(UserProfileMapper::map).toImmutableList(),
|
||||
limited = result.limited,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatu
|
|||
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
|
||||
import io.element.android.libraries.matrix.api.verification.VerificationFlowState
|
||||
import io.element.android.libraries.matrix.impl.sync.RustSyncService
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
|
@ -106,8 +107,9 @@ class RustSessionVerificationService(
|
|||
|
||||
override fun didReceiveVerificationData(data: List<SessionVerificationEmoji>) {
|
||||
val emojis = data.map { emoji ->
|
||||
emoji.use { VerificationEmoji(it.symbol(), it.description()) }
|
||||
}
|
||||
emoji.use { VerificationEmoji(it.symbol(), it.description()) }
|
||||
}
|
||||
.toImmutableList()
|
||||
_verificationFlowState.value = VerificationFlowState.ReceivedVerificationData(emojis)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,4 +28,5 @@ dependencies {
|
|||
api(libs.coroutines.core)
|
||||
implementation(libs.coroutines.test)
|
||||
implementation(projects.tests.testutils)
|
||||
implementation(libs.kotlinx.collections.immutable)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ import io.element.android.libraries.matrix.test.notificationsettings.FakeNotific
|
|||
import io.element.android.libraries.matrix.test.timeline.FakeMatrixTimeline
|
||||
import io.element.android.libraries.matrix.test.widget.FakeWidgetDriver
|
||||
import io.element.android.tests.testutils.simulateLongTask
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
|
|
@ -110,6 +111,7 @@ class FakeMatrixRoom(
|
|||
private var generateWidgetWebViewUrlResult = Result.success("https://call.element.io")
|
||||
private var getWidgetDriverResult: Result<MatrixWidgetDriver> = Result.success(FakeWidgetDriver())
|
||||
private var canUserTriggerRoomNotificationResult: Result<Boolean> = Result.success(true)
|
||||
private var canUserJoinCallResult: Result<Boolean> = Result.success(true)
|
||||
var sendMessageMentions = emptyList<Mention>()
|
||||
val editMessageCalls = mutableListOf<Pair<String, String?>>()
|
||||
|
||||
|
|
@ -291,6 +293,10 @@ class FakeMatrixRoom(
|
|||
return canUserTriggerRoomNotificationResult
|
||||
}
|
||||
|
||||
override suspend fun canUserJoinCall(userId: UserId): Result<Boolean> {
|
||||
return canUserJoinCallResult
|
||||
}
|
||||
|
||||
override suspend fun sendImage(
|
||||
file: File,
|
||||
thumbnailFile: File,
|
||||
|
|
@ -473,6 +479,10 @@ class FakeMatrixRoom(
|
|||
canUserTriggerRoomNotificationResult = result
|
||||
}
|
||||
|
||||
fun givenCanUserJoinCall(result: Result<Boolean>) {
|
||||
canUserJoinCallResult = result
|
||||
}
|
||||
|
||||
fun givenIgnoreResult(result: Result<Unit>) {
|
||||
ignoreResult = result
|
||||
}
|
||||
|
|
@ -615,7 +625,7 @@ fun aRoomInfo(
|
|||
isSpace = isSpace,
|
||||
isTombstoned = isTombstoned,
|
||||
canonicalAlias = canonicalAlias,
|
||||
alternativeAliases = alternativeAliases,
|
||||
alternativeAliases = alternativeAliases.toImmutableList(),
|
||||
currentUserMembership = currentUserMembership,
|
||||
latestEvent = latestEvent,
|
||||
inviter = inviter,
|
||||
|
|
@ -626,5 +636,5 @@ fun aRoomInfo(
|
|||
notificationCount = notificationCount,
|
||||
userDefinedNotificationMode = userDefinedNotificationMode,
|
||||
hasRoomCall = hasRoomCall,
|
||||
activeRoomCallParticipants = activeRoomCallParticipants
|
||||
activeRoomCallParticipants = activeRoomCallParticipants.toImmutableList(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,9 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID
|
|||
import io.element.android.libraries.matrix.test.A_ROOM_NAME
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||
import io.element.android.libraries.matrix.test.A_USER_NAME
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
|
||||
fun aRoomSummaryFilled(
|
||||
roomId: RoomId = A_ROOM_ID,
|
||||
|
|
@ -107,8 +110,8 @@ fun anEventTimelineItem(
|
|||
isOwn: Boolean = false,
|
||||
isRemote: Boolean = false,
|
||||
localSendState: LocalEventSendState? = null,
|
||||
reactions: List<EventReaction> = emptyList(),
|
||||
receipts: List<Receipt> = emptyList(),
|
||||
reactions: ImmutableList<EventReaction> = persistentListOf(),
|
||||
receipts: ImmutableList<Receipt> = persistentListOf(),
|
||||
sender: UserId = A_USER_ID,
|
||||
senderProfile: ProfileTimelineDetails = aProfileTimelineDetails(),
|
||||
timestamp: Long = 0L,
|
||||
|
|
@ -181,12 +184,12 @@ fun aTimelineItemDebugInfo(
|
|||
|
||||
fun aPollContent(
|
||||
question: String = "Do you like polls?",
|
||||
answers: List<PollAnswer> = listOf(PollAnswer("1", "Yes"), PollAnswer("2", "No")),
|
||||
answers: ImmutableList<PollAnswer> = persistentListOf(PollAnswer("1", "Yes"), PollAnswer("2", "No")),
|
||||
) = PollContent(
|
||||
question = question,
|
||||
kind = PollKind.Disclosed,
|
||||
maxSelections = 1u,
|
||||
answers = answers,
|
||||
votes = mapOf(),
|
||||
votes = persistentMapOf(),
|
||||
endTime = null
|
||||
)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import io.element.android.libraries.matrix.api.verification.SessionVerificationS
|
|||
import io.element.android.libraries.matrix.api.verification.VerificationFlowState
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
||||
import io.element.android.libraries.matrix.api.verification.VerificationEmoji
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
|
@ -29,7 +31,7 @@ class FakeSessionVerificationService : SessionVerificationService {
|
|||
private val _sessionVerifiedStatus = MutableStateFlow<SessionVerifiedStatus>(SessionVerifiedStatus.Unknown)
|
||||
private var _verificationFlowState = MutableStateFlow<VerificationFlowState>(VerificationFlowState.Initial)
|
||||
private var _canVerifySessionFlow = MutableStateFlow(true)
|
||||
private var emojiList = emptyList<VerificationEmoji>()
|
||||
private var emojiList = persistentListOf<VerificationEmoji>()
|
||||
var shouldFail = false
|
||||
|
||||
override val verificationFlowState: StateFlow<VerificationFlowState> =_verificationFlowState
|
||||
|
|
@ -87,7 +89,7 @@ class FakeSessionVerificationService : SessionVerificationService {
|
|||
}
|
||||
|
||||
fun givenEmojiList(emojis: List<VerificationEmoji>) {
|
||||
this.emojiList = emojis
|
||||
this.emojiList = emojis.toPersistentList()
|
||||
}
|
||||
|
||||
override suspend fun reset() {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package io.element.android.libraries.textcomposer
|
|||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.libraries.designsystem.theme.bgSubtleTertiary
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.wysiwyg.compose.RichTextEditorDefaults
|
||||
|
|
@ -39,7 +40,8 @@ internal object ElementRichTextEditorStyle {
|
|||
m3colors.primary
|
||||
} else {
|
||||
m3colors.secondary
|
||||
}
|
||||
},
|
||||
lineHeight = 16.25.sp,
|
||||
),
|
||||
cursor = RichTextEditorDefaults.cursorStyle(
|
||||
color = colors.iconAccentTertiary,
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
|
|
@ -85,7 +84,6 @@ import io.element.android.libraries.textcomposer.model.VoiceMessagePlayerEvent
|
|||
import io.element.android.libraries.textcomposer.model.VoiceMessageRecorderEvent
|
||||
import io.element.android.libraries.textcomposer.model.VoiceMessageState
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.wysiwyg.compose.PillStyle
|
||||
import io.element.android.wysiwyg.compose.RichTextEditor
|
||||
import io.element.android.wysiwyg.compose.RichTextEditorState
|
||||
import io.element.android.wysiwyg.display.TextDisplay
|
||||
|
|
@ -444,8 +442,6 @@ private fun TextInput(
|
|||
.fillMaxWidth(),
|
||||
style = ElementRichTextEditorStyle.create(
|
||||
hasFocus = state.hasFocus
|
||||
).copy(
|
||||
pill = PillStyle(Color.Red)
|
||||
),
|
||||
resolveMentionDisplay = resolveMentionDisplay,
|
||||
resolveRoomMentionDisplay = resolveRoomMentionDisplay,
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ dependencies {
|
|||
implementation(projects.libraries.matrixui)
|
||||
implementation(projects.libraries.matrix.api)
|
||||
api(projects.libraries.usersearch.api)
|
||||
implementation(libs.kotlinx.collections.immutable)
|
||||
|
||||
testImplementation(libs.test.junit)
|
||||
testImplementation(libs.coroutines.test)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import io.element.android.libraries.matrix.test.A_USER_ID
|
|||
import io.element.android.libraries.matrix.test.A_USER_ID_2
|
||||
import io.element.android.libraries.matrix.test.A_USER_NAME
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
|
|
@ -37,7 +38,7 @@ internal class MatrixUserListDataSourceTest {
|
|||
searchTerm = "test",
|
||||
result = Result.success(
|
||||
MatrixSearchUserResults(
|
||||
results = listOf(
|
||||
results = persistentListOf(
|
||||
aMatrixUserProfile(),
|
||||
aMatrixUserProfile(userId = A_USER_ID_2)
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue