|
|
|
@ -24,16 +24,21 @@ import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
|
|
|
|
import org.koitharu.kotatsu.core.prefs.ListMode
|
|
|
|
import org.koitharu.kotatsu.core.prefs.ListMode
|
|
|
|
import org.koitharu.kotatsu.databinding.FragmentListBinding
|
|
|
|
import org.koitharu.kotatsu.databinding.FragmentListBinding
|
|
|
|
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
|
|
|
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
|
|
|
|
|
|
|
import org.koitharu.kotatsu.list.ui.adapter.AsyncViewFactory
|
|
|
|
import org.koitharu.kotatsu.list.ui.adapter.MangaListAdapter
|
|
|
|
import org.koitharu.kotatsu.list.ui.adapter.MangaListAdapter
|
|
|
|
|
|
|
|
import org.koitharu.kotatsu.list.ui.adapter.MangaListAdapter.Companion.ITEM_TYPE_MANGA_GRID
|
|
|
|
import org.koitharu.kotatsu.list.ui.adapter.MangaListListener
|
|
|
|
import org.koitharu.kotatsu.list.ui.adapter.MangaListListener
|
|
|
|
import org.koitharu.kotatsu.list.ui.model.ListModel
|
|
|
|
import org.koitharu.kotatsu.list.ui.model.ListModel
|
|
|
|
import org.koitharu.kotatsu.main.ui.AppBarOwner
|
|
|
|
import org.koitharu.kotatsu.main.ui.AppBarOwner
|
|
|
|
import org.koitharu.kotatsu.main.ui.MainActivity
|
|
|
|
import org.koitharu.kotatsu.main.ui.MainActivity
|
|
|
|
import org.koitharu.kotatsu.parsers.model.Manga
|
|
|
|
import org.koitharu.kotatsu.parsers.model.Manga
|
|
|
|
import org.koitharu.kotatsu.parsers.model.MangaTag
|
|
|
|
import org.koitharu.kotatsu.parsers.model.MangaTag
|
|
|
|
import org.koitharu.kotatsu.utils.RecycledViewPoolHolder
|
|
|
|
|
|
|
|
import org.koitharu.kotatsu.utils.ext.*
|
|
|
|
import org.koitharu.kotatsu.utils.ext.*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private const val PREFETCH_ITEM_LIST = 10
|
|
|
|
|
|
|
|
private const val PREFETCH_ITEM_DETAILED = 8
|
|
|
|
|
|
|
|
private const val PREFETCH_ITEM_GRID = 16
|
|
|
|
|
|
|
|
|
|
|
|
abstract class MangaListFragment : BaseFragment<FragmentListBinding>(),
|
|
|
|
abstract class MangaListFragment : BaseFragment<FragmentListBinding>(),
|
|
|
|
PaginationScrollListener.Callback, MangaListListener,
|
|
|
|
PaginationScrollListener.Callback, MangaListListener,
|
|
|
|
SwipeRefreshLayout.OnRefreshListener {
|
|
|
|
SwipeRefreshLayout.OnRefreshListener {
|
|
|
|
@ -45,6 +50,7 @@ abstract class MangaListFragment : BaseFragment<FragmentListBinding>(),
|
|
|
|
private val listCommitCallback = Runnable {
|
|
|
|
private val listCommitCallback = Runnable {
|
|
|
|
spanSizeLookup.invalidateCache()
|
|
|
|
spanSizeLookup.invalidateCache()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private var asyncViewFactory: AsyncViewFactory? = null
|
|
|
|
open val isSwipeRefreshEnabled = true
|
|
|
|
open val isSwipeRefreshEnabled = true
|
|
|
|
|
|
|
|
|
|
|
|
protected abstract val viewModel: MangaListViewModel
|
|
|
|
protected abstract val viewModel: MangaListViewModel
|
|
|
|
@ -61,10 +67,12 @@ abstract class MangaListFragment : BaseFragment<FragmentListBinding>(),
|
|
|
|
|
|
|
|
|
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
|
|
super.onViewCreated(view, savedInstanceState)
|
|
|
|
super.onViewCreated(view, savedInstanceState)
|
|
|
|
|
|
|
|
asyncViewFactory = AsyncViewFactory(binding.recyclerView)
|
|
|
|
listAdapter = MangaListAdapter(
|
|
|
|
listAdapter = MangaListAdapter(
|
|
|
|
coil = get(),
|
|
|
|
coil = get(),
|
|
|
|
lifecycleOwner = viewLifecycleOwner,
|
|
|
|
lifecycleOwner = viewLifecycleOwner,
|
|
|
|
listener = this,
|
|
|
|
listener = this,
|
|
|
|
|
|
|
|
viewFactory = checkNotNull(asyncViewFactory),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
paginationListener = PaginationScrollListener(4, this)
|
|
|
|
paginationListener = PaginationScrollListener(4, this)
|
|
|
|
with(binding.recyclerView) {
|
|
|
|
with(binding.recyclerView) {
|
|
|
|
@ -79,10 +87,6 @@ abstract class MangaListFragment : BaseFragment<FragmentListBinding>(),
|
|
|
|
isEnabled = isSwipeRefreshEnabled
|
|
|
|
isEnabled = isSwipeRefreshEnabled
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
(parentFragment as? RecycledViewPoolHolder)?.let {
|
|
|
|
|
|
|
|
binding.recyclerView.setRecycledViewPool(it.recycledViewPool)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
viewModel.content.observe(viewLifecycleOwner, ::onListChanged)
|
|
|
|
viewModel.content.observe(viewLifecycleOwner, ::onListChanged)
|
|
|
|
viewModel.onError.observe(viewLifecycleOwner, ::onError)
|
|
|
|
viewModel.onError.observe(viewLifecycleOwner, ::onError)
|
|
|
|
viewModel.isLoading.observe(viewLifecycleOwner, ::onLoadingStateChanged)
|
|
|
|
viewModel.isLoading.observe(viewLifecycleOwner, ::onLoadingStateChanged)
|
|
|
|
@ -93,6 +97,8 @@ abstract class MangaListFragment : BaseFragment<FragmentListBinding>(),
|
|
|
|
override fun onDestroyView() {
|
|
|
|
override fun onDestroyView() {
|
|
|
|
listAdapter = null
|
|
|
|
listAdapter = null
|
|
|
|
paginationListener = null
|
|
|
|
paginationListener = null
|
|
|
|
|
|
|
|
asyncViewFactory?.clear()
|
|
|
|
|
|
|
|
asyncViewFactory = null
|
|
|
|
spanSizeLookup.invalidateCache()
|
|
|
|
spanSizeLookup.invalidateCache()
|
|
|
|
super.onDestroyView()
|
|
|
|
super.onDestroyView()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -215,18 +221,26 @@ abstract class MangaListFragment : BaseFragment<FragmentListBinding>(),
|
|
|
|
with(binding.recyclerView) {
|
|
|
|
with(binding.recyclerView) {
|
|
|
|
clearItemDecorations()
|
|
|
|
clearItemDecorations()
|
|
|
|
removeOnLayoutChangeListener(spanResolver)
|
|
|
|
removeOnLayoutChangeListener(spanResolver)
|
|
|
|
|
|
|
|
asyncViewFactory?.clear()
|
|
|
|
|
|
|
|
val isListPending = viewModel.isListPending()
|
|
|
|
when (mode) {
|
|
|
|
when (mode) {
|
|
|
|
ListMode.LIST -> {
|
|
|
|
ListMode.LIST -> {
|
|
|
|
layoutManager = FitHeightLinearLayoutManager(context)
|
|
|
|
layoutManager = FitHeightLinearLayoutManager(context)
|
|
|
|
val spacing = resources.getDimensionPixelOffset(R.dimen.list_spacing)
|
|
|
|
val spacing = resources.getDimensionPixelOffset(R.dimen.list_spacing)
|
|
|
|
addItemDecoration(SpacingItemDecoration(spacing))
|
|
|
|
addItemDecoration(SpacingItemDecoration(spacing))
|
|
|
|
updatePadding(left = spacing, right = spacing)
|
|
|
|
updatePadding(left = spacing, right = spacing)
|
|
|
|
|
|
|
|
if (isListPending) {
|
|
|
|
|
|
|
|
asyncViewFactory?.prefetch(R.layout.item_manga_list, PREFETCH_ITEM_LIST)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ListMode.DETAILED_LIST -> {
|
|
|
|
ListMode.DETAILED_LIST -> {
|
|
|
|
layoutManager = FitHeightLinearLayoutManager(context)
|
|
|
|
layoutManager = FitHeightLinearLayoutManager(context)
|
|
|
|
val spacing = resources.getDimensionPixelOffset(R.dimen.list_spacing)
|
|
|
|
val spacing = resources.getDimensionPixelOffset(R.dimen.list_spacing)
|
|
|
|
updatePadding(left = spacing, right = spacing)
|
|
|
|
updatePadding(left = spacing, right = spacing)
|
|
|
|
addItemDecoration(SpacingItemDecoration(spacing))
|
|
|
|
addItemDecoration(SpacingItemDecoration(spacing))
|
|
|
|
|
|
|
|
if (isListPending) {
|
|
|
|
|
|
|
|
asyncViewFactory?.prefetch(R.layout.item_manga_list_details, PREFETCH_ITEM_DETAILED)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ListMode.GRID -> {
|
|
|
|
ListMode.GRID -> {
|
|
|
|
layoutManager = FitHeightGridLayoutManager(context, spanResolver.spanCount).also {
|
|
|
|
layoutManager = FitHeightGridLayoutManager(context, spanResolver.spanCount).also {
|
|
|
|
@ -236,6 +250,9 @@ abstract class MangaListFragment : BaseFragment<FragmentListBinding>(),
|
|
|
|
addItemDecoration(SpacingItemDecoration(spacing))
|
|
|
|
addItemDecoration(SpacingItemDecoration(spacing))
|
|
|
|
updatePadding(left = spacing, right = spacing)
|
|
|
|
updatePadding(left = spacing, right = spacing)
|
|
|
|
addOnLayoutChangeListener(spanResolver)
|
|
|
|
addOnLayoutChangeListener(spanResolver)
|
|
|
|
|
|
|
|
if (isListPending) {
|
|
|
|
|
|
|
|
asyncViewFactory?.prefetch(R.layout.item_manga_grid, PREFETCH_ITEM_GRID)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -256,7 +273,7 @@ abstract class MangaListFragment : BaseFragment<FragmentListBinding>(),
|
|
|
|
val total =
|
|
|
|
val total =
|
|
|
|
(binding.recyclerView.layoutManager as? GridLayoutManager)?.spanCount ?: return 1
|
|
|
|
(binding.recyclerView.layoutManager as? GridLayoutManager)?.spanCount ?: return 1
|
|
|
|
return when (listAdapter?.getItemViewType(position)) {
|
|
|
|
return when (listAdapter?.getItemViewType(position)) {
|
|
|
|
MangaListAdapter.ITEM_TYPE_MANGA_GRID -> 1
|
|
|
|
ITEM_TYPE_MANGA_GRID -> 1
|
|
|
|
else -> total
|
|
|
|
else -> total
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|