Improve reliability of markItemsReadOnScroll pref implementation in TimelineTab

This commit is contained in:
Shinokuni 2024-07-22 17:56:02 +02:00
parent 0adf55eb02
commit f95c808aa0
2 changed files with 58 additions and 15 deletions

View File

@ -48,6 +48,11 @@ class TimelineScreenModel(
private val _timelineState = MutableStateFlow(TimelineState())
val timelineState = _timelineState.asStateFlow()
// separate this from main Timeline state for performances
// as it will be very often updated
private val _listIndexState = MutableStateFlow(0)
val listIndexState = _listIndexState.asStateFlow()
private val filters = MutableStateFlow(_timelineState.value.filters)
init {
@ -80,11 +85,12 @@ class TimelineScreenModel(
}
.cachedIn(screenModelScope),
isAccountLocal = account.isLocal,
lastFirstVisibleItemIndex = 0,
scrollToTop = true
)
}
_listIndexState.update { 0 }
preferences.hideReadFeeds.flow
.flatMapLatest { hideReadFeeds ->
getFoldersWithFeeds.get(
@ -371,7 +377,7 @@ class TimelineScreenModel(
}
fun updateLastFirstVisibleItemIndex(index: Int) {
_timelineState.update { it.copy(lastFirstVisibleItemIndex = index) }
_listIndexState.update { index }
}
}
@ -395,7 +401,6 @@ data class TimelineState(
val isAccountLocal: Boolean = false,
val hideReadAllFAB: Boolean = false,
val itemSize: TimelineItemSize = TimelineItemSize.LARGE,
val lastFirstVisibleItemIndex: Int = 0,
val markReadOnScroll: Boolean = false
) {

View File

@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
@ -65,6 +66,7 @@ import com.readrops.app.util.theme.spacing
import com.readrops.db.filters.ListSortType
import com.readrops.db.filters.MainFilter
import com.readrops.db.filters.SubFilter
import com.readrops.db.pojo.ItemWithFeed
import kotlinx.coroutines.flow.filter
@ -340,18 +342,12 @@ object TimelineTab : Tab {
else -> {
if (items.itemCount > 0) {
LaunchedEffect(Unit) {
snapshotFlow { lazyListState.firstVisibleItemIndex }
.filter { it > state.lastFirstVisibleItemIndex }
.collect {
val item = items[state.lastFirstVisibleItemIndex]!!.item
if (!item.isRead && state.markReadOnScroll) {
screenModel.setItemRead(item)
}
screenModel.updateLastFirstVisibleItemIndex(it)
}
}
MarkItemsRead(
lazyListState = lazyListState,
items = items,
markReadOnScroll = state.markReadOnScroll,
screenModel = screenModel
)
LazyColumn(
state = lazyListState,
@ -422,6 +418,48 @@ object TimelineTab : Tab {
}
}
}
@Composable
private fun MarkItemsRead(
lazyListState: LazyListState,
items: LazyPagingItems<ItemWithFeed>,
markReadOnScroll: Boolean,
screenModel: TimelineScreenModel
) {
val lastFirstVisibleItemIndex by screenModel.listIndexState.collectAsStateWithLifecycle()
LaunchedEffect(Unit) {
snapshotFlow { lazyListState.firstVisibleItemIndex }
.filter {
if (it < lastFirstVisibleItemIndex) {
screenModel.updateLastFirstVisibleItemIndex(it)
}
it > lastFirstVisibleItemIndex
}
.collect { newLastFirstVisibleItemIndex ->
if (newLastFirstVisibleItemIndex - lastFirstVisibleItemIndex > 1) {
val difference = newLastFirstVisibleItemIndex - lastFirstVisibleItemIndex
for (subCount in 0 until difference) {
val item = items[lastFirstVisibleItemIndex + subCount]?.item
if (item != null && !item.isRead && markReadOnScroll) {
screenModel.setItemRead(item)
}
}
} else {
val item = items[lastFirstVisibleItemIndex]?.item
if (item != null && !item.isRead && markReadOnScroll) {
screenModel.setItemRead(item)
}
}
screenModel.updateLastFirstVisibleItemIndex(newLastFirstVisibleItemIndex)
}
}
}
}