mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-14 14:20:30 +05:30
commit
8e065fc44b
@ -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
|
||||||
|
@ -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)
|
||||||
fetchChannels()
|
if (viewModel.subscriptions.value == null) {
|
||||||
loadedSubbedChannels = true
|
viewModel.fetchSubscriptions()
|
||||||
|
} else {
|
||||||
|
showSubscriptions()
|
||||||
}
|
}
|
||||||
binding.subChannelsContainer.visibility = View.VISIBLE
|
binding.subChannelsContainer.visibility = View.VISIBLE
|
||||||
binding.subFeedContainer.visibility = View.GONE
|
binding.subFeedContainer.visibility = View.GONE
|
||||||
@ -99,14 +92,13 @@ 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun showSortDialog() {
|
private fun showSortDialog() {
|
||||||
val sortOptions = resources.getStringArray(R.array.sortOptions)
|
val sortOptions = resources.getStringArray(R.array.sortOptions)
|
||||||
@ -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,32 +127,13 @@ 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() {
|
|
||||||
lifecycleScope.launchWhenCreated {
|
|
||||||
val response = try {
|
|
||||||
if (token != "") {
|
|
||||||
RetrofitInstance.authApi.subscriptions(token)
|
|
||||||
} 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@launchWhenCreated
|
|
||||||
} catch (e: HttpException) {
|
|
||||||
Log.e(TAG(), "HttpException, unexpected response")
|
|
||||||
return@launchWhenCreated
|
|
||||||
} finally {
|
|
||||||
binding.subRefresh.isRefreshing = false
|
binding.subRefresh.isRefreshing = false
|
||||||
}
|
|
||||||
if (response.isNotEmpty()) {
|
|
||||||
binding.subChannels.adapter =
|
binding.subChannels.adapter =
|
||||||
if (PreferenceHelper.getBoolean(
|
if (PreferenceHelper.getBoolean(
|
||||||
PreferenceKeys.LEGACY_SUBSCRIPTIONS,
|
PreferenceKeys.LEGACY_SUBSCRIPTIONS,
|
||||||
@ -210,15 +147,13 @@ class SubscriptionsFragment : BaseFragment() {
|
|||||||
"4"
|
"4"
|
||||||
).toInt()
|
).toInt()
|
||||||
)
|
)
|
||||||
LegacySubscriptionAdapter(response)
|
LegacySubscriptionAdapter(
|
||||||
|
viewModel.subscriptions.value!!
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
SubscriptionChannelAdapter(response.toMutableList())
|
SubscriptionChannelAdapter(
|
||||||
|
viewModel.subscriptions.value!!.toMutableList()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Toast.makeText(context, R.string.subscribeIsEmpty, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
run()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user