Merge pull request #1176 from Bnyro/master

load feed in background
This commit is contained in:
Bnyro 2022-08-26 18:32:36 +02:00 committed by GitHub
commit 8e065fc44b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 131 additions and 117 deletions

View File

@ -28,7 +28,7 @@ class LibraryFragment : BaseFragment() {
lateinit var token: String lateinit var token: String
private lateinit var binding: FragmentLibraryBinding private lateinit var binding: FragmentLibraryBinding
val playerViewModel: PlayerViewModel by activityViewModels() private val playerViewModel: PlayerViewModel by activityViewModels()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -88,7 +88,7 @@ class LibraryFragment : BaseFragment() {
} }
} }
fun updateFABMargin() { private fun updateFABMargin() {
// optimize CreatePlaylistFab bottom margin if miniPlayer active // optimize CreatePlaylistFab bottom margin if miniPlayer active
val bottomMargin = if (playerViewModel.isMiniPlayerVisible.value == true) 180 else 64 val bottomMargin = if (playerViewModel.isMiniPlayerVisible.value == true) 180 else 64
val layoutParams = binding.createPlaylist.layoutParams as ViewGroup.MarginLayoutParams val layoutParams = binding.createPlaylist.layoutParams as ViewGroup.MarginLayoutParams

View File

@ -1,47 +1,31 @@
package com.github.libretube.fragments package com.github.libretube.fragments
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.adapters.LegacySubscriptionAdapter import com.github.libretube.adapters.LegacySubscriptionAdapter
import com.github.libretube.adapters.SubscriptionChannelAdapter import com.github.libretube.adapters.SubscriptionChannelAdapter
import com.github.libretube.adapters.TrendingAdapter import com.github.libretube.adapters.TrendingAdapter
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.SubscriptionHelper
import com.github.libretube.databinding.FragmentSubscriptionsBinding import com.github.libretube.databinding.FragmentSubscriptionsBinding
import com.github.libretube.extensions.BaseFragment import com.github.libretube.extensions.BaseFragment
import com.github.libretube.extensions.TAG import com.github.libretube.models.SubscriptionsViewModel
import com.github.libretube.obj.StreamItem
import com.github.libretube.preferences.PreferenceHelper import com.github.libretube.preferences.PreferenceHelper
import com.github.libretube.preferences.PreferenceKeys import com.github.libretube.preferences.PreferenceKeys
import com.github.libretube.util.toID
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import retrofit2.HttpException
import java.io.IOException
class SubscriptionsFragment : BaseFragment() { class SubscriptionsFragment : BaseFragment() {
private lateinit var binding: FragmentSubscriptionsBinding private lateinit var binding: FragmentSubscriptionsBinding
private val viewModel: SubscriptionsViewModel by activityViewModels()
lateinit var token: String
private var isLoaded = false
private var subscriptionAdapter: TrendingAdapter? = null private var subscriptionAdapter: TrendingAdapter? = null
private var feed: List<StreamItem> = listOf()
private var sortOrder = "most_recent" private var sortOrder = "most_recent"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
}
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
@ -53,7 +37,6 @@ class SubscriptionsFragment : BaseFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
token = PreferenceHelper.getToken()
binding.subRefresh.isEnabled = true binding.subRefresh.isEnabled = true
@ -63,12 +46,22 @@ class SubscriptionsFragment : BaseFragment() {
PreferenceKeys.GRID_COLUMNS, PreferenceKeys.GRID_COLUMNS,
resources.getInteger(R.integer.grid_items).toString() resources.getInteger(R.integer.grid_items).toString()
) )
binding.subFeed.layoutManager = GridLayoutManager(view.context, grid.toInt()) binding.subFeed.layoutManager = GridLayoutManager(view.context, grid.toInt())
fetchFeed()
if (viewModel.videoFeed.value == null) viewModel.fetchFeed()
viewModel.videoFeed.observe(viewLifecycleOwner) {
if (it != null) showFeed()
}
viewModel.subscriptions.observe(viewLifecycleOwner) {
if (it != null) showSubscriptions()
}
binding.subRefresh.setOnRefreshListener { binding.subRefresh.setOnRefreshListener {
fetchChannels() viewModel.fetchSubscriptions()
fetchFeed() viewModel.fetchFeed()
} }
binding.sortTV.setOnClickListener { binding.sortTV.setOnClickListener {
@ -76,14 +69,14 @@ class SubscriptionsFragment : BaseFragment() {
} }
binding.toggleSubs.visibility = View.VISIBLE binding.toggleSubs.visibility = View.VISIBLE
var loadedSubbedChannels = false
binding.toggleSubs.setOnClickListener { binding.toggleSubs.setOnClickListener {
if (!binding.subChannelsContainer.isVisible) { if (!binding.subChannelsContainer.isVisible) {
if (!loadedSubbedChannels) { binding.subChannels.layoutManager = LinearLayoutManager(context)
binding.subChannels.layoutManager = LinearLayoutManager(context) if (viewModel.subscriptions.value == null) {
fetchChannels() viewModel.fetchSubscriptions()
loadedSubbedChannels = true } else {
showSubscriptions()
} }
binding.subChannelsContainer.visibility = View.VISIBLE binding.subChannelsContainer.visibility = View.VISIBLE
binding.subFeedContainer.visibility = View.GONE binding.subFeedContainer.visibility = View.GONE
@ -99,11 +92,10 @@ class SubscriptionsFragment : BaseFragment() {
== (binding.scrollviewSub.height + binding.scrollviewSub.scrollY) == (binding.scrollviewSub.height + binding.scrollviewSub.scrollY)
) { ) {
// scroll view is at bottom // scroll view is at bottom
if (isLoaded) { if (viewModel.videoFeed.value == null) return@addOnScrollChangedListener
binding.subRefresh.isRefreshing = true binding.subRefresh.isRefreshing = true
subscriptionAdapter?.updateItems() subscriptionAdapter?.updateItems()
binding.subRefresh.isRefreshing = false binding.subRefresh.isRefreshing = false
}
} }
} }
} }
@ -122,45 +114,9 @@ class SubscriptionsFragment : BaseFragment() {
.show() .show()
} }
private fun fetchFeed() {
fun run() {
lifecycleScope.launchWhenCreated {
feed = try {
if (token != "") {
RetrofitInstance.authApi.getFeed(token)
} else {
RetrofitInstance.authApi.getUnauthenticatedFeed(
SubscriptionHelper.getFormattedLocalSubscriptions()
)
}
} catch (e: IOException) {
Log.e(TAG(), e.toString())
Log.e(TAG(), "IOException, you might not have internet connection")
return@launchWhenCreated
} catch (e: HttpException) {
Log.e(TAG(), "HttpException, unexpected response")
return@launchWhenCreated
} finally {
binding.subRefresh.isRefreshing = false
}
if (feed.isNotEmpty()) {
// save the last recent video to the prefs for the notification worker
PreferenceHelper.setLatestVideoId(feed[0].url.toID())
// show the feed
showFeed()
} else {
runOnUiThread {
binding.emptyFeed.visibility = View.VISIBLE
}
}
binding.subProgress.visibility = View.GONE
isLoaded = true
}
}
run()
}
private fun showFeed() { private fun showFeed() {
binding.subRefresh.isRefreshing = false
val feed = viewModel.videoFeed.value!!
// sort the feed // sort the feed
val sortedFeed = when (sortOrder) { val sortedFeed = when (sortOrder) {
"most_recent" -> feed "most_recent" -> feed
@ -171,54 +127,33 @@ class SubscriptionsFragment : BaseFragment() {
"channel_name_za" -> feed.sortedBy { it.uploaderName }.reversed() "channel_name_za" -> feed.sortedBy { it.uploaderName }.reversed()
else -> feed else -> feed
} }
binding.subProgress.visibility = View.GONE
subscriptionAdapter = TrendingAdapter(sortedFeed, childFragmentManager, false) subscriptionAdapter = TrendingAdapter(sortedFeed, childFragmentManager, false)
binding.subFeed.adapter = subscriptionAdapter binding.subFeed.adapter = subscriptionAdapter
} }
private fun fetchChannels() { private fun showSubscriptions() {
fun run() { binding.subRefresh.isRefreshing = false
lifecycleScope.launchWhenCreated { binding.subChannels.adapter =
val response = try { if (PreferenceHelper.getBoolean(
if (token != "") { PreferenceKeys.LEGACY_SUBSCRIPTIONS,
RetrofitInstance.authApi.subscriptions(token) false
} else { )
RetrofitInstance.authApi.unauthenticatedSubscriptions( ) {
SubscriptionHelper.getFormattedLocalSubscriptions() binding.subChannels.layoutManager = GridLayoutManager(
) context,
} PreferenceHelper.getString(
} catch (e: IOException) { PreferenceKeys.LEGACY_SUBSCRIPTIONS_COLUMNS,
Log.e(TAG(), e.toString()) "4"
Log.e(TAG(), "IOException, you might not have internet connection") ).toInt()
return@launchWhenCreated )
} catch (e: HttpException) { LegacySubscriptionAdapter(
Log.e(TAG(), "HttpException, unexpected response") viewModel.subscriptions.value!!
return@launchWhenCreated )
} finally { } else {
binding.subRefresh.isRefreshing = false SubscriptionChannelAdapter(
} viewModel.subscriptions.value!!.toMutableList()
if (response.isNotEmpty()) { )
binding.subChannels.adapter =
if (PreferenceHelper.getBoolean(
PreferenceKeys.LEGACY_SUBSCRIPTIONS,
false
)
) {
binding.subChannels.layoutManager = GridLayoutManager(
context,
PreferenceHelper.getString(
PreferenceKeys.LEGACY_SUBSCRIPTIONS_COLUMNS,
"4"
).toInt()
)
LegacySubscriptionAdapter(response)
} else {
SubscriptionChannelAdapter(response.toMutableList())
}
} else {
Toast.makeText(context, R.string.subscribeIsEmpty, Toast.LENGTH_SHORT).show()
}
} }
}
run()
} }
} }

