From f60948696ef2c944e8775001712c13daee065384 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Tue, 14 May 2024 21:51:03 +0200 Subject: [PATCH] feat: download popup that can be displayed over other apps --- app/src/main/AndroidManifest.xml | 36 ++++++++++----- .../github/libretube/helpers/ImportHelper.kt | 4 +- .../github/libretube/helpers/IntentHelper.kt | 33 ++++++++++++++ .../github/libretube/helpers/ThemeHelper.kt | 4 ++ .../ui/activities/AddToQueueActivity.kt | 37 +++++++--------- .../ui/activities/DownloadActivity.kt | 44 +++++++++++++++++++ .../libretube/ui/activities/RouterActivity.kt | 39 ++-------------- .../github/libretube/ui/base/BaseActivity.kt | 3 ++ .../ui/dialogs/DownloadPlaylistDialog.kt | 3 +- .../ui/dialogs/ImportTempPlaylistDialog.kt | 4 +- .../com/github/libretube/util/TextUtils.kt | 3 ++ app/src/main/res/values/themes.xml | 29 ++++++++++++ 12 files changed, 167 insertions(+), 72 deletions(-) create mode 100644 app/src/main/java/com/github/libretube/ui/activities/DownloadActivity.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e4df93379..1c6d44f23 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,7 +15,7 @@ - + @@ -23,6 +23,7 @@ android:name=".LibreTubeApp" android:allowBackup="true" android:banner="@mipmap/ic_launcher" + android:enableOnBackInvokedCallback="true" android:hardwareAccelerated="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" @@ -32,7 +33,6 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/StartupTheme" - android:enableOnBackInvokedCallback="true" tools:targetApi="tiramisu"> + + + + + + + + + + + android:exported="false" + android:foregroundServiceType="dataSync" /> + android:exported="false" + android:foregroundServiceType="dataSync" /> + android:exported="false" + android:foregroundServiceType="mediaPlayback" /> + android:exported="false" + android:foregroundServiceType="mediaPlayback" /> { + putExtra(IntentData.query, uri.getQueryParameter("search_query")) + } + secondLastSegment == "channel" -> { + putExtra(IntentData.channelId, lastSegment) + } + secondLastSegment == "c" || secondLastSegment == "user" -> { + putExtra(IntentData.channelName, lastSegment) + } + lastSegment == "playlist" -> { + putExtra(IntentData.playlistId, uri.getQueryParameter("list")) + } + lastSegment == "watch_videos" -> { + putExtra(IntentData.playlistName, uri.getQueryParameter("title")) + val videoIds = uri.getQueryParameter("video_ids")?.split(",") + putExtra(IntentData.videoIds, videoIds?.toTypedArray()) + } + else -> { + val id = if (lastSegment == "watch") uri.getQueryParameter("v") else lastSegment + putExtra(IntentData.videoId, id) + putExtra(IntentData.timeStamp, uri.getQueryParameter("t")?.toTimeInSeconds()) + } + } + } } diff --git a/app/src/main/java/com/github/libretube/helpers/ThemeHelper.kt b/app/src/main/java/com/github/libretube/helpers/ThemeHelper.kt index a8c4dc97d..4e362e180 100644 --- a/app/src/main/java/com/github/libretube/helpers/ThemeHelper.kt +++ b/app/src/main/java/com/github/libretube/helpers/ThemeHelper.kt @@ -112,6 +112,10 @@ object ThemeHelper { if (pureThemeEnabled) activity.theme.applyStyle(R.style.Pure, true) } + fun applyDialogActivityTheme(activity: Activity) { + activity.theme.applyStyle(R.style.DialogActivity, true) + } + /** * set the theme mode (light, dark, auto) */ diff --git a/app/src/main/java/com/github/libretube/ui/activities/AddToQueueActivity.kt b/app/src/main/java/com/github/libretube/ui/activities/AddToQueueActivity.kt index 982db410e..f3b5225ed 100644 --- a/app/src/main/java/com/github/libretube/ui/activities/AddToQueueActivity.kt +++ b/app/src/main/java/com/github/libretube/ui/activities/AddToQueueActivity.kt @@ -4,6 +4,7 @@ import android.content.Intent import android.os.Bundle import androidx.core.net.toUri import com.github.libretube.constants.IntentData +import com.github.libretube.helpers.IntentHelper import com.github.libretube.ui.base.BaseActivity import com.github.libretube.util.PlayingQueue @@ -15,31 +16,23 @@ class AddToQueueActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val uri = intent.getStringExtra(Intent.EXTRA_TEXT)!!.toUri() - var videoId: String? = null - listOf("/shorts/", "/v/", "/embed/").forEach { - if (uri.path!!.contains(it)) { - videoId = uri.path!!.replace(it, "") + val videoId = intent.getStringExtra(Intent.EXTRA_TEXT) + ?.let { IntentHelper.resolveType(Intent(), it.toUri()) } + ?.getStringExtra(IntentData.videoId) + + if (videoId != null) { + val newIntent = packageManager.getLaunchIntentForPackage(packageName) + + // if playing a video currently, the video will be added to the queue + if (PlayingQueue.isNotEmpty()) { + PlayingQueue.insertByVideoId(videoId) + } else { + newIntent?.putExtra(IntentData.videoId, videoId) } - } - if ( - uri.path!!.contains("/watch") && uri.query != null - ) { - videoId = uri.getQueryParameter("v") + + startActivity(newIntent) } - if (videoId == null) videoId = uri.path!!.replace("/", "") - - val intent = packageManager.getLaunchIntentForPackage(packageName) - - // if playing a video currently, the video will be added to the queue - if (PlayingQueue.isNotEmpty()) { - PlayingQueue.insertByVideoId(videoId!!) - } else { - intent?.putExtra(IntentData.videoId, videoId) - } - - startActivity(intent) finishAndRemoveTask() } } diff --git a/app/src/main/java/com/github/libretube/ui/activities/DownloadActivity.kt b/app/src/main/java/com/github/libretube/ui/activities/DownloadActivity.kt new file mode 100644 index 000000000..7e5454f36 --- /dev/null +++ b/app/src/main/java/com/github/libretube/ui/activities/DownloadActivity.kt @@ -0,0 +1,44 @@ +package com.github.libretube.ui.activities + +import android.content.Intent +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.core.net.toUri +import androidx.core.os.bundleOf +import com.github.libretube.constants.IntentData +import com.github.libretube.enums.PlaylistType +import com.github.libretube.helpers.IntentHelper +import com.github.libretube.helpers.ThemeHelper +import com.github.libretube.ui.base.BaseActivity +import com.github.libretube.ui.dialogs.DownloadDialog +import com.github.libretube.ui.dialogs.DownloadPlaylistDialog + +class DownloadActivity: BaseActivity() { + override val isDialogActivity: Boolean = true + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val intentData = intent.getStringExtra(Intent.EXTRA_TEXT)?.let { + IntentHelper.resolveType(Intent(), it.toUri()) + } + + val videoId = intentData?.getStringExtra(IntentData.videoId) + val playlistId = intentData?.getStringExtra(IntentData.playlistId) + if (videoId != null) { + DownloadDialog().apply { + arguments = bundleOf(IntentData.videoId to videoId) + }.show(supportFragmentManager, null) + } else if (playlistId != null) { + DownloadPlaylistDialog().apply { + arguments = bundleOf( + IntentData.playlistId to playlistId, + IntentData.playlistType to PlaylistType.PUBLIC, + IntentData.playlistName to intent.getStringExtra(Intent.EXTRA_TITLE) + ) + }.show(supportFragmentManager, null) + } else { + finishAndRemoveTask() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/libretube/ui/activities/RouterActivity.kt b/app/src/main/java/com/github/libretube/ui/activities/RouterActivity.kt index e7d619db6..89d7068a4 100644 --- a/app/src/main/java/com/github/libretube/ui/activities/RouterActivity.kt +++ b/app/src/main/java/com/github/libretube/ui/activities/RouterActivity.kt @@ -5,11 +5,10 @@ import android.net.Uri import android.os.Bundle import android.util.Log import androidx.core.net.toUri -import com.github.libretube.constants.IntentData import com.github.libretube.extensions.TAG +import com.github.libretube.helpers.IntentHelper import com.github.libretube.helpers.NavigationHelper import com.github.libretube.ui.base.BaseActivity -import com.github.libretube.util.TextUtils.toTimeInSeconds class RouterActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -25,42 +24,12 @@ class RouterActivity : BaseActivity() { } } - /** - * Resolve the uri and return a bundle with the arguments - */ - private fun Intent.resolveType(uri: Uri) = apply { - val lastSegment = uri.lastPathSegment - val secondLastSegment = uri.pathSegments.getOrNull(uri.pathSegments.size - 2) - when { - lastSegment == "results" -> { - putExtra(IntentData.query, uri.getQueryParameter("search_query")) - } - secondLastSegment == "channel" -> { - putExtra(IntentData.channelId, lastSegment) - } - secondLastSegment == "c" || secondLastSegment == "user" -> { - putExtra(IntentData.channelName, lastSegment) - } - lastSegment == "playlist" -> { - putExtra(IntentData.playlistId, uri.getQueryParameter("list")) - } - lastSegment == "watch_videos" -> { - putExtra(IntentData.playlistName, uri.getQueryParameter("title")) - val videoIds = uri.getQueryParameter("video_ids")?.split(",") - putExtra(IntentData.videoIds, videoIds?.toTypedArray()) - } - else -> { - val id = if (lastSegment == "watch") uri.getQueryParameter("v") else lastSegment - putExtra(IntentData.videoId, id) - putExtra(IntentData.timeStamp, uri.getQueryParameter("t")?.toTimeInSeconds()) - } - } - } - private fun handleSendText(uri: Uri) { Log.i(TAG(), uri.toString()) - val intent = packageManager.getLaunchIntentForPackage(packageName)!!.resolveType(uri) + val intent = packageManager.getLaunchIntentForPackage(packageName)!!.let { intent -> + IntentHelper.resolveType(intent, uri) + } intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK startActivity(intent) finishAndRemoveTask() diff --git a/app/src/main/java/com/github/libretube/ui/base/BaseActivity.kt b/app/src/main/java/com/github/libretube/ui/base/BaseActivity.kt index cfe1dadd7..31f3ea2d2 100644 --- a/app/src/main/java/com/github/libretube/ui/base/BaseActivity.kt +++ b/app/src/main/java/com/github/libretube/ui/base/BaseActivity.kt @@ -15,6 +15,8 @@ import com.github.libretube.helpers.WindowHelper * Activity that applies the LibreTube theme and the in-app language */ open class BaseActivity : AppCompatActivity() { + open val isDialogActivity: Boolean = false + val screenOrientationPref by lazy { val orientationPref = PreferenceHelper.getString( PreferenceKeys.ORIENTATION, @@ -36,6 +38,7 @@ open class BaseActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { // set the app theme (e.g. Material You) ThemeHelper.updateTheme(this) + if (isDialogActivity) ThemeHelper.applyDialogActivityTheme(this) // Set the navigation and statusBar color if SDK < 23 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { diff --git a/app/src/main/java/com/github/libretube/ui/dialogs/DownloadPlaylistDialog.kt b/app/src/main/java/com/github/libretube/ui/dialogs/DownloadPlaylistDialog.kt index 1ad9a4ed0..a8e0082a0 100644 --- a/app/src/main/java/com/github/libretube/ui/dialogs/DownloadPlaylistDialog.kt +++ b/app/src/main/java/com/github/libretube/ui/dialogs/DownloadPlaylistDialog.kt @@ -14,6 +14,7 @@ import com.github.libretube.extensions.getWhileDigit import com.github.libretube.extensions.serializable import com.github.libretube.helpers.LocaleHelper import com.github.libretube.services.PlaylistDownloadEnqueueService +import com.github.libretube.util.TextUtils import com.google.android.material.dialog.MaterialAlertDialogBuilder class DownloadPlaylistDialog : DialogFragment() { @@ -25,7 +26,7 @@ class DownloadPlaylistDialog : DialogFragment() { super.onCreate(savedInstanceState) playlistId = requireArguments().getString(IntentData.playlistId)!! - playlistName = requireArguments().getString(IntentData.playlistName)!! + playlistName = requireArguments().getString(IntentData.playlistName) ?: TextUtils.defaultPlaylistName playlistType = requireArguments().serializable(IntentData.playlistType)!! } diff --git a/app/src/main/java/com/github/libretube/ui/dialogs/ImportTempPlaylistDialog.kt b/app/src/main/java/com/github/libretube/ui/dialogs/ImportTempPlaylistDialog.kt index 07eea9138..502818570 100644 --- a/app/src/main/java/com/github/libretube/ui/dialogs/ImportTempPlaylistDialog.kt +++ b/app/src/main/java/com/github/libretube/ui/dialogs/ImportTempPlaylistDialog.kt @@ -10,17 +10,17 @@ import com.github.libretube.constants.IntentData import com.github.libretube.extensions.TAG import com.github.libretube.extensions.toastFromMainDispatcher import com.github.libretube.obj.PipedImportPlaylist +import com.github.libretube.util.TextUtils import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import java.util.Date class ImportTempPlaylistDialog : DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val title = arguments?.getString(IntentData.playlistName) ?.takeIf { it.isNotEmpty() } - ?: Date().toString() + ?: TextUtils.defaultPlaylistName val videoIds = arguments?.getStringArray(IntentData.videoIds).orEmpty() return MaterialAlertDialogBuilder(requireContext()) diff --git a/app/src/main/java/com/github/libretube/util/TextUtils.kt b/app/src/main/java/com/github/libretube/util/TextUtils.kt index 3d4666faa..ff84891f9 100644 --- a/app/src/main/java/com/github/libretube/util/TextUtils.kt +++ b/app/src/main/java/com/github/libretube/util/TextUtils.kt @@ -14,6 +14,7 @@ import java.time.ZoneId import java.time.format.DateTimeFormatter import java.time.format.FormatStyle import java.time.temporal.ChronoUnit +import java.util.Date import kotlin.time.Duration import kotlinx.datetime.LocalDate as KotlinLocalDate @@ -33,6 +34,8 @@ object TextUtils { */ private val MEDIUM_DATE_FORMATTER = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM) + val defaultPlaylistName get() = Date().toString() + /** * Localize the date from a date string, using the medium format. * @param date The date to parse diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 106fff2c7..c2093bae2 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -262,4 +262,33 @@ + + \ No newline at end of file