Merge branch 'develop' into feature/fga/fix_left_room_membership_change
This commit is contained in:
commit
091d41b09d
153 changed files with 2885 additions and 1088 deletions
|
|
@ -120,10 +120,6 @@ class RustClientSessionDelegate(
|
|||
}
|
||||
}
|
||||
|
||||
override fun didRefreshTokens() {
|
||||
// This is done in `saveSessionInKeychain(Session)` instead.
|
||||
}
|
||||
|
||||
override fun retrieveSessionFromKeychain(userId: String): Session {
|
||||
// This should never be called, as it's only used for multi-process setups
|
||||
error("retrieveSessionFromKeychain should never be called for Android")
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ class RustMatrixClient(
|
|||
)
|
||||
private val notificationProcessSetup = NotificationProcessSetup.SingleProcess(innerSyncService)
|
||||
private val innerNotificationClient = runBlocking { innerClient.notificationClient(notificationProcessSetup) }
|
||||
private val notificationService = RustNotificationService(innerNotificationClient, dispatchers, clock)
|
||||
private val notificationService = RustNotificationService(sessionId, innerNotificationClient, dispatchers, clock)
|
||||
private val notificationSettingsService = RustNotificationSettingsService(innerClient, sessionCoroutineScope, dispatchers)
|
||||
private val encryptionService = RustEncryptionService(
|
||||
client = innerClient,
|
||||
|
|
@ -189,7 +189,6 @@ class RustMatrixClient(
|
|||
|
||||
private val roomMembershipObserver = RoomMembershipObserver()
|
||||
private val roomFactory = RustRoomFactory(
|
||||
innerClient = innerClient,
|
||||
roomListService = roomListService,
|
||||
innerRoomListService = innerRoomListService,
|
||||
sessionId = sessionId,
|
||||
|
|
|
|||
|
|
@ -72,8 +72,9 @@ class RustMatrixClientFactory @Inject constructor(
|
|||
suspend fun create(client: Client): RustMatrixClient {
|
||||
val (anonymizedAccessToken, anonymizedRefreshToken) = client.session().anonymizedTokens()
|
||||
|
||||
client.setUtdDelegate(UtdTracker(analyticsService))
|
||||
|
||||
val syncService = client.syncService()
|
||||
.withUtdHook(UtdTracker(analyticsService))
|
||||
.withOfflineMode()
|
||||
.finish()
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ 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.SessionId
|
||||
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
|
||||
|
|
@ -25,6 +26,7 @@ class NotificationMapper(
|
|||
private val notificationContentMapper = NotificationContentMapper()
|
||||
|
||||
fun map(
|
||||
sessionId: SessionId,
|
||||
eventId: EventId,
|
||||
roomId: RoomId,
|
||||
notificationItem: NotificationItem
|
||||
|
|
@ -35,6 +37,7 @@ class NotificationMapper(
|
|||
activeMembersCount = item.roomInfo.joinedMembersCount.toInt(),
|
||||
)
|
||||
NotificationData(
|
||||
sessionId = sessionId,
|
||||
eventId = eventId,
|
||||
// FIXME once the `NotificationItem` in the SDK returns the thread id
|
||||
threadId = null,
|
||||
|
|
|
|||
|
|
@ -10,28 +10,45 @@ package io.element.android.libraries.matrix.impl.notification
|
|||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
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.notification.NotificationData
|
||||
import io.element.android.libraries.matrix.api.notification.NotificationService
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.rustcomponents.sdk.NotificationClient
|
||||
import org.matrix.rustcomponents.sdk.use
|
||||
import org.matrix.rustcomponents.sdk.NotificationItemsRequest
|
||||
import timber.log.Timber
|
||||
|
||||
class RustNotificationService(
|
||||
private val sessionId: SessionId,
|
||||
private val notificationClient: NotificationClient,
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
clock: SystemClock,
|
||||
) : NotificationService {
|
||||
private val notificationMapper: NotificationMapper = NotificationMapper(clock)
|
||||
|
||||
override suspend fun getNotification(
|
||||
roomId: RoomId,
|
||||
eventId: EventId,
|
||||
): Result<NotificationData?> = withContext(dispatchers.io) {
|
||||
override suspend fun getNotifications(
|
||||
ids: Map<RoomId, List<EventId>>
|
||||
): Result<Map<EventId, NotificationData>> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
val item = notificationClient.getNotification(roomId.value, eventId.value)
|
||||
item?.use {
|
||||
notificationMapper.map(eventId, roomId, it)
|
||||
val requests = ids.map { (roomId, eventIds) ->
|
||||
NotificationItemsRequest(
|
||||
roomId = roomId.value,
|
||||
eventIds = eventIds.map { it.value }
|
||||
)
|
||||
}
|
||||
val items = notificationClient.getNotifications(requests)
|
||||
buildMap {
|
||||
val eventIds = requests.flatMap { it.eventIds }
|
||||
for (eventId in eventIds) {
|
||||
val item = items[eventId]
|
||||
if (item != null) {
|
||||
val roomId = RoomId(requests.find { it.eventIds.contains(eventId) }?.roomId!!)
|
||||
put(EventId(eventId), notificationMapper.map(sessionId, EventId(eventId), roomId, item))
|
||||
} else {
|
||||
Timber.e("Could not retrieve event for notification with $eventId")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@
|
|||
package io.element.android.libraries.matrix.impl.proxy
|
||||
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import android.provider.Settings
|
||||
import androidx.core.content.getSystemService
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
|
|
@ -32,6 +34,13 @@ class DefaultProxyProvider @Inject constructor(
|
|||
private val context: Context
|
||||
) : ProxyProvider {
|
||||
override fun provides(): String? {
|
||||
val defaultProxy = context.getSystemService<ConnectivityManager>()?.defaultProxy
|
||||
if (defaultProxy == null) {
|
||||
// Note: can be tested by running:
|
||||
// adb shell settings put global http_proxy :0
|
||||
Timber.d("No default proxy")
|
||||
return null
|
||||
}
|
||||
return Settings.Global.getString(context.contentResolver, Settings.Global.HTTP_PROXY)
|
||||
?.also {
|
||||
Timber.d("Using global proxy")
|
||||
|
|
|
|||
|
|
@ -212,6 +212,7 @@ class JoinedRustRoom(
|
|||
internalIdPrefix = internalIdPrefix,
|
||||
dateDividerMode = dateDividerMode,
|
||||
trackReadReceipts = trackReadReceipts,
|
||||
reportUtds = true,
|
||||
)
|
||||
).let { innerTimeline ->
|
||||
val mode = when (createTimelineParams) {
|
||||
|
|
@ -416,7 +417,6 @@ class JoinedRustRoom(
|
|||
RustWidgetDriver(
|
||||
widgetSettings = widgetSettings,
|
||||
room = innerRoom,
|
||||
joinedRustRoom = this,
|
||||
widgetCapabilitiesProvider = object : WidgetCapabilitiesProvider {
|
||||
override fun acquireCapabilities(capabilities: WidgetCapabilities): WidgetCapabilities {
|
||||
return getElementCallRequiredPermissions(sessionId.value, baseRoom.deviceId.value)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import io.element.android.libraries.core.coroutine.parallelMap
|
|||
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.room.ForwardEventException
|
||||
import io.element.android.libraries.matrix.impl.roomlist.fullRoomWithTimeline
|
||||
import io.element.android.libraries.matrix.impl.roomlist.roomOrNull
|
||||
import io.element.android.libraries.matrix.impl.timeline.runWithTimelineListenerRegistered
|
||||
import kotlinx.coroutines.CancellationException
|
||||
|
|
@ -49,10 +48,7 @@ class RoomContentForwarder(
|
|||
val content = (messageLikeContent.kind as? MsgLikeKind.Message)?.content
|
||||
?: throw ForwardEventException(toRoomIds)
|
||||
|
||||
val targetSlidingSyncRooms = toRoomIds.mapNotNull { roomId -> roomListService.roomOrNull(roomId.value) }
|
||||
val targetRooms = targetSlidingSyncRooms.map { slidingSyncRoom ->
|
||||
slidingSyncRoom.use { it.fullRoomWithTimeline(null) }
|
||||
}
|
||||
val targetRooms = toRoomIds.mapNotNull { roomId -> roomListService.roomOrNull(roomId.value) }
|
||||
val failedForwardingTo = mutableSetOf<RoomId>()
|
||||
targetRooms.parallelMap { room ->
|
||||
room.use { targetRoom ->
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
|||
import io.element.android.libraries.matrix.api.roomlist.RoomListService
|
||||
import io.element.android.libraries.matrix.api.roomlist.awaitLoaded
|
||||
import io.element.android.libraries.matrix.impl.room.preview.RoomPreviewInfoMapper
|
||||
import io.element.android.libraries.matrix.impl.roomlist.fullRoomWithTimeline
|
||||
import io.element.android.libraries.matrix.impl.roomlist.roomOrNull
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -28,10 +27,12 @@ import kotlinx.coroutines.NonCancellable
|
|||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.rustcomponents.sdk.Client
|
||||
import org.matrix.rustcomponents.sdk.DateDividerMode
|
||||
import org.matrix.rustcomponents.sdk.Membership
|
||||
import org.matrix.rustcomponents.sdk.Room
|
||||
import org.matrix.rustcomponents.sdk.RoomListItem
|
||||
import org.matrix.rustcomponents.sdk.TimelineConfiguration
|
||||
import org.matrix.rustcomponents.sdk.TimelineFilter
|
||||
import org.matrix.rustcomponents.sdk.TimelineFocus
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import org.matrix.rustcomponents.sdk.RoomListService as InnerRoomListService
|
||||
|
|
@ -39,7 +40,6 @@ import org.matrix.rustcomponents.sdk.RoomListService as InnerRoomListService
|
|||
class RustRoomFactory(
|
||||
private val sessionId: SessionId,
|
||||
private val deviceId: DeviceId,
|
||||
private val innerClient: Client,
|
||||
private val notificationSettingsService: NotificationSettingsService,
|
||||
private val sessionCoroutineScope: CoroutineScope,
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
|
|
@ -79,16 +79,11 @@ class RustRoomFactory(
|
|||
Timber.d("Room factory is destroyed, returning null for $roomId")
|
||||
return@withContext null
|
||||
}
|
||||
val roomListItem = awaitRoomListItem(roomId) ?: return@withContext null
|
||||
getBaseRoom(roomListItem)
|
||||
val room = awaitRoomInRoomList(roomId) ?: return@withContext null
|
||||
getBaseRoom(room)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getBaseRoom(roomListItem: RoomListItem): RustBaseRoom? {
|
||||
val sdkRoom = innerClient.getRoom(roomListItem.id()) ?: return null
|
||||
return getBaseRoom(sdkRoom)
|
||||
}
|
||||
|
||||
private suspend fun getBaseRoom(sdkRoom: Room): RustBaseRoom {
|
||||
val initialRoomInfo = sdkRoom.roomInfo()
|
||||
return RustBaseRoom(
|
||||
|
|
@ -110,18 +105,27 @@ class RustRoomFactory(
|
|||
Timber.d("Room factory is destroyed, returning null for $roomId")
|
||||
return@withContext null
|
||||
}
|
||||
val roomListItem = awaitRoomListItem(roomId) ?: return@withContext null
|
||||
val sdkRoom = awaitRoomInRoomList(roomId) ?: return@withContext null
|
||||
|
||||
if (roomListItem.membership() == Membership.JOINED) {
|
||||
// Init the live timeline in the SDK from the RoomListItem
|
||||
val sdkRoom = roomListItem.fullRoomWithTimeline(eventFilters)
|
||||
if (sdkRoom.membership() == Membership.JOINED) {
|
||||
// Init the live timeline in the SDK from the Room
|
||||
val timeline = sdkRoom.timelineWithConfiguration(
|
||||
TimelineConfiguration(
|
||||
focus = TimelineFocus.Live,
|
||||
filter = eventFilters?.let(TimelineFilter::EventTypeFilter) ?: TimelineFilter.All,
|
||||
internalIdPrefix = "live",
|
||||
dateDividerMode = DateDividerMode.DAILY,
|
||||
trackReadReceipts = true,
|
||||
reportUtds = true,
|
||||
)
|
||||
)
|
||||
|
||||
GetRoomResult.Joined(
|
||||
JoinedRustRoom(
|
||||
baseRoom = getBaseRoom(sdkRoom),
|
||||
notificationSettingsService = notificationSettingsService,
|
||||
roomContentForwarder = roomContentForwarder,
|
||||
liveInnerTimeline = sdkRoom.timeline(),
|
||||
liveInnerTimeline = timeline,
|
||||
coroutineDispatchers = dispatchers,
|
||||
systemClock = systemClock,
|
||||
featureFlagService = featureFlagService,
|
||||
|
|
@ -129,7 +133,7 @@ class RustRoomFactory(
|
|||
)
|
||||
} else {
|
||||
val preview = try {
|
||||
roomListItem.previewRoom(via = emptyList())
|
||||
sdkRoom.previewRoom(via = emptyList())
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Failed to get room preview for $roomId")
|
||||
return@withContext null
|
||||
|
|
@ -138,7 +142,7 @@ class RustRoomFactory(
|
|||
GetRoomResult.NotJoined(
|
||||
NotJoinedRustRoom(
|
||||
sessionId = sessionId,
|
||||
localRoom = getBaseRoom(roomListItem),
|
||||
localRoom = getBaseRoom(sdkRoom),
|
||||
previewInfo = RoomPreviewInfoMapper.map(preview.info()),
|
||||
)
|
||||
)
|
||||
|
|
@ -147,22 +151,22 @@ class RustRoomFactory(
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the Rust room list item for a room, retrying after the room list is loaded if necessary.
|
||||
* Get the Rust room for a room, retrying after the room list is loaded if necessary.
|
||||
*/
|
||||
private suspend fun awaitRoomListItem(roomId: RoomId): RoomListItem? {
|
||||
var roomListItem = innerRoomListService.roomOrNull(roomId.value)
|
||||
if (roomListItem == null) {
|
||||
private suspend fun awaitRoomInRoomList(roomId: RoomId): Room? {
|
||||
var sdkRoom = innerRoomListService.roomOrNull(roomId.value)
|
||||
if (sdkRoom == null) {
|
||||
// ... otherwise, lets wait for the SS to load all rooms and check again.
|
||||
roomListService.allRooms.awaitLoaded()
|
||||
roomListItem = innerRoomListService.roomOrNull(roomId.value)
|
||||
sdkRoom = innerRoomListService.roomOrNull(roomId.value)
|
||||
}
|
||||
|
||||
if (roomListItem == null) {
|
||||
if (sdkRoom == null) {
|
||||
Timber.d("Room not found for $roomId")
|
||||
return null
|
||||
}
|
||||
|
||||
return roomListItem
|
||||
return sdkRoom
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ import kotlinx.coroutines.flow.callbackFlow
|
|||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.matrix.rustcomponents.sdk.Room
|
||||
import org.matrix.rustcomponents.sdk.RoomListEntriesDynamicFilterKind
|
||||
import org.matrix.rustcomponents.sdk.RoomListEntriesListener
|
||||
import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate
|
||||
import org.matrix.rustcomponents.sdk.RoomListInterface
|
||||
import org.matrix.rustcomponents.sdk.RoomListItem
|
||||
import org.matrix.rustcomponents.sdk.RoomListLoadingState
|
||||
import org.matrix.rustcomponents.sdk.RoomListLoadingStateListener
|
||||
import org.matrix.rustcomponents.sdk.RoomListServiceInterface
|
||||
|
|
@ -114,7 +114,7 @@ internal fun RoomListServiceInterface.syncIndicator(): Flow<RoomListServiceSyncI
|
|||
)
|
||||
}.buffer(Channel.UNLIMITED)
|
||||
|
||||
internal fun RoomListServiceInterface.roomOrNull(roomId: String): RoomListItem? {
|
||||
internal fun RoomListServiceInterface.roomOrNull(roomId: String): Room? {
|
||||
return tryOrNull(
|
||||
onError = { Timber.e(it, "Failed finding room with id=$roomId.") }
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* Copyright 2024 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.roomlist
|
||||
|
||||
import org.matrix.rustcomponents.sdk.Room
|
||||
import org.matrix.rustcomponents.sdk.RoomListItem
|
||||
import org.matrix.rustcomponents.sdk.TimelineEventTypeFilter
|
||||
|
||||
/** Returns a `Room` with an initialized timeline using the given [filter]. */
|
||||
suspend fun RoomListItem.fullRoomWithTimeline(filter: TimelineEventTypeFilter? = null): Room {
|
||||
if (!isTimelineInitialized()) {
|
||||
initTimeline(filter, "live")
|
||||
}
|
||||
return fullRoom()
|
||||
}
|
||||
|
|
@ -10,16 +10,16 @@ package io.element.android.libraries.matrix.impl.roomlist
|
|||
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
|
||||
import io.element.android.libraries.matrix.impl.room.RoomInfoMapper
|
||||
import io.element.android.libraries.matrix.impl.room.message.RoomMessageFactory
|
||||
import org.matrix.rustcomponents.sdk.RoomListItem
|
||||
import org.matrix.rustcomponents.sdk.Room
|
||||
import org.matrix.rustcomponents.sdk.use
|
||||
|
||||
class RoomSummaryFactory(
|
||||
private val roomMessageFactory: RoomMessageFactory = RoomMessageFactory(),
|
||||
private val roomInfoMapper: RoomInfoMapper = RoomInfoMapper(),
|
||||
) {
|
||||
suspend fun create(roomListItem: RoomListItem): RoomSummary {
|
||||
val roomInfo = roomListItem.roomInfo().let(roomInfoMapper::map)
|
||||
val latestRoomMessage = roomListItem.latestEvent().use { event ->
|
||||
suspend fun create(room: Room): RoomSummary {
|
||||
val roomInfo = room.roomInfo().let(roomInfoMapper::map)
|
||||
val latestRoomMessage = room.latestEvent().use { event ->
|
||||
roomMessageFactory.create(event)
|
||||
}
|
||||
return RoomSummary(
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ import kotlinx.coroutines.flow.MutableSharedFlow
|
|||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.rustcomponents.sdk.Room
|
||||
import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate
|
||||
import org.matrix.rustcomponents.sdk.RoomListItem
|
||||
import org.matrix.rustcomponents.sdk.RoomListServiceInterface
|
||||
import org.matrix.rustcomponents.sdk.use
|
||||
import timber.log.Timber
|
||||
|
|
@ -95,20 +95,16 @@ class RoomSummaryListProcessor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun buildSummaryForRoomListEntry(entry: RoomListItem): RoomSummary {
|
||||
return buildRoomSummaryForRoomListItem(entry)
|
||||
private suspend fun buildSummaryForRoomListEntry(entry: Room): RoomSummary {
|
||||
return entry.use { roomSummaryDetailsFactory.create(room = it) }
|
||||
}
|
||||
|
||||
private suspend fun buildRoomSummaryForIdentifier(identifier: String): RoomSummary? {
|
||||
return roomListService.roomOrNull(identifier)?.use { roomListItem ->
|
||||
buildRoomSummaryForRoomListItem(roomListItem)
|
||||
return roomListService.roomOrNull(identifier)?.let { room ->
|
||||
buildSummaryForRoomListEntry(room)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun buildRoomSummaryForRoomListItem(roomListItem: RoomListItem): RoomSummary {
|
||||
return roomSummaryDetailsFactory.create(roomListItem = roomListItem)
|
||||
}
|
||||
|
||||
private suspend fun updateRoomSummaries(block: suspend MutableList<RoomSummary>.() -> Unit) = withContext(coroutineContext) {
|
||||
mutex.withLock {
|
||||
val current = roomSummaries.replayCache.lastOrNull()
|
||||
|
|
|
|||
|
|
@ -53,4 +53,5 @@ fun TracingConfiguration.map(): org.matrix.rustcomponents.sdk.TracingConfigurati
|
|||
extraTargets = extraTargets,
|
||||
traceLogPacks = traceLogPacks.map(),
|
||||
writeToFiles = writesToFilesConfiguration.toTracingFileConfiguration(),
|
||||
sentryDsn = null,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ package io.element.android.libraries.matrix.impl.widget
|
|||
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
|
||||
import io.element.android.libraries.matrix.impl.room.JoinedRustRoom
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
|
|
@ -25,7 +24,6 @@ import kotlin.coroutines.coroutineContext
|
|||
class RustWidgetDriver(
|
||||
widgetSettings: MatrixWidgetSettings,
|
||||
private val room: Room,
|
||||
private val joinedRustRoom: JoinedRustRoom,
|
||||
private val widgetCapabilitiesProvider: WidgetCapabilitiesProvider,
|
||||
) : MatrixWidgetDriver {
|
||||
// It's important to have extra capacity here to make sure we don't drop any messages
|
||||
|
|
@ -71,6 +69,5 @@ class RustWidgetDriver(
|
|||
override fun close() {
|
||||
receiveMessageJob?.cancel()
|
||||
driverAndHandle.driver.close()
|
||||
joinedRustRoom.destroy()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import org.matrix.rustcomponents.sdk.RoomDirectorySearch
|
|||
import org.matrix.rustcomponents.sdk.Session
|
||||
import org.matrix.rustcomponents.sdk.SyncServiceBuilder
|
||||
import org.matrix.rustcomponents.sdk.TaskHandle
|
||||
import org.matrix.rustcomponents.sdk.UnableToDecryptDelegate
|
||||
|
||||
class FakeRustClient(
|
||||
private val userId: String = A_USER_ID.value,
|
||||
|
|
@ -34,6 +35,7 @@ class FakeRustClient(
|
|||
private val encryption: Encryption = FakeRustEncryption(),
|
||||
private val session: Session = aRustSession(),
|
||||
private val clearCachesResult: () -> Unit = { lambdaError() },
|
||||
private val withUtdHook: (UnableToDecryptDelegate) -> Unit = { lambdaError() },
|
||||
private val closeResult: () -> Unit = {},
|
||||
) : Client(NoPointer) {
|
||||
override fun userId(): String = userId
|
||||
|
|
@ -58,5 +60,6 @@ class FakeRustClient(
|
|||
|
||||
override suspend fun deletePusher(identifiers: PusherIdentifiers) = Unit
|
||||
override suspend fun clearCaches() = simulateLongTask { clearCachesResult() }
|
||||
override suspend fun setUtdDelegate(utdDelegate: UnableToDecryptDelegate) = withUtdHook(utdDelegate)
|
||||
override fun close() = closeResult()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,6 @@ class FakeRustClientBuilder : ClientBuilder(NoPointer) {
|
|||
}
|
||||
|
||||
override suspend fun build(): Client {
|
||||
return FakeRustClient()
|
||||
return FakeRustClient(withUtdHook = {})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,15 +7,15 @@
|
|||
|
||||
package io.element.android.libraries.matrix.impl.fixtures.fakes
|
||||
|
||||
import io.element.android.tests.testutils.simulateLongTask
|
||||
import org.matrix.rustcomponents.sdk.NoPointer
|
||||
import org.matrix.rustcomponents.sdk.NotificationClient
|
||||
import org.matrix.rustcomponents.sdk.NotificationItem
|
||||
import org.matrix.rustcomponents.sdk.NotificationItemsRequest
|
||||
|
||||
class FakeRustNotificationClient(
|
||||
var notificationItemResult: NotificationItem? = null
|
||||
var notificationItemResult: Map<String, NotificationItem> = emptyMap(),
|
||||
) : NotificationClient(NoPointer) {
|
||||
override suspend fun getNotification(roomId: String, eventId: String): NotificationItem? = simulateLongTask {
|
||||
notificationItemResult
|
||||
override suspend fun getNotifications(requests: List<NotificationItemsRequest>): Map<String, NotificationItem> {
|
||||
return notificationItemResult
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,10 +8,13 @@
|
|||
package io.element.android.libraries.matrix.impl.fixtures.fakes
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.tests.testutils.lambda.lambdaError
|
||||
import org.matrix.rustcomponents.sdk.EventTimelineItem
|
||||
import org.matrix.rustcomponents.sdk.NoPointer
|
||||
import org.matrix.rustcomponents.sdk.Room
|
||||
import org.matrix.rustcomponents.sdk.RoomInfo
|
||||
import org.matrix.rustcomponents.sdk.RoomMembersIterator
|
||||
|
||||
class FakeRustRoom(
|
||||
|
|
@ -19,6 +22,8 @@ class FakeRustRoom(
|
|||
private val getMembers: () -> RoomMembersIterator = { lambdaError() },
|
||||
private val getMembersNoSync: () -> RoomMembersIterator = { lambdaError() },
|
||||
private val leaveLambda: () -> Unit = { lambdaError() },
|
||||
private val latestEventLambda: () -> EventTimelineItem? = { lambdaError() },
|
||||
private val roomInfo: RoomInfo = aRustRoomInfo(id = roomId.value),
|
||||
) : Room(NoPointer) {
|
||||
override fun id(): String {
|
||||
return roomId.value
|
||||
|
|
@ -36,6 +41,14 @@ class FakeRustRoom(
|
|||
leaveLambda()
|
||||
}
|
||||
|
||||
override suspend fun roomInfo(): RoomInfo {
|
||||
return roomInfo
|
||||
}
|
||||
|
||||
override suspend fun latestEvent(): EventTimelineItem? {
|
||||
return latestEventLambda()
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
// No-op
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright 2024 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.fixtures.fakes
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo
|
||||
import org.matrix.rustcomponents.sdk.EventTimelineItem
|
||||
import org.matrix.rustcomponents.sdk.NoPointer
|
||||
import org.matrix.rustcomponents.sdk.RoomInfo
|
||||
import org.matrix.rustcomponents.sdk.RoomListItem
|
||||
|
||||
class FakeRustRoomListItem(
|
||||
private val roomId: RoomId,
|
||||
private val roomInfo: RoomInfo = aRustRoomInfo(id = roomId.value),
|
||||
private val latestEvent: EventTimelineItem? = null,
|
||||
) : RoomListItem(NoPointer) {
|
||||
override fun id(): String {
|
||||
return roomId.value
|
||||
}
|
||||
|
||||
override suspend fun roomInfo(): RoomInfo {
|
||||
return roomInfo
|
||||
}
|
||||
|
||||
override suspend fun latestEvent(): EventTimelineItem? {
|
||||
return latestEvent
|
||||
}
|
||||
}
|
||||
|
|
@ -10,10 +10,8 @@ package io.element.android.libraries.matrix.impl.fixtures.fakes
|
|||
import org.matrix.rustcomponents.sdk.NoPointer
|
||||
import org.matrix.rustcomponents.sdk.SyncService
|
||||
import org.matrix.rustcomponents.sdk.SyncServiceBuilder
|
||||
import org.matrix.rustcomponents.sdk.UnableToDecryptDelegate
|
||||
|
||||
class FakeRustSyncServiceBuilder : SyncServiceBuilder(NoPointer) {
|
||||
override suspend fun withUtdHook(delegate: UnableToDecryptDelegate): SyncServiceBuilder = this
|
||||
override fun withOfflineMode(): SyncServiceBuilder = this
|
||||
override suspend fun finish(): SyncService = FakeRustSyncService()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustNotificat
|
|||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.matrix.test.A_MESSAGE
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID_2
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
|
||||
|
|
@ -28,12 +29,12 @@ class RustNotificationServiceTest {
|
|||
@Test
|
||||
fun test() = runTest {
|
||||
val notificationClient = FakeRustNotificationClient(
|
||||
notificationItemResult = aRustNotificationItem(),
|
||||
notificationItemResult = mapOf(AN_EVENT_ID.value to aRustNotificationItem()),
|
||||
)
|
||||
val sut = createRustNotificationService(
|
||||
notificationClient = notificationClient,
|
||||
)
|
||||
val result = sut.getNotification(A_ROOM_ID, AN_EVENT_ID).getOrThrow()!!
|
||||
val result = sut.getNotifications(mapOf(A_ROOM_ID to listOf(AN_EVENT_ID))).getOrThrow()[AN_EVENT_ID]!!
|
||||
assertThat(result.isEncrypted).isTrue()
|
||||
assertThat(result.content).isEqualTo(
|
||||
NotificationContent.MessageLike.RoomMessage(
|
||||
|
|
@ -51,6 +52,7 @@ class RustNotificationServiceTest {
|
|||
clock: SystemClock = FakeSystemClock(),
|
||||
) =
|
||||
RustNotificationService(
|
||||
sessionId = A_SESSION_ID,
|
||||
notificationClient = notificationClient,
|
||||
dispatchers = testCoroutineDispatchers(),
|
||||
clock = clock,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
package io.element.android.libraries.matrix.impl.room
|
||||
|
||||
import app.cash.turbine.TurbineTestContext
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
|
||||
|
|
@ -19,7 +20,6 @@ import io.element.android.libraries.matrix.test.A_DEVICE_ID
|
|||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.matrix.test.room.aRoomInfo
|
||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.shareIn
|
||||
import kotlinx.coroutines.isActive
|
||||
|
|
@ -30,10 +30,7 @@ import org.junit.Test
|
|||
class RustBaseRoomTest {
|
||||
@Test
|
||||
fun `RustBaseRoom should cancel the room coroutine scope when it is destroyed`() = runTest {
|
||||
val rustBaseRoom = createRustBaseRoom(
|
||||
// Not using backgroundScope here, but the test scope
|
||||
sessionCoroutineScope = this
|
||||
)
|
||||
val rustBaseRoom = createRustBaseRoom()
|
||||
assertThat(rustBaseRoom.roomCoroutineScope.isActive).isTrue()
|
||||
rustBaseRoom.destroy()
|
||||
assertThat(rustBaseRoom.roomCoroutineScope.isActive).isFalse()
|
||||
|
|
@ -43,7 +40,6 @@ class RustBaseRoomTest {
|
|||
fun `when currentUserMembership=JOINED and user leave room succeed then roomMembershipObserver emits change as LEFT`() = runTest {
|
||||
val roomMembershipObserver = RoomMembershipObserver()
|
||||
val rustBaseRoom = createRustBaseRoom(
|
||||
sessionCoroutineScope = this,
|
||||
initialRoomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.JOINED),
|
||||
innerRoom = FakeRustRoom(
|
||||
leaveLambda = {
|
||||
|
|
@ -52,23 +48,18 @@ class RustBaseRoomTest {
|
|||
),
|
||||
roomMembershipObserver = roomMembershipObserver,
|
||||
)
|
||||
val shared = roomMembershipObserver.updates.shareIn(scope = backgroundScope, started = SharingStarted.Eagerly, replay = 1)
|
||||
rustBaseRoom.leave()
|
||||
shared.test {
|
||||
leaveRoomAndObserveMembershipChange(roomMembershipObserver, rustBaseRoom) {
|
||||
val membershipUpdate = awaitItem()
|
||||
assertThat(membershipUpdate.roomId).isEqualTo(rustBaseRoom.roomId)
|
||||
assertThat(membershipUpdate.isUserInRoom).isFalse()
|
||||
assertThat(membershipUpdate.change).isEqualTo(MembershipChange.LEFT)
|
||||
ensureAllEventsConsumed()
|
||||
}
|
||||
rustBaseRoom.destroy()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when currentUserMembership=KNOCKED and user leave room succeed then roomMembershipObserver emits change as KNOCK_RETRACTED`() = runTest {
|
||||
val roomMembershipObserver = RoomMembershipObserver()
|
||||
val rustBaseRoom = createRustBaseRoom(
|
||||
sessionCoroutineScope = this,
|
||||
initialRoomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.KNOCKED),
|
||||
innerRoom = FakeRustRoom(
|
||||
leaveLambda = {
|
||||
|
|
@ -77,23 +68,18 @@ class RustBaseRoomTest {
|
|||
),
|
||||
roomMembershipObserver = roomMembershipObserver,
|
||||
)
|
||||
val shared = roomMembershipObserver.updates.shareIn(scope = backgroundScope, started = SharingStarted.Eagerly, replay = 1)
|
||||
rustBaseRoom.leave()
|
||||
shared.test {
|
||||
leaveRoomAndObserveMembershipChange(roomMembershipObserver, rustBaseRoom) {
|
||||
val membershipUpdate = awaitItem()
|
||||
assertThat(membershipUpdate.roomId).isEqualTo(rustBaseRoom.roomId)
|
||||
assertThat(membershipUpdate.isUserInRoom).isFalse()
|
||||
assertThat(membershipUpdate.change).isEqualTo(MembershipChange.KNOCK_RETRACTED)
|
||||
ensureAllEventsConsumed()
|
||||
}
|
||||
rustBaseRoom.destroy()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when currentUserMembership=INVITED and user leave room succeed then roomMembershipObserver emits change as INVITATION_REJECTED`() = runTest {
|
||||
val roomMembershipObserver = RoomMembershipObserver()
|
||||
val rustBaseRoom = createRustBaseRoom(
|
||||
sessionCoroutineScope = this,
|
||||
initialRoomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.INVITED),
|
||||
innerRoom = FakeRustRoom(
|
||||
leaveLambda = {
|
||||
|
|
@ -102,39 +88,44 @@ class RustBaseRoomTest {
|
|||
),
|
||||
roomMembershipObserver = roomMembershipObserver,
|
||||
)
|
||||
val shared = roomMembershipObserver.updates.shareIn(scope = backgroundScope, started = SharingStarted.Eagerly, replay = 1)
|
||||
rustBaseRoom.leave()
|
||||
shared.test {
|
||||
leaveRoomAndObserveMembershipChange(roomMembershipObserver, rustBaseRoom) {
|
||||
val membershipUpdate = awaitItem()
|
||||
assertThat(membershipUpdate.roomId).isEqualTo(rustBaseRoom.roomId)
|
||||
assertThat(membershipUpdate.isUserInRoom).isFalse()
|
||||
assertThat(membershipUpdate.change).isEqualTo(MembershipChange.INVITATION_REJECTED)
|
||||
ensureAllEventsConsumed()
|
||||
}
|
||||
rustBaseRoom.destroy()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when user leave room fails then roomMembershipObserver emits nothing`() = runTest {
|
||||
val roomMembershipObserver = RoomMembershipObserver()
|
||||
val rustBaseRoom = createRustBaseRoom(
|
||||
sessionCoroutineScope = this,
|
||||
initialRoomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.INVITED),
|
||||
innerRoom = FakeRustRoom(
|
||||
leaveLambda = { error("Leave failed") }
|
||||
),
|
||||
roomMembershipObserver = roomMembershipObserver,
|
||||
)
|
||||
leaveRoomAndObserveMembershipChange(roomMembershipObserver, rustBaseRoom) {
|
||||
// No emit
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun TestScope.leaveRoomAndObserveMembershipChange(
|
||||
roomMembershipObserver: RoomMembershipObserver,
|
||||
rustBaseRoom: RustBaseRoom,
|
||||
validate: suspend TurbineTestContext<RoomMembershipObserver.RoomMembershipUpdate>.() -> Unit
|
||||
) {
|
||||
val shared = roomMembershipObserver.updates.shareIn(scope = backgroundScope, started = SharingStarted.Eagerly, replay = 1)
|
||||
rustBaseRoom.leave()
|
||||
shared.test {
|
||||
validate()
|
||||
ensureAllEventsConsumed()
|
||||
}
|
||||
rustBaseRoom.destroy()
|
||||
}
|
||||
|
||||
private fun TestScope.createRustBaseRoom(
|
||||
sessionCoroutineScope: CoroutineScope,
|
||||
initialRoomInfo: RoomInfo = aRoomInfo(),
|
||||
innerRoom: FakeRustRoom = FakeRustRoom(),
|
||||
roomMembershipObserver: RoomMembershipObserver = RoomMembershipObserver(),
|
||||
|
|
@ -150,7 +141,8 @@ class RustBaseRoomTest {
|
|||
dispatchers = dispatchers,
|
||||
),
|
||||
roomMembershipObserver = roomMembershipObserver,
|
||||
sessionCoroutineScope = sessionCoroutineScope,
|
||||
// Not using backgroundScope here, but the test scope
|
||||
sessionCoroutineScope = this,
|
||||
roomInfoMapper = RoomInfoMapper(),
|
||||
initialRoomInfo = initialRoomInfo,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryList
|
|||
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomDescription
|
||||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomDirectorySearch
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID_2
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
|
|
@ -31,7 +30,6 @@ class RustBaseRoomDirectoryListTest {
|
|||
val mapper = RoomDescriptionMapper()
|
||||
val sut = createRustRoomDirectoryList(
|
||||
roomDirectorySearch = roomDirectorySearch,
|
||||
scope = backgroundScope,
|
||||
)
|
||||
// Let the mxCallback be ready
|
||||
runCurrent()
|
||||
|
|
@ -81,10 +79,9 @@ class RustBaseRoomDirectoryListTest {
|
|||
|
||||
private fun TestScope.createRustRoomDirectoryList(
|
||||
roomDirectorySearch: RoomDirectorySearch = FakeRustRoomDirectorySearch(),
|
||||
scope: CoroutineScope,
|
||||
) = RustRoomDirectoryList(
|
||||
inner = roomDirectorySearch,
|
||||
coroutineScope = scope,
|
||||
coroutineScope = backgroundScope,
|
||||
coroutineContext = StandardTestDispatcher(testScheduler),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@
|
|||
package io.element.android.libraries.matrix.impl.roomlist
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
|
||||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomListItem
|
||||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoom
|
||||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomListService
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID_2
|
||||
|
|
@ -30,7 +31,7 @@ class RoomSummaryListProcessorTest {
|
|||
summaries.value = listOf(aRoomSummary())
|
||||
val processor = createProcessor()
|
||||
|
||||
val newEntry = FakeRustRoomListItem(A_ROOM_ID_2)
|
||||
val newEntry = aRustRoom(A_ROOM_ID_2)
|
||||
processor.postUpdate(listOf(RoomListEntriesUpdate.Append(listOf(newEntry, newEntry, newEntry))))
|
||||
|
||||
assertThat(summaries.value.count()).isEqualTo(4)
|
||||
|
|
@ -41,7 +42,7 @@ class RoomSummaryListProcessorTest {
|
|||
fun `PushBack adds a new entry at the end of the list`() = runTest {
|
||||
summaries.value = listOf(aRoomSummary())
|
||||
val processor = createProcessor()
|
||||
processor.postUpdate(listOf(RoomListEntriesUpdate.PushBack(FakeRustRoomListItem(A_ROOM_ID_2))))
|
||||
processor.postUpdate(listOf(RoomListEntriesUpdate.PushBack(aRustRoom(A_ROOM_ID_2))))
|
||||
|
||||
assertThat(summaries.value.count()).isEqualTo(2)
|
||||
assertThat(summaries.value.last().roomId).isEqualTo(A_ROOM_ID_2)
|
||||
|
|
@ -51,7 +52,7 @@ class RoomSummaryListProcessorTest {
|
|||
fun `PushFront inserts a new entry at the start of the list`() = runTest {
|
||||
summaries.value = listOf(aRoomSummary())
|
||||
val processor = createProcessor()
|
||||
processor.postUpdate(listOf(RoomListEntriesUpdate.PushFront(FakeRustRoomListItem(A_ROOM_ID_2))))
|
||||
processor.postUpdate(listOf(RoomListEntriesUpdate.PushFront(aRustRoom(A_ROOM_ID_2))))
|
||||
|
||||
assertThat(summaries.value.count()).isEqualTo(2)
|
||||
assertThat(summaries.value.first().roomId).isEqualTo(A_ROOM_ID_2)
|
||||
|
|
@ -63,7 +64,7 @@ class RoomSummaryListProcessorTest {
|
|||
val processor = createProcessor()
|
||||
val index = 0
|
||||
|
||||
processor.postUpdate(listOf(RoomListEntriesUpdate.Set(index.toUInt(), FakeRustRoomListItem(A_ROOM_ID_2))))
|
||||
processor.postUpdate(listOf(RoomListEntriesUpdate.Set(index.toUInt(), aRustRoom(A_ROOM_ID_2))))
|
||||
|
||||
assertThat(summaries.value.count()).isEqualTo(1)
|
||||
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2)
|
||||
|
|
@ -75,7 +76,7 @@ class RoomSummaryListProcessorTest {
|
|||
val processor = createProcessor()
|
||||
val index = 0
|
||||
|
||||
processor.postUpdate(listOf(RoomListEntriesUpdate.Insert(index.toUInt(), FakeRustRoomListItem(A_ROOM_ID_2))))
|
||||
processor.postUpdate(listOf(RoomListEntriesUpdate.Insert(index.toUInt(), aRustRoom(A_ROOM_ID_2))))
|
||||
|
||||
assertThat(summaries.value.count()).isEqualTo(2)
|
||||
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2)
|
||||
|
|
@ -163,12 +164,17 @@ class RoomSummaryListProcessorTest {
|
|||
val processor = createProcessor()
|
||||
val index = 0
|
||||
|
||||
processor.postUpdate(listOf(RoomListEntriesUpdate.Reset(listOf(FakeRustRoomListItem(A_ROOM_ID_3)))))
|
||||
processor.postUpdate(listOf(RoomListEntriesUpdate.Reset(listOf(aRustRoom(A_ROOM_ID_3)))))
|
||||
|
||||
assertThat(summaries.value.count()).isEqualTo(1)
|
||||
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_3)
|
||||
}
|
||||
|
||||
private fun aRustRoom(roomId: RoomId = A_ROOM_ID) = FakeRustRoom(
|
||||
roomId = roomId,
|
||||
latestEventLambda = { null },
|
||||
)
|
||||
|
||||
private fun TestScope.createProcessor() = RoomSummaryListProcessor(
|
||||
summaries,
|
||||
FakeRustRoomListService(),
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import io.element.android.libraries.matrix.api.roomlist.RoomListService
|
|||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomListService
|
||||
import io.element.android.libraries.matrix.impl.room.RoomSyncSubscriber
|
||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
|
|
@ -28,7 +27,6 @@ class RustBaseRoomListServiceTest {
|
|||
fun `syncIndicator should emit the expected values`() = runTest {
|
||||
val roomListService = FakeRustRoomListService()
|
||||
val sut = createRustRoomListService(
|
||||
sessionCoroutineScope = backgroundScope,
|
||||
roomListService = roomListService,
|
||||
)
|
||||
// Give time for mxCallback to setup
|
||||
|
|
@ -44,18 +42,17 @@ class RustBaseRoomListServiceTest {
|
|||
}
|
||||
|
||||
private fun TestScope.createRustRoomListService(
|
||||
sessionCoroutineScope: CoroutineScope,
|
||||
roomListService: RustRoomListService = FakeRustRoomListService(),
|
||||
) = RustRoomListService(
|
||||
innerRoomListService = roomListService,
|
||||
sessionDispatcher = StandardTestDispatcher(testScheduler),
|
||||
roomListFactory = RoomListFactory(
|
||||
innerRoomListService = roomListService,
|
||||
sessionCoroutineScope = sessionCoroutineScope,
|
||||
sessionCoroutineScope = backgroundScope,
|
||||
),
|
||||
roomSyncSubscriber = RoomSyncSubscriber(
|
||||
roomListService = roomListService,
|
||||
dispatchers = testCoroutineDispatchers(),
|
||||
),
|
||||
sessionCoroutineScope = sessionCoroutineScope,
|
||||
sessionCoroutineScope = backgroundScope,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustTimelineI
|
|||
import io.element.android.tests.testutils.lambda.lambdaError
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -38,7 +37,6 @@ class TimelineItemsSubscriberTest {
|
|||
MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE)
|
||||
val timeline = FakeRustTimeline()
|
||||
val timelineItemsSubscriber = createTimelineItemsSubscriber(
|
||||
coroutineScope = backgroundScope,
|
||||
timeline = timeline,
|
||||
timelineItems = timelineItems,
|
||||
)
|
||||
|
|
@ -59,7 +57,6 @@ class TimelineItemsSubscriberTest {
|
|||
MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE)
|
||||
val timeline = FakeRustTimeline()
|
||||
val timelineItemsSubscriber = createTimelineItemsSubscriber(
|
||||
coroutineScope = backgroundScope,
|
||||
timeline = timeline,
|
||||
timelineItems = timelineItems,
|
||||
)
|
||||
|
|
@ -81,7 +78,6 @@ class TimelineItemsSubscriberTest {
|
|||
val timeline = FakeRustTimeline()
|
||||
val onNewSyncedEventRecorder = lambdaRecorder<Unit> { }
|
||||
val timelineItemsSubscriber = createTimelineItemsSubscriber(
|
||||
coroutineScope = backgroundScope,
|
||||
timeline = timeline,
|
||||
timelineItems = timelineItems,
|
||||
onNewSyncedEvent = onNewSyncedEventRecorder,
|
||||
|
|
@ -109,9 +105,7 @@ class TimelineItemsSubscriberTest {
|
|||
|
||||
@Test
|
||||
fun `multiple subscriptions does not have side effect`() = runTest {
|
||||
val timelineItemsSubscriber = createTimelineItemsSubscriber(
|
||||
coroutineScope = backgroundScope,
|
||||
)
|
||||
val timelineItemsSubscriber = createTimelineItemsSubscriber()
|
||||
timelineItemsSubscriber.subscribeIfNeeded()
|
||||
timelineItemsSubscriber.subscribeIfNeeded()
|
||||
timelineItemsSubscriber.unsubscribeIfNeeded()
|
||||
|
|
@ -120,7 +114,6 @@ class TimelineItemsSubscriberTest {
|
|||
}
|
||||
|
||||
private fun TestScope.createTimelineItemsSubscriber(
|
||||
coroutineScope: CoroutineScope,
|
||||
timeline: Timeline = FakeRustTimeline(),
|
||||
timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> = MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE),
|
||||
initLatch: CompletableDeferred<Unit> = CompletableDeferred(),
|
||||
|
|
@ -128,7 +121,7 @@ private fun TestScope.createTimelineItemsSubscriber(
|
|||
onNewSyncedEvent: () -> Unit = { lambdaError() },
|
||||
): TimelineItemsSubscriber {
|
||||
return TimelineItemsSubscriber(
|
||||
timelineCoroutineScope = coroutineScope,
|
||||
timelineCoroutineScope = backgroundScope,
|
||||
dispatcher = StandardTestDispatcher(testScheduler),
|
||||
timeline = timeline,
|
||||
timelineDiffProcessor = createMatrixTimelineDiffProcessor(timelineItems),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue