Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: download popup that can be displayed over other apps #6034

Merged
merged 1 commit into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 26 additions & 10 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<application
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"
Expand All @@ -32,7 +33,6 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/StartupTheme"
android:enableOnBackInvokedCallback="true"
tools:targetApi="tiramisu">

<activity
Expand Down Expand Up @@ -79,6 +79,22 @@

</activity>

<activity
android:name=".ui.activities.DownloadActivity"
android:enabled="true"
android:exported="true"
android:label="@string/download"
android:launchMode="singleTop"
android:theme="@style/Theme.Material3.DayNight.Dialog">

<intent-filter android:label="@string/download">
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>

</activity>

<activity
android:name=".ui.activities.OfflinePlayerActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
Expand Down Expand Up @@ -356,27 +372,27 @@

<service
android:name=".services.DownloadService"
android:foregroundServiceType="dataSync"
android:enabled="true"
android:exported="false" />
android:exported="false"
android:foregroundServiceType="dataSync" />

<service
android:name=".services.PlaylistDownloadEnqueueService"
android:foregroundServiceType="dataSync"
android:enabled="true"
android:exported="false" />
android:exported="false"
android:foregroundServiceType="dataSync" />

<service
android:name=".services.OnlinePlayerService"
android:foregroundServiceType="mediaPlayback"
android:enabled="true"
android:exported="false" />
android:exported="false"
android:foregroundServiceType="mediaPlayback" />

<service
android:name=".services.OfflinePlayerService"
android:foregroundServiceType="mediaPlayback"
android:enabled="true"
android:exported="false" />
android:exported="false"
android:foregroundServiceType="mediaPlayback" />

<receiver
android:name=".receivers.NotificationReceiver"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import com.github.libretube.obj.NewPipeSubscriptions
import com.github.libretube.obj.PipedImportPlaylist
import com.github.libretube.obj.PipedPlaylistFile
import com.github.libretube.ui.dialogs.ShareDialog
import com.github.libretube.util.TextUtils
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.decodeFromStream
import kotlinx.serialization.json.encodeToStream
import java.util.Date
import java.util.stream.Collectors

object ImportHelper {
Expand Down Expand Up @@ -182,7 +182,7 @@ object ImportHelper {

val playlistName = lines[1].split(",").reversed().getOrNull(2)
// the playlist name can be undefined in some cases, e.g. watch later lists
playlist.name = playlistName ?: Date().toString()
playlist.name = playlistName ?: TextUtils.defaultPlaylistName

// start directly at the beginning if header playlist info such as name is missing
val startIndex = if (playlistName == null) {
Expand Down
33 changes: 33 additions & 0 deletions app/src/main/java/com/github/libretube/helpers/IntentHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.github.libretube.constants.IntentData
import com.github.libretube.extensions.toastFromMainThread
import com.github.libretube.ui.sheets.IntentChooserSheet
import com.github.libretube.util.TextUtils.toTimeInSeconds

object IntentHelper {
private fun getResolveIntent(link: String) = Intent(Intent.ACTION_VIEW)
Expand Down Expand Up @@ -67,4 +68,36 @@
Toast.makeText(context, R.string.no_player_found, Toast.LENGTH_SHORT).show()
}
}

/**
* Resolve the uri and return a bundle with the arguments
*/
fun resolveType(intent: Intent, uri: Uri) = with(intent) {

Check failure on line 75 in app/src/main/java/com/github/libretube/helpers/IntentHelper.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 Newline expected after opening parenthesis Raw Output: app/src/main/java/com/github/libretube/helpers/IntentHelper.kt:75:21: error: Newline expected after opening parenthesis (standard:function-signature)

Check failure on line 75 in app/src/main/java/com/github/libretube/helpers/IntentHelper.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 Parameter should start on a newline Raw Output: app/src/main/java/com/github/libretube/helpers/IntentHelper.kt:75:37: error: Parameter should start on a newline (standard:function-signature)

Check failure on line 75 in app/src/main/java/com/github/libretube/helpers/IntentHelper.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 Newline expected before closing parenthesis Raw Output: app/src/main/java/com/github/libretube/helpers/IntentHelper.kt:75:45: error: Newline expected before closing parenthesis (standard:function-signature)

Check failure on line 75 in app/src/main/java/com/github/libretube/helpers/IntentHelper.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 A multiline expression should start on a new line Raw Output: app/src/main/java/com/github/libretube/helpers/IntentHelper.kt:75:49: error: A multiline expression should start on a new line (standard:multiline-expression-wrapping)

Check failure on line 75 in app/src/main/java/com/github/libretube/helpers/IntentHelper.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 Newline expected before expression body Raw Output: app/src/main/java/com/github/libretube/helpers/IntentHelper.kt:75:49: error: Newline expected before expression body (standard:function-signature)
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())
}
}
}
}
4 changes: 4 additions & 0 deletions app/src/main/java/com/github/libretube/helpers/ThemeHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
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

Expand All @@ -15,31 +16,23 @@
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, "")
}
}
if (
uri.path!!.contains("/watch") && uri.query != null
) {
videoId = uri.getQueryParameter("v")
}
val videoId = intent.getStringExtra(Intent.EXTRA_TEXT)

Check failure on line 19 in app/src/main/java/com/github/libretube/ui/activities/AddToQueueActivity.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 A multiline expression should start on a new line Raw Output: app/src/main/java/com/github/libretube/ui/activities/AddToQueueActivity.kt:19:23: error: A multiline expression should start on a new line (standard:multiline-expression-wrapping)
?.let { IntentHelper.resolveType(Intent(), it.toUri()) }
?.getStringExtra(IntentData.videoId)

if (videoId == null) videoId = uri.path!!.replace("/", "")
if (videoId != null) {
val newIntent = packageManager.getLaunchIntentForPackage(packageName)

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 {
newIntent?.putExtra(IntentData.videoId, videoId)
}

// 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(newIntent)
}

startActivity(intent)
finishAndRemoveTask()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.github.libretube.ui.activities

import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

Check failure on line 5 in app/src/main/java/com/github/libretube/ui/activities/DownloadActivity.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 Unused import Raw Output: app/src/main/java/com/github/libretube/ui/activities/DownloadActivity.kt:5:1: error: Unused import (standard:no-unused-imports)
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

Check failure on line 11 in app/src/main/java/com/github/libretube/ui/activities/DownloadActivity.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 Unused import Raw Output: app/src/main/java/com/github/libretube/ui/activities/DownloadActivity.kt:11:1: error: Unused import (standard:no-unused-imports)
import com.github.libretube.ui.base.BaseActivity
import com.github.libretube.ui.dialogs.DownloadDialog
import com.github.libretube.ui.dialogs.DownloadPlaylistDialog

class DownloadActivity: BaseActivity() {

Check failure on line 16 in app/src/main/java/com/github/libretube/ui/activities/DownloadActivity.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 Missing spacing before ":" Raw Output: app/src/main/java/com/github/libretube/ui/activities/DownloadActivity.kt:16:23: error: Missing spacing before ":" (standard:colon-spacing)
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()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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?) {
Expand All @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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)!!
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/com/github/libretube/util/TextUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down
Loading
Loading