Updated on 2026-08-14

This commit is contained in:
Tangem 2024-07-23 12:02:56 +03:00
parent 4ec02d0447
commit f426a1f922
26 changed files with 748 additions and 247 deletions

View file

@ -68,4 +68,10 @@ sealed class BatchAction<out TKey, out TRequestParams, out TUpdate> {
class CancelUpdates<TKey, TUpdate>(
val predicate: (UpdateBatches<TKey, TUpdate>) -> Boolean,
) : BatchAction<TKey, Nothing, TUpdate>()
/**
* Clears the state and stops all current batch loading and updates
* After this status becomes [PaginationStatus.None]
*/
data object Reset : BatchAction<Nothing, Nothing, Nothing>()
}

View file

@ -12,10 +12,12 @@ sealed class BatchFetchResult<out TData> {
* Represents a successful result of a batch fetch request.
*
* @param data fetched data.
* @param empty indicates that data is empty and [BatchListSource] shouldn't create new batch for this result
* @param last indicates if this is the last batch for the request.
*/
data class Success<TData>(
val data: TData,
val empty: Boolean,
val last: Boolean,
) : BatchFetchResult<TData>()

View file

@ -92,11 +92,7 @@ private class DefaultBatchListSource<TKey, TData, TRequestParams : Any, TUpdate>
awaitCancellation()
} finally {
withContext(NonCancellable) {
stopAllUpdates()
loadMoreActionJob = null
loadMoreActionJob = null
lastRequestResult.value = null
state.value = BatchListState(emptyList(), PaginationStatus.None)
resetState()
}
}
}
@ -110,6 +106,7 @@ private class DefaultBatchListSource<TKey, TData, TRequestParams : Any, TUpdate>
}
}
@Suppress("CyclomaticComplexMethod")
private fun collectActions(action: BatchAction<TKey, TRequestParams, TUpdate>) {
when (action) {
is BatchAction.Reload -> {
@ -165,6 +162,9 @@ private class DefaultBatchListSource<TKey, TData, TRequestParams : Any, TUpdate>
loadMoreActionJob?.cancel()
reloadActionJob?.cancel()
}
BatchAction.Reset -> {
resetState()
}
}
}
@ -237,13 +237,17 @@ private class DefaultBatchListSource<TKey, TData, TRequestParams : Any, TUpdate>
state.value = when (res) {
is BatchFetchResult.Success -> {
val key = generateNewKey(listOf())
val batch = Batch(
key = key,
data = res.data,
)
val batch = if (res.empty.not()) {
Batch(
key = generateNewKey(listOf()),
data = res.data,
)
} else {
null
}
BatchListState(
data = listOf(batch),
data = batch?.let { listOf(it) } ?: emptyList(),
status = if (res.last) {
PaginationStatus.EndOfPagination
} else {
@ -289,13 +293,17 @@ private class DefaultBatchListSource<TKey, TData, TRequestParams : Any, TUpdate>
state.update { currentState ->
when (res) {
is BatchFetchResult.Success -> {
val newBatch = Batch(
key = generateNewKey(currentState.data.map { it.key }),
data = res.data,
)
val newBatch = if (res.empty.not()) {
Batch(
key = generateNewKey(currentState.data.map { it.key }),
data = res.data,
)
} else {
null
}
currentState.copy(
data = currentState.data + newBatch,
data = newBatch?.let { currentState.data + it } ?: currentState.data,
status = if (res.last) {
PaginationStatus.EndOfPagination
} else {
@ -400,6 +408,18 @@ private class DefaultBatchListSource<TKey, TData, TRequestParams : Any, TUpdate>
waitingUpdateJobs.value.any { it.first.operationId == operationId }
}
private fun resetState() {
if (updateFetcher != null) {
stopAllUpdates()
}
loadMoreActionJob?.cancel()
loadMoreActionJob = null
reloadActionJob?.cancel()
reloadActionJob = null
lastRequestResult.value = null
state.value = BatchListState(emptyList(), PaginationStatus.None)
}
private fun stopAllUpdates() {
updateAsyncJobs.update { actionAsyncJobs ->
actionAsyncJobs.forEach {

View file

@ -32,6 +32,7 @@ class LimitOffsetBatchFetcher<TRequestParams : Any, TData>(
suspend fun fetch(
request: Request<TRequestParams>,
lastResult: BatchFetchResult<TData>?,
isFirstBatchFetching: Boolean,
): BatchFetchResult<TData>
}
@ -45,7 +46,7 @@ class LimitOffsetBatchFetcher<TRequestParams : Any, TData>(
)
val res = runCatching {
subFetcher.fetch(req, null)
subFetcher.fetch(request = req, lastResult = null, isFirstBatchFetching = true)
}.getOrElse {
currentCoroutineContext().ensureActive()
BatchFetchResult.Error(it)
@ -77,7 +78,7 @@ class LimitOffsetBatchFetcher<TRequestParams : Any, TData>(
}
val res = runCatching {
subFetcher.fetch(req, lastResult)
subFetcher.fetch(request = req, lastResult = lastResult, isFirstBatchFetching = false)
}.getOrElse {
currentCoroutineContext().ensureActive()
BatchFetchResult.Error(it)