Use the right live timeline instance in RustRoomFactory (#4745)

This commit is contained in:
Jorge Martin Espinosa 2025-05-20 17:33:25 +02:00 committed by GitHub
parent 1a6596a89a
commit 01abba6205

View file

@ -9,7 +9,6 @@ package io.element.android.libraries.matrix.impl.room
import io.element.android.appconfig.TimelineConfig import io.element.android.appconfig.TimelineConfig
import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.core.data.tryOrNull
import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.matrix.api.core.DeviceId import io.element.android.libraries.matrix.api.core.DeviceId
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
@ -21,6 +20,7 @@ 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.RoomListService
import io.element.android.libraries.matrix.api.roomlist.awaitLoaded 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.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.libraries.matrix.impl.roomlist.roomOrNull
import io.element.android.services.toolbox.api.systemclock.SystemClock import io.element.android.services.toolbox.api.systemclock.SystemClock
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -30,10 +30,10 @@ import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.matrix.rustcomponents.sdk.Client import org.matrix.rustcomponents.sdk.Client
import org.matrix.rustcomponents.sdk.Membership import org.matrix.rustcomponents.sdk.Membership
import org.matrix.rustcomponents.sdk.Room
import org.matrix.rustcomponents.sdk.RoomListItem import org.matrix.rustcomponents.sdk.RoomListItem
import timber.log.Timber import timber.log.Timber
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
import org.matrix.rustcomponents.sdk.Room as SdkRoom
import org.matrix.rustcomponents.sdk.RoomListService as InnerRoomListService import org.matrix.rustcomponents.sdk.RoomListService as InnerRoomListService
class RustRoomFactory( class RustRoomFactory(
@ -56,11 +56,6 @@ class RustRoomFactory(
private val mutex = Mutex() private val mutex = Mutex()
private val isDestroyed: AtomicBoolean = AtomicBoolean(false) private val isDestroyed: AtomicBoolean = AtomicBoolean(false)
private data class RustRoomReferences(
val roomListItem: RoomListItem,
val room: SdkRoom,
)
private val roomInfoMapper = RoomInfoMapper() private val roomInfoMapper = RoomInfoMapper()
private val eventFilters = TimelineConfig.excludedEvents private val eventFilters = TimelineConfig.excludedEvents
@ -84,17 +79,22 @@ class RustRoomFactory(
Timber.d("Room factory is destroyed, returning null for $roomId") Timber.d("Room factory is destroyed, returning null for $roomId")
return@withContext null return@withContext null
} }
val roomReferences = awaitRoomReferences(roomId) ?: return@withContext null val roomListItem = awaitRoomListItem(roomId) ?: return@withContext null
getBaseRoom(roomReferences) getBaseRoom(roomListItem)
} }
} }
private suspend fun getBaseRoom(roomReferences: RustRoomReferences): RustBaseRoom? { private suspend fun getBaseRoom(roomListItem: RoomListItem): RustBaseRoom? {
val initialRoomInfo = roomReferences.room.roomInfo() val sdkRoom = innerClient.getRoom(roomListItem.id()) ?: return null
return getBaseRoom(sdkRoom)
}
private suspend fun getBaseRoom(sdkRoom: Room): RustBaseRoom {
val initialRoomInfo = sdkRoom.roomInfo()
return RustBaseRoom( return RustBaseRoom(
sessionId = sessionId, sessionId = sessionId,
deviceId = deviceId, deviceId = deviceId,
innerRoom = roomReferences.room, innerRoom = sdkRoom,
coroutineDispatchers = dispatchers, coroutineDispatchers = dispatchers,
roomSyncSubscriber = roomSyncSubscriber, roomSyncSubscriber = roomSyncSubscriber,
roomMembershipObserver = roomMembershipObserver, roomMembershipObserver = roomMembershipObserver,
@ -110,22 +110,18 @@ class RustRoomFactory(
Timber.d("Room factory is destroyed, returning null for $roomId") Timber.d("Room factory is destroyed, returning null for $roomId")
return@withContext null return@withContext null
} }
val roomReferences = awaitRoomReferences(roomId) ?: return@withContext null val roomListItem = awaitRoomListItem(roomId) ?: return@withContext null
if (roomReferences.room.membership() == Membership.JOINED) {
val baseRoom = getBaseRoom(roomReferences) ?: return@withContext null
if (roomListItem.membership() == Membership.JOINED) {
// Init the live timeline in the SDK from the RoomListItem // Init the live timeline in the SDK from the RoomListItem
if (!roomReferences.roomListItem.isTimelineInitialized()) { val sdkRoom = roomListItem.fullRoomWithTimeline(eventFilters)
roomReferences.roomListItem.initTimeline(eventFilters, "LIVE")
}
GetRoomResult.Joined( GetRoomResult.Joined(
JoinedRustRoom( JoinedRustRoom(
baseRoom = baseRoom, baseRoom = getBaseRoom(sdkRoom),
notificationSettingsService = notificationSettingsService, notificationSettingsService = notificationSettingsService,
roomContentForwarder = roomContentForwarder, roomContentForwarder = roomContentForwarder,
liveInnerTimeline = roomReferences.room.timeline(), liveInnerTimeline = sdkRoom.timeline(),
coroutineDispatchers = dispatchers, coroutineDispatchers = dispatchers,
systemClock = systemClock, systemClock = systemClock,
featureFlagService = featureFlagService, featureFlagService = featureFlagService,
@ -133,7 +129,7 @@ class RustRoomFactory(
) )
} else { } else {
val preview = try { val preview = try {
roomReferences.roomListItem.previewRoom(via = emptyList()) roomListItem.previewRoom(via = emptyList())
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e, "Failed to get room preview for $roomId") Timber.e(e, "Failed to get room preview for $roomId")
return@withContext null return@withContext null
@ -142,7 +138,7 @@ class RustRoomFactory(
GetRoomResult.NotJoined( GetRoomResult.NotJoined(
NotJoinedRustRoom( NotJoinedRustRoom(
sessionId = sessionId, sessionId = sessionId,
localRoom = getBaseRoom(roomReferences), localRoom = getBaseRoom(roomListItem),
previewInfo = RoomPreviewInfoMapper.map(preview.info()), previewInfo = RoomPreviewInfoMapper.map(preview.info()),
) )
) )
@ -150,36 +146,23 @@ class RustRoomFactory(
} }
} }
private fun getRoomReferences(roomId: RoomId): RustRoomReferences? { /**
val roomListItem = innerRoomListService.roomOrNull(roomId.value) * Get the Rust room list item 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) {
// ... otherwise, lets wait for the SS to load all rooms and check again.
roomListService.allRooms.awaitLoaded()
roomListItem = innerRoomListService.roomOrNull(roomId.value)
}
if (roomListItem == null) { if (roomListItem == null) {
Timber.d("Room not found for $roomId") Timber.d("Room not found for $roomId")
return null return null
} }
val room = tryOrNull {
innerClient.getRoom(roomId.value)
} ?: error("Failed to get room for room id: $roomId")
Timber.d("Got room for $roomId") return roomListItem
return RustRoomReferences(
roomListItem = roomListItem,
room = room,
)
}
/**
* Get the Rust room references for a room, retrying after the room list is loaded if necessary.
*/
private suspend fun awaitRoomReferences(roomId: RoomId): RustRoomReferences? {
var roomReferences = getRoomReferences(roomId)
if (roomReferences == null) {
// ... otherwise, lets wait for the SS to load all rooms and check again.
roomListService.allRooms.awaitLoaded()
roomReferences = getRoomReferences(roomId)
}
return roomReferences
} }
} }