mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-13 22:00:30 +05:30
Merge pull request #5127 from Bnyro/master
refactor: remove unnecessary repeatOnLifecycle calls
This commit is contained in:
commit
2afdb1f359
@ -10,9 +10,7 @@ import android.widget.ArrayAdapter
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.isGone
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.api.RetrofitInstance
|
||||
import com.github.libretube.api.obj.PipedStream
|
||||
@ -27,11 +25,11 @@ import com.github.libretube.helpers.PreferenceHelper
|
||||
import com.github.libretube.parcelable.DownloadData
|
||||
import com.github.libretube.util.TextUtils
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import java.io.IOException
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
class DownloadDialog : DialogFragment() {
|
||||
private lateinit var videoId: String
|
||||
@ -80,23 +78,21 @@ class DownloadDialog : DialogFragment() {
|
||||
|
||||
private fun fetchAvailableSources(binding: DialogDownloadBinding) {
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.CREATED) {
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
RetrofitInstance.api.getStreams(videoId)
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
println(e)
|
||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
||||
Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
||||
return@repeatOnLifecycle
|
||||
} catch (e: HttpException) {
|
||||
Log.e(TAG(), "HttpException, unexpected response")
|
||||
Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show()
|
||||
return@repeatOnLifecycle
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
RetrofitInstance.api.getStreams(videoId)
|
||||
}
|
||||
initDownloadOptions(binding, response)
|
||||
} catch (e: IOException) {
|
||||
println(e)
|
||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
||||
Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
||||
return@launch
|
||||
} catch (e: HttpException) {
|
||||
Log.e(TAG(), "HttpException, unexpected response")
|
||||
Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show()
|
||||
return@launch
|
||||
}
|
||||
initDownloadOptions(binding, response)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,9 +11,7 @@ import androidx.core.view.children
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.api.RetrofitInstance
|
||||
@ -34,11 +32,11 @@ import com.github.libretube.ui.adapters.VideosAdapter
|
||||
import com.github.libretube.ui.dialogs.ShareDialog
|
||||
import com.github.libretube.ui.extensions.setupSubscriptionButton
|
||||
import com.github.libretube.util.deArrow
|
||||
import java.io.IOException
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
class ChannelFragment : Fragment() {
|
||||
private var _binding: FragmentChannelBinding? = null
|
||||
@ -113,115 +111,113 @@ class ChannelFragment : Fragment() {
|
||||
|
||||
private fun fetchChannel() {
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.CREATED) {
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
if (channelId != null) {
|
||||
RetrofitInstance.api.getChannel(channelId!!)
|
||||
} else {
|
||||
RetrofitInstance.api.getChannelByName(channelName!!)
|
||||
}.apply {
|
||||
relatedStreams = relatedStreams.deArrow()
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
_binding?.channelRefresh?.isRefreshing = false
|
||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
||||
return@repeatOnLifecycle
|
||||
} catch (e: HttpException) {
|
||||
_binding?.channelRefresh?.isRefreshing = false
|
||||
Log.e(TAG(), "HttpException, unexpected response")
|
||||
return@repeatOnLifecycle
|
||||
}
|
||||
val binding = _binding ?: return@repeatOnLifecycle
|
||||
|
||||
// needed if the channel gets loaded by the ID
|
||||
channelId = response.id
|
||||
channelName = response.name
|
||||
val shareData = ShareData(currentChannel = response.name)
|
||||
|
||||
onScrollEnd = {
|
||||
fetchChannelNextPage()
|
||||
}
|
||||
|
||||
val channelId = channelId ?: return@repeatOnLifecycle
|
||||
// fetch and update the subscription status
|
||||
isSubscribed = SubscriptionHelper.isSubscribed(channelId)
|
||||
if (isSubscribed == null) return@repeatOnLifecycle
|
||||
|
||||
binding.channelSubscribe.setupSubscriptionButton(
|
||||
channelId,
|
||||
channelName,
|
||||
binding.notificationBell
|
||||
)
|
||||
|
||||
binding.channelShare.setOnClickListener {
|
||||
val bundle = bundleOf(
|
||||
IntentData.id to channelId.toID(),
|
||||
IntentData.shareObjectType to ShareObjectType.CHANNEL,
|
||||
IntentData.shareData to shareData
|
||||
)
|
||||
val newShareDialog = ShareDialog()
|
||||
newShareDialog.arguments = bundle
|
||||
newShareDialog.show(childFragmentManager, ShareDialog::class.java.name)
|
||||
}
|
||||
|
||||
nextPage = response.nextpage
|
||||
isLoading = false
|
||||
binding.channelRefresh.isRefreshing = false
|
||||
|
||||
binding.channelScrollView.isVisible = true
|
||||
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()
|
||||
)
|
||||
if (response.description.orEmpty().isBlank()) {
|
||||
binding.channelDescription.isGone = true
|
||||
} else {
|
||||
binding.channelDescription.text = response.description.orEmpty().trim()
|
||||
}
|
||||
|
||||
binding.channelDescription.setOnClickListener {
|
||||
(it as TextView).apply {
|
||||
it.maxLines = if (it.maxLines == Int.MAX_VALUE) 2 else Int.MAX_VALUE
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
if (channelId != null) {
|
||||
RetrofitInstance.api.getChannel(channelId!!)
|
||||
} else {
|
||||
RetrofitInstance.api.getChannelByName(channelName!!)
|
||||
}.apply {
|
||||
relatedStreams = relatedStreams.deArrow()
|
||||
}
|
||||
}
|
||||
|
||||
ImageHelper.loadImage(response.bannerUrl, binding.channelBanner)
|
||||
ImageHelper.loadImage(response.avatarUrl, binding.channelImage)
|
||||
|
||||
binding.channelImage.setOnClickListener {
|
||||
NavigationHelper.openImagePreview(
|
||||
requireContext(),
|
||||
response.avatarUrl ?: return@setOnClickListener
|
||||
)
|
||||
}
|
||||
|
||||
binding.channelBanner.setOnClickListener {
|
||||
NavigationHelper.openImagePreview(
|
||||
requireContext(),
|
||||
response.bannerUrl ?: return@setOnClickListener
|
||||
)
|
||||
}
|
||||
|
||||
// recyclerview of the videos by the channel
|
||||
channelAdapter = VideosAdapter(
|
||||
response.relatedStreams.toMutableList(),
|
||||
forceMode = VideosAdapter.Companion.ForceMode.CHANNEL
|
||||
)
|
||||
binding.channelRecView.adapter = channelAdapter
|
||||
|
||||
setupTabs(response.tabs)
|
||||
} catch (e: IOException) {
|
||||
_binding?.channelRefresh?.isRefreshing = false
|
||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
||||
return@launch
|
||||
} catch (e: HttpException) {
|
||||
_binding?.channelRefresh?.isRefreshing = false
|
||||
Log.e(TAG(), "HttpException, unexpected response")
|
||||
return@launch
|
||||
}
|
||||
val binding = _binding ?: return@launch
|
||||
|
||||
// needed if the channel gets loaded by the ID
|
||||
channelId = response.id
|
||||
channelName = response.name
|
||||
val shareData = ShareData(currentChannel = response.name)
|
||||
|
||||
onScrollEnd = {
|
||||
fetchChannelNextPage()
|
||||
}
|
||||
|
||||
val channelId = channelId ?: return@launch
|
||||
// fetch and update the subscription status
|
||||
isSubscribed = SubscriptionHelper.isSubscribed(channelId)
|
||||
if (isSubscribed == null) return@launch
|
||||
|
||||
binding.channelSubscribe.setupSubscriptionButton(
|
||||
channelId,
|
||||
channelName,
|
||||
binding.notificationBell
|
||||
)
|
||||
|
||||
binding.channelShare.setOnClickListener {
|
||||
val bundle = bundleOf(
|
||||
IntentData.id to channelId.toID(),
|
||||
IntentData.shareObjectType to ShareObjectType.CHANNEL,
|
||||
IntentData.shareData to shareData
|
||||
)
|
||||
val newShareDialog = ShareDialog()
|
||||
newShareDialog.arguments = bundle
|
||||
newShareDialog.show(childFragmentManager, ShareDialog::class.java.name)
|
||||
}
|
||||
|
||||
nextPage = response.nextpage
|
||||
isLoading = false
|
||||
binding.channelRefresh.isRefreshing = false
|
||||
|
||||
binding.channelScrollView.isVisible = true
|
||||
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()
|
||||
)
|
||||
if (response.description.orEmpty().isBlank()) {
|
||||
binding.channelDescription.isGone = true
|
||||
} else {
|
||||
binding.channelDescription.text = response.description.orEmpty().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)
|
||||
|
||||
binding.channelImage.setOnClickListener {
|
||||
NavigationHelper.openImagePreview(
|
||||
requireContext(),
|
||||
response.avatarUrl ?: return@setOnClickListener
|
||||
)
|
||||
}
|
||||
|
||||
binding.channelBanner.setOnClickListener {
|
||||
NavigationHelper.openImagePreview(
|
||||
requireContext(),
|
||||
response.bannerUrl ?: return@setOnClickListener
|
||||
)
|
||||
}
|
||||
|
||||
// recyclerview of the videos by the channel
|
||||
channelAdapter = VideosAdapter(
|
||||
response.relatedStreams.toMutableList(),
|
||||
forceMode = VideosAdapter.Companion.ForceMode.CHANNEL
|
||||
)
|
||||
binding.channelRecView.adapter = channelAdapter
|
||||
|
||||
setupTabs(response.tabs)
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,29 +288,27 @@ class ChannelFragment : Fragment() {
|
||||
binding.channelRefresh.isRefreshing = true
|
||||
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.CREATED) {
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
RetrofitInstance.api.getChannelNextPage(channelId!!, nextPage!!).apply {
|
||||
relatedStreams = relatedStreams.deArrow()
|
||||
}
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
RetrofitInstance.api.getChannelNextPage(channelId!!, nextPage!!).apply {
|
||||
relatedStreams = relatedStreams.deArrow()
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
_binding?.channelRefresh?.isRefreshing = false
|
||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
||||
return@repeatOnLifecycle
|
||||
} catch (e: HttpException) {
|
||||
_binding?.channelRefresh?.isRefreshing = false
|
||||
Log.e(TAG(), "HttpException, unexpected response," + e.response())
|
||||
return@repeatOnLifecycle
|
||||
}
|
||||
val binding = _binding ?: return@repeatOnLifecycle
|
||||
|
||||
nextPage = response.nextpage
|
||||
channelAdapter?.insertItems(response.relatedStreams)
|
||||
isLoading = false
|
||||
binding.channelRefresh.isRefreshing = false
|
||||
} catch (e: IOException) {
|
||||
_binding?.channelRefresh?.isRefreshing = false
|
||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
||||
return@launch
|
||||
} catch (e: HttpException) {
|
||||
_binding?.channelRefresh?.isRefreshing = false
|
||||
Log.e(TAG(), "HttpException, unexpected response," + e.response())
|
||||
return@launch
|
||||
}
|
||||
val binding = _binding ?: return@launch
|
||||
|
||||
nextPage = response.nextpage
|
||||
channelAdapter?.insertItems(response.relatedStreams)
|
||||
isLoading = false
|
||||
binding.channelRefresh.isRefreshing = false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,7 @@ import androidx.core.view.isVisible
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@ -122,146 +120,144 @@ class PlaylistFragment : Fragment() {
|
||||
private fun fetchPlaylist() {
|
||||
binding.playlistScrollview.isGone = true
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.CREATED) {
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
PlaylistsHelper.getPlaylist(playlistId!!)
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
PlaylistsHelper.getPlaylist(playlistId!!)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG(), e.toString())
|
||||
return@launch
|
||||
}
|
||||
val binding = _binding ?: return@launch
|
||||
|
||||
playlistFeed = response.relatedStreams.toMutableList()
|
||||
binding.playlistScrollview.isVisible = true
|
||||
nextPage = response.nextpage
|
||||
playlistName = response.name
|
||||
isLoading = false
|
||||
ImageHelper.loadImage(response.thumbnailUrl, binding.thumbnail)
|
||||
binding.playlistProgress.isGone = true
|
||||
binding.playlistName.text = response.name
|
||||
|
||||
binding.playlistName.setOnClickListener {
|
||||
binding.playlistName.maxLines =
|
||||
if (binding.playlistName.maxLines == 2) Int.MAX_VALUE else 2
|
||||
}
|
||||
|
||||
binding.playlistInfo.text = getChannelAndVideoString(response, response.videos)
|
||||
binding.playlistInfo.setOnClickListener {
|
||||
(context as MainActivity).navController.navigate(
|
||||
R.id.channelFragment,
|
||||
bundleOf(IntentData.channelId to response.uploaderUrl?.toID())
|
||||
)
|
||||
}
|
||||
|
||||
binding.playlistDescription.text = response.description
|
||||
// hide playlist description text view if not provided
|
||||
binding.playlistDescription.isGone = response.description.orEmpty().isBlank()
|
||||
|
||||
binding.playlistDescription.let { textView ->
|
||||
textView.setOnClickListener {
|
||||
textView.maxLines =
|
||||
if (textView.maxLines == Int.MAX_VALUE) 3 else Int.MAX_VALUE
|
||||
}
|
||||
}
|
||||
|
||||
showPlaylistVideos(response)
|
||||
|
||||
// show playlist options
|
||||
binding.optionsMenu.setOnClickListener {
|
||||
val sheet = PlaylistOptionsBottomSheet()
|
||||
sheet.arguments = bundleOf(
|
||||
IntentData.playlistId to playlistId.orEmpty(),
|
||||
IntentData.playlistName to playlistName.orEmpty(),
|
||||
IntentData.playlistType to playlistType
|
||||
)
|
||||
|
||||
val fragmentManager = (context as BaseActivity).supportFragmentManager
|
||||
fragmentManager.setFragmentResultListener(
|
||||
PlaylistOptionsBottomSheet.PLAYLIST_OPTIONS_REQUEST_KEY,
|
||||
(context as BaseActivity)
|
||||
) { _, resultBundle ->
|
||||
val newPlaylistDescription =
|
||||
resultBundle.getString(IntentData.playlistDescription)
|
||||
val newPlaylistName =
|
||||
resultBundle.getString(IntentData.playlistName)
|
||||
val isPlaylistToBeDeleted =
|
||||
resultBundle.getBoolean(IntentData.playlistTask)
|
||||
|
||||
newPlaylistDescription?.let {
|
||||
binding.playlistDescription.text = it
|
||||
response.description = it
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG(), e.toString())
|
||||
return@repeatOnLifecycle
|
||||
}
|
||||
val binding = _binding ?: return@repeatOnLifecycle
|
||||
|
||||
playlistFeed = response.relatedStreams.toMutableList()
|
||||
binding.playlistScrollview.isVisible = true
|
||||
nextPage = response.nextpage
|
||||
playlistName = response.name
|
||||
isLoading = false
|
||||
ImageHelper.loadImage(response.thumbnailUrl, binding.thumbnail)
|
||||
binding.playlistProgress.isGone = true
|
||||
binding.playlistName.text = response.name
|
||||
newPlaylistName?.let {
|
||||
binding.playlistName.text = it
|
||||
playlistName = it
|
||||
}
|
||||
|
||||
binding.playlistName.setOnClickListener {
|
||||
binding.playlistName.maxLines =
|
||||
if (binding.playlistName.maxLines == 2) Int.MAX_VALUE else 2
|
||||
}
|
||||
|
||||
binding.playlistInfo.text = getChannelAndVideoString(response, response.videos)
|
||||
binding.playlistInfo.setOnClickListener {
|
||||
(context as MainActivity).navController.navigate(
|
||||
R.id.channelFragment,
|
||||
bundleOf(IntentData.channelId to response.uploaderUrl?.toID())
|
||||
)
|
||||
}
|
||||
|
||||
binding.playlistDescription.text = response.description
|
||||
// hide playlist description text view if not provided
|
||||
binding.playlistDescription.isGone = response.description.orEmpty().isBlank()
|
||||
|
||||
binding.playlistDescription.let { textView ->
|
||||
textView.setOnClickListener {
|
||||
textView.maxLines =
|
||||
if (textView.maxLines == Int.MAX_VALUE) 3 else Int.MAX_VALUE
|
||||
if (isPlaylistToBeDeleted) {
|
||||
// TODO move back: navController().popBackStack() crashes
|
||||
return@setFragmentResultListener
|
||||
}
|
||||
}
|
||||
|
||||
showPlaylistVideos(response)
|
||||
sheet.show(fragmentManager)
|
||||
}
|
||||
|
||||
// show playlist options
|
||||
binding.optionsMenu.setOnClickListener {
|
||||
val sheet = PlaylistOptionsBottomSheet()
|
||||
sheet.arguments = bundleOf(
|
||||
IntentData.playlistId to playlistId.orEmpty(),
|
||||
IntentData.playlistName to playlistName.orEmpty(),
|
||||
IntentData.playlistType to playlistType
|
||||
)
|
||||
binding.playAll.setOnClickListener {
|
||||
if (playlistFeed.isEmpty()) return@setOnClickListener
|
||||
NavigationHelper.navigateVideo(
|
||||
requireContext(),
|
||||
response.relatedStreams.first().url?.toID(),
|
||||
playlistId
|
||||
)
|
||||
}
|
||||
|
||||
val fragmentManager = (context as BaseActivity).supportFragmentManager
|
||||
fragmentManager.setFragmentResultListener(
|
||||
PlaylistOptionsBottomSheet.PLAYLIST_OPTIONS_REQUEST_KEY,
|
||||
(context as BaseActivity)
|
||||
) { _, resultBundle ->
|
||||
val newPlaylistDescription =
|
||||
resultBundle.getString(IntentData.playlistDescription)
|
||||
val newPlaylistName =
|
||||
resultBundle.getString(IntentData.playlistName)
|
||||
val isPlaylistToBeDeleted =
|
||||
resultBundle.getBoolean(IntentData.playlistTask)
|
||||
|
||||
newPlaylistDescription?.let {
|
||||
binding.playlistDescription.text = it
|
||||
response.description = it
|
||||
}
|
||||
|
||||
newPlaylistName?.let {
|
||||
binding.playlistName.text = it
|
||||
playlistName = it
|
||||
}
|
||||
|
||||
if (isPlaylistToBeDeleted) {
|
||||
// TODO move back: navController().popBackStack() crashes
|
||||
return@setFragmentResultListener
|
||||
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()
|
||||
.insert(response.toPlaylistBookmark(playlistId!!))
|
||||
}
|
||||
}
|
||||
|
||||
sheet.show(fragmentManager)
|
||||
}
|
||||
|
||||
binding.playAll.setOnClickListener {
|
||||
} 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(),
|
||||
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()
|
||||
.insert(response.toPlaylistBookmark(playlistId!!))
|
||||
}
|
||||
binding.sortContainer.isGone = false
|
||||
binding.sortTV.text = sortOptions[selectedSortOrder]
|
||||
binding.sortContainer.setOnClickListener {
|
||||
BaseBottomSheet().apply {
|
||||
setSimpleItems(sortOptions.toList()) { index ->
|
||||
selectedSortOrder = index
|
||||
binding.sortTV.text = sortOptions[index]
|
||||
showPlaylistVideos(response)
|
||||
}
|
||||
}
|
||||
} 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
|
||||
)
|
||||
}
|
||||
binding.sortContainer.isGone = false
|
||||
binding.sortTV.text = sortOptions[selectedSortOrder]
|
||||
binding.sortContainer.setOnClickListener {
|
||||
BaseBottomSheet().apply {
|
||||
setSimpleItems(sortOptions.toList()) { index ->
|
||||
selectedSortOrder = index
|
||||
binding.sortTV.text = sortOptions[index]
|
||||
showPlaylistVideos(response)
|
||||
}
|
||||
}.show(childFragmentManager)
|
||||
}
|
||||
}.show(childFragmentManager)
|
||||
}
|
||||
|
||||
updatePlaylistBookmark(response)
|
||||
}
|
||||
|
||||
updatePlaylistBookmark(response)
|
||||
}
|
||||
}
|
||||
|
||||
@ -380,26 +376,24 @@ class PlaylistFragment : Fragment() {
|
||||
isLoading = true
|
||||
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.CREATED) {
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
// load locally stored playlists with the auth api
|
||||
if (playlistType == PlaylistType.PRIVATE) {
|
||||
RetrofitInstance.authApi.getPlaylistNextPage(playlistId!!, nextPage!!)
|
||||
} else {
|
||||
RetrofitInstance.api.getPlaylistNextPage(playlistId!!, nextPage!!)
|
||||
}
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
// load locally stored playlists with the auth api
|
||||
if (playlistType == PlaylistType.PRIVATE) {
|
||||
RetrofitInstance.authApi.getPlaylistNextPage(playlistId!!, nextPage!!)
|
||||
} else {
|
||||
RetrofitInstance.api.getPlaylistNextPage(playlistId!!, nextPage!!)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
context?.toastFromMainDispatcher(e.localizedMessage.orEmpty())
|
||||
Log.e(TAG(), e.toString())
|
||||
return@repeatOnLifecycle
|
||||
}
|
||||
|
||||
nextPage = response.nextpage
|
||||
playlistAdapter?.updateItems(response.relatedStreams)
|
||||
isLoading = false
|
||||
} catch (e: Exception) {
|
||||
context?.toastFromMainDispatcher(e.localizedMessage.orEmpty())
|
||||
Log.e(TAG(), e.toString())
|
||||
return@launch
|
||||
}
|
||||
|
||||
nextPage = response.nextpage
|
||||
playlistAdapter?.updateItems(response.relatedStreams)
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,9 +9,7 @@ import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.github.libretube.api.RetrofitInstance
|
||||
import com.github.libretube.constants.IntentData
|
||||
@ -74,23 +72,21 @@ class SearchFragment : Fragment() {
|
||||
|
||||
private fun fetchSuggestions(query: String) {
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.CREATED) {
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
RetrofitInstance.api.getSuggestions(query)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG(), e.toString())
|
||||
return@repeatOnLifecycle
|
||||
}
|
||||
// only load the suggestions if the input field didn't get cleared yet
|
||||
val suggestionsAdapter = SearchSuggestionsAdapter(
|
||||
response.reversed(),
|
||||
(activity as MainActivity).searchView
|
||||
)
|
||||
if (isAdded && !viewModel.searchQuery.value.isNullOrEmpty()) {
|
||||
binding.suggestionsRecycler.adapter = suggestionsAdapter
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
RetrofitInstance.api.getSuggestions(query)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG(), e.toString())
|
||||
return@launch
|
||||
}
|
||||
// only load the suggestions if the input field didn't get cleared yet
|
||||
val suggestionsAdapter = SearchSuggestionsAdapter(
|
||||
response.reversed(),
|
||||
(activity as MainActivity).searchView
|
||||
)
|
||||
if (isAdded && !viewModel.searchQuery.value.isNullOrEmpty()) {
|
||||
binding.suggestionsRecycler.adapter = suggestionsAdapter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,7 @@ import android.view.ViewGroup
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.api.RetrofitInstance
|
||||
@ -114,55 +112,51 @@ class SearchResultFragment : Fragment() {
|
||||
"${ShareDialog.YOUTUBE_FRONTEND_URL}/watch?v=$videoId"
|
||||
} ?: query
|
||||
|
||||
repeatOnLifecycle(Lifecycle.State.CREATED) {
|
||||
view?.let { context?.hideKeyboard(it) }
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
RetrofitInstance.api.getSearchResults(searchQuery, searchFilter).apply {
|
||||
items = items.deArrow()
|
||||
}
|
||||
view?.let { context?.hideKeyboard(it) }
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
RetrofitInstance.api.getSearchResults(searchQuery, searchFilter).apply {
|
||||
items = items.deArrow()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG(), e.toString())
|
||||
context?.toastFromMainDispatcher(R.string.unknown_error)
|
||||
return@repeatOnLifecycle
|
||||
}
|
||||
|
||||
val binding = _binding ?: return@repeatOnLifecycle
|
||||
searchAdapter = SearchAdapter(timeStamp = timeStamp ?: 0)
|
||||
binding.searchRecycler.adapter = searchAdapter
|
||||
searchAdapter.submitList(response.items)
|
||||
|
||||
binding.searchResultsLayout.isVisible = true
|
||||
binding.progress.isGone = true
|
||||
binding.noSearchResult.isVisible = response.items.isEmpty()
|
||||
|
||||
nextPage = response.nextpage
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG(), e.toString())
|
||||
context?.toastFromMainDispatcher(R.string.unknown_error)
|
||||
return@launch
|
||||
}
|
||||
|
||||
val binding = _binding ?: return@launch
|
||||
searchAdapter = SearchAdapter(timeStamp = timeStamp ?: 0)
|
||||
binding.searchRecycler.adapter = searchAdapter
|
||||
searchAdapter.submitList(response.items)
|
||||
|
||||
binding.searchResultsLayout.isVisible = true
|
||||
binding.progress.isGone = true
|
||||
binding.noSearchResult.isVisible = response.items.isEmpty()
|
||||
|
||||
nextPage = response.nextpage
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchNextSearchItems() {
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.CREATED) {
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
RetrofitInstance.api.getSearchResultsNextPage(
|
||||
query,
|
||||
searchFilter,
|
||||
nextPage!!
|
||||
).apply {
|
||||
items = items.deArrow()
|
||||
}
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
RetrofitInstance.api.getSearchResultsNextPage(
|
||||
query,
|
||||
searchFilter,
|
||||
nextPage!!
|
||||
).apply {
|
||||
items = items.deArrow()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG(), e.toString())
|
||||
return@repeatOnLifecycle
|
||||
}
|
||||
nextPage = response.nextpage
|
||||
if (response.items.isNotEmpty()) {
|
||||
searchAdapter.submitList(searchAdapter.currentList + response.items)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG(), e.toString())
|
||||
return@launch
|
||||
}
|
||||
nextPage = response.nextpage
|
||||
if (response.items.isNotEmpty()) {
|
||||
searchAdapter.submitList(searchAdapter.currentList + response.items)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,9 +9,7 @@ import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.isGone
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.api.RetrofitInstance
|
||||
import com.github.libretube.databinding.FragmentTrendsBinding
|
||||
@ -21,11 +19,11 @@ import com.github.libretube.ui.activities.SettingsActivity
|
||||
import com.github.libretube.ui.adapters.VideosAdapter
|
||||
import com.github.libretube.util.deArrow
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import java.io.IOException
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
class TrendsFragment : Fragment() {
|
||||
private var _binding: FragmentTrendsBinding? = null
|
||||
@ -57,41 +55,39 @@ class TrendsFragment : Fragment() {
|
||||
|
||||
private fun fetchTrending() {
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.CREATED) {
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
val region = LocaleHelper.getTrendingRegion(requireContext())
|
||||
RetrofitInstance.api.getTrending(region).deArrow()
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
println(e)
|
||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
||||
Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
||||
return@repeatOnLifecycle
|
||||
} catch (e: HttpException) {
|
||||
Log.e(TAG(), "HttpException, unexpected response")
|
||||
Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show()
|
||||
return@repeatOnLifecycle
|
||||
val response = try {
|
||||
withContext(Dispatchers.IO) {
|
||||
val region = LocaleHelper.getTrendingRegion(requireContext())
|
||||
RetrofitInstance.api.getTrending(region).deArrow()
|
||||
}
|
||||
|
||||
val binding = _binding ?: return@repeatOnLifecycle
|
||||
binding.homeRefresh.isRefreshing = false
|
||||
binding.progressBar.isGone = true
|
||||
|
||||
// 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) {
|
||||
val settingsIntent = Intent(context, SettingsActivity::class.java)
|
||||
startActivity(settingsIntent)
|
||||
}
|
||||
.show()
|
||||
return@repeatOnLifecycle
|
||||
}
|
||||
|
||||
binding.recview.adapter = VideosAdapter(response.toMutableList())
|
||||
binding.recview.layoutManager = VideosAdapter.getLayout(requireContext())
|
||||
} catch (e: IOException) {
|
||||
println(e)
|
||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
||||
Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
||||
return@launch
|
||||
} catch (e: HttpException) {
|
||||
Log.e(TAG(), "HttpException, unexpected response")
|
||||
Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show()
|
||||
return@launch
|
||||
}
|
||||
|
||||
val binding = _binding ?: return@launch
|
||||
binding.homeRefresh.isRefreshing = false
|
||||
binding.progressBar.isGone = true
|
||||
|
||||
// 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) {
|
||||
val settingsIntent = Intent(context, SettingsActivity::class.java)
|
||||
startActivity(settingsIntent)
|
||||
}
|
||||
.show()
|
||||
return@launch
|
||||
}
|
||||
|
||||
binding.recview.adapter = VideosAdapter(response.toMutableList())
|
||||
binding.recview.layoutManager = VideosAdapter.getLayout(requireContext())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user