View File

@ -0,0 +1,79 @@
package com.github.libretube.models
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.SubscriptionHelper
import com.github.libretube.extensions.TAG
import com.github.libretube.obj.StreamItem
import com.github.libretube.obj.Subscription
import com.github.libretube.preferences.PreferenceHelper
import com.github.libretube.util.toID
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import retrofit2.HttpException
import java.io.IOException
class SubscriptionsViewModel : ViewModel() {
var videoFeed = MutableLiveData<List<StreamItem>?>().apply {
value = null
}
var subscriptions = MutableLiveData<List<Subscription>?>().apply {
value = null
}
fun fetchFeed() {
CoroutineScope(Dispatchers.IO).launch {
val videoFeed = try {
if (PreferenceHelper.getToken() != "") {
RetrofitInstance.authApi.getFeed(
PreferenceHelper.getToken()
)
} else {
RetrofitInstance.authApi.getUnauthenticatedFeed(
SubscriptionHelper.getFormattedLocalSubscriptions()
)
}
} catch (e: IOException) {
Log.e(TAG(), e.toString())
Log.e(TAG(), "IOException, you might not have internet connection")
return@launch
} catch (e: HttpException) {
Log.e(TAG(), "HttpException, unexpected response")
return@launch
}
this@SubscriptionsViewModel.videoFeed.postValue(videoFeed)
if (videoFeed.isNotEmpty()) {
// save the last recent video to the prefs for the notification worker
PreferenceHelper.setLatestVideoId(videoFeed[0].url.toID())
}
}
}
fun fetchSubscriptions() {
CoroutineScope(Dispatchers.IO).launch {
val subscriptions = try {
if (PreferenceHelper.getToken() != "") {
RetrofitInstance.authApi.subscriptions(
PreferenceHelper.getToken()
)
} else {
RetrofitInstance.authApi.unauthenticatedSubscriptions(
SubscriptionHelper.getFormattedLocalSubscriptions()
)
}
} catch (e: IOException) {
Log.e(TAG(), e.toString())
Log.e(TAG(), "IOException, you might not have internet connection")
return@launch
} catch (e: HttpException) {
Log.e(TAG(), "HttpException, unexpected response")
return@launch
}
this@SubscriptionsViewModel.subscriptions.postValue(subscriptions)
}
}
}