Avoids running through the entire filter when collection is Empty

This commit is contained in:
Vitor Pamplona
2023-05-28 17:53:08 -04:00
parent 446273de80
commit 02ad85a740
4 changed files with 28 additions and 12 deletions
@@ -290,6 +290,7 @@ open class CardFeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
}
fun <T> equalImmutableLists(list1: ImmutableList<T>, list2: ImmutableList<T>): Boolean {
if (list1 === list2) return true
if (list1.size != list2.size) return false
for (i in 0 until list1.size) {
if (list1[i] !== list2[i]) {
@@ -2,10 +2,11 @@ package com.vitorpamplona.amethyst.ui.screen
import androidx.compose.runtime.MutableState
import com.vitorpamplona.amethyst.model.Note
import kotlinx.collections.immutable.ImmutableList
sealed class FeedState {
object Loading : FeedState()
class Loaded(val feed: MutableState<List<Note>>) : FeedState()
class Loaded(val feed: MutableState<ImmutableList<Note>>) : FeedState()
object Empty : FeedState()
class FeedError(val errorMessage: String) : FeedState()
}
@@ -25,6 +25,8 @@ import com.vitorpamplona.amethyst.ui.dal.UserProfileConversationsFeedFilter
import com.vitorpamplona.amethyst.ui.dal.UserProfileNewThreadFeedFilter
import com.vitorpamplona.amethyst.ui.dal.UserProfileReportsFeedFilter
import com.vitorpamplona.amethyst.ui.dal.VideoFeedFilter
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@@ -55,8 +57,8 @@ abstract class FeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
private val _feedContent = MutableStateFlow<FeedState>(FeedState.Loading)
val feedContent = _feedContent.asStateFlow()
fun newListFromDataSource(): List<Note> {
return localFilter.loadTop()
fun newListFromDataSource(): ImmutableList<Note> {
return localFilter.loadTop().toImmutableList()
}
private fun refresh() {
@@ -71,8 +73,7 @@ abstract class FeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
val oldNotesState = _feedContent.value
if (oldNotesState is FeedState.Loaded) {
// Using size as a proxy for has changed.
if (notes != oldNotesState.feed.value) {
if (!equalImmutableLists(notes, oldNotesState.feed.value)) {
updateFeed(notes)
}
} else {
@@ -80,7 +81,7 @@ abstract class FeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
}
}
private fun updateFeed(notes: List<Note>) {
private fun updateFeed(notes: ImmutableList<Note>) {
val scope = CoroutineScope(Job() + Dispatchers.Main)
scope.launch {
val currentState = _feedContent.value
@@ -97,10 +98,20 @@ abstract class FeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
fun refreshFromOldState(newItems: Set<Note>) {
val oldNotesState = _feedContent.value
if (localFilter is AdditiveFeedFilter && oldNotesState is FeedState.Loaded) {
val newList = localFilter.updateListWith(oldNotesState.feed.value, newItems.toSet())
if (newList !== oldNotesState.feed.value) {
updateFeed(newList)
if (localFilter is AdditiveFeedFilter) {
if (oldNotesState is FeedState.Loaded) {
val newList = localFilter.updateListWith(oldNotesState.feed.value, newItems.toSet()).toImmutableList()
if (!equalImmutableLists(newList, oldNotesState.feed.value)) {
updateFeed(newList)
}
} else if (oldNotesState is FeedState.Empty) {
val newList = localFilter.updateListWith(emptyList(), newItems.toSet()).toImmutableList()
if (newList.isNotEmpty()) {
updateFeed(newList)
}
} else {
// Refresh Everything
refreshSuspended()
}
} else {
// Refresh Everything
@@ -130,7 +141,9 @@ abstract class FeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
init {
collectorJob = viewModelScope.launch(Dispatchers.IO) {
LocalCache.live.newEventBundles.collect { newNotes ->
if (localFilter is AdditiveFeedFilter && _feedContent.value is FeedState.Loaded) {
if (localFilter is AdditiveFeedFilter &&
(_feedContent.value is FeedState.Loaded || _feedContent.value is FeedState.Empty)
) {
invalidateInsertData(newNotes)
} else {
// Refresh Everything
@@ -86,6 +86,7 @@ import com.vitorpamplona.amethyst.ui.screen.LoadingFeed
import com.vitorpamplona.amethyst.ui.screen.NostrVideoFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.ScrollStateKeys
import com.vitorpamplona.amethyst.ui.screen.rememberForeverPagerState
import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@@ -198,7 +199,7 @@ fun FeedView(
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun SlidingCarousel(
feed: MutableState<List<Note>>,
feed: MutableState<ImmutableList<Note>>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
scrollStateKey: String? = null,