mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-17 15:26:23 +00:00
[fenix] Closes https://github.com/mozilla-mobile/fenix/issues/24276: updating pagination library, changing history related classes
This commit is contained in:
parent
8106fb3d15
commit
3bbd8d2571
@ -76,9 +76,9 @@ interface PagedHistoryProvider {
|
||||
*
|
||||
* @param offset How much to offset the list by
|
||||
* @param numberOfItems How many items to fetch
|
||||
* @param onComplete A callback that returns the list of [HistoryDB]
|
||||
* @return list of [HistoryDB]
|
||||
*/
|
||||
fun getHistory(offset: Int, numberOfItems: Int, onComplete: (List<HistoryDB>) -> Unit)
|
||||
fun getHistory(offset: Int, numberOfItems: Int): List<HistoryDB>
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,15 +112,11 @@ class DefaultPagedHistoryProvider(
|
||||
|
||||
@Volatile private var historyGroups: List<HistoryDB.Group>? = null
|
||||
|
||||
@Suppress("LongMethod")
|
||||
override fun getHistory(
|
||||
offset: Int,
|
||||
numberOfItems: Int,
|
||||
onComplete: (List<HistoryDB>) -> Unit,
|
||||
) {
|
||||
// A PagedList DataSource runs on a background thread automatically.
|
||||
// If we run this in our own coroutineScope it breaks the PagedList
|
||||
runBlockingIncrement {
|
||||
numberOfItems: Int
|
||||
): List<HistoryDB> {
|
||||
return runBlockingIncrement {
|
||||
// We need to re-fetch all the history metadata if the offset resets back at 0
|
||||
// in the case of a pull to refresh.
|
||||
if (historyGroups == null || offset == 0) {
|
||||
@ -146,7 +142,7 @@ class DefaultPagedHistoryProvider(
|
||||
.toList()
|
||||
}
|
||||
|
||||
onComplete(getHistoryAndSearchGroups(offset, numberOfItems))
|
||||
getHistoryAndSearchGroups(offset, numberOfItems)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,14 @@ package org.mozilla.fenix.library.history
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.paging.PagedListAdapter
|
||||
import androidx.paging.PagingDataAdapter
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import org.mozilla.fenix.selection.SelectionHolder
|
||||
import org.mozilla.fenix.library.history.viewholders.HistoryListItemViewHolder
|
||||
|
||||
class HistoryAdapter(
|
||||
private val historyInteractor: HistoryInteractor,
|
||||
) : PagedListAdapter<History, HistoryListItemViewHolder>(historyDiffCallback),
|
||||
) : PagingDataAdapter<History, HistoryListItemViewHolder>(historyDiffCallback),
|
||||
SelectionHolder<History> {
|
||||
|
||||
private var mode: HistoryFragmentState.Mode = HistoryFragmentState.Mode.Normal
|
||||
|
@ -5,38 +5,40 @@
|
||||
package org.mozilla.fenix.library.history
|
||||
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.paging.ItemKeyedDataSource
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import org.mozilla.fenix.components.history.HistoryDB
|
||||
import org.mozilla.fenix.components.history.PagedHistoryProvider
|
||||
|
||||
class HistoryDataSource(
|
||||
private val historyProvider: PagedHistoryProvider
|
||||
) : ItemKeyedDataSource<Int, History>() {
|
||||
private val historyProvider: PagedHistoryProvider,
|
||||
private val onZeroItemsLoaded: () -> Unit
|
||||
) : PagingSource<Int, History>() {
|
||||
|
||||
// Because the pagination is not based off of the key
|
||||
// we want to start at 1, not 0 to be able to send the correct offset
|
||||
// to the `historyProvider.getHistory` call.
|
||||
override fun getKey(item: History): Int = item.position + 1
|
||||
// having any value but null creates visual glitches in case or swipe to refresh and immediate
|
||||
// scroll down
|
||||
override fun getRefreshKey(state: PagingState<Int, History>): Int? = null
|
||||
|
||||
override fun loadInitial(
|
||||
params: LoadInitialParams<Int>,
|
||||
callback: LoadInitialCallback<History>
|
||||
) {
|
||||
historyProvider.getHistory(INITIAL_OFFSET, params.requestedLoadSize) { history ->
|
||||
callback.onResult(history.positionWithOffset(INITIAL_OFFSET))
|
||||
// params.key is expected to be null for the initial load or a refresh
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, History> {
|
||||
val offset = params.key ?: 0
|
||||
val historyItems = historyProvider.getHistory(offset, params.loadSize).run {
|
||||
positionWithOffset(offset)
|
||||
}
|
||||
val nextOffset = if (historyItems.isEmpty()) {
|
||||
if (params.key == null) {
|
||||
onZeroItemsLoaded.invoke()
|
||||
}
|
||||
|
||||
override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<History>) {
|
||||
historyProvider.getHistory(params.key, params.requestedLoadSize) { history ->
|
||||
callback.onResult(history.positionWithOffset(params.key))
|
||||
null
|
||||
} else {
|
||||
(offset + historyItems.size) + 1
|
||||
}
|
||||
}
|
||||
|
||||
override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<History>) { /* noop */ }
|
||||
|
||||
companion object {
|
||||
internal const val INITIAL_OFFSET = 0
|
||||
// prevKey is needed in case load would work upwards, so passing null is fine
|
||||
return LoadResult.Page(
|
||||
data = historyItems,
|
||||
prevKey = null,
|
||||
nextKey = nextOffset
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.library.history
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.paging.DataSource
|
||||
import org.mozilla.fenix.components.history.PagedHistoryProvider
|
||||
|
||||
class HistoryDataSourceFactory(
|
||||
private val historyProvider: PagedHistoryProvider
|
||||
) : DataSource.Factory<Int, History>() {
|
||||
val datasource = MutableLiveData<HistoryDataSource>()
|
||||
|
||||
override fun create(): DataSource<Int, History> {
|
||||
val datasource = HistoryDataSource(historyProvider)
|
||||
this.datasource.postValue(datasource)
|
||||
return datasource
|
||||
}
|
||||
}
|
@ -15,11 +15,13 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation.NavDirections
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.Dispatchers.Main
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import mozilla.components.browser.state.action.EngineAction
|
||||
import mozilla.components.browser.state.action.HistoryMetadataAction
|
||||
@ -158,10 +160,11 @@ class HistoryFragment : LibraryPageFragment<History>(), UserInteractionHandler {
|
||||
historyView::updateEmptyState
|
||||
)
|
||||
|
||||
model.history.observe(
|
||||
viewLifecycleOwner,
|
||||
historyView.historyAdapter::submitList
|
||||
)
|
||||
model.viewModelScope.launch {
|
||||
model.history.collect {
|
||||
historyView.historyAdapter.submitData(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -322,7 +325,7 @@ class HistoryFragment : LibraryPageFragment<History>(), UserInteractionHandler {
|
||||
requireComponents.core.historyStorage.deleteEverything()
|
||||
deleteOpenTabsEngineHistory(requireComponents.core.store)
|
||||
launch(Main) {
|
||||
viewModel.invalidate()
|
||||
historyView.historyAdapter.refresh()
|
||||
historyStore.dispatch(HistoryFragmentAction.ExitDeletionMode)
|
||||
showSnackBar(
|
||||
requireView(),
|
||||
@ -411,6 +414,6 @@ class HistoryFragment : LibraryPageFragment<History>(), UserInteractionHandler {
|
||||
private suspend fun syncHistory() {
|
||||
val accountManager = requireComponents.backgroundServices.accountManager
|
||||
accountManager.syncNow(SyncReason.User)
|
||||
viewModel.invalidate()
|
||||
historyView.historyAdapter.refresh()
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ class HistoryView(
|
||||
|
||||
historyAdapter.updatePendingDeletionIds(state.pendingDeletionIds)
|
||||
|
||||
updateEmptyState(state.pendingDeletionIds.size != historyAdapter.currentList?.size)
|
||||
updateEmptyState(state.pendingDeletionIds.size != historyAdapter.itemCount)
|
||||
|
||||
historyAdapter.updateMode(state.mode)
|
||||
val first = layoutManager.findFirstVisibleItemPosition()
|
||||
|
@ -4,33 +4,28 @@
|
||||
|
||||
package org.mozilla.fenix.library.history
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.paging.LivePagedListBuilder
|
||||
import androidx.paging.PagedList
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.mozilla.fenix.components.history.PagedHistoryProvider
|
||||
|
||||
class HistoryViewModel(historyProvider: PagedHistoryProvider) : ViewModel() {
|
||||
var history: LiveData<PagedList<History>>
|
||||
var history: Flow<PagingData<History>>
|
||||
var userHasHistory = MutableLiveData(true)
|
||||
private val datasource: LiveData<HistoryDataSource>
|
||||
|
||||
init {
|
||||
val historyDataSourceFactory = HistoryDataSourceFactory(historyProvider)
|
||||
datasource = historyDataSourceFactory.datasource
|
||||
|
||||
history = LivePagedListBuilder(historyDataSourceFactory, PAGE_SIZE)
|
||||
.setBoundaryCallback(object : PagedList.BoundaryCallback<History>() {
|
||||
override fun onZeroItemsLoaded() {
|
||||
userHasHistory.value = false
|
||||
}
|
||||
})
|
||||
.build()
|
||||
}
|
||||
|
||||
fun invalidate() {
|
||||
datasource.value?.invalidate()
|
||||
history = Pager(
|
||||
PagingConfig(PAGE_SIZE),
|
||||
null
|
||||
) {
|
||||
HistoryDataSource(
|
||||
historyProvider = historyProvider,
|
||||
onZeroItemsLoaded = { userHasHistory.value = false }
|
||||
)
|
||||
}.flow
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -17,8 +17,6 @@ import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.paging.LivePagedListBuilder
|
||||
import androidx.paging.PagedListAdapter
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@ -36,6 +34,7 @@ import org.mozilla.fenix.ext.nav
|
||||
|
||||
private const val MAX_ITEMS_PER_PAGE = 50
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
class SitePermissionsExceptionsFragment :
|
||||
Fragment(R.layout.fragment_site_permissions_exceptions), View.OnClickListener {
|
||||
private lateinit var emptyContainerMessage: View
|
||||
@ -63,7 +62,7 @@ class SitePermissionsExceptionsFragment :
|
||||
|
||||
withContext(Main) {
|
||||
val adapter = ExceptionsAdapter(this@SitePermissionsExceptionsFragment)
|
||||
val liveData = LivePagedListBuilder(sitePermissionsPaged, MAX_ITEMS_PER_PAGE).build()
|
||||
val liveData = androidx.paging.LivePagedListBuilder(sitePermissionsPaged, MAX_ITEMS_PER_PAGE).build()
|
||||
|
||||
liveData.observe(
|
||||
viewLifecycleOwner,
|
||||
@ -135,8 +134,9 @@ class SitePermissionsExceptionsFragment :
|
||||
class SitePermissionsViewHolder(val view: View, val iconView: ImageView, val siteTextView: TextView) :
|
||||
RecyclerView.ViewHolder(view)
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
class ExceptionsAdapter(private val clickListener: View.OnClickListener) :
|
||||
PagedListAdapter<SitePermissions, SitePermissionsViewHolder>(diffCallback) {
|
||||
androidx.paging.PagedListAdapter<SitePermissions, SitePermissionsViewHolder>(diffCallback) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SitePermissionsViewHolder {
|
||||
val context = parent.context
|
||||
|
@ -35,7 +35,7 @@ object Versions {
|
||||
const val androidx_navigation = "2.3.3"
|
||||
const val androidx_recyclerview = "1.2.1"
|
||||
const val androidx_core = "1.3.2"
|
||||
const val androidx_paging = "2.1.2"
|
||||
const val androidx_paging = "3.1.0"
|
||||
const val androidx_transition = "1.4.0"
|
||||
const val androidx_work = "2.7.1"
|
||||
const val androidx_datastore = "1.0.0"
|
||||
|
Loading…
Reference in New Issue
Block a user