Implement progressive fetching for messages
Start fetching from API when messages fetched in last API request are shown in the list MAILAND-2089
This commit is contained in:
parent
62ba8725fc
commit
968e2e2956
|
@ -211,13 +211,15 @@ class MailboxRecyclerViewAdapter(
|
|||
mailboxLocation = locationType
|
||||
}
|
||||
|
||||
fun getOldestMailboxItemTimestamp(): Long {
|
||||
val lastItemTimeMs = if (mailboxItems.isNotEmpty()) {
|
||||
mailboxItems.minOf { it.lastMessageTimeMs }
|
||||
} else {
|
||||
System.currentTimeMillis()
|
||||
}
|
||||
return lastItemTimeMs / 1000
|
||||
}
|
||||
/**
|
||||
* @return `true` if any items withing the given positions' range has an [MailboxUiItem.itemId] that matches one
|
||||
* from [mailboxItemsIds]
|
||||
*/
|
||||
fun isAnyMailboxItemWithinPositions(
|
||||
mailboxItemsIds: List<String>,
|
||||
startPosition: Int,
|
||||
endPosition: Int
|
||||
) = mailboxItems.subList(startPosition, endPosition + 1)
|
||||
.any { it.itemId in mailboxItemsIds }
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import me.proton.core.domain.arch.ResponseSource
|
|||
import me.proton.core.domain.arch.mapSuccess
|
||||
import me.proton.core.domain.arch.onSuccess
|
||||
import me.proton.core.util.kotlin.invoke
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* [ProtonStore] works in a similar manner as [com.dropbox.android.external.store4.Store] but provide us a more
|
||||
|
@ -102,6 +103,7 @@ class ProtonStore<Key : Any, ApiModel : Any, DatabaseModel : Any, DomainModel :
|
|||
freshAsApiModel(key).toDomainModelsDataResult()
|
||||
|
||||
private suspend fun freshAsApiModel(key: Key): DataResult<ApiModel> {
|
||||
Timber.i("Fetching for: $key")
|
||||
@Suppress("TooGenericExceptionCaught")
|
||||
val apiResult = try {
|
||||
val apiModels = fetcher(key)
|
||||
|
|
|
@ -210,6 +210,7 @@ internal class MailboxActivity :
|
|||
setNewLabel(value ?: EMPTY_STRING)
|
||||
}
|
||||
private var mailboxLabelName: String? = null
|
||||
private var lastFetchedMailboxItemsIds = emptyList<String>()
|
||||
private var refreshMailboxJobRunning = false
|
||||
private lateinit var syncUUID: String
|
||||
private var customizeSwipeSnackShown = false
|
||||
|
@ -219,7 +220,6 @@ internal class MailboxActivity :
|
|||
|
||||
override val currentLabelId get() = mailboxLabelId
|
||||
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.activity_mailbox
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
@ -571,6 +571,7 @@ internal class MailboxActivity :
|
|||
if (isLoadingMore.get()) setLoadingMore(false)
|
||||
}
|
||||
is MailboxState.ApiRefresh -> {
|
||||
lastFetchedMailboxItemsIds = state.lastFetchedMessagesIds
|
||||
setRefreshing(false)
|
||||
}
|
||||
is MailboxState.Data -> {
|
||||
|
@ -611,19 +612,29 @@ internal class MailboxActivity :
|
|||
if (!scrollStateChanged) {
|
||||
return
|
||||
}
|
||||
val layoutManager = recyclerView.layoutManager as LinearLayoutManager?
|
||||
val adapter = recyclerView.adapter
|
||||
val lastVisibleItem = layoutManager!!.findLastVisibleItemPosition()
|
||||
val lastPosition = adapter!!.itemCount - 1
|
||||
if (lastVisibleItem == lastPosition && dy > 0 && !setLoadingMore(true)) {
|
||||
mailboxViewModel.loadMore()
|
||||
// TODO: remove, use loadMore only
|
||||
loadMailboxItems(oldestItemTimestamp = mailboxAdapter.getOldestMailboxItemTimestamp())
|
||||
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
|
||||
|
||||
val firstCompletelyVisibleItemPosition = layoutManager.findFirstCompletelyVisibleItemPosition()
|
||||
|
||||
// Load more when showing last fetched messages or at the end of the list
|
||||
if (dy > 0 && isLoadingMore.get().not()) {
|
||||
val lastCompletelyVisibleItemPosition = layoutManager.findLastCompletelyVisibleItemPosition()
|
||||
val isAtBottomOfTheList = lastCompletelyVisibleItemPosition == mailboxAdapter.itemCount - 1
|
||||
fun inAnyLastFetchedMailboxItemVisible() =
|
||||
mailboxAdapter.isAnyMailboxItemWithinPositions(
|
||||
mailboxItemsIds = lastFetchedMailboxItemsIds,
|
||||
startPosition = firstCompletelyVisibleItemPosition,
|
||||
endPosition = lastCompletelyVisibleItemPosition
|
||||
)
|
||||
if (isAtBottomOfTheList || inAnyLastFetchedMailboxItemVisible()) {
|
||||
setLoadingMore(true)
|
||||
mailboxViewModel.loadMore()
|
||||
lastFetchedMailboxItemsIds = emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
// Increase the elevation if the list is scrolled down and decrease if it is scrolled to the top
|
||||
val firstVisibleItem = layoutManager.findFirstCompletelyVisibleItemPosition()
|
||||
if (firstVisibleItem == 0) {
|
||||
if (firstCompletelyVisibleItemPosition == 0) {
|
||||
setElevationOnToolbarAndStatusView(false)
|
||||
} else {
|
||||
setElevationOnToolbarAndStatusView(true)
|
||||
|
@ -631,13 +642,7 @@ internal class MailboxActivity :
|
|||
}
|
||||
}
|
||||
|
||||
private fun loadMailboxItems(
|
||||
includeLabels: Boolean = false,
|
||||
refreshMessages: Boolean = false,
|
||||
oldestItemTimestamp: Long = now()
|
||||
) {
|
||||
|
||||
Timber.v("loadMailboxItems last: $oldestItemTimestamp")
|
||||
private fun loadMailboxItems() {
|
||||
mailboxViewModel.loadMailboxItems()
|
||||
}
|
||||
|
||||
|
@ -667,7 +672,7 @@ internal class MailboxActivity :
|
|||
// TODO: is this needed?
|
||||
mailboxViewModel.loadMore()
|
||||
// TODO: remove, use loadMore only
|
||||
loadMailboxItems(includeLabels = true)
|
||||
loadMailboxItems()
|
||||
}
|
||||
mailboxViewModel.checkConnectivityDelayed()
|
||||
}
|
||||
|
|
|
@ -367,6 +367,7 @@ class MailboxViewModel @Inject constructor(
|
|||
}
|
||||
is GetMessagesResult.ApiRefresh -> {
|
||||
if (hasReceivedFirstApiRefresh == null) hasReceivedFirstApiRefresh = true
|
||||
else if (hasReceivedFirstApiRefresh == true) hasReceivedFirstApiRefresh = false
|
||||
|
||||
MailboxState.ApiRefresh(
|
||||
lastFetchedMessagesIds = result.lastFetchedMessages.mapNotNull { it.messageId }
|
||||
|
|
Loading…
Reference in New Issue