feat: support for external download apps

This commit is contained in:
Bnyro 2024-05-26 19:35:20 +02:00
parent 58f9878baa
commit 1b6e8fe27d
7 changed files with 81 additions and 27 deletions

View File

@ -144,6 +144,7 @@ object PreferenceKeys {
const val CONFIRM_UNSUBSCRIBE = "confirm_unsubscribing" const val CONFIRM_UNSUBSCRIBE = "confirm_unsubscribing"
const val CLEAR_BOOKMARKS = "clear_bookmarks" const val CLEAR_BOOKMARKS = "clear_bookmarks"
const val MAX_CONCURRENT_DOWNLOADS = "max_parallel_downloads" 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 DISABLE_VIDEO_IMAGE_PROXY = "disable_video_image_proxy"
const val CONTRIBUTE_TO_SB = "sb_contribute_key" const val CONTRIBUTE_TO_SB = "sb_contribute_key"
const val CONTRIBUTE_TO_DEARROW = "dearrow_contribute_key" const val CONTRIBUTE_TO_DEARROW = "dearrow_contribute_key"

View File

@ -4,11 +4,18 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Build import android.os.Build
import androidx.core.content.ContextCompat 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.IntentData
import com.github.libretube.constants.PreferenceKeys import com.github.libretube.constants.PreferenceKeys
import com.github.libretube.db.obj.DownloadItem import com.github.libretube.db.obj.DownloadItem
import com.github.libretube.enums.PlaylistType
import com.github.libretube.parcelable.DownloadData import com.github.libretube.parcelable.DownloadData
import com.github.libretube.services.DownloadService 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 java.nio.file.Path
import kotlin.io.path.createDirectories import kotlin.io.path.createDirectories
import kotlin.io.path.div import kotlin.io.path.div
@ -17,11 +24,11 @@ object DownloadHelper {
const val VIDEO_DIR = "video" const val VIDEO_DIR = "video"
const val AUDIO_DIR = "audio" const val AUDIO_DIR = "audio"
const val SUBTITLE_DIR = "subtitle" const val SUBTITLE_DIR = "subtitle"
const val METADATA_DIR = "metadata"
const val THUMBNAIL_DIR = "thumbnail" const val THUMBNAIL_DIR = "thumbnail"
const val DOWNLOAD_CHUNK_SIZE = 8L * 1024 const val DOWNLOAD_CHUNK_SIZE = 8L * 1024
const val DEFAULT_TIMEOUT = 15 * 1000 const val DEFAULT_TIMEOUT = 15 * 1000
const val DEFAULT_RETRY = 3 const val DEFAULT_RETRY = 3
private const val videoMimeType = "video/*"
fun getDownloadDir(context: Context, path: String): Path { fun getDownloadDir(context: Context, path: String): Path {
val storageDir = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { val storageDir = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
@ -53,4 +60,49 @@ object DownloadHelper {
fun DownloadItem.getNotificationId(): Int { fun DownloadItem.getNotificationId(): Int {
return Int.MAX_VALUE - id 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) }
}
}
} }

View File

@ -72,6 +72,7 @@ import com.github.libretube.extensions.togglePlayPauseState
import com.github.libretube.extensions.updateIfChanged import com.github.libretube.extensions.updateIfChanged
import com.github.libretube.extensions.updateParameters import com.github.libretube.extensions.updateParameters
import com.github.libretube.helpers.BackgroundHelper import com.github.libretube.helpers.BackgroundHelper
import com.github.libretube.helpers.DownloadHelper
import com.github.libretube.helpers.ImageHelper import com.github.libretube.helpers.ImageHelper
import com.github.libretube.helpers.IntentHelper import com.github.libretube.helpers.IntentHelper
import com.github.libretube.helpers.NavBarHelper 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.adapters.VideosAdapter
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 com.github.libretube.ui.dialogs.DownloadDialog
import com.github.libretube.ui.dialogs.ShareDialog import com.github.libretube.ui.dialogs.ShareDialog
import com.github.libretube.ui.extensions.animateDown import com.github.libretube.ui.extensions.animateDown
import com.github.libretube.ui.extensions.setupSubscriptionButton import com.github.libretube.ui.extensions.setupSubscriptionButton
@ -625,9 +625,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
if (streams.duration <= 0) { if (streams.duration <= 0) {
Toast.makeText(context, R.string.cannotDownload, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.cannotDownload, Toast.LENGTH_SHORT).show()
} else { } else {
val newFragment = DownloadDialog() DownloadHelper.startDownloadDialog(requireContext(), childFragmentManager, videoId)
newFragment.arguments = bundleOf(IntentData.videoId to videoId)
newFragment.show(childFragmentManager, DownloadDialog::class.java.name)
} }
} }

View File

