Merge pull request #6384 from Bnyro/master

refactor: reduce amount of api calls for adding video to playlist
This commit is contained in:
Bnyro 2024-08-23 13:33:58 +02:00 committed by GitHub
commit 84056dd883
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 93 additions and 41 deletions

View File

@ -33,7 +33,7 @@ object StreamsExtractor {
description = resp.description.toString(), description = resp.description.toString(),
uploader = resp.uploaderName, uploader = resp.uploaderName,
uploaderAvatar = resp.uploaderAvatars.maxBy { it.height }.url, uploaderAvatar = resp.uploaderAvatars.maxBy { it.height }.url,
uploaderUrl = resp.uploaderUrl, uploaderUrl = resp.uploaderUrl.replace("https://www.youtube.com", ""),
uploaderVerified = resp.isUploaderVerified, uploaderVerified = resp.isUploaderVerified,
uploaderSubscriberCount = resp.uploaderSubscriberCount, uploaderSubscriberCount = resp.uploaderSubscriberCount,
category = resp.category, category = resp.category,
@ -58,12 +58,12 @@ object StreamsExtractor {
thumbnailUrl = resp.thumbnails.maxBy { it.height }.url, thumbnailUrl = resp.thumbnails.maxBy { it.height }.url,
relatedStreams = resp.relatedItems.map { it as StreamInfoItem }.map { relatedStreams = resp.relatedItems.map { it as StreamInfoItem }.map {
StreamItem( StreamItem(
it.url, it.url.replace("https://www.youtube.com", ""),
it.infoType.name, StreamItem.TYPE_STREAM,
it.name, it.name,
it.thumbnails.maxBy { image -> image.height }.url, it.thumbnails.maxBy { image -> image.height }.url,
it.uploaderName, it.uploaderName,
it.uploaderUrl, it.uploaderUrl.replace("https://www.youtube.com", ""),
it.uploaderAvatars.maxBy { image -> image.height }.url, it.uploaderAvatars.maxBy { image -> image.height }.url,
it.textualUploadDate, it.textualUploadDate,
it.duration, it.duration,

View File

@ -47,4 +47,5 @@ object IntentData {
const val tabData = "tabData" const val tabData = "tabData"
const val videoList = "videoList" const val videoList = "videoList"
const val nextPage = "nextPage" const val nextPage = "nextPage"
const val videoInfo = "videoInfo"
} }

View File

@ -19,13 +19,26 @@ object ProxyHelper {
} }
fun rewriteUrl(url: String?): String? { fun rewriteUrl(url: String?): String? {
if (url == null) return null
val proxyUrl = PreferenceHelper.getString(PreferenceKeys.IMAGE_PROXY_URL, "") val proxyUrl = PreferenceHelper.getString(PreferenceKeys.IMAGE_PROXY_URL, "")
.toHttpUrlOrNull() ?: return url .toHttpUrlOrNull() ?: return url
return url?.toHttpUrlOrNull()?.newBuilder() val parsedUrl = url.toHttpUrlOrNull() ?: return url
?.host(proxyUrl.host) if (parsedUrl.queryParameter("host").isNullOrEmpty()) {
?.port(proxyUrl.port) return parsedUrl.newBuilder()
?.toString() .host(proxyUrl.host)
.port(proxyUrl.port)
.setQueryParameter("host", parsedUrl.host)
.build()
.toString()
}
return parsedUrl.newBuilder()
.host(proxyUrl.host)
.port(proxyUrl.port)
.build()
.toString()
} }
/** /**

View File

@ -4,12 +4,21 @@ import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.lifecycle.lifecycleScope
import com.github.libretube.R
import com.github.libretube.api.StreamsExtractor
import com.github.libretube.api.obj.StreamItem
import com.github.libretube.constants.IntentData import com.github.libretube.constants.IntentData
import com.github.libretube.extensions.toastFromMainDispatcher
import com.github.libretube.helpers.IntentHelper import com.github.libretube.helpers.IntentHelper
import com.github.libretube.helpers.PreferenceHelper
import com.github.libretube.ui.base.BaseActivity import com.github.libretube.ui.base.BaseActivity
import com.github.libretube.ui.dialogs.AddToPlaylistDialog import com.github.libretube.ui.dialogs.AddToPlaylistDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class AddToPlaylistActivity: BaseActivity() { class AddToPlaylistActivity : BaseActivity() {
override val isDialogActivity: Boolean = true override val isDialogActivity: Boolean = true
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -29,8 +38,22 @@ class AddToPlaylistActivity: BaseActivity() {
this this
) { _, _ -> finish() } ) { _, _ -> finish() }
AddToPlaylistDialog().apply { lifecycleScope.launch(Dispatchers.IO) {
arguments = bundleOf(IntentData.videoId to videoId) val videoInfo = if (PreferenceHelper.getToken().isEmpty()) {
}.show(supportFragmentManager, null) try {
StreamsExtractor.extractStreams(videoId).toStreamItem(videoId)
} catch (e: Exception) {
toastFromMainDispatcher(R.string.unknown_error)
}
} else {
StreamItem(videoId)
}
withContext(Dispatchers.Main) {
AddToPlaylistDialog().apply {
arguments = bundleOf(IntentData.videoInfo to videoInfo)
}.show(supportFragmentManager, null)
}
}
} }
} }

View File

@ -15,12 +15,12 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.api.PlaylistsHelper import com.github.libretube.api.PlaylistsHelper
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.StreamsExtractor
import com.github.libretube.api.obj.Playlists import com.github.libretube.api.obj.Playlists
import com.github.libretube.api.obj.StreamItem
import com.github.libretube.constants.IntentData import com.github.libretube.constants.IntentData
import com.github.libretube.databinding.DialogAddToPlaylistBinding import com.github.libretube.databinding.DialogAddToPlaylistBinding
import com.github.libretube.extensions.TAG import com.github.libretube.extensions.TAG
import com.github.libretube.extensions.parcelable
import com.github.libretube.extensions.toastFromMainDispatcher import com.github.libretube.extensions.toastFromMainDispatcher
import com.github.libretube.ui.models.PlaylistViewModel import com.github.libretube.ui.models.PlaylistViewModel
import com.github.libretube.util.PlayingQueue import com.github.libretube.util.PlayingQueue
@ -32,14 +32,15 @@ import kotlinx.coroutines.launch
* videoId: The id of the video to add. If non is provided, insert the whole playing queue * videoId: The id of the video to add. If non is provided, insert the whole playing queue
*/ */
class AddToPlaylistDialog : DialogFragment() { class AddToPlaylistDialog : DialogFragment() {
private var videoId: String? = null private var videoInfo: StreamItem? = null
private val viewModel: PlaylistViewModel by activityViewModels() private val viewModel: PlaylistViewModel by activityViewModels()
var playlists = emptyList<Playlists>() var playlists = emptyList<Playlists>()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
videoId = arguments?.getString(IntentData.videoId) videoInfo = arguments?.parcelable(IntentData.videoInfo)
Log.e("video info", videoInfo.toString())
} }
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
@ -110,15 +111,7 @@ class AddToPlaylistDialog : DialogFragment() {
@SuppressLint("StringFormatInvalid") @SuppressLint("StringFormatInvalid")
private suspend fun addToPlaylist(playlistId: String, playlistName: String) { private suspend fun addToPlaylist(playlistId: String, playlistName: String) {
val appContext = context?.applicationContext ?: return val appContext = context?.applicationContext ?: return
val streams = when { val streams = videoInfo?.let { listOf(it) } ?: PlayingQueue.getStreams()
videoId != null -> listOfNotNull(
runCatching {
StreamsExtractor.extractStreams(videoId!!).toStreamItem(videoId!!)
}.getOrNull()
)
else -> PlayingQueue.getStreams()
}
val success = try { val success = try {
if (streams.isEmpty()) throw IllegalArgumentException() if (streams.isEmpty()) throw IllegalArgumentException()

View File

@ -104,8 +104,8 @@ import com.github.libretube.ui.interfaces.OnlinePlayerOptions
import com.github.libretube.ui.listeners.SeekbarPreviewListener import com.github.libretube.ui.listeners.SeekbarPreviewListener
import com.github.libretube.ui.models.ChaptersViewModel import com.github.libretube.ui.models.ChaptersViewModel
import com.github.libretube.ui.models.CommentsViewModel import com.github.libretube.ui.models.CommentsViewModel
import com.github.libretube.ui.models.PlayerViewModel
import com.github.libretube.ui.models.CommonPlayerViewModel import com.github.libretube.ui.models.CommonPlayerViewModel
import com.github.libretube.ui.models.PlayerViewModel
import com.github.libretube.ui.sheets.BaseBottomSheet import com.github.libretube.ui.sheets.BaseBottomSheet
import com.github.libretube.ui.sheets.CommentsSheet import com.github.libretube.ui.sheets.CommentsSheet
import com.github.libretube.ui.sheets.StatsSheet import com.github.libretube.ui.sheets.StatsSheet
@ -282,7 +282,11 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
} }
if (events.contains(Player.EVENT_TRACKS_CHANGED)) { if (events.contains(Player.EVENT_TRACKS_CHANGED)) {
PlayerHelper.setPreferredAudioQuality(requireContext(), viewModel.player, viewModel.trackSelector) PlayerHelper.setPreferredAudioQuality(
requireContext(),
viewModel.player,
viewModel.trackSelector
)
} }
} }
@ -628,9 +632,11 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
) )
binding.relPlayerSave.setOnClickListener { binding.relPlayerSave.setOnClickListener {
val newAddToPlaylistDialog = AddToPlaylistDialog() if (!::streams.isInitialized) return@setOnClickListener
newAddToPlaylistDialog.arguments = bundleOf(IntentData.videoId to videoId)
newAddToPlaylistDialog.show(childFragmentManager, AddToPlaylistDialog::class.java.name) AddToPlaylistDialog().apply {
arguments = bundleOf(IntentData.videoInfo to streams.toStreamItem(videoId))
}.show(childFragmentManager, AddToPlaylistDialog::class.java.name)
} }
playerBinding.skipPrev.setOnClickListener { playerBinding.skipPrev.setOnClickListener {
@ -1074,7 +1080,13 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
playerGestureControlsViewBinding, playerGestureControlsViewBinding,
chaptersViewModel chaptersViewModel
) )
binding.player.initPlayerOptions(viewModel, commonPlayerViewModel, viewLifecycleOwner, viewModel.trackSelector, this) binding.player.initPlayerOptions(
viewModel,
commonPlayerViewModel,
viewLifecycleOwner,
viewModel.trackSelector,
this
)
binding.descriptionLayout.setStreams(streams) binding.descriptionLayout.setStreams(streams)
@ -1534,11 +1546,12 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
} }
} }
private fun updateCurrentSubtitle(subtitle: Subtitle?) = viewModel.trackSelector.updateParameters { private fun updateCurrentSubtitle(subtitle: Subtitle?) =
val roleFlags = if (subtitle?.code != null) getSubtitleRoleFlags(subtitle) else 0 viewModel.trackSelector.updateParameters {
setPreferredTextRoleFlags(roleFlags) val roleFlags = if (subtitle?.code != null) getSubtitleRoleFlags(subtitle) else 0
setPreferredTextLanguage(subtitle?.code) setPreferredTextRoleFlags(roleFlags)
} setPreferredTextLanguage(subtitle?.code)
}
fun onUserLeaveHint() { fun onUserLeaveHint() {
if (shouldStartPiP()) { if (shouldStartPiP()) {
@ -1550,7 +1563,12 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
private val pipParams private val pipParams
get() = PictureInPictureParamsCompat.Builder() get() = PictureInPictureParamsCompat.Builder()
.setActions(PlayerHelper.getPiPModeActions(requireActivity(), viewModel.player.isPlaying)) .setActions(
PlayerHelper.getPiPModeActions(
requireActivity(),
viewModel.player.isPlaying
)
)
.setAutoEnterEnabled(PlayerHelper.pipEnabled && viewModel.player.isPlaying) .setAutoEnterEnabled(PlayerHelper.pipEnabled && viewModel.player.isPlaying)
.apply { .apply {
if (viewModel.player.isPlaying) { if (viewModel.player.isPlaying) {

View File

@ -62,16 +62,20 @@ class VideoOptionsBottomSheet : BaseBottomSheet() {
} }
// Add Video to Playlist Dialog // Add Video to Playlist Dialog
R.string.addToPlaylist -> { R.string.addToPlaylist -> {
val newAddToPlaylistDialog = AddToPlaylistDialog() AddToPlaylistDialog().apply {
newAddToPlaylistDialog.arguments = bundleOf(IntentData.videoId to videoId) arguments = bundleOf(IntentData.videoInfo to streamItem)
newAddToPlaylistDialog.show( }.show(
parentFragmentManager, parentFragmentManager,
AddToPlaylistDialog::class.java.name AddToPlaylistDialog::class.java.name
) )
} }
R.string.download -> { R.string.download -> {
DownloadHelper.startDownloadDialog(requireContext(), parentFragmentManager, videoId) DownloadHelper.startDownloadDialog(
requireContext(),
parentFragmentManager,
videoId
)
} }
R.string.share -> { R.string.share -> {