fix the lagging user experience

This commit is contained in:
Bnyro 2022-11-18 16:08:09 +01:00
parent df00881cff
commit 42e326f9b8
3 changed files with 62 additions and 93 deletions

View File

@ -1,28 +1,31 @@
package com.github.libretube.ui.fragments
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.R
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.SubscriptionHelper
import com.github.libretube.databinding.FragmentHomeBinding
import com.github.libretube.extensions.toastFromMainThread
import com.github.libretube.ui.adapters.PlaylistsAdapter
import com.github.libretube.ui.adapters.VideosAdapter
import com.github.libretube.ui.base.BaseFragment
import com.github.libretube.ui.models.HomeModel
import com.github.libretube.ui.extensions.withMaxSize
import com.github.libretube.util.LocaleHelper
import com.github.libretube.util.PreferenceHelper
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class HomeFragment : BaseFragment() {
private lateinit var binding: FragmentHomeBinding
private val viewModel: HomeModel by activityViewModels()
override fun onCreateView(
inflater: LayoutInflater,
@ -49,45 +52,66 @@ class HomeFragment : BaseFragment() {
}
lifecycleScope.launch(Dispatchers.IO) {
viewModel.fetchHome(requireContext(), LocaleHelper.getTrendingRegion(requireContext()))
fetchHome(requireContext(), LocaleHelper.getTrendingRegion(requireContext()))
}
}
private suspend fun fetchHome(context: Context, trendingRegion: String) {
val token = PreferenceHelper.getToken()
val appContext = context.applicationContext
runOrError(appContext) {
val feed = SubscriptionHelper.getFeed().withMaxSize(20)
runOnUiThread {
makeVisible(binding.featuredRV, binding.featuredTV)
binding.featuredRV.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
binding.featuredRV.adapter = VideosAdapter(
feed.toMutableList(),
childFragmentManager,
forceMode = VideosAdapter.Companion.ForceMode.RELATED
)
}
}
viewModel.feed.observe(viewLifecycleOwner) {
makeVisible(binding.featuredRV, binding.featuredTV)
binding.featuredRV.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
binding.featuredRV.adapter = VideosAdapter(
it.toMutableList(),
childFragmentManager,
forceMode = VideosAdapter.Companion.ForceMode.RELATED
)
runOrError(appContext) {
val trending = RetrofitInstance.api.getTrending(trendingRegion).withMaxSize(10)
runOnUiThread {
makeVisible(binding.trendingRV, binding.trendingTV)
binding.trendingRV.layoutManager = GridLayoutManager(context, 2)
binding.trendingRV.adapter = VideosAdapter(
trending.toMutableList(),
childFragmentManager,
forceMode = VideosAdapter.Companion.ForceMode.TRENDING
)
}
}
viewModel.trending.observe(viewLifecycleOwner) {
if (it.isEmpty()) return@observe
makeVisible(binding.trendingRV, binding.trendingTV)
binding.trendingRV.layoutManager = GridLayoutManager(context, 2)
binding.trendingRV.adapter = VideosAdapter(
it.toMutableList(),
childFragmentManager,
forceMode = VideosAdapter.Companion.ForceMode.TRENDING
)
}
viewModel.playlists.observe(viewLifecycleOwner) {
if (it.isEmpty()) return@observe
makeVisible(binding.playlistsRV, binding.playlistsTV)
binding.playlistsRV.layoutManager = LinearLayoutManager(context)
binding.playlistsRV.adapter = PlaylistsAdapter(it.toMutableList(), childFragmentManager)
binding.playlistsRV.adapter?.registerAdapterDataObserver(object :
RecyclerView.AdapterDataObserver() {
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
super.onItemRangeRemoved(positionStart, itemCount)
if (itemCount == 0) {
binding.playlistsRV.visibility = View.GONE
binding.playlistsTV.visibility = View.GONE
runOrError(appContext) {
val playlists = RetrofitInstance.authApi.getUserPlaylists(token).withMaxSize(20)
runOnUiThread {
makeVisible(binding.playlistsRV, binding.playlistsTV)
binding.playlistsRV.layoutManager = LinearLayoutManager(context)
binding.playlistsRV.adapter = PlaylistsAdapter(playlists.toMutableList(), childFragmentManager)
binding.playlistsRV.adapter?.registerAdapterDataObserver(object :
RecyclerView.AdapterDataObserver() {
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
super.onItemRangeRemoved(positionStart, itemCount)
if (itemCount == 0) {
binding.playlistsRV.visibility = View.GONE
binding.playlistsTV.visibility = View.GONE
}
}
}
})
})
}
}
}
private fun runOrError(context: Context, action: suspend () -> Unit) {
lifecycleScope.launch(Dispatchers.IO) {
try {
action.invoke()
} catch (e: Exception) {
e.localizedMessage?.let { context.toastFromMainThread(it) }
}
}
}

View File

@ -1,56 +0,0 @@
package com.github.libretube.ui.models
import android.content.Context
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.SubscriptionHelper
import com.github.libretube.api.obj.Playlists
import com.github.libretube.api.obj.StreamItem
import com.github.libretube.extensions.toastFromMainThread
import com.github.libretube.ui.extensions.withMaxSize
import com.github.libretube.util.PreferenceHelper
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class HomeModel : ViewModel() {
val feed = MutableLiveData<List<StreamItem>>()
var trending = MutableLiveData<List<StreamItem>>()
val playlists = MutableLiveData<List<Playlists>>()
suspend fun fetchHome(context: Context, trendingRegion: String, forceReload: Boolean = false) {
val token = PreferenceHelper.getToken()
val appContext = context.applicationContext
runOrError(appContext) {
if (!feed.value.isNullOrEmpty() && !forceReload) return@runOrError
feed.postValue(
SubscriptionHelper.getFeed().withMaxSize(20)
)
}
runOrError(appContext) {
if (!trending.value.isNullOrEmpty() && !forceReload) return@runOrError
trending.postValue(
RetrofitInstance.api.getTrending(trendingRegion).withMaxSize(10)
)
}
runOrError(appContext) {
if ((token == "" || playlists.value.isNullOrEmpty()) && !forceReload) return@runOrError
playlists.postValue(
RetrofitInstance.authApi.getUserPlaylists(token).withMaxSize(20)
)
}
}
private fun runOrError(context: Context, action: suspend () -> Unit) {
CoroutineScope(Dispatchers.IO).launch {
try {
action.invoke()
} catch (e: Exception) {
e.localizedMessage?.let { context.toastFromMainThread(it) }
}
}
}
}

View File

@ -10,6 +10,7 @@
android:layout_gravity="center" />
<ScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="wrap_content">