@ -13,10 +13,10 @@ import com.github.libretube.extensions.serializable
import com.github.libretube.extensions.toID import com.github.libretube.extensions.toID
import com.github.libretube.extensions.toastFromMainDispatcher import com.github.libretube.extensions.toastFromMainDispatcher
import com.github.libretube.helpers.BackgroundHelper import com.github.libretube.helpers.BackgroundHelper
import com.github.libretube.helpers.DownloadHelper
import com.github.libretube.obj.ShareData import com.github.libretube.obj.ShareData
import com.github.libretube.ui.base.BaseActivity import com.github.libretube.ui.base.BaseActivity
import com.github.libretube.ui.dialogs.DeletePlaylistDialog 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.PlaylistDescriptionDialog
import com.github.libretube.ui.dialogs.RenamePlaylistDialog import com.github.libretube.ui.dialogs.RenamePlaylistDialog
import com.github.libretube.ui.dialogs.ShareDialog import com.github.libretube.ui.dialogs.ShareDialog
@ -139,14 +139,7 @@ class PlaylistOptionsBottomSheet : BaseBottomSheet() {
} }
R.string.download -> { R.string.download -> {
val downloadPlaylistDialog = DownloadPlaylistDialog().apply { DownloadHelper.startDownloadPlaylistDialog(requireContext(), mFragmentManager, playlistId, playlistName, playlistType)
arguments = bundleOf(
IntentData.playlistId to playlistId,
IntentData.playlistName to playlistName,
IntentData.playlistType to playlistType
)
}
downloadPlaylistDialog.show(mFragmentManager, null)
} }
else -> { else -> {

View File

@ -15,13 +15,13 @@ import com.github.libretube.enums.ShareObjectType
import com.github.libretube.extensions.parcelable import com.github.libretube.extensions.parcelable
import com.github.libretube.extensions.toID import com.github.libretube.extensions.toID
import com.github.libretube.helpers.BackgroundHelper import com.github.libretube.helpers.BackgroundHelper
import com.github.libretube.helpers.DownloadHelper
import com.github.libretube.helpers.NavigationHelper import com.github.libretube.helpers.NavigationHelper
import com.github.libretube.helpers.PlayerHelper import com.github.libretube.helpers.PlayerHelper
import com.github.libretube.helpers.PreferenceHelper import com.github.libretube.helpers.PreferenceHelper
import com.github.libretube.obj.ShareData import com.github.libretube.obj.ShareData
import com.github.libretube.ui.activities.MainActivity import com.github.libretube.ui.activities.MainActivity
import com.github.libretube.ui.dialogs.AddToPlaylistDialog 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.dialogs.ShareDialog
import com.github.libretube.ui.fragments.SubscriptionsFragment import com.github.libretube.ui.fragments.SubscriptionsFragment
import com.github.libretube.util.PlayingQueue import com.github.libretube.util.PlayingQueue
@ -71,9 +71,7 @@ class VideoOptionsBottomSheet : BaseBottomSheet() {
} }
R.string.download -> { R.string.download -> {
val newFragment = DownloadDialog() DownloadHelper.startDownloadDialog(requireContext(), parentFragmentManager, videoId)
newFragment.arguments = bundleOf(IntentData.videoId to videoId)
newFragment.show(parentFragmentManager, DownloadDialog::class.java.name)
} }
R.string.share -> { R.string.share -> {

View File

@ -506,6 +506,8 @@
<string name="uptime">%.2f%% uptime</string> <string name="uptime">%.2f%% uptime</string>
<string name="change">Change</string> <string name="change">Change</string>
<string name="gestures">Gestures</string> <string name="gestures">Gestures</string>
<string name="external_download_provider">External download provider</string>
<string name="external_download_provider_summary">Enter the package name of the app you want to use for downloading videos. Leave blank to use LibreTube\'s inbuilt downloader.</string>
<!-- Notification channel strings --> <!-- Notification channel strings -->
<string name="download_channel_name">Download Service</string> <string name="download_channel_name">Download Service</string>

View File

@ -26,15 +26,6 @@
app:key="play_automatically" app:key="play_automatically"
app:title="@string/play_automatically" /> app:title="@string/play_automatically" />
<com.github.libretube.ui.views.SliderPreference
android:icon="@drawable/ic_download"
android:key="max_parallel_downloads"
android:title="@string/concurrent_downloads"
app:defValue="6"
app:stepSize="1"
app:valueFrom="1"
app:valueTo="6" />
<ListPreference <ListPreference
android:entries="@array/cacheSize" android:entries="@array/cacheSize"
android:entryValues="@array/cacheSizeValues" android:entryValues="@array/cacheSizeValues"
@ -58,6 +49,25 @@
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory app:title="@string/downloads">
<com.github.libretube.ui.views.SliderPreference
android:icon="@drawable/ic_download"
android:key="max_parallel_downloads"
android:title="@string/concurrent_downloads"
app:defValue="6"
app:stepSize="1"
app:valueFrom="1"
app:valueTo="6" />
<EditTextPreference
android:icon="@drawable/ic_open"
android:key="external_download_provider"
android:summary="@string/external_download_provider_summary"
android:title="@string/external_download_provider" />
</PreferenceCategory>
<PreferenceCategory app:title="@string/misc"> <PreferenceCategory app:title="@string/misc">
<Preference <Preference