From 1b6e8fe27d9ffeef7cd73fc66de0287a8cbcf619 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Sun, 26 May 2024 19:35:20 +0200 Subject: [PATCH] feat: support for external download apps --- .../libretube/constants/PreferenceKeys.kt | 1 + .../libretube/helpers/DownloadHelper.kt | 54 ++++++++++++++++++- .../libretube/ui/fragments/PlayerFragment.kt | 6 +-- .../ui/sheets/PlaylistOptionsBottomSheet.kt | 11 +--- .../ui/sheets/VideoOptionsBottomSheet.kt | 6 +-- app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/advanced_settings.xml | 28 ++++++---- 7 files changed, 81 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt b/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt index bf14c71043..f47ce5a741 100644 --- a/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt +++ b/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt @@ -144,6 +144,7 @@ object PreferenceKeys { const val CONFIRM_UNSUBSCRIBE = "confirm_unsubscribing" const val CLEAR_BOOKMARKS = "clear_bookmarks" const val MAX_CONCURRENT_DOWNLOADS = "max_parallel_downloads" + const val EXTERNAL_DOWNLOAD_PROVIDER = "external_download_provider" const val DISABLE_VIDEO_IMAGE_PROXY = "disable_video_image_proxy" const val CONTRIBUTE_TO_SB = "sb_contribute_key" const val CONTRIBUTE_TO_DEARROW = "dearrow_contribute_key" diff --git a/app/src/main/java/com/github/libretube/helpers/DownloadHelper.kt b/app/src/main/java/com/github/libretube/helpers/DownloadHelper.kt index b3cac32eb8..61e5a4e503 100644 --- a/app/src/main/java/com/github/libretube/helpers/DownloadHelper.kt +++ b/app/src/main/java/com/github/libretube/helpers/DownloadHelper.kt @@ -4,11 +4,18 @@ import android.content.Context import android.content.Intent import android.os.Build import androidx.core.content.ContextCompat +import androidx.core.net.toUri +import androidx.core.os.bundleOf +import androidx.fragment.app.FragmentManager import com.github.libretube.constants.IntentData import com.github.libretube.constants.PreferenceKeys import com.github.libretube.db.obj.DownloadItem +import com.github.libretube.enums.PlaylistType import com.github.libretube.parcelable.DownloadData import com.github.libretube.services.DownloadService +import com.github.libretube.ui.dialogs.DownloadDialog +import com.github.libretube.ui.dialogs.DownloadPlaylistDialog +import com.github.libretube.ui.dialogs.ShareDialog import java.nio.file.Path import kotlin.io.path.createDirectories import kotlin.io.path.div @@ -17,11 +24,11 @@ object DownloadHelper { const val VIDEO_DIR = "video" const val AUDIO_DIR = "audio" const val SUBTITLE_DIR = "subtitle" - const val METADATA_DIR = "metadata" const val THUMBNAIL_DIR = "thumbnail" const val DOWNLOAD_CHUNK_SIZE = 8L * 1024 const val DEFAULT_TIMEOUT = 15 * 1000 const val DEFAULT_RETRY = 3 + private const val videoMimeType = "video/*" fun getDownloadDir(context: Context, path: String): Path { val storageDir = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { @@ -53,4 +60,49 @@ object DownloadHelper { fun DownloadItem.getNotificationId(): Int { return Int.MAX_VALUE - id } + + fun startDownloadDialog(context: Context, fragmentManager: FragmentManager, videoId: String) { + val externalProviderPackageName = + PreferenceHelper.getString(PreferenceKeys.EXTERNAL_DOWNLOAD_PROVIDER, "") + + if (externalProviderPackageName.isBlank()) { + DownloadDialog().apply { + arguments = bundleOf(IntentData.videoId to videoId) + }.show(fragmentManager, DownloadDialog::class.java.name) + } else { + val intent = Intent(Intent.ACTION_VIEW) + .setPackage(externalProviderPackageName) + .setDataAndType("${ShareDialog.YOUTUBE_FRONTEND_URL}/watch?v=$videoId".toUri(), videoMimeType) + + runCatching { context.startActivity(intent) } + } + } + + fun startDownloadPlaylistDialog( + context: Context, + fragmentManager: FragmentManager, + playlistId: String, + playlistName: String, + playlistType: PlaylistType + ) { + val externalProviderPackageName = + PreferenceHelper.getString(PreferenceKeys.EXTERNAL_DOWNLOAD_PROVIDER, "") + + if (externalProviderPackageName.isBlank()) { + val downloadPlaylistDialog = DownloadPlaylistDialog().apply { + arguments = bundleOf( + IntentData.playlistId to playlistId, + IntentData.playlistName to playlistName, + IntentData.playlistType to playlistType + ) + } + downloadPlaylistDialog.show(fragmentManager, null) + } else { + val intent = Intent(Intent.ACTION_VIEW) + .setPackage(externalProviderPackageName) + .setDataAndType("${ShareDialog.YOUTUBE_FRONTEND_URL}/playlist?list=$playlistId".toUri(), videoMimeType) + + runCatching { context.startActivity(intent) } + } + } } diff --git a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt index 20e2572db7..b48dc5930f 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt @@ -72,6 +72,7 @@ import com.github.libretube.extensions.togglePlayPauseState import com.github.libretube.extensions.updateIfChanged import com.github.libretube.extensions.updateParameters import com.github.libretube.helpers.BackgroundHelper +import com.github.libretube.helpers.DownloadHelper import com.github.libretube.helpers.ImageHelper import com.github.libretube.helpers.IntentHelper import com.github.libretube.helpers.NavBarHelper @@ -92,7 +93,6 @@ import com.github.libretube.ui.activities.MainActivity import com.github.libretube.ui.adapters.VideosAdapter import com.github.libretube.ui.base.BaseActivity import com.github.libretube.ui.dialogs.AddToPlaylistDialog -import com.github.libretube.ui.dialogs.DownloadDialog import com.github.libretube.ui.dialogs.ShareDialog import com.github.libretube.ui.extensions.animateDown import com.github.libretube.ui.extensions.setupSubscriptionButton @@ -625,9 +625,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions { if (streams.duration <= 0) { Toast.makeText(context, R.string.cannotDownload, Toast.LENGTH_SHORT).show() } else { - val newFragment = DownloadDialog() - newFragment.arguments = bundleOf(IntentData.videoId to videoId) - newFragment.show(childFragmentManager, DownloadDialog::class.java.name) + DownloadHelper.startDownloadDialog(requireContext(), childFragmentManager, videoId) } } diff --git a/app/src/main/java/com/github/libretube/ui/sheets/PlaylistOptionsBottomSheet.kt b/app/src/main/java/com/github/libretube/ui/sheets/PlaylistOptionsBottomSheet.kt index cd9e864c49..9581310529 100644 --- a/app/src/main/java/com/github/libretube/ui/sheets/PlaylistOptionsBottomSheet.kt +++ b/app/src/main/java/com/github/libretube/ui/sheets/PlaylistOptionsBottomSheet.kt @@ -13,10 +13,10 @@ import com.github.libretube.extensions.serializable import com.github.libretube.extensions.toID import com.github.libretube.extensions.toastFromMainDispatcher import com.github.libretube.helpers.BackgroundHelper +import com.github.libretube.helpers.DownloadHelper import com.github.libretube.obj.ShareData import com.github.libretube.ui.base.BaseActivity import com.github.libretube.ui.dialogs.DeletePlaylistDialog -import com.github.libretube.ui.dialogs.DownloadPlaylistDialog import com.github.libretube.ui.dialogs.PlaylistDescriptionDialog import com.github.libretube.ui.dialogs.RenamePlaylistDialog import com.github.libretube.ui.dialogs.ShareDialog @@ -139,14 +139,7 @@ class PlaylistOptionsBottomSheet : BaseBottomSheet() { } R.string.download -> { - val downloadPlaylistDialog = DownloadPlaylistDialog().apply { - arguments = bundleOf( - IntentData.playlistId to playlistId, - IntentData.playlistName to playlistName, - IntentData.playlistType to playlistType - ) - } - downloadPlaylistDialog.show(mFragmentManager, null) + DownloadHelper.startDownloadPlaylistDialog(requireContext(), mFragmentManager, playlistId, playlistName, playlistType) } else -> { diff --git a/app/src/main/java/com/github/libretube/ui/sheets/VideoOptionsBottomSheet.kt b/app/src/main/java/com/github/libretube/ui/sheets/VideoOptionsBottomSheet.kt index e37f349412..ffbf7eec56 100644 --- a/app/src/main/java/com/github/libretube/ui/sheets/VideoOptionsBottomSheet.kt +++ b/app/src/main/java/com/github/libretube/ui/sheets/VideoOptionsBottomSheet.kt @@ -15,13 +15,13 @@ import com.github.libretube.enums.ShareObjectType import com.github.libretube.extensions.parcelable import com.github.libretube.extensions.toID import com.github.libretube.helpers.BackgroundHelper +import com.github.libretube.helpers.DownloadHelper import com.github.libretube.helpers.NavigationHelper import com.github.libretube.helpers.PlayerHelper import com.github.libretube.helpers.PreferenceHelper import com.github.libretube.obj.ShareData import com.github.libretube.ui.activities.MainActivity import com.github.libretube.ui.dialogs.AddToPlaylistDialog -import com.github.libretube.ui.dialogs.DownloadDialog import com.github.libretube.ui.dialogs.ShareDialog import com.github.libretube.ui.fragments.SubscriptionsFragment import com.github.libretube.util.PlayingQueue @@ -71,9 +71,7 @@ class VideoOptionsBottomSheet : BaseBottomSheet() { } R.string.download -> { - val newFragment = DownloadDialog() - newFragment.arguments = bundleOf(IntentData.videoId to videoId) - newFragment.show(parentFragmentManager, DownloadDialog::class.java.name) + DownloadHelper.startDownloadDialog(requireContext(), parentFragmentManager, videoId) } R.string.share -> { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 58d879af8b..1ee39ddb6c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -506,6 +506,8 @@ %.2f%% uptime Change Gestures + External download provider + Enter the package name of the app you want to use for downloading videos. Leave blank to use LibreTube\'s inbuilt downloader. Download Service diff --git a/app/src/main/res/xml/advanced_settings.xml b/app/src/main/res/xml/advanced_settings.xml index dba5d608ca..3b72725aaf 100644 --- a/app/src/main/res/xml/advanced_settings.xml +++ b/app/src/main/res/xml/advanced_settings.xml @@ -26,15 +26,6 @@ app:key="play_automatically" app:title="@string/play_automatically" /> - - + + + + + + + +