mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-14 14:20:30 +05:30
Merge pull request #3182 from Isira-Seneviratne/Remove_BaseFragment
Remove BaseFragment.
This commit is contained in:
commit
9a659d7a03
@ -1,14 +0,0 @@
|
||||
package com.github.libretube.extensions
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
fun Fragment.launchWhenCreatedIO(block: suspend () -> Unit) {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
withContext(Dispatchers.IO) {
|
||||
block.invoke()
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package com.github.libretube.ui.base
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
open class BaseFragment : Fragment() {
|
||||
fun runOnUiThread(action: () -> Unit) {
|
||||
if (!isAdded) return // Fragment not attached to an Activity
|
||||
activity?.runOnUiThread(action)
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ import android.text.format.DateUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.api.obj.StreamItem
|
||||
@ -27,7 +28,6 @@ import com.github.libretube.helpers.NavigationHelper
|
||||
import com.github.libretube.obj.ShareData
|
||||
import com.github.libretube.services.BackgroundMode
|
||||
import com.github.libretube.ui.activities.MainActivity
|
||||
import com.github.libretube.ui.base.BaseFragment
|
||||
import com.github.libretube.ui.dialogs.ShareDialog
|
||||
import com.github.libretube.ui.interfaces.AudioPlayerOptions
|
||||
import com.github.libretube.ui.listeners.AudioPlayerThumbnailListener
|
||||
@ -36,7 +36,7 @@ import com.github.libretube.ui.sheets.PlayingQueueSheet
|
||||
import com.github.libretube.ui.sheets.VideoOptionsBottomSheet
|
||||
import com.github.libretube.util.PlayingQueue
|
||||
|
||||
class AudioPlayerFragment : BaseFragment(), AudioPlayerOptions {
|
||||
class AudioPlayerFragment : Fragment(), AudioPlayerOptions {
|
||||
private lateinit var binding: FragmentAudioPlayerBinding
|
||||
private lateinit var audioHelper: AudioHelper
|
||||
|
||||
|
@ -7,6 +7,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.children
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.github.libretube.R
|
||||
@ -24,7 +25,6 @@ import com.github.libretube.obj.ChannelTabs
|
||||
import com.github.libretube.obj.ShareData
|
||||
import com.github.libretube.ui.adapters.SearchAdapter
|
||||
import com.github.libretube.ui.adapters.VideosAdapter
|
||||
import com.github.libretube.ui.base.BaseFragment
|
||||
import com.github.libretube.ui.dialogs.ShareDialog
|
||||
import com.github.libretube.ui.extensions.setupSubscriptionButton
|
||||
import java.io.IOException
|
||||
@ -33,7 +33,7 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import retrofit2.HttpException
|
||||
|
||||
class ChannelFragment : BaseFragment() {
|
||||
class ChannelFragment : Fragment() {
|
||||
private lateinit var binding: FragmentChannelBinding
|
||||
|
||||
private var channelId: String? = null
|
||||
@ -102,10 +102,12 @@ class ChannelFragment : BaseFragment() {
|
||||
private fun fetchChannel() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val response = try {
|
||||
if (channelId != null) {
|
||||
RetrofitInstance.api.getChannel(channelId!!)
|
||||
} else {
|
||||
RetrofitInstance.api.getChannelByName(channelName!!)
|
||||
withContext(Dispatchers.IO) {
|
||||
if (channelId != null) {
|
||||
RetrofitInstance.api.getChannel(channelId!!)
|
||||
} else {
|
||||
RetrofitInstance.api.getChannelByName(channelName!!)
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
binding.channelRefresh.isRefreshing = false
|
||||
@ -129,64 +131,60 @@ class ChannelFragment : BaseFragment() {
|
||||
isSubscribed = SubscriptionHelper.isSubscribed(channelId!!)
|
||||
if (isSubscribed == null) return@launchWhenCreated
|
||||
|
||||
runOnUiThread {
|
||||
binding.channelSubscribe.setupSubscriptionButton(
|
||||
channelId,
|
||||
channelName,
|
||||
binding.notificationBell
|
||||
)
|
||||
binding.channelSubscribe.setupSubscriptionButton(
|
||||
channelId,
|
||||
channelName,
|
||||
binding.notificationBell
|
||||
)
|
||||
|
||||
binding.channelShare.setOnClickListener {
|
||||
val shareDialog = ShareDialog(
|
||||
response.id!!.toID(),
|
||||
ShareObjectType.CHANNEL,
|
||||
shareData
|
||||
)
|
||||
shareDialog.show(childFragmentManager, ShareDialog::class.java.name)
|
||||
}
|
||||
binding.channelShare.setOnClickListener {
|
||||
val shareDialog = ShareDialog(
|
||||
response.id!!.toID(),
|
||||
ShareObjectType.CHANNEL,
|
||||
shareData
|
||||
)
|
||||
shareDialog.show(childFragmentManager, ShareDialog::class.java.name)
|
||||
}
|
||||
|
||||
nextPage = response.nextpage
|
||||
isLoading = false
|
||||
binding.channelRefresh.isRefreshing = false
|
||||
|
||||
runOnUiThread {
|
||||
binding.channelScrollView.visibility = View.VISIBLE
|
||||
binding.channelName.text = response.name
|
||||
if (response.verified) {
|
||||
binding.channelName.setCompoundDrawablesWithIntrinsicBounds(
|
||||
0,
|
||||
0,
|
||||
R.drawable.ic_verified,
|
||||
0
|
||||
)
|
||||
}
|
||||
binding.channelSubs.text = resources.getString(
|
||||
R.string.subscribers,
|
||||
response.subscriberCount.formatShort()
|
||||
binding.channelScrollView.visibility = View.VISIBLE
|
||||
binding.channelName.text = response.name
|
||||
if (response.verified) {
|
||||
binding.channelName.setCompoundDrawablesWithIntrinsicBounds(
|
||||
0,
|
||||
0,
|
||||
R.drawable.ic_verified,
|
||||
0
|
||||
)
|
||||
if (response.description.isBlank()) {
|
||||
binding.channelDescription.visibility = View.GONE
|
||||
} else {
|
||||
binding.channelDescription.text = response.description.trim()
|
||||
}
|
||||
|
||||
binding.channelDescription.setOnClickListener {
|
||||
(it as TextView).apply {
|
||||
it.maxLines = if (it.maxLines == Int.MAX_VALUE) 2 else Int.MAX_VALUE
|
||||
}
|
||||
}
|
||||
|
||||
ImageHelper.loadImage(response.bannerUrl, binding.channelBanner)
|
||||
ImageHelper.loadImage(response.avatarUrl, binding.channelImage)
|
||||
|
||||
// recyclerview of the videos by the channel
|
||||
channelAdapter = VideosAdapter(
|
||||
response.relatedStreams.toMutableList(),
|
||||
forceMode = VideosAdapter.Companion.ForceMode.CHANNEL
|
||||
)
|
||||
binding.channelRecView.adapter = channelAdapter
|
||||
}
|
||||
binding.channelSubs.text = resources.getString(
|
||||
R.string.subscribers,
|
||||
response.subscriberCount.formatShort()
|
||||
)
|
||||
if (response.description.isBlank()) {
|
||||
binding.channelDescription.visibility = View.GONE
|
||||
} else {
|
||||
binding.channelDescription.text = response.description.trim()
|
||||
}
|
||||
|
||||
binding.channelDescription.setOnClickListener {
|
||||
(it as TextView).apply {
|
||||
it.maxLines = if (it.maxLines == Int.MAX_VALUE) 2 else Int.MAX_VALUE
|
||||
}
|
||||
}
|
||||
|
||||
ImageHelper.loadImage(response.bannerUrl, binding.channelBanner)
|
||||
ImageHelper.loadImage(response.avatarUrl, binding.channelImage)
|
||||
|
||||
// recyclerview of the videos by the channel
|
||||
channelAdapter = VideosAdapter(
|
||||
response.relatedStreams.toMutableList(),
|
||||
forceMode = VideosAdapter.Companion.ForceMode.CHANNEL
|
||||
)
|
||||
binding.channelRecView.adapter = channelAdapter
|
||||
|
||||
setupTabs(response.tabs)
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import android.os.IBinder
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@ -22,7 +23,6 @@ import com.github.libretube.obj.DownloadStatus
|
||||
import com.github.libretube.receivers.DownloadReceiver
|
||||
import com.github.libretube.services.DownloadService
|
||||
import com.github.libretube.ui.adapters.DownloadsAdapter
|
||||
import com.github.libretube.ui.base.BaseFragment
|
||||
import com.github.libretube.ui.viewholders.DownloadsViewHolder
|
||||
import java.io.File
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -31,7 +31,7 @@ import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
class DownloadsFragment : BaseFragment() {
|
||||
class DownloadsFragment : Fragment() {
|
||||
private lateinit var binding: FragmentDownloadsBinding
|
||||
private var binder: DownloadService.LocalBinder? = null
|
||||
private val downloads = mutableListOf<DownloadWithItems>()
|
||||
|
@ -4,6 +4,7 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
@ -17,19 +18,16 @@ import com.github.libretube.api.SubscriptionHelper
|
||||
import com.github.libretube.constants.PreferenceKeys
|
||||
import com.github.libretube.databinding.FragmentHomeBinding
|
||||
import com.github.libretube.db.DatabaseHolder
|
||||
import com.github.libretube.extensions.launchWhenCreatedIO
|
||||
import com.github.libretube.helpers.LocaleHelper
|
||||
import com.github.libretube.helpers.PreferenceHelper
|
||||
import com.github.libretube.ui.adapters.PlaylistBookmarkAdapter
|
||||
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.SubscriptionsViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class HomeFragment : BaseFragment() {
|
||||
class HomeFragment : Fragment() {
|
||||
private lateinit var binding: FragmentHomeBinding
|
||||
private val subscriptionsViewModel: SubscriptionsViewModel by activityViewModels()
|
||||
|
||||
@ -70,11 +68,11 @@ class HomeFragment : BaseFragment() {
|
||||
}
|
||||
|
||||
private fun fetchHomeFeed() {
|
||||
launchWhenCreatedIO {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
loadTrending()
|
||||
loadBookmarks()
|
||||
}
|
||||
launchWhenCreatedIO {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
loadFeed()
|
||||
loadPlaylists()
|
||||
}
|
||||
@ -83,89 +81,86 @@ class HomeFragment : BaseFragment() {
|
||||
private suspend fun loadTrending() {
|
||||
val region = LocaleHelper.getTrendingRegion(requireContext())
|
||||
val trending = runCatching {
|
||||
RetrofitInstance.api.getTrending(region).take(10)
|
||||
}.getOrNull().takeIf { it?.isNotEmpty() == true } ?: return
|
||||
withContext(Dispatchers.IO) {
|
||||
RetrofitInstance.api.getTrending(region).take(10)
|
||||
}
|
||||
}.getOrNull()?.takeIf { it.isNotEmpty() } ?: return
|
||||
|
||||
runOnUiThread {
|
||||
makeVisible(binding.trendingRV, binding.trendingTV)
|
||||
binding.trendingRV.layoutManager = GridLayoutManager(context, 2)
|
||||
binding.trendingRV.adapter = VideosAdapter(
|
||||
trending.toMutableList(),
|
||||
forceMode = VideosAdapter.Companion.ForceMode.TRENDING
|
||||
)
|
||||
}
|
||||
makeVisible(binding.trendingRV, binding.trendingTV)
|
||||
binding.trendingRV.layoutManager = GridLayoutManager(context, 2)
|
||||
binding.trendingRV.adapter = VideosAdapter(
|
||||
trending.toMutableList(),
|
||||
forceMode = VideosAdapter.Companion.ForceMode.TRENDING
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun loadFeed() {
|
||||
val savedFeed = withContext(Dispatchers.Main) {
|
||||
subscriptionsViewModel.videoFeed.value
|
||||
}
|
||||
val savedFeed = subscriptionsViewModel.videoFeed.value
|
||||
val feed = if (
|
||||
PreferenceHelper.getBoolean(PreferenceKeys.SAVE_FEED, false) &&
|
||||
!savedFeed.isNullOrEmpty()
|
||||
) { savedFeed } else {
|
||||
runCatching {
|
||||
SubscriptionHelper.getFeed()
|
||||
withContext(Dispatchers.IO) {
|
||||
SubscriptionHelper.getFeed()
|
||||
}
|
||||
}.getOrElse { return }
|
||||
}.takeIf { it.isNotEmpty() }?.take(20) ?: return
|
||||
}.take(20)
|
||||
|
||||
runOnUiThread {
|
||||
makeVisible(binding.featuredRV, binding.featuredTV)
|
||||
binding.featuredRV.layoutManager = LinearLayoutManager(
|
||||
makeVisible(binding.featuredRV, binding.featuredTV)
|
||||
binding.featuredRV.layoutManager = LinearLayoutManager(
|
||||
context,
|
||||
LinearLayoutManager.HORIZONTAL,
|
||||
false
|
||||
)
|
||||
binding.featuredRV.adapter = VideosAdapter(
|
||||
feed.toMutableList(),
|
||||
forceMode = VideosAdapter.Companion.ForceMode.HOME
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun loadBookmarks() {
|
||||
val bookmarkedPlaylists = withContext(Dispatchers.IO) {
|
||||
DatabaseHolder.Database.playlistBookmarkDao().getAll()
|
||||
}
|
||||
|
||||
if (bookmarkedPlaylists.isNotEmpty()) {
|
||||
makeVisible(binding.bookmarksTV, binding.bookmarksRV)
|
||||
binding.bookmarksRV.layoutManager = LinearLayoutManager(
|
||||
context,
|
||||
LinearLayoutManager.HORIZONTAL,
|
||||
false
|
||||
)
|
||||
binding.featuredRV.adapter = VideosAdapter(
|
||||
feed.toMutableList(),
|
||||
forceMode = VideosAdapter.Companion.ForceMode.HOME
|
||||
binding.bookmarksRV.adapter = PlaylistBookmarkAdapter(
|
||||
bookmarkedPlaylists,
|
||||
PlaylistBookmarkAdapter.Companion.BookmarkMode.HOME
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadBookmarks() {
|
||||
lifecycleScope.launch {
|
||||
val bookmarkedPlaylists = withContext(Dispatchers.IO) {
|
||||
DatabaseHolder.Database.playlistBookmarkDao().getAll()
|
||||
}
|
||||
if (bookmarkedPlaylists.isNotEmpty()) {
|
||||
makeVisible(binding.bookmarksTV, binding.bookmarksRV)
|
||||
binding.bookmarksRV.layoutManager = LinearLayoutManager(
|
||||
context,
|
||||
LinearLayoutManager.HORIZONTAL,
|
||||
false
|
||||
)
|
||||
binding.bookmarksRV.adapter = PlaylistBookmarkAdapter(
|
||||
bookmarkedPlaylists,
|
||||
PlaylistBookmarkAdapter.Companion.BookmarkMode.HOME
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadPlaylists() {
|
||||
val playlists = runCatching {
|
||||
PlaylistsHelper.getPlaylists().take(20)
|
||||
}.getOrNull().takeIf { it?.isNotEmpty() == true } ?: return
|
||||
withContext(Dispatchers.IO) {
|
||||
PlaylistsHelper.getPlaylists().take(20)
|
||||
}
|
||||
}.getOrNull()?.takeIf { it.isNotEmpty() } ?: return
|
||||
|
||||
runOnUiThread {
|
||||
makeVisible(binding.playlistsRV, binding.playlistsTV)
|
||||
binding.playlistsRV.layoutManager = LinearLayoutManager(context)
|
||||
binding.playlistsRV.adapter = PlaylistsAdapter(
|
||||
playlists.toMutableList(),
|
||||
PlaylistsHelper.getPrivatePlaylistType()
|
||||
)
|
||||
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
|
||||
}
|
||||
makeVisible(binding.playlistsRV, binding.playlistsTV)
|
||||
binding.playlistsRV.layoutManager = LinearLayoutManager(context)
|
||||
binding.playlistsRV.adapter = PlaylistsAdapter(
|
||||
playlists.toMutableList(),
|
||||
PlaylistsHelper.getPrivatePlaylistType()
|
||||
)
|
||||
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 makeVisible(vararg views: View) {
|
||||
|
@ -9,6 +9,7 @@ import android.view.ViewGroup.MarginLayoutParams
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
@ -25,15 +26,13 @@ import com.github.libretube.helpers.NavBarHelper
|
||||
import com.github.libretube.helpers.PreferenceHelper
|
||||
import com.github.libretube.ui.adapters.PlaylistBookmarkAdapter
|
||||
import com.github.libretube.ui.adapters.PlaylistsAdapter
|
||||
import com.github.libretube.ui.base.BaseFragment
|
||||
import com.github.libretube.ui.dialogs.CreatePlaylistDialog
|
||||
import com.github.libretube.ui.models.PlayerViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class LibraryFragment : BaseFragment() {
|
||||
|
||||
class LibraryFragment : Fragment() {
|
||||
private lateinit var binding: FragmentLibraryBinding
|
||||
private val playerViewModel: PlayerViewModel by activityViewModels()
|
||||
|
||||
@ -118,7 +117,9 @@ class LibraryFragment : BaseFragment() {
|
||||
binding.playlistRefresh.isRefreshing = true
|
||||
lifecycleScope.launchWhenCreated {
|
||||
var playlists = try {
|
||||
PlaylistsHelper.getPlaylists()
|
||||
withContext(Dispatchers.IO) {
|
||||
PlaylistsHelper.getPlaylists()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG(), e.toString())
|
||||
Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
||||
@ -128,10 +129,7 @@ class LibraryFragment : BaseFragment() {
|
||||
}
|
||||
if (playlists.isNotEmpty()) {
|
||||
playlists = when (
|
||||
PreferenceHelper.getString(
|
||||
PreferenceKeys.PLAYLISTS_ORDER,
|
||||
"recent"
|
||||
)
|
||||
PreferenceHelper.getString(PreferenceKeys.PLAYLISTS_ORDER, "recent")
|
||||
) {
|
||||
"recent" -> playlists
|
||||
"recent_reversed" -> playlists.reversed()
|
||||
@ -158,9 +156,7 @@ class LibraryFragment : BaseFragment() {
|
||||
binding.nothingHere.visibility = View.GONE
|
||||
binding.playlistRecView.adapter = playlistsAdapter
|
||||
} else {
|
||||
runOnUiThread {
|
||||
binding.nothingHere.visibility = View.VISIBLE
|
||||
}
|
||||
binding.nothingHere.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
@ -27,7 +28,6 @@ import com.github.libretube.extensions.toID
|
||||
import com.github.libretube.helpers.ImageHelper
|
||||
import com.github.libretube.helpers.NavigationHelper
|
||||
import com.github.libretube.ui.adapters.PlaylistAdapter
|
||||
import com.github.libretube.ui.base.BaseFragment
|
||||
import com.github.libretube.ui.models.PlayerViewModel
|
||||
import com.github.libretube.ui.sheets.PlaylistOptionsBottomSheet
|
||||
import com.github.libretube.util.PlayingQueue
|
||||
@ -35,8 +35,9 @@ import com.github.libretube.util.TextUtils
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class PlaylistFragment : BaseFragment() {
|
||||
class PlaylistFragment : Fragment() {
|
||||
private lateinit var binding: FragmentPlaylistBinding
|
||||
|
||||
// general playlist information
|
||||
@ -104,7 +105,9 @@ class PlaylistFragment : BaseFragment() {
|
||||
binding.playlistScrollview.visibility = View.GONE
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val response = try {
|
||||
PlaylistsHelper.getPlaylist(playlistId!!)
|
||||
withContext(Dispatchers.IO) {
|
||||
PlaylistsHelper.getPlaylist(playlistId!!)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG(), e.toString())
|
||||
return@launchWhenCreated
|
||||
@ -114,154 +117,151 @@ class PlaylistFragment : BaseFragment() {
|
||||
nextPage = response.nextpage
|
||||
playlistName = response.name
|
||||
isLoading = false
|
||||
runOnUiThread {
|
||||
ImageHelper.loadImage(response.thumbnailUrl, binding.thumbnail)
|
||||
binding.playlistProgress.visibility = View.GONE
|
||||
binding.playlistName.text = response.name
|
||||
ImageHelper.loadImage(response.thumbnailUrl, binding.thumbnail)
|
||||
binding.playlistProgress.visibility = View.GONE
|
||||
binding.playlistName.text = response.name
|
||||
|
||||
binding.playlistName.setOnClickListener {
|
||||
binding.playlistName.maxLines =
|
||||
if (binding.playlistName.maxLines == 2) Int.MAX_VALUE else 2
|
||||
}
|
||||
binding.playlistName.setOnClickListener {
|
||||
binding.playlistName.maxLines =
|
||||
if (binding.playlistName.maxLines == 2) Int.MAX_VALUE else 2
|
||||
}
|
||||
|
||||
binding.playlistInfo.text =
|
||||
(if (response.uploader != null) response.uploader + TextUtils.SEPARATOR else "") +
|
||||
binding.playlistInfo.text =
|
||||
(if (response.uploader != null) response.uploader + TextUtils.SEPARATOR else "") +
|
||||
getString(R.string.videoCount, response.videos.toString())
|
||||
|
||||
// show playlist options
|
||||
binding.optionsMenu.setOnClickListener {
|
||||
PlaylistOptionsBottomSheet(playlistId!!, playlistName ?: "", playlistType).show(
|
||||
childFragmentManager,
|
||||
PlaylistOptionsBottomSheet::class.java.name
|
||||
)
|
||||
}
|
||||
// show playlist options
|
||||
binding.optionsMenu.setOnClickListener {
|
||||
PlaylistOptionsBottomSheet(playlistId!!, playlistName ?: "", playlistType).show(
|
||||
childFragmentManager,
|
||||
PlaylistOptionsBottomSheet::class.java.name
|
||||
)
|
||||
}
|
||||
|
||||
binding.playAll.setOnClickListener {
|
||||
if (playlistFeed.isEmpty()) return@setOnClickListener
|
||||
binding.playAll.setOnClickListener {
|
||||
if (playlistFeed.isEmpty()) return@setOnClickListener
|
||||
NavigationHelper.navigateVideo(
|
||||
requireContext(),
|
||||
response.relatedStreams.first().url?.toID(),
|
||||
playlistId
|
||||
)
|
||||
}
|
||||
|
||||
if (playlistType == PlaylistType.PUBLIC) {
|
||||
binding.bookmark.setOnClickListener {
|
||||
isBookmarked = !isBookmarked
|
||||
updateBookmarkRes()
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
if (!isBookmarked) {
|
||||
DatabaseHolder.Database.playlistBookmarkDao()
|
||||
.deleteById(playlistId!!)
|
||||
} else {
|
||||
DatabaseHolder.Database.playlistBookmarkDao()
|
||||
.insertAll(listOf(response.toPlaylistBookmark(playlistId!!)))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// private playlist, means shuffle is possible because all videos are received at once
|
||||
binding.bookmark.setIconResource(R.drawable.ic_shuffle)
|
||||
binding.bookmark.text = getString(R.string.shuffle)
|
||||
binding.bookmark.setOnClickListener {
|
||||
val queue = playlistFeed.shuffled()
|
||||
PlayingQueue.resetToDefaults()
|
||||
PlayingQueue.add(*queue.toTypedArray())
|
||||
NavigationHelper.navigateVideo(
|
||||
requireContext(),
|
||||
response.relatedStreams.first().url?.toID(),
|
||||
playlistId
|
||||
queue.first().url?.toID(),
|
||||
playlistId = playlistId,
|
||||
keepQueue = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (playlistType == PlaylistType.PUBLIC) {
|
||||
binding.bookmark.setOnClickListener {
|
||||
isBookmarked = !isBookmarked
|
||||
updateBookmarkRes()
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
if (!isBookmarked) {
|
||||
DatabaseHolder.Database.playlistBookmarkDao()
|
||||
.deleteById(playlistId!!)
|
||||
} else {
|
||||
DatabaseHolder.Database.playlistBookmarkDao()
|
||||
.insertAll(listOf(response.toPlaylistBookmark(playlistId!!)))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// private playlist, means shuffle is possible because all videos are received at once
|
||||
binding.bookmark.setIconResource(R.drawable.ic_shuffle)
|
||||
binding.bookmark.text = getString(R.string.shuffle)
|
||||
binding.bookmark.setOnClickListener {
|
||||
if (playlistFeed.isEmpty()) return@setOnClickListener
|
||||
val queue = playlistFeed.shuffled()
|
||||
PlayingQueue.resetToDefaults()
|
||||
PlayingQueue.add(*queue.toTypedArray())
|
||||
NavigationHelper.navigateVideo(
|
||||
requireContext(),
|
||||
queue.first().url?.toID(),
|
||||
playlistId = playlistId,
|
||||
keepQueue = true
|
||||
playlistAdapter = PlaylistAdapter(
|
||||
playlistFeed,
|
||||
playlistId!!,
|
||||
playlistType
|
||||
)
|
||||
|
||||
// listen for playlist items to become deleted
|
||||
playlistAdapter!!.registerAdapterDataObserver(object :
|
||||
RecyclerView.AdapterDataObserver() {
|
||||
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
|
||||
if (positionStart == 0) {
|
||||
ImageHelper.loadImage(
|
||||
playlistFeed.firstOrNull()?.thumbnail ?: "",
|
||||
binding.thumbnail
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
playlistAdapter = PlaylistAdapter(
|
||||
playlistFeed,
|
||||
playlistId!!,
|
||||
playlistType
|
||||
)
|
||||
|
||||
// listen for playlist items to become deleted
|
||||
playlistAdapter!!.registerAdapterDataObserver(object :
|
||||
RecyclerView.AdapterDataObserver() {
|
||||
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
|
||||
if (positionStart == 0) {
|
||||
ImageHelper.loadImage(
|
||||
playlistFeed.firstOrNull()?.thumbnail ?: "",
|
||||
binding.thumbnail
|
||||
)
|
||||
}
|
||||
|
||||
val info = binding.playlistInfo.text.split(TextUtils.SEPARATOR)
|
||||
binding.playlistInfo.text = (
|
||||
val info = binding.playlistInfo.text.split(TextUtils.SEPARATOR)
|
||||
binding.playlistInfo.text = (
|
||||
if (info.size == 2) {
|
||||
info[0] + TextUtils.SEPARATOR
|
||||
} else {
|
||||
""
|
||||
}
|
||||
) + getString(
|
||||
R.string.videoCount,
|
||||
playlistAdapter!!.itemCount.toString()
|
||||
)
|
||||
super.onItemRangeRemoved(positionStart, itemCount)
|
||||
}
|
||||
})
|
||||
R.string.videoCount,
|
||||
playlistAdapter!!.itemCount.toString()
|
||||
)
|
||||
super.onItemRangeRemoved(positionStart, itemCount)
|
||||
}
|
||||
})
|
||||
|
||||
binding.playlistRecView.adapter = playlistAdapter
|
||||
binding.playlistScrollview.viewTreeObserver
|
||||
.addOnScrollChangedListener {
|
||||
if (!binding.playlistScrollview.canScrollVertically(1)) {
|
||||
if (isLoading) return@addOnScrollChangedListener
|
||||
binding.playlistRecView.adapter = playlistAdapter
|
||||
binding.playlistScrollview.viewTreeObserver
|
||||
.addOnScrollChangedListener {
|
||||
if (!binding.playlistScrollview.canScrollVertically(1)) {
|
||||
if (isLoading) return@addOnScrollChangedListener
|
||||
|
||||
// append more playlists to the recycler view
|
||||
if (playlistType != PlaylistType.PUBLIC) {
|
||||
isLoading = true
|
||||
playlistAdapter?.showMoreItems()
|
||||
isLoading = false
|
||||
} else {
|
||||
fetchNextPage()
|
||||
}
|
||||
// append more playlists to the recycler view
|
||||
if (playlistType != PlaylistType.PUBLIC) {
|
||||
isLoading = true
|
||||
playlistAdapter?.showMoreItems()
|
||||
isLoading = false
|
||||
} else {
|
||||
fetchNextPage()
|
||||
}
|
||||
}
|
||||
|
||||
// listener for swiping to the left or right
|
||||
if (playlistType != PlaylistType.PUBLIC) {
|
||||
val itemTouchCallback = object : ItemTouchHelper.SimpleCallback(
|
||||
0,
|
||||
ItemTouchHelper.LEFT
|
||||
) {
|
||||
override fun onMove(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
target: RecyclerView.ViewHolder
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onSwiped(
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
direction: Int
|
||||
) {
|
||||
val position = viewHolder.absoluteAdapterPosition
|
||||
playlistAdapter!!.removeFromPlaylist(requireContext(), position)
|
||||
}
|
||||
}
|
||||
|
||||
val itemTouchHelper = ItemTouchHelper(itemTouchCallback)
|
||||
itemTouchHelper.attachToRecyclerView(binding.playlistRecView)
|
||||
}
|
||||
|
||||
// listener for swiping to the left or right
|
||||
if (playlistType != PlaylistType.PUBLIC) {
|
||||
val itemTouchCallback = object : ItemTouchHelper.SimpleCallback(
|
||||
0,
|
||||
ItemTouchHelper.LEFT
|
||||
) {
|
||||
override fun onMove(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
target: RecyclerView.ViewHolder
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onSwiped(
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
direction: Int
|
||||
) {
|
||||
val position = viewHolder.absoluteAdapterPosition
|
||||
playlistAdapter!!.removeFromPlaylist(requireContext(), position)
|
||||
}
|
||||
}
|
||||
|
||||
val itemTouchHelper = ItemTouchHelper(itemTouchCallback)
|
||||
itemTouchHelper.attachToRecyclerView(binding.playlistRecView)
|
||||
}
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
// update the playlist thumbnail if bookmarked
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val playlistBookmark = DatabaseHolder.Database.playlistBookmarkDao().getAll()
|
||||
.firstOrNull { it.playlistId == playlistId }
|
||||
playlistBookmark?.let {
|
||||
if (it.thumbnailUrl != response.thumbnailUrl) {
|
||||
it.thumbnailUrl = response.thumbnailUrl
|
||||
DatabaseHolder.Database.playlistBookmarkDao().update(it)
|
||||
}
|
||||
val playlistBookmark = DatabaseHolder.Database.playlistBookmarkDao().getAll()
|
||||
.firstOrNull { it.playlistId == playlistId }
|
||||
playlistBookmark?.let {
|
||||
if (it.thumbnailUrl != response.thumbnailUrl) {
|
||||
it.thumbnailUrl = response.thumbnailUrl
|
||||
DatabaseHolder.Database.playlistBookmarkDao().update(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
@ -19,13 +20,12 @@ import com.github.libretube.helpers.PreferenceHelper
|
||||
import com.github.libretube.ui.adapters.LegacySubscriptionAdapter
|
||||
import com.github.libretube.ui.adapters.SubscriptionChannelAdapter
|
||||
import com.github.libretube.ui.adapters.VideosAdapter
|
||||
import com.github.libretube.ui.base.BaseFragment
|
||||
import com.github.libretube.ui.models.SubscriptionsViewModel
|
||||
import com.github.libretube.ui.sheets.BaseBottomSheet
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
class SubscriptionsFragment : BaseFragment() {
|
||||
class SubscriptionsFragment : Fragment() {
|
||||
private lateinit var binding: FragmentSubscriptionsBinding
|
||||
private val viewModel: SubscriptionsViewModel by activityViewModels()
|
||||
|
||||
|
@ -7,6 +7,7 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.api.RetrofitInstance
|
||||
@ -15,12 +16,13 @@ import com.github.libretube.extensions.TAG
|
||||
import com.github.libretube.helpers.LocaleHelper
|
||||
import com.github.libretube.ui.activities.SettingsActivity
|
||||
import com.github.libretube.ui.adapters.VideosAdapter
|
||||
import com.github.libretube.ui.base.BaseFragment
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.IOException
|
||||
import retrofit2.HttpException
|
||||
|
||||
class TrendsFragment : BaseFragment() {
|
||||
class TrendsFragment : Fragment() {
|
||||
private lateinit var binding: FragmentTrendsBinding
|
||||
|
||||
override fun onCreateView(
|
||||
@ -45,9 +47,11 @@ class TrendsFragment : BaseFragment() {
|
||||
private fun fetchTrending() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val response = try {
|
||||
RetrofitInstance.api.getTrending(
|
||||
LocaleHelper.getTrendingRegion(requireContext())
|
||||
)
|
||||
withContext(Dispatchers.IO) {
|
||||
RetrofitInstance.api.getTrending(
|
||||
LocaleHelper.getTrendingRegion(requireContext())
|
||||
)
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
println(e)
|
||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
||||
@ -60,36 +64,20 @@ class TrendsFragment : BaseFragment() {
|
||||
} finally {
|
||||
binding.homeRefresh.isRefreshing = false
|
||||
}
|
||||
runOnUiThread {
|
||||
binding.progressBar.visibility = View.GONE
|
||||
binding.progressBar.visibility = View.GONE
|
||||
|
||||
// show a [SnackBar] if there are no trending videos available
|
||||
if (response.isEmpty()) {
|
||||
Snackbar.make(
|
||||
binding.root,
|
||||
R.string.change_region,
|
||||
Snackbar.LENGTH_LONG
|
||||
)
|
||||
.setAction(
|
||||
R.string.settings
|
||||
) {
|
||||
startActivity(
|
||||
Intent(
|
||||
context,
|
||||
SettingsActivity::class.java
|
||||
)
|
||||
)
|
||||
}
|
||||
.show()
|
||||
return@runOnUiThread
|
||||
}
|
||||
|
||||
binding.recview.adapter = VideosAdapter(
|
||||
response.toMutableList()
|
||||
)
|
||||
|
||||
binding.recview.layoutManager = VideosAdapter.getLayout(requireContext())
|
||||
// show a [SnackBar] if there are no trending videos available
|
||||
if (response.isEmpty()) {
|
||||
Snackbar.make(binding.root, R.string.change_region, Snackbar.LENGTH_LONG)
|
||||
.setAction(R.string.settings) {
|
||||
startActivity(Intent(context, SettingsActivity::class.java))
|
||||
}
|
||||
.show()
|
||||
return@launchWhenCreated
|
||||
}
|
||||
|
||||
binding.recview.adapter = VideosAdapter(response.toMutableList())
|
||||
binding.recview.layoutManager = VideosAdapter.getLayout(requireContext())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.os.postDelayed
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
@ -21,7 +22,6 @@ import com.github.libretube.extensions.dpToPx
|
||||
import com.github.libretube.helpers.NavigationHelper
|
||||
import com.github.libretube.helpers.ProxyHelper
|
||||
import com.github.libretube.ui.adapters.WatchHistoryAdapter
|
||||
import com.github.libretube.ui.base.BaseFragment
|
||||
import com.github.libretube.ui.models.PlayerViewModel
|
||||
import com.github.libretube.util.PlayingQueue
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
@ -29,7 +29,7 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
class WatchHistoryFragment : BaseFragment() {
|
||||
class WatchHistoryFragment : Fragment() {
|
||||
private lateinit var binding: FragmentWatchHistoryBinding
|
||||
|
||||
private val playerViewModel: PlayerViewModel by activityViewModels()
|
||||
|
Loading…
Reference in New Issue
Block a user