Fix pinned events banner reappearing when loading (#3519)
* Fix pinned events banner reappearing when loading. Make the `RustTimelineItem.timelineItems` property a `SharedFlow` so we don't always incorrectly load an empty state by default.
This commit is contained in:
parent
60db5fb8e7
commit
103627d6ad
4 changed files with 14 additions and 11 deletions
|
|
@ -24,7 +24,6 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.FlowPreview
|
|
||||||
import kotlinx.coroutines.flow.flatMapLatest
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
|
@ -106,7 +105,7 @@ class PinnedMessagesBannerPresenter @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun PinnedMessagesBannerItemsEffect(
|
private fun PinnedMessagesBannerItemsEffect(
|
||||||
onItemsChange: (AsyncData<ImmutableList<PinnedMessagesBannerItem>>) -> Unit,
|
onItemsChange: (AsyncData<ImmutableList<PinnedMessagesBannerItem>>) -> Unit,
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ import io.element.android.libraries.matrix.api.room.roomMembers
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.FlowPreview
|
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
|
@ -161,7 +160,6 @@ class PinnedMessagesListPresenter @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(FlowPreview::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun PinnedMessagesListEffect(onItemsChange: (AsyncData<ImmutableList<TimelineItem>>) -> Unit) {
|
private fun PinnedMessagesListEffect(onItemsChange: (AsyncData<ImmutableList<TimelineItem>>) -> Unit) {
|
||||||
val updatedOnItemsChange by rememberUpdatedState(onItemsChange)
|
val updatedOnItemsChange by rememberUpdatedState(onItemsChange)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent
|
import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import org.matrix.rustcomponents.sdk.TimelineChange
|
import org.matrix.rustcomponents.sdk.TimelineChange
|
||||||
|
|
@ -20,7 +20,7 @@ import org.matrix.rustcomponents.sdk.TimelineItem
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
internal class MatrixTimelineDiffProcessor(
|
internal class MatrixTimelineDiffProcessor(
|
||||||
private val timelineItems: MutableStateFlow<List<MatrixTimelineItem>>,
|
private val timelineItems: MutableSharedFlow<List<MatrixTimelineItem>>,
|
||||||
private val timelineItemFactory: MatrixTimelineItemMapper,
|
private val timelineItemFactory: MatrixTimelineItemMapper,
|
||||||
) {
|
) {
|
||||||
private val mutex = Mutex()
|
private val mutex = Mutex()
|
||||||
|
|
@ -47,9 +47,13 @@ internal class MatrixTimelineDiffProcessor(
|
||||||
|
|
||||||
private suspend fun updateTimelineItems(block: MutableList<MatrixTimelineItem>.() -> Unit) =
|
private suspend fun updateTimelineItems(block: MutableList<MatrixTimelineItem>.() -> Unit) =
|
||||||
mutex.withLock {
|
mutex.withLock {
|
||||||
val mutableTimelineItems = timelineItems.value.toMutableList()
|
val mutableTimelineItems = if (timelineItems.replayCache.isNotEmpty()) {
|
||||||
|
timelineItems.first().toMutableList()
|
||||||
|
} else {
|
||||||
|
mutableListOf()
|
||||||
|
}
|
||||||
block(mutableTimelineItems)
|
block(mutableTimelineItems)
|
||||||
timelineItems.value = mutableTimelineItems
|
timelineItems.tryEmit(mutableTimelineItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MutableList<MatrixTimelineItem>.applyDiff(diff: TimelineDiff) {
|
private fun MutableList<MatrixTimelineItem>.applyDiff(diff: TimelineDiff) {
|
||||||
|
|
|
||||||
|
|
@ -49,10 +49,12 @@ import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.NonCancellable
|
import kotlinx.coroutines.NonCancellable
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.getAndUpdate
|
import kotlinx.coroutines.flow.getAndUpdate
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
@ -88,8 +90,8 @@ class RustTimeline(
|
||||||
private val initLatch = CompletableDeferred<Unit>()
|
private val initLatch = CompletableDeferred<Unit>()
|
||||||
private val isTimelineInitialized = MutableStateFlow(false)
|
private val isTimelineInitialized = MutableStateFlow(false)
|
||||||
|
|
||||||
private val _timelineItems: MutableStateFlow<List<MatrixTimelineItem>> =
|
private val _timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> =
|
||||||
MutableStateFlow(emptyList())
|
MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE)
|
||||||
|
|
||||||
private val timelineEventContentMapper = TimelineEventContentMapper()
|
private val timelineEventContentMapper = TimelineEventContentMapper()
|
||||||
private val inReplyToMapper = InReplyToMapper(timelineEventContentMapper)
|
private val inReplyToMapper = InReplyToMapper(timelineEventContentMapper)
|
||||||
|
|
@ -522,7 +524,7 @@ class RustTimeline(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun loadReplyDetails(eventId: EventId): InReplyTo = withContext(dispatcher) {
|
override suspend fun loadReplyDetails(eventId: EventId): InReplyTo = withContext(dispatcher) {
|
||||||
val timelineItem = _timelineItems.value.firstOrNull { timelineItem ->
|
val timelineItem = _timelineItems.first().firstOrNull { timelineItem ->
|
||||||
timelineItem is MatrixTimelineItem.Event && timelineItem.eventId == eventId
|
timelineItem is MatrixTimelineItem.Event && timelineItem.eventId == eventId
|
||||||
} as? MatrixTimelineItem.Event
|
} as? MatrixTimelineItem.Event
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue