Improve refresh loading behaviour in TimelineTab

This commit is contained in:
Shinokuni 2024-08-12 20:55:23 +02:00
parent e9b3a26074
commit 57d66b565c
1 changed files with 49 additions and 33 deletions

View File

@ -36,7 +36,6 @@ import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.transformLatest
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -64,35 +63,10 @@ class TimelineScreenModel(
accountEvent, accountEvent,
filters filters
) { account, filters -> ) { account, filters ->
Pair(account, filters.copy(accountId = account.id)) account to filters.copy(accountId = account.id)
}.collectLatest { (account, filters) -> }.collectLatest { (account, filters) ->
val query = this@TimelineScreenModel.filters.update { filters }
ItemsQueryBuilder.buildItemsQuery(filters, account.config.useSeparateState) buildPager()
_timelineState.update {
it.copy(
itemState = Pager(
config = PagingConfig(
initialLoadSize = 50,
pageSize = 50,
prefetchDistance = 15
),
pagingSourceFactory = {
database.itemDao().selectAll(query)
},
).flow
.transformLatest { value ->
if (!timelineState.value.isRefreshing) {
emit(value)
}
}
.cachedIn(screenModelScope),
isAccountLocal = account.isLocal,
scrollToTop = true
)
}
_listIndexState.update { 0 }
preferences.hideReadFeeds.flow preferences.hideReadFeeds.flow
.flatMapLatest { hideReadFeeds -> .flatMapLatest { hideReadFeeds ->
@ -146,11 +120,46 @@ class TimelineScreenModel(
} }
} }
private fun buildPager(empty: Boolean = false) {
val query = ItemsQueryBuilder.buildItemsQuery(
filters.value,
currentAccount!!.config.useSeparateState
)
val pager = Pager(
config = PagingConfig(
initialLoadSize = 50,
pageSize = 50,
prefetchDistance = 15
),
pagingSourceFactory = {
database.itemDao().selectAll(query)
},
).flow
.cachedIn(screenModelScope)
_timelineState.update {
it.copy(
itemState = if (!empty) {
pager
} else {
emptyFlow()
},
isAccountLocal = currentAccount!!.isLocal,
scrollToTop = true
)
}
_listIndexState.update { 0 }
}
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
fun refreshTimeline(context: Context) { fun refreshTimeline(context: Context) {
buildPager(empty = true)
screenModelScope.launch(dispatcher) { screenModelScope.launch(dispatcher) {
val filterPair = with(filters.value) { val filterPair = with(filters.value) {
when (subFilter) { when (subFilter) {
SubFilter.FEED -> SyncWorker.FEED_ID_KEY to filterFeedId SubFilter.FEED -> SyncWorker.FEED_ID_KEY to filterFeedId
SubFilter.FOLDER -> SyncWorker.FOLDER_ID_KEY to filterFolderId SubFilter.FOLDER -> SyncWorker.FOLDER_ID_KEY to filterFolderId
else -> null else -> null
@ -173,7 +182,8 @@ class TimelineScreenModel(
SyncWorker.startNow(context, workData) { workInfo -> SyncWorker.startNow(context, workData) { workInfo ->
when { when {
workInfo.outputData.getBoolean(SyncWorker.END_SYNC_KEY, false) -> { workInfo.outputData.getBoolean(SyncWorker.END_SYNC_KEY, false) -> {
val errors = workInfo.outputData.getSerializable(SyncWorker.LOCAL_SYNC_ERRORS_KEY) as ErrorResult? val errors =
workInfo.outputData.getSerializable(SyncWorker.LOCAL_SYNC_ERRORS_KEY) as ErrorResult?
workInfo.outputData.clearSerializables() workInfo.outputData.clearSerializables()
_timelineState.update { _timelineState.update {
@ -184,9 +194,12 @@ class TimelineScreenModel(
localSyncErrors = errors?.ifEmpty { null } localSyncErrors = errors?.ifEmpty { null }
) )
} }
buildPager()
} }
workInfo.outputData.getBoolean(SyncWorker.SYNC_FAILURE_KEY, false) -> { workInfo.outputData.getBoolean(SyncWorker.SYNC_FAILURE_KEY, false) -> {
val error = workInfo.outputData.getSerializable(SyncWorker.SYNC_FAILURE_EXCEPTION_KEY) as Exception? val error =
workInfo.outputData.getSerializable(SyncWorker.SYNC_FAILURE_EXCEPTION_KEY) as Exception?
workInfo.outputData.clearSerializables() workInfo.outputData.clearSerializables()
_timelineState.update { _timelineState.update {
@ -196,13 +209,16 @@ class TimelineScreenModel(
hideReadAllFAB = false hideReadAllFAB = false
) )
} }
buildPager()
} }
workInfo.progress.getString(SyncWorker.FEED_NAME_KEY) != null -> { workInfo.progress.getString(SyncWorker.FEED_NAME_KEY) != null -> {
_timelineState.update { _timelineState.update {
it.copy( it.copy(
isRefreshing = true, isRefreshing = true,
hideReadAllFAB = true, hideReadAllFAB = true,
currentFeed = workInfo.progress.getString(SyncWorker.FEED_NAME_KEY) ?: "", currentFeed = workInfo.progress.getString(SyncWorker.FEED_NAME_KEY)
?: "",
feedCount = workInfo.progress.getInt(SyncWorker.FEED_COUNT_KEY, 0), feedCount = workInfo.progress.getInt(SyncWorker.FEED_COUNT_KEY, 0),
feedMax = workInfo.progress.getInt(SyncWorker.FEED_MAX_KEY, 0) feedMax = workInfo.progress.getInt(SyncWorker.FEED_MAX_KEY, 0)
) )