added remove audio feature and fixes on the finished download notification
|
|
@ -172,8 +172,29 @@
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<receiver android:name=".receiver.CancelDownloadNotificationReceiver" />
|
<receiver android:name=".receiver.CancelDownloadNotificationReceiver" />
|
||||||
<receiver android:name=".receiver.SharedDownloadNotificationReceiver" />
|
<activity
|
||||||
<receiver android:name=".receiver.OpenDownloadNotificationReceiver" />
|
android:name=".receiver.BlankActivity"
|
||||||
|
android:exported="true"
|
||||||
|
android:excludeFromRecents="true"
|
||||||
|
android:launchMode="singleInstance"
|
||||||
|
android:theme="@style/Theme.BottomSheet">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="ytdlnis.BlankActivity" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".receiver.SharedDownloadNotificationReceiver"
|
||||||
|
android:exported="true"
|
||||||
|
android:excludeFromRecents="true"
|
||||||
|
android:launchMode="singleInstance"
|
||||||
|
android:theme="@style/Theme.BottomSheet">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="ytdlnis.SharedDownloadNotificationReceiver" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
|
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
|
||||||
|
|
@ -188,6 +209,7 @@
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="com.deniscerri.ytdl.fileprovider"
|
android:authorities="com.deniscerri.ytdl.fileprovider"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
|
android:enabled="true"
|
||||||
android:grantUriPermissions="true">
|
android:grantUriPermissions="true">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
|
@ -13,7 +13,7 @@ data class DownloadItem(
|
||||||
var title: String,
|
var title: String,
|
||||||
var author: String,
|
var author: String,
|
||||||
var thumb: String,
|
var thumb: String,
|
||||||
val duration: String,
|
var duration: String,
|
||||||
var type: DownloadViewModel.Type,
|
var type: DownloadViewModel.Type,
|
||||||
var format: Format,
|
var format: Format,
|
||||||
@ColumnInfo(defaultValue = "")
|
@ColumnInfo(defaultValue = "")
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,6 @@ data class VideoPreferences (
|
||||||
var splitByChapters: Boolean = false,
|
var splitByChapters: Boolean = false,
|
||||||
var sponsorBlockFilters: ArrayList<String>,
|
var sponsorBlockFilters: ArrayList<String>,
|
||||||
var writeSubs: Boolean = false,
|
var writeSubs: Boolean = false,
|
||||||
var subsLanguages: String = "en.*,.*-orig"
|
var subsLanguages: String = "en.*,.*-orig",
|
||||||
|
var removeAudio: Boolean = false
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.deniscerri.ytdlnis.receiver
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.DialogInterface
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import android.graphics.drawable.ColorDrawable
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.Window
|
||||||
|
import android.view.WindowManager
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.WindowCompat
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.deniscerri.ytdlnis.MainActivity
|
||||||
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
|
import com.deniscerri.ytdlnis.database.viewmodel.CookieViewModel
|
||||||
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
|
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||||
|
import com.deniscerri.ytdlnis.ui.BaseActivity
|
||||||
|
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
|
||||||
|
import com.deniscerri.ytdlnis.ui.downloadcard.SelectPlaylistItemsBottomSheetDialog
|
||||||
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
|
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||||
|
import com.deniscerri.ytdlnis.util.ThemeUtil
|
||||||
|
import com.deniscerri.ytdlnis.util.UiUtil
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
class BlankActivity : BaseActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.blank)
|
||||||
|
val intent = intent
|
||||||
|
handleIntents(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNewIntent(intent: Intent) {
|
||||||
|
super.onNewIntent(intent)
|
||||||
|
handleIntents(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleIntents(intent: Intent) {
|
||||||
|
val message = intent.getStringExtra("message")
|
||||||
|
val path = intent.getStringExtra("path")
|
||||||
|
val notificationId = intent.getIntExtra("notificationID", 0)
|
||||||
|
if (message != null && path != null) {
|
||||||
|
if (notificationId != 0) NotificationUtil(this).cancelDownloadNotification(notificationId)
|
||||||
|
val uiUtil = UiUtil(FileUtil())
|
||||||
|
when(message) {
|
||||||
|
"share" -> {
|
||||||
|
uiUtil.shareFileIntent(this, listOf(path))
|
||||||
|
}
|
||||||
|
"open" -> {
|
||||||
|
uiUtil.openFileIntent(this, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
package com.deniscerri.ytdlnis.receiver
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.work.WorkManager
|
|
||||||
import com.deniscerri.ytdlnis.util.FileUtil
|
|
||||||
import com.deniscerri.ytdlnis.util.NotificationUtil
|
|
||||||
import com.deniscerri.ytdlnis.util.UiUtil
|
|
||||||
import com.yausername.youtubedl_android.YoutubeDL
|
|
||||||
|
|
||||||
class OpenDownloadNotificationReceiver : BroadcastReceiver() {
|
|
||||||
override fun onReceive(c: Context, intent: Intent) {
|
|
||||||
val message = intent.getStringExtra("open")
|
|
||||||
val path = intent.getStringExtra("path")
|
|
||||||
val notificationId = intent.getIntExtra("notificationID", 0)
|
|
||||||
if (message != null && path != null) {
|
|
||||||
if (notificationId != 0) NotificationUtil(c).cancelDownloadNotification(notificationId)
|
|
||||||
val uiUtil = UiUtil(FileUtil())
|
|
||||||
uiUtil.openFileIntent(c, path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
package com.deniscerri.ytdlnis.receiver
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import com.deniscerri.ytdlnis.util.FileUtil
|
|
||||||
import com.deniscerri.ytdlnis.util.NotificationUtil
|
|
||||||
import com.deniscerri.ytdlnis.util.UiUtil
|
|
||||||
|
|
||||||
class SharedDownloadNotificationReceiver : BroadcastReceiver() {
|
|
||||||
override fun onReceive(c: Context, intent: Intent) {
|
|
||||||
val message = intent.getStringExtra("share")
|
|
||||||
val path = intent.getStringExtra("path")
|
|
||||||
val notificationId = intent.getIntExtra("notificationID", 0)
|
|
||||||
if (message != null && path != null) {
|
|
||||||
if (notificationId != 0) NotificationUtil(c).cancelDownloadNotification(notificationId)
|
|
||||||
val uiUtil = UiUtil(FileUtil())
|
|
||||||
uiUtil.shareFileIntent(c, listOf(path))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.deniscerri.ytdlnis.receiver
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
|
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||||
|
import com.deniscerri.ytdlnis.util.UiUtil
|
||||||
|
|
||||||
|
class SharedDownloadNotificationReceiver : AppCompatActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.blank)
|
||||||
|
val intent = intent
|
||||||
|
val message = intent.getStringExtra("share")
|
||||||
|
val path = intent.getStringExtra("path")
|
||||||
|
val notificationId = intent.getIntExtra("notificationID", 0)
|
||||||
|
if (message != null && path != null) {
|
||||||
|
if (notificationId != 0) NotificationUtil(this).cancelDownloadNotification(notificationId)
|
||||||
|
val uiUtil = UiUtil(FileUtil())
|
||||||
|
uiUtil.shareFileIntent(this, listOf(path))
|
||||||
|
this.finishAffinity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -148,7 +148,7 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
}
|
}
|
||||||
items.forEachIndexed { index, it ->
|
items.forEachIndexed { index, it ->
|
||||||
it.allFormats.clear()
|
it.allFormats.clear()
|
||||||
it.allFormats.addAll(formatCollection[index])
|
if (formatCollection.isNotEmpty() && formatCollection[index].isNotEmpty()) it.allFormats.addAll(formatCollection[index])
|
||||||
it.format = selectedFormats[index]
|
it.format = selectedFormats[index]
|
||||||
}
|
}
|
||||||
listAdapter.submitList(items.toList())
|
listAdapter.submitList(items.toList())
|
||||||
|
|
|
||||||
|
|
@ -360,6 +360,11 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
dialog.getButton(AlertDialog.BUTTON_NEUTRAL).gravity = Gravity.START
|
dialog.getButton(AlertDialog.BUTTON_NEUTRAL).gravity = Gravity.START
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val removeAudio = view.findViewById<Chip>(R.id.remove_audio)
|
||||||
|
removeAudio.setOnCheckedChangeListener { compoundButton, b ->
|
||||||
|
downloadItem.videoPreferences.removeAudio = removeAudio.isChecked
|
||||||
|
}
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,11 @@ class FormatSelectionBottomSheetDialog(private val items: List<DownloadItem?>, p
|
||||||
formatCollection.forEach {
|
formatCollection.forEach {
|
||||||
selectedFormats.add(it.first{ f -> f.format_id == format.format_id})
|
selectedFormats.add(it.first{ f -> f.format_id == format.format_id})
|
||||||
}
|
}
|
||||||
|
if (selectedFormats.isEmpty()) {
|
||||||
|
items.forEach {
|
||||||
|
selectedFormats.add(format)
|
||||||
|
}
|
||||||
|
}
|
||||||
listener.onFormatClick(formatCollection, selectedFormats)
|
listener.onFormatClick(formatCollection, selectedFormats)
|
||||||
}
|
}
|
||||||
dismiss()
|
dismiss()
|
||||||
|
|
@ -220,7 +225,7 @@ class FormatSelectionBottomSheetDialog(private val items: List<DownloadItem?>, p
|
||||||
else {
|
else {
|
||||||
formatIdParent?.findViewById<TextView>(R.id.format_id_value)?.text = format.format_id
|
formatIdParent?.findViewById<TextView>(R.id.format_id_value)?.text = format.format_id
|
||||||
formatIdParent?.setOnClickListener {
|
formatIdParent?.setOnClickListener {
|
||||||
copyToClipboard(format.format_note)
|
copyToClipboard(format.format_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,14 +15,12 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.Window
|
import android.view.Window
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.EditText
|
import android.widget.*
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.ScrollView
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.view.forEach
|
import androidx.core.view.forEach
|
||||||
|
import androidx.core.view.get
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.work.*
|
import androidx.work.*
|
||||||
|
|
@ -86,31 +84,49 @@ class TerminalActivity : BaseActivity() {
|
||||||
|
|
||||||
|
|
||||||
bottomAppBar = findViewById(R.id.bottomAppBar)
|
bottomAppBar = findViewById(R.id.bottomAppBar)
|
||||||
|
var templateCount = 0
|
||||||
|
var shortcutCount = 0
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val templateCount = withContext(Dispatchers.IO){
|
templateCount = withContext(Dispatchers.IO){
|
||||||
commandTemplateViewModel.getTotalNumber()
|
commandTemplateViewModel.getTotalNumber()
|
||||||
}
|
}
|
||||||
if (templateCount == 0) bottomAppBar.menu.getItem(0).isEnabled = false
|
if (templateCount == 0){
|
||||||
|
bottomAppBar.menu.getItem(0).icon?.alpha = 30
|
||||||
|
}else{
|
||||||
|
bottomAppBar.menu.getItem(0).icon?.alpha = 255
|
||||||
|
}
|
||||||
|
|
||||||
val shortcutCount = withContext(Dispatchers.IO){
|
shortcutCount = withContext(Dispatchers.IO){
|
||||||
commandTemplateViewModel.getTotalShortcutNumber()
|
commandTemplateViewModel.getTotalShortcutNumber()
|
||||||
}
|
}
|
||||||
if (shortcutCount == 0) bottomAppBar.menu.getItem(1).isEnabled = false
|
if (shortcutCount == 0) {
|
||||||
|
bottomAppBar.menu.getItem(1).icon?.alpha = 30
|
||||||
|
}else{
|
||||||
|
bottomAppBar.menu.getItem(1).icon?.alpha = 255
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bottomAppBar.setOnMenuItemClickListener {
|
bottomAppBar.setOnMenuItemClickListener {
|
||||||
when(it.itemId){
|
when(it.itemId){
|
||||||
R.id.command_templates -> {
|
R.id.command_templates -> {
|
||||||
lifecycleScope.launch {
|
if (templateCount == 0){
|
||||||
uiUtil.showCommandTemplates(this@TerminalActivity, commandTemplateViewModel){ template ->
|
Toast.makeText(context, getString(R.string.add_template_first), Toast.LENGTH_SHORT).show()
|
||||||
input!!.text.insert(input!!.selectionStart, template.content + " ")
|
}else{
|
||||||
input!!.postDelayed({
|
lifecycleScope.launch {
|
||||||
input!!.requestFocus()
|
uiUtil.showCommandTemplates(this@TerminalActivity, commandTemplateViewModel){ template ->
|
||||||
imm.showSoftInput(input!!, 0)
|
input!!.text.insert(input!!.selectionStart, template.content + " ")
|
||||||
}, 200)
|
input!!.postDelayed({
|
||||||
|
input!!.requestFocus()
|
||||||
|
imm.showSoftInput(input!!, 0)
|
||||||
|
}, 200)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
R.id.shortcuts -> showShortcuts()
|
R.id.shortcuts -> {
|
||||||
|
if (shortcutCount > 0){
|
||||||
|
showShortcuts()
|
||||||
|
}
|
||||||
|
}
|
||||||
R.id.folder -> {
|
R.id.folder -> {
|
||||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||||
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||||
|
|
|
||||||
|
|
@ -310,7 +310,23 @@ class InfoUtil(private val context: Context) {
|
||||||
for (f in 0 until formatsInJSON.length()){
|
for (f in 0 until formatsInJSON.length()){
|
||||||
val format = formatsInJSON.getJSONObject(f)
|
val format = formatsInJSON.getJSONObject(f)
|
||||||
if(!format.has("container")) continue
|
if(!format.has("container")) continue
|
||||||
formats.add(Gson().fromJson(format.toString(), Format::class.java))
|
val formatObj = Gson().fromJson(format.toString(), Format::class.java)
|
||||||
|
try{
|
||||||
|
if (!formatObj.format_note.contains("audio", ignoreCase = true)){
|
||||||
|
val codecs = "\"([^\"]*)\"".toRegex().find(format.getString("type").split(";")[1])!!.value.split(",")
|
||||||
|
if (codecs.size > 1){
|
||||||
|
formatObj.vcodec = codecs[0].replace("\"", "")
|
||||||
|
formatObj.acodec = codecs[1].replace("\"", "")
|
||||||
|
}else if (codecs.size == 1){
|
||||||
|
formatObj.vcodec = codecs[0].replace("\"", "")
|
||||||
|
formatObj.acodec = "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
formats.add(formatObj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,20 @@ import android.app.NotificationManager
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.pm.ResolveInfo
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
|
import androidx.core.content.ContextCompat.startActivity
|
||||||
|
import androidx.core.content.FileProvider
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.receiver.CancelDownloadNotificationReceiver
|
import com.deniscerri.ytdlnis.receiver.CancelDownloadNotificationReceiver
|
||||||
import com.deniscerri.ytdlnis.receiver.OpenDownloadNotificationReceiver
|
|
||||||
import com.deniscerri.ytdlnis.receiver.SharedDownloadNotificationReceiver
|
import com.deniscerri.ytdlnis.receiver.SharedDownloadNotificationReceiver
|
||||||
import com.deniscerri.ytdlnis.ui.more.downloadLogs.DownloadLogActivity
|
import com.deniscerri.ytdlnis.ui.more.downloadLogs.DownloadLogActivity
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
class NotificationUtil(var context: Context) {
|
class NotificationUtil(var context: Context) {
|
||||||
private val downloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, DOWNLOAD_SERVICE_CHANNEL_ID)
|
private val downloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, DOWNLOAD_SERVICE_CHANNEL_ID)
|
||||||
|
|
@ -108,41 +114,42 @@ class NotificationUtil(var context: Context) {
|
||||||
) {
|
) {
|
||||||
val notificationBuilder = getBuilder(channel)
|
val notificationBuilder = getBuilder(channel)
|
||||||
|
|
||||||
val openIntent = Intent(context, OpenDownloadNotificationReceiver::class.java)
|
|
||||||
openIntent.putExtra("open", "")
|
|
||||||
openIntent.putExtra("path", filepath)
|
|
||||||
openIntent.putExtra("notificationID", DOWNLOAD_FINISHED_NOTIFICATION_ID)
|
|
||||||
val openNotificationPendingIntent = PendingIntent.getBroadcast(
|
|
||||||
context,
|
|
||||||
1,
|
|
||||||
openIntent,
|
|
||||||
PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
|
|
||||||
val shareIntent = Intent(context, SharedDownloadNotificationReceiver::class.java)
|
|
||||||
shareIntent.putExtra("share", "")
|
|
||||||
shareIntent.putExtra("path", filepath)
|
|
||||||
openIntent.putExtra("notificationID", DOWNLOAD_FINISHED_NOTIFICATION_ID)
|
|
||||||
val shareNotificationPendingIntent = PendingIntent.getBroadcast(
|
|
||||||
context,
|
|
||||||
1,
|
|
||||||
shareIntent,
|
|
||||||
PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
|
|
||||||
notificationBuilder
|
notificationBuilder
|
||||||
.setContentTitle("${context.getString(R.string.downloaded)} $title")
|
.setContentTitle("${context.getString(R.string.downloaded)} $title")
|
||||||
.setSmallIcon(R.drawable.ic_app_icon)
|
.setSmallIcon(R.drawable.ic_launcher_foreground_large)
|
||||||
.setLargeIcon(
|
.setLargeIcon(
|
||||||
BitmapFactory.decodeResource(
|
BitmapFactory.decodeResource(
|
||||||
context.resources,
|
context.resources,
|
||||||
R.drawable.ic_app_icon
|
R.drawable.ic_launcher_foreground_large
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.setPriority(NotificationCompat.PRIORITY_MAX)
|
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
.clearActions()
|
.clearActions()
|
||||||
if (filepath != null){
|
if (filepath != null){
|
||||||
|
val file = File(filepath)
|
||||||
|
val uri = FileProvider.getUriForFile(
|
||||||
|
context,
|
||||||
|
"com.deniscerri.ytdl.fileprovider",
|
||||||
|
file
|
||||||
|
)
|
||||||
|
|
||||||
|
//open intent
|
||||||
|
val intent = Intent()
|
||||||
|
intent.action = Intent.ACTION_VIEW
|
||||||
|
intent.setDataAndType(uri, "*/*")
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
|
val openNotificationPendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
|
||||||
|
|
||||||
|
//share intent
|
||||||
|
val shareIntent = Intent(context, SharedDownloadNotificationReceiver::class.java)
|
||||||
|
shareIntent.putExtra("share", "")
|
||||||
|
shareIntent.putExtra("path", filepath)
|
||||||
|
shareIntent.putExtra("notificationID", DOWNLOAD_FINISHED_NOTIFICATION_ID)
|
||||||
|
shareIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
|
val shareNotificationPendingIntent = PendingIntent.getActivity(context, 0, shareIntent, PendingIntent.FLAG_IMMUTABLE)
|
||||||
|
|
||||||
|
|
||||||
notificationBuilder.addAction(0, context.getString(R.string.Open_File), openNotificationPendingIntent)
|
notificationBuilder.addAction(0, context.getString(R.string.Open_File), openNotificationPendingIntent)
|
||||||
notificationBuilder.addAction(0, context.getString(R.string.share), shareNotificationPendingIntent)
|
notificationBuilder.addAction(0, context.getString(R.string.share), shareNotificationPendingIntent)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
import com.deniscerri.ytdlnis.ui.more.downloadLogs.DownloadLogActivity
|
import com.deniscerri.ytdlnis.ui.more.downloadLogs.DownloadLogActivity
|
||||||
import com.deniscerri.ytdlnis.util.FileUtil
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
|
import com.deniscerri.ytdlnis.util.InfoUtil
|
||||||
import com.deniscerri.ytdlnis.util.NotificationUtil
|
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||||
import com.yausername.youtubedl_android.YoutubeDL
|
import com.yausername.youtubedl_android.YoutubeDL
|
||||||
import com.yausername.youtubedl_android.YoutubeDLRequest
|
import com.yausername.youtubedl_android.YoutubeDLRequest
|
||||||
|
|
@ -25,6 +26,8 @@ import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
|
|
||||||
class DownloadWorker(
|
class DownloadWorker(
|
||||||
|
|
@ -37,6 +40,7 @@ class DownloadWorker(
|
||||||
|
|
||||||
val notificationUtil = NotificationUtil(context)
|
val notificationUtil = NotificationUtil(context)
|
||||||
val fileUtil = FileUtil()
|
val fileUtil = FileUtil()
|
||||||
|
val infoUtil = InfoUtil(context)
|
||||||
val dbManager = DBManager.getInstance(context)
|
val dbManager = DBManager.getInstance(context)
|
||||||
val dao = dbManager.downloadDao
|
val dao = dbManager.downloadDao
|
||||||
val repository = DownloadRepository(dao)
|
val repository = DownloadRepository(dao)
|
||||||
|
|
@ -209,12 +213,12 @@ class DownloadWorker(
|
||||||
|
|
||||||
var videoFormatID = downloadItem.format.format_id
|
var videoFormatID = downloadItem.format.format_id
|
||||||
Log.e(TAG, videoFormatID)
|
Log.e(TAG, videoFormatID)
|
||||||
var formatArgument = "bestvideo+bestaudio/best"
|
var formatArgument = if (downloadItem.videoPreferences.removeAudio) "bestvideo" else "bestvideo+bestaudio/best"
|
||||||
if (videoFormatID.isNotEmpty()) {
|
if (videoFormatID.isNotEmpty()) {
|
||||||
if (videoFormatID == context.resources.getString(R.string.best_quality)) videoFormatID = "bestvideo"
|
if (videoFormatID == context.resources.getString(R.string.best_quality)) videoFormatID = "bestvideo"
|
||||||
else if (videoFormatID == context.resources.getString(R.string.worst_quality)) videoFormatID = "worst"
|
else if (videoFormatID == context.resources.getString(R.string.worst_quality)) videoFormatID = "worst"
|
||||||
else if (defaultFormats.contains(videoFormatID)) videoFormatID = "bestvideo[height<="+videoFormatID.substring(0, videoFormatID.length -1)+"]"
|
else if (defaultFormats.contains(videoFormatID)) videoFormatID = "bestvideo[height<="+videoFormatID.substring(0, videoFormatID.length -1)+"]"
|
||||||
formatArgument = "$videoFormatID+bestaudio/best/$videoFormatID"
|
if (!downloadItem.videoPreferences.removeAudio) formatArgument = "$videoFormatID+bestaudio/best/$videoFormatID"
|
||||||
}
|
}
|
||||||
Log.e(TAG, formatArgument)
|
Log.e(TAG, formatArgument)
|
||||||
request.addOption("-f", formatArgument)
|
request.addOption("-f", formatArgument)
|
||||||
|
|
@ -237,6 +241,11 @@ class DownloadWorker(
|
||||||
request.addOption("--sub-langs", downloadItem.videoPreferences.subsLanguages)
|
request.addOption("--sub-langs", downloadItem.videoPreferences.subsLanguages)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (downloadItem.videoPreferences.removeAudio &&
|
||||||
|
(downloadItem.format.acodec.isNotEmpty() && downloadItem.format.acodec != "none")){
|
||||||
|
request.addOption("--ppa", "ffmpeg:-an")
|
||||||
|
}
|
||||||
|
|
||||||
if (downloadItem.videoPreferences.splitByChapters && downloadItem.downloadSections.isBlank()){
|
if (downloadItem.videoPreferences.splitByChapters && downloadItem.downloadSections.isBlank()){
|
||||||
request.addOption("--split-chapters")
|
request.addOption("--split-chapters")
|
||||||
request.addOption("-P", tempFileDir.absolutePath)
|
request.addOption("-P", tempFileDir.absolutePath)
|
||||||
|
|
@ -280,6 +289,7 @@ class DownloadWorker(
|
||||||
if (downloadItem.title.isEmpty()) downloadItem.title = info.title.toString()
|
if (downloadItem.title.isEmpty()) downloadItem.title = info.title.toString()
|
||||||
if (downloadItem.author.isEmpty()) downloadItem.author = info.uploader.toString()
|
if (downloadItem.author.isEmpty()) downloadItem.author = info.uploader.toString()
|
||||||
if (downloadItem.thumb.isEmpty()) downloadItem.thumb = info.thumbnail.toString()
|
if (downloadItem.thumb.isEmpty()) downloadItem.thumb = info.thumbnail.toString()
|
||||||
|
downloadItem.duration = infoUtil.formatIntegerDuration(info.duration, Locale.US)
|
||||||
runBlocking {
|
runBlocking {
|
||||||
dao.update(downloadItem)
|
dao.update(downloadItem)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
21
app/src/main/res/drawable/ic_launcher_foreground_large.xml
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
<vector
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:name="vector"
|
||||||
|
android:width="200dp"
|
||||||
|
android:gravity="fill_horizontal|fill_vertical"
|
||||||
|
android:height="200dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
<group
|
||||||
|
android:scaleX="2"
|
||||||
|
android:scaleY="2"
|
||||||
|
android:translateX="-54"
|
||||||
|
android:translateY="-54">
|
||||||
|
<path
|
||||||
|
android:name="path"
|
||||||
|
android:pathData="M 73.977 46.512 C 75.734 48.222 76.781 50.662 76.872 53.315 C 76.945 55.412 77 57.629 77 59.482 C 77 61.335 76.945 63.552 76.872 65.649 C 76.718 70.133 73.835 74.006 69.404 74.78 C 65.706 75.426 60.571 76 54 76 C 47.429 76 42.294 75.426 38.596 74.78 C 34.165 74.006 31.282 70.133 31.128 65.649 C 31.055 63.552 31 61.335 31 59.482 C 31 57.629 31.055 55.412 31.128 53.315 C 31.282 48.831 34.165 44.957 38.596 44.183 C 41.576 43.663 45.489 43.189 50.335 43.025 C 51.232 37.348 56.145 33 62.083 33 C 68.658 33 73.977 38.331 73.977 44.895 L 73.977 46.512 Z M 52.345 42.976 C 52.886 42.968 53.438 42.963 54 42.963 L 54.086 42.963 C 53.495 42.964 52.915 42.969 52.347 42.978 C 52.224 43.601 52.16 44.244 52.16 44.902 L 52.16 51.756 L 48.489 51.76 C 46.26 51.763 44.867 54.174 45.98 56.106 L 51.541 65.764 C 52.656 67.699 55.448 67.701 56.565 65.767 L 62.15 56.095 C 63.267 54.161 61.869 51.744 59.636 51.747 L 55.803 51.752 L 55.803 44.902 L 55.803 44.895 L 55.782 44.895 C 55.782 41.413 58.603 38.59 62.083 38.59 C 65.26 38.59 67.888 40.943 68.322 44.003 C 68.695 44.062 69.056 44.122 69.404 44.183 C 70.345 44.347 71.216 44.651 72.006 45.071 L 72.006 44.895 C 72.006 39.412 67.563 34.967 62.083 34.967 C 57.259 34.967 53.239 38.411 52.345 42.976 Z M 66.248 43.705 C 65.731 41.885 64.058 40.557 62.083 40.557 C 60.356 40.557 58.86 41.571 58.166 43.043 C 61.248 43.162 63.941 43.407 66.248 43.705 Z"
|
||||||
|
android:fillColor="@color/icon_fg"
|
||||||
|
android:strokeWidth="1"
|
||||||
|
android:fillType="evenOdd"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
<com.google.android.material.progressindicator.LinearProgressIndicator
|
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
android:id="@+id/progress"
|
android:id="@+id/progress"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
app:trackColor="#000"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
android:alpha="0.3"
|
android:alpha="0.3"
|
||||||
|
|
|
||||||
7
app/src/main/res/layout/blank.xml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:layout_height="0dp">
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -249,6 +249,19 @@
|
||||||
android:checked="false"
|
android:checked="false"
|
||||||
android:text="@string/subtitle_languages"/>
|
android:text="@string/subtitle_languages"/>
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/remove_audio"
|
||||||
|
style="@style/Widget.Material3.Chip.Filter.Elevated"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/remove_audio"
|
||||||
|
android:minWidth="30dp"
|
||||||
|
app:cornerRadius="10dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
</com.google.android.material.chip.ChipGroup>
|
</com.google.android.material.chip.ChipGroup>
|
||||||
|
|
||||||
</HorizontalScrollView>
|
</HorizontalScrollView>
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,5 @@
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
|
|
@ -2,5 +2,4 @@
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
|
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
|
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 12 KiB |
|
|
@ -243,4 +243,5 @@
|
||||||
<string name="finished_download_notification_channel_description">Notification for finished or faulty downloads</string>
|
<string name="finished_download_notification_channel_description">Notification for finished or faulty downloads</string>
|
||||||
<string name="quick_download">Quick Download</string>
|
<string name="quick_download">Quick Download</string>
|
||||||
<string name="quick_download_summary">Don\'t fetch data beforehand</string>
|
<string name="quick_download_summary">Don\'t fetch data beforehand</string>
|
||||||
|
<string name="remove_audio">Remove Audio</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<paths>
|
<paths>
|
||||||
<external-path name="external_files" path="."/>
|
<external-path name="external_files" path="."/>
|
||||||
<root-path name="external_files" path="/storage/" />
|
|
||||||
<cache-path
|
<cache-path
|
||||||
name="cache"
|
name="cache"
|
||||||
path="." />
|
path="." />
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
app:title="@string/video_directory" />
|
app:title="@string/video_directory" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
app:icon="@drawable/ic_baseline_keyboard_arrow_right_24"
|
app:icon="@drawable/ic_terminal"
|
||||||
app:key="command_path"
|
app:key="command_path"
|
||||||
app:defaultValue="@string/command_path"
|
app:defaultValue="@string/command_path"
|
||||||
app:title="@string/command_directory" />
|
app:title="@string/command_directory" />
|
||||||
|
|
|
||||||