MatrixRoom API refinement (#719)
- `syncUpdateFlow` becomes a `val` and always returns the same instance of the underlying `StateFlow` instead of different `Flow` instances to allow consumers not to remember the `Flow` and not to specify an unneeded initial value. - `timeline` becomes a `val` as it already always returns the same instance. - Amends calling code accordingly - Removes a few unneeded `val`s in `RustMatrixClient - Fixes a small bug in `MessagesPresenter` that allowed to sometime show a newly created room's name as "Empty room" (changes `LaunchedEffect(syncUpdateFlow)` to `LaunchedEffect(syncUpdateFlow.value)`)
This commit is contained in:
parent
79f7537c0b
commit
b504dbe5f0
8 changed files with 23 additions and 34 deletions
|
|
@ -99,7 +99,7 @@ class MessagesPresenter @AssistedInject constructor(
|
||||||
val customReactionState = customReactionPresenter.present()
|
val customReactionState = customReactionPresenter.present()
|
||||||
val retryState = retrySendMenuPresenter.present()
|
val retryState = retrySendMenuPresenter.present()
|
||||||
|
|
||||||
val syncUpdateFlow = room.syncUpdateFlow().collectAsState(0L)
|
val syncUpdateFlow = room.syncUpdateFlow.collectAsState()
|
||||||
val userHasPermissionToSendMessage by room.canSendEventAsState(type = MessageEventType.ROOM_MESSAGE, updateKey = syncUpdateFlow.value)
|
val userHasPermissionToSendMessage by room.canSendEventAsState(type = MessageEventType.ROOM_MESSAGE, updateKey = syncUpdateFlow.value)
|
||||||
val roomName: MutableState<String?> = rememberSaveable {
|
val roomName: MutableState<String?> = rememberSaveable {
|
||||||
mutableStateOf(null)
|
mutableStateOf(null)
|
||||||
|
|
@ -112,7 +112,7 @@ class MessagesPresenter @AssistedInject constructor(
|
||||||
|
|
||||||
val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState()
|
val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState()
|
||||||
|
|
||||||
LaunchedEffect(syncUpdateFlow) {
|
LaunchedEffect(syncUpdateFlow.value) {
|
||||||
roomAvatar.value =
|
roomAvatar.value =
|
||||||
AvatarData(
|
AvatarData(
|
||||||
id = room.roomId.value,
|
id = room.roomId.value,
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class TimelinePresenter @Inject constructor(
|
||||||
room: MatrixRoom,
|
room: MatrixRoom,
|
||||||
) : Presenter<TimelineState> {
|
) : Presenter<TimelineState> {
|
||||||
|
|
||||||
private val timeline = room.timeline()
|
private val timeline = room.timeline
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun present(): TimelineState {
|
override fun present(): TimelineState {
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ class RoomDetailsEditPresenter @Inject constructor(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun present(): RoomDetailsEditState {
|
override fun present(): RoomDetailsEditState {
|
||||||
val roomSyncUpdateFlow = room.syncUpdateFlow().collectAsState(0L)
|
val roomSyncUpdateFlow = room.syncUpdateFlow.collectAsState()
|
||||||
|
|
||||||
// Since there is no way to obtain the new avatar uri after uploading a new avatar,
|
// Since there is no way to obtain the new avatar uri after uploading a new avatar,
|
||||||
// just erase the local value when the room field has changed
|
// just erase the local value when the room field has changed
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,9 @@ interface MatrixRoom : Closeable {
|
||||||
*/
|
*/
|
||||||
suspend fun updateMembers(): Result<Unit>
|
suspend fun updateMembers(): Result<Unit>
|
||||||
|
|
||||||
fun syncUpdateFlow(): Flow<Long>
|
val syncUpdateFlow: StateFlow<Long>
|
||||||
|
|
||||||
fun timeline(): MatrixTimeline
|
val timeline: MatrixTimeline
|
||||||
|
|
||||||
fun open(): Result<Unit>
|
fun open(): Result<Unit>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,10 +73,10 @@ import org.matrix.rustcomponents.sdk.RoomVisibility as RustRoomVisibility
|
||||||
class RustMatrixClient constructor(
|
class RustMatrixClient constructor(
|
||||||
private val client: Client,
|
private val client: Client,
|
||||||
private val sessionStore: SessionStore,
|
private val sessionStore: SessionStore,
|
||||||
private val appCoroutineScope: CoroutineScope,
|
appCoroutineScope: CoroutineScope,
|
||||||
private val dispatchers: CoroutineDispatchers,
|
private val dispatchers: CoroutineDispatchers,
|
||||||
private val baseDirectory: File,
|
private val baseDirectory: File,
|
||||||
private val baseCacheDirectory: File,
|
baseCacheDirectory: File,
|
||||||
private val clock: SystemClock,
|
private val clock: SystemClock,
|
||||||
) : MatrixClient {
|
) : MatrixClient {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
@ -71,15 +72,10 @@ class RustMatrixRoom(
|
||||||
override val roomId = RoomId(innerRoom.id())
|
override val roomId = RoomId(innerRoom.id())
|
||||||
|
|
||||||
private val roomCoroutineScope = sessionCoroutineScope.childScope(coroutineDispatchers.main, "RoomScope-$roomId")
|
private val roomCoroutineScope = sessionCoroutineScope.childScope(coroutineDispatchers.main, "RoomScope-$roomId")
|
||||||
|
private val _membersStateFlow = MutableStateFlow<MatrixRoomMembersState>(MatrixRoomMembersState.Unknown)
|
||||||
override val membersStateFlow: StateFlow<MatrixRoomMembersState>
|
|
||||||
get() = _membersStateFlow
|
|
||||||
|
|
||||||
private var _membersStateFlow = MutableStateFlow<MatrixRoomMembersState>(MatrixRoomMembersState.Unknown)
|
|
||||||
private val isInit = MutableStateFlow(false)
|
private val isInit = MutableStateFlow(false)
|
||||||
private val syncUpdateFlow = MutableStateFlow(systemClock.epochMillis())
|
private val _syncUpdateFlow = MutableStateFlow(0L)
|
||||||
|
private val _timeline by lazy {
|
||||||
private val timeline by lazy {
|
|
||||||
RustMatrixTimeline(
|
RustMatrixTimeline(
|
||||||
matrixRoom = this,
|
matrixRoom = this,
|
||||||
innerRoom = innerRoom,
|
innerRoom = innerRoom,
|
||||||
|
|
@ -88,13 +84,11 @@ class RustMatrixRoom(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun syncUpdateFlow(): Flow<Long> {
|
override val membersStateFlow: StateFlow<MatrixRoomMembersState> = _membersStateFlow.asStateFlow()
|
||||||
return syncUpdateFlow
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun timeline(): MatrixTimeline {
|
override val syncUpdateFlow: StateFlow<Long> = _syncUpdateFlow.asStateFlow()
|
||||||
return timeline
|
|
||||||
}
|
override val timeline: MatrixTimeline = _timeline
|
||||||
|
|
||||||
override fun open(): Result<Unit> {
|
override fun open(): Result<Unit> {
|
||||||
if (isInit.value) return Result.failure(IllegalStateException("Listener already registered"))
|
if (isInit.value) return Result.failure(IllegalStateException("Listener already registered"))
|
||||||
|
|
@ -110,10 +104,10 @@ class RustMatrixRoom(
|
||||||
roomListItem.subscribe(settings)
|
roomListItem.subscribe(settings)
|
||||||
roomCoroutineScope.launch(coroutineDispatchers.computation) {
|
roomCoroutineScope.launch(coroutineDispatchers.computation) {
|
||||||
innerRoom.timelineDiffFlow { initialList ->
|
innerRoom.timelineDiffFlow { initialList ->
|
||||||
timeline.postItems(initialList)
|
_timeline.postItems(initialList)
|
||||||
}.onEach {
|
}.onEach {
|
||||||
syncUpdateFlow.value = systemClock.epochMillis()
|
_syncUpdateFlow.value = systemClock.epochMillis()
|
||||||
timeline.postDiff(it)
|
_timeline.postDiff(it)
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
fetchMembers()
|
fetchMembers()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,8 @@ 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_SESSION_ID
|
||||||
import io.element.android.libraries.matrix.test.timeline.FakeMatrixTimeline
|
import io.element.android.libraries.matrix.test.timeline.FakeMatrixTimeline
|
||||||
import io.element.android.tests.testutils.simulateLongTask
|
import io.element.android.tests.testutils.simulateLongTask
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.emptyFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class FakeMatrixRoom(
|
class FakeMatrixRoom(
|
||||||
|
|
@ -126,13 +125,9 @@ class FakeMatrixRoom(
|
||||||
updateMembersResult
|
updateMembersResult
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun syncUpdateFlow(): Flow<Long> {
|
override val syncUpdateFlow: StateFlow<Long> = MutableStateFlow(0L)
|
||||||
return emptyFlow()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun timeline(): MatrixTimeline {
|
override val timeline: MatrixTimeline = matrixTimeline
|
||||||
return matrixTimeline
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun open(): Result<Unit> {
|
override fun open(): Result<Unit> {
|
||||||
return Result.success(Unit)
|
return Result.success(Unit)
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ class RoomListScreen(
|
||||||
withContext(coroutineDispatchers.io) {
|
withContext(coroutineDispatchers.io) {
|
||||||
matrixClient.getRoom(roomId)!!.use { room ->
|
matrixClient.getRoom(roomId)!!.use { room ->
|
||||||
room.open()
|
room.open()
|
||||||
val timeline = room.timeline()
|
val timeline = room.timeline
|
||||||
timeline.apply {
|
timeline.apply {
|
||||||
// TODO This doesn't work reliably as initialize is asynchronous, and the timeline can't be used until it's finished
|
// TODO This doesn't work reliably as initialize is asynchronous, and the timeline can't be used until it's finished
|
||||||
paginateBackwards(20, 50)
|
paginateBackwards(20, 50)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue