mirror of
https://github.com/whyorean/AuroraStore.git
synced 2026-06-12 09:48:34 -04:00
Add stashing to SubCategory Streams
This commit is contained in:
committed by
Aayush Gupta
parent
6f425fe641
commit
8a12ffcd96
@@ -21,15 +21,16 @@ package com.aurora.store.view.ui.commons
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import com.aurora.gplayapi.data.models.App
|
||||
import com.aurora.gplayapi.data.models.StreamBundle
|
||||
import com.aurora.gplayapi.data.models.StreamCluster
|
||||
import com.aurora.gplayapi.helpers.contracts.StreamContract
|
||||
import com.aurora.store.R
|
||||
import com.aurora.store.data.model.ViewState
|
||||
import com.aurora.store.data.model.ViewState.Loading.getDataAs
|
||||
import com.aurora.store.databinding.ActivityGenericRecyclerBinding
|
||||
import com.aurora.store.view.custom.recycler.EndlessRecyclerOnScrollListener
|
||||
import com.aurora.store.view.epoxy.controller.CategoryCarouselController
|
||||
@@ -46,16 +47,20 @@ class CategoryBrowseFragment : BaseFragment(R.layout.activity_generic_recycler),
|
||||
get() = _binding!!
|
||||
|
||||
private val args: CategoryBrowseFragmentArgs by navArgs()
|
||||
private val viewModel: SubCategoryClusterViewModel by viewModels()
|
||||
private val viewModel: SubCategoryClusterViewModel by activityViewModels()
|
||||
|
||||
private lateinit var genericCarouselController: GenericCarouselController
|
||||
private lateinit var endlessRecyclerOnScrollListener: EndlessRecyclerOnScrollListener
|
||||
private lateinit var category: StreamContract.Category
|
||||
private var streamBundle: StreamBundle? = StreamBundle()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
_binding = ActivityGenericRecyclerBinding.bind(view)
|
||||
genericCarouselController = CategoryCarouselController(this)
|
||||
|
||||
val rawCategory = args.browseUrl.split("/").last()
|
||||
category = StreamContract.Category.NONE.apply { value = rawCategory }
|
||||
|
||||
val genericCarouselController = CategoryCarouselController(this)
|
||||
|
||||
// Toolbar
|
||||
binding.layoutToolbarAction.apply {
|
||||
@@ -65,39 +70,30 @@ class CategoryBrowseFragment : BaseFragment(R.layout.activity_generic_recycler),
|
||||
|
||||
// RecyclerView
|
||||
binding.recycler.setController(genericCarouselController)
|
||||
binding.recycler.addOnScrollListener(object : EndlessRecyclerOnScrollListener() {
|
||||
override fun onLoadMore(currentPage: Int) {
|
||||
viewModel.observe(category)
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.liveData.observe(viewLifecycleOwner) {
|
||||
when (it) {
|
||||
is ViewState.Empty -> {
|
||||
}
|
||||
|
||||
is ViewState.Loading -> {
|
||||
updateController(null)
|
||||
}
|
||||
|
||||
is ViewState.Error -> {
|
||||
|
||||
genericCarouselController.setData(null)
|
||||
}
|
||||
|
||||
is ViewState.Success<*> -> {
|
||||
updateController(it.data as StreamBundle)
|
||||
val stash = it.getDataAs<Map<String, StreamBundle>>()
|
||||
streamBundle = stash[category.value]
|
||||
|
||||
genericCarouselController.setData(streamBundle)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
endlessRecyclerOnScrollListener = object : EndlessRecyclerOnScrollListener() {
|
||||
override fun onLoadMore(currentPage: Int) {
|
||||
viewModel.observe()
|
||||
}
|
||||
}
|
||||
|
||||
endlessRecyclerOnScrollListener.disable()
|
||||
binding.recycler.addOnScrollListener(endlessRecyclerOnScrollListener)
|
||||
|
||||
viewModel.observeCategory(args.browseUrl)
|
||||
updateController(null)
|
||||
viewModel.observe(category)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
@@ -105,25 +101,12 @@ class CategoryBrowseFragment : BaseFragment(R.layout.activity_generic_recycler),
|
||||
_binding = null
|
||||
}
|
||||
|
||||
private fun updateController(streamBundle: StreamBundle?) {
|
||||
if (streamBundle != null) endlessRecyclerOnScrollListener.enable()
|
||||
genericCarouselController.setData(streamBundle)
|
||||
}
|
||||
|
||||
override fun onHeaderClicked(streamCluster: StreamCluster) {
|
||||
if (streamCluster.clusterBrowseUrl.isNotEmpty())
|
||||
openStreamBrowseFragment(streamCluster.clusterBrowseUrl)
|
||||
else
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
getString(R.string.toast_page_unavailable),
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
.show()
|
||||
|
||||
}
|
||||
|
||||
override fun onClusterScrolled(streamCluster: StreamCluster) {
|
||||
viewModel.observeCluster(streamCluster)
|
||||
viewModel.observeCluster(category, streamCluster)
|
||||
}
|
||||
|
||||
override fun onAppClick(app: App) {
|
||||
|
||||
@@ -118,8 +118,7 @@ class ForYouFragment : BaseFragment(R.layout.fragment_for_you),
|
||||
}
|
||||
|
||||
override fun onHeaderClicked(streamCluster: StreamCluster) {
|
||||
if (streamCluster.clusterBrowseUrl.isNotEmpty())
|
||||
openStreamBrowseFragment(streamCluster.clusterBrowseUrl, streamCluster.clusterTitle)
|
||||
|
||||
}
|
||||
|
||||
override fun onClusterScrolled(streamCluster: StreamCluster) {
|
||||
|
||||
@@ -77,25 +77,26 @@ class StreamViewModel @Inject constructor(
|
||||
fun observe(category: StreamContract.Category, type: StreamContract.Type) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
supervisorScope {
|
||||
if (targetBundle(category).streamClusters.isNotEmpty()) {
|
||||
val bundle = targetBundle(category)
|
||||
if (bundle.streamClusters.isNotEmpty()) {
|
||||
liveData.postValue(ViewState.Success(stash))
|
||||
}
|
||||
|
||||
try {
|
||||
if (!targetBundle(category).hasCluster() || targetBundle(category).hasNext()) {
|
||||
if (!bundle.hasCluster() || bundle.hasNext()) {
|
||||
|
||||
//Fetch new stream bundle
|
||||
val newBundle = if (targetBundle(category).streamClusters.isEmpty()) {
|
||||
val newBundle = if (bundle.streamClusters.isEmpty()) {
|
||||
contract().fetch(type, category)
|
||||
} else {
|
||||
contract().nextStreamBundle(
|
||||
category,
|
||||
targetBundle((category)).streamNextPageUrl
|
||||
bundle.streamNextPageUrl
|
||||
)
|
||||
}
|
||||
|
||||
//Update old bundle
|
||||
targetBundle(category).apply {
|
||||
bundle.apply {
|
||||
streamClusters.putAll(newBundle.streamClusters)
|
||||
streamNextPageUrl = newBundle.streamNextPageUrl
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ import com.aurora.store.data.model.ViewState
|
||||
import com.aurora.gplayapi.helpers.contracts.StreamContract
|
||||
import com.aurora.gplayapi.helpers.web.WebStreamHelper
|
||||
import com.aurora.store.data.network.HttpClient
|
||||
import com.aurora.store.data.providers.AuthProvider
|
||||
import com.aurora.store.util.Log
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
@@ -50,76 +49,64 @@ class SubCategoryClusterViewModel @Inject constructor(
|
||||
.using(HttpClient.getPreferredClient(context))
|
||||
|
||||
val liveData: MutableLiveData<ViewState> = MutableLiveData()
|
||||
var streamBundle: StreamBundle = StreamBundle()
|
||||
|
||||
private lateinit var homeUrl: String
|
||||
private lateinit var type: StreamContract.Type
|
||||
private lateinit var category: StreamContract.Category
|
||||
|
||||
init {
|
||||
liveData.postValue(ViewState.Loading)
|
||||
}
|
||||
private var stash: MutableMap<String, StreamBundle> = mutableMapOf()
|
||||
|
||||
private fun getCategoryStreamBundle(
|
||||
category: StreamContract.Category,
|
||||
nextPageUrl: String
|
||||
): StreamBundle {
|
||||
return if (streamBundle.streamClusters.isEmpty())
|
||||
contract.fetch(type, category)
|
||||
return if (targetBundle(category).streamClusters.isEmpty())
|
||||
contract.fetch(StreamContract.Type.HOME, category)
|
||||
else
|
||||
contract.nextStreamBundle(category, nextPageUrl)
|
||||
}
|
||||
|
||||
fun observeCategory(homeUrl: String) {
|
||||
this.homeUrl = homeUrl
|
||||
|
||||
val rawCategory = homeUrl.split("/").last()
|
||||
|
||||
type = StreamContract.Type.HOME
|
||||
category = StreamContract.Category.NONE.apply {
|
||||
value = rawCategory
|
||||
}
|
||||
|
||||
observe()
|
||||
}
|
||||
|
||||
fun observe() {
|
||||
fun observe(category: StreamContract.Category) {
|
||||
liveData.postValue(ViewState.Loading)
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
supervisorScope {
|
||||
val bundle = targetBundle(category)
|
||||
|
||||
if (bundle.streamClusters.isNotEmpty()) {
|
||||
liveData.postValue(ViewState.Success(stash))
|
||||
}
|
||||
|
||||
try {
|
||||
if (!streamBundle.hasCluster() || streamBundle.hasNext()) {
|
||||
if (!bundle.hasCluster() || bundle.hasNext()) {
|
||||
//Fetch new stream bundle
|
||||
val newBundle = getCategoryStreamBundle(
|
||||
streamBundle.streamNextPageUrl
|
||||
category,
|
||||
bundle.streamNextPageUrl
|
||||
)
|
||||
|
||||
//Update old bundle
|
||||
streamBundle.apply {
|
||||
bundle.apply {
|
||||
streamClusters.putAll(newBundle.streamClusters)
|
||||
streamNextPageUrl = newBundle.streamNextPageUrl
|
||||
}
|
||||
|
||||
//Post updated to UI
|
||||
liveData.postValue(ViewState.Success(streamBundle))
|
||||
liveData.postValue(ViewState.Success(stash))
|
||||
} else {
|
||||
Log.i("End of Bundle")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
liveData.postValue(ViewState.Error(e.message))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun observeCluster(streamCluster: StreamCluster) {
|
||||
fun observeCluster(category: StreamContract.Category, streamCluster: StreamCluster) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
supervisorScope {
|
||||
try {
|
||||
if (streamCluster.hasNext()) {
|
||||
val newCluster =
|
||||
contract.nextStreamCluster(streamCluster.clusterNextPageUrl)
|
||||
updateCluster(newCluster)
|
||||
liveData.postValue(ViewState.Success(streamBundle))
|
||||
updateCluster(category, streamCluster.id, newCluster)
|
||||
liveData.postValue(ViewState.Success(stash))
|
||||
} else {
|
||||
Log.i("End of cluster")
|
||||
streamCluster.clusterNextPageUrl = String()
|
||||
@@ -131,10 +118,22 @@ class SubCategoryClusterViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateCluster(newCluster: StreamCluster) {
|
||||
streamBundle.streamClusters[newCluster.id]?.apply {
|
||||
private fun updateCluster(
|
||||
category: StreamContract.Category,
|
||||
clusterID: Int,
|
||||
newCluster: StreamCluster
|
||||
) {
|
||||
targetBundle(category).streamClusters[clusterID]?.apply {
|
||||
clusterAppList.addAll(newCluster.clusterAppList)
|
||||
clusterNextPageUrl = newCluster.clusterNextPageUrl
|
||||
}
|
||||
}
|
||||
|
||||
private fun targetBundle(category: StreamContract.Category): StreamBundle {
|
||||
val streamBundle = stash.getOrPut(category.value) {
|
||||
StreamBundle()
|
||||
}
|
||||
|
||||
return streamBundle
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user