more stuff

tapping running download notification, will open download queue screen now
fixed app closing running application when trying to share a file from the notification
trending videos and search results will use piped now
pull/161/head
deniscerri 3 years ago
parent 4061f3878a
commit 3289a4fb96
No known key found for this signature in database
GPG Key ID: 95C43D517D830350

@ -128,18 +128,6 @@
</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
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
@ -149,6 +137,10 @@
android:value="true" />
</service>
<service
android:name=".receiver.ShareFileService"
android:exported="false" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.deniscerri.ytdl.fileprovider"

@ -299,6 +299,21 @@ class MainActivity : BaseActivity() {
e.printStackTrace()
}
}
else{
//coming from errored notification
if (intent.hasExtra("logpath")){
val bundle = Bundle()
bundle.putString("logpath", intent.getStringExtra("logpath"))
navController.navigate(
R.id.downloadLogFragment,
bundle
)
//coming from active download notification
}else if (intent.hasExtra("activedownload")){
navController.popBackStack(R.id.downloadQueueMainFragment, true)
navController.navigate(R.id.downloadQueueMainFragment)
}
}
}

@ -33,6 +33,7 @@ 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.ThemeUtil
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@ -207,9 +208,9 @@ class ShareActivity : BaseActivity() {
private fun createDefaultFolders(){
val audio = File(getString(R.string.music_path))
val video = File(getString(R.string.video_path))
val command = File(getString(R.string.command_path))
val audio = File(FileUtil.getDefautAudioPath())
val video = File(FileUtil.getDefautVideoPath())
val command = File(FileUtil.getDefaultCommandPath())
audio.mkdirs()
video.mkdirs()
@ -267,8 +268,4 @@ class ShareActivity : BaseActivity() {
startActivity(Intent(this, MainActivity::class.java))
super.onConfigurationChanged(newConfig)
}
companion object {
private const val TAG = "ShareActivity"
}
}

@ -0,0 +1,26 @@
package com.deniscerri.ytdlnis.receiver
import android.app.Service
import android.content.Intent
import android.os.IBinder
import com.deniscerri.ytdlnis.util.NotificationUtil
import com.deniscerri.ytdlnis.util.UiUtil
class ShareFileService : Service() {
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
val paths = intent.getStringArrayExtra("path")
val notificationId = intent.getIntExtra("notificationID", 0)
NotificationUtil(this).cancelDownloadNotification(notificationId)
UiUtil.shareFileIntent(this, paths!!.toList())
return START_NOT_STICKY
}
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onDestroy() {
super.onDestroy()
stopForeground(true)
}
}

@ -1,25 +0,0 @@
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()
uiUtil.shareFileIntent(this, listOf(path))
this.finishAffinity()
}
}
}

@ -42,7 +42,6 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
private lateinit var commandTemplateDao: CommandTemplateDao
private lateinit var behavior: BottomSheetBehavior<View>
private lateinit var onDownloadItemUpdateListener: OnDownloadItemUpdateListener
private lateinit var uiUtil: UiUtil
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -50,7 +49,6 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
commandTemplateDao = DBManager.getInstance(requireContext()).commandTemplateDao
onDownloadItemUpdateListener = listener
uiUtil = UiUtil()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -188,10 +186,10 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
val link = view.findViewById<Button>(R.id.bottom_sheet_link)
link.text = resultItem.url
link.setOnClickListener{
uiUtil.openLinkIntent(requireContext(), resultItem.url, null)
UiUtil.openLinkIntent(requireContext(), resultItem.url, null)
}
link.setOnLongClickListener{
uiUtil.copyLinkToClipBoard(requireContext(), resultItem.url, null)
UiUtil.copyLinkToClipBoard(requireContext(), resultItem.url, null)
true
}

@ -18,9 +18,7 @@ import androidx.lifecycle.lifecycleScope
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.models.ChapterItem
import com.deniscerri.ytdlnis.database.models.DownloadItem
import com.deniscerri.ytdlnis.util.FileUtil
import com.deniscerri.ytdlnis.util.InfoUtil
import com.deniscerri.ytdlnis.util.UiUtil
import com.google.android.exoplayer2.C
import com.google.android.exoplayer2.DefaultLoadControl
import com.google.android.exoplayer2.DefaultRenderersFactory
@ -63,7 +61,6 @@ import kotlin.properties.Delegates
class CutVideoBottomSheetDialog(private val item: DownloadItem, private val urls : String?, private var chapters: List<ChapterItem>?, private val listener: VideoCutListener) : BottomSheetDialogFragment() {
private lateinit var behavior: BottomSheetBehavior<View>
private lateinit var infoUtil: InfoUtil
private lateinit var uiUtil: UiUtil
private lateinit var player: Player
private lateinit var cutSection : ConstraintLayout
@ -90,7 +87,6 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val urls
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
uiUtil = UiUtil()
infoUtil = InfoUtil(requireActivity().applicationContext)
}

@ -51,7 +51,6 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel
private lateinit var resultViewModel : ResultViewModel
private lateinit var uiUtil : UiUtil
private lateinit var title : TextInputLayout
private lateinit var author : TextInputLayout
@ -70,7 +69,6 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
uiUtil = UiUtil()
return fragmentView
}
@ -142,11 +140,11 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
val formatCard = view.findViewById<MaterialCardView>(R.id.format_card_constraintLayout)
val chosenFormat = downloadItem.format
uiUtil.populateFormatCard(formatCard, chosenFormat, null)
UiUtil.populateFormatCard(formatCard, chosenFormat, null)
val listener = object : OnFormatClickListener {
override fun onFormatClick(allFormats: List<List<Format>>, item: List<Format>) {
downloadItem.format = item.first()
uiUtil.populateFormatCard(formatCard, item.first(), null)
UiUtil.populateFormatCard(formatCard, item.first(), null)
lifecycleScope.launch {
withContext(Dispatchers.IO){
resultItem.formats.removeAll(formats.toSet())
@ -164,7 +162,7 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
}
}
formatCard.setOnLongClickListener {
uiUtil.showFormatDetails(downloadItem.format, requireActivity())
UiUtil.showFormatDetails(downloadItem.format, requireActivity())
true
}

@ -47,7 +47,6 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
private lateinit var resultViewModel: ResultViewModel
private lateinit var behavior: BottomSheetBehavior<View>
private lateinit var commandTemplateDao : CommandTemplateDao
private lateinit var uiUtil: UiUtil
private lateinit var infoUtil: InfoUtil
private lateinit var downloadAudioFragment: DownloadAudioFragment
@ -59,7 +58,6 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
commandTemplateDao = DBManager.getInstance(requireContext()).commandTemplateDao
uiUtil = UiUtil()
infoUtil = InfoUtil(requireContext())
}
@ -180,7 +178,7 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
scheduleBtn.setOnClickListener{
uiUtil.showDatePicker(fragmentManager) {
UiUtil.showDatePicker(fragmentManager) {
scheduleBtn.isEnabled = false
download.isEnabled = false
val item: DownloadItem = getDownloadItem();
@ -206,10 +204,10 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
val link = view.findViewById<Button>(R.id.bottom_sheet_link)
link.text = resultItem.url
link.setOnClickListener{
uiUtil.openLinkIntent(requireContext(), resultItem.url, null)
UiUtil.openLinkIntent(requireContext(), resultItem.url, null)
}
link.setOnLongClickListener{
uiUtil.copyLinkToClipBoard(requireContext(), resultItem.url, null)
UiUtil.copyLinkToClipBoard(requireContext(), resultItem.url, null)
true
}

@ -42,7 +42,6 @@ class DownloadCommandFragment(private val resultItem: ResultItem, private var cu
private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel
private lateinit var commandTemplateViewModel : CommandTemplateViewModel
private lateinit var uiUtil : UiUtil
private lateinit var saveDir : TextInputLayout
private lateinit var freeSpace : TextView
@ -58,7 +57,6 @@ class DownloadCommandFragment(private val resultItem: ResultItem, private var cu
activity = getActivity()
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
uiUtil = UiUtil()
return fragmentView
}
@ -155,7 +153,7 @@ class DownloadCommandFragment(private val resultItem: ResultItem, private var cu
val newTemplate : Chip = view.findViewById(R.id.newTemplate)
newTemplate.setOnClickListener {
uiUtil.showCommandTemplateCreationOrUpdatingSheet(null, requireActivity(), viewLifecycleOwner, commandTemplateViewModel) {
UiUtil.showCommandTemplateCreationOrUpdatingSheet(null, requireActivity(), viewLifecycleOwner, commandTemplateViewModel) {
templates.add(it)
chosenCommandView.editText!!.setText(it.content)
downloadItem.format = Format(
@ -175,7 +173,7 @@ class DownloadCommandFragment(private val resultItem: ResultItem, private var cu
editSelected.setOnClickListener {
var current = templates.find { it.title == autoCompleteTextView.text.toString() }
if (current == null) current = CommandTemplate(0, "", chosenCommandView.editText!!.text.toString())
uiUtil.showCommandTemplateCreationOrUpdatingSheet(current, requireActivity(), viewLifecycleOwner, commandTemplateViewModel) {
UiUtil.showCommandTemplateCreationOrUpdatingSheet(current, requireActivity(), viewLifecycleOwner, commandTemplateViewModel) {
templates.add(it)
chosenCommandView.editText!!.setText(it.content)
downloadItem.format = Format(

@ -59,7 +59,6 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
private lateinit var listAdapter : ConfigureMultipleDownloadsAdapter
private lateinit var recyclerView: RecyclerView
private lateinit var behavior: BottomSheetBehavior<View>
private lateinit var uiUtil: UiUtil
private lateinit var bottomAppBar: BottomAppBar
@ -68,7 +67,6 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
uiUtil = UiUtil()
}
@SuppressLint("RestrictedApi", "NotifyDataSetChanged")
@ -104,7 +102,7 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
scheduleBtn.setOnClickListener{
uiUtil.showDatePicker(parentFragmentManager) {
UiUtil.showDatePicker(parentFragmentManager) {
scheduleBtn.isEnabled = false
download.isEnabled = false
items.forEach { item ->
@ -238,7 +236,7 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
}else{
if (items.first().type == DownloadViewModel.Type.command){
lifecycleScope.launch {
uiUtil.showCommandTemplates(requireActivity(), commandTemplateViewModel) {
UiUtil.showCommandTemplates(requireActivity(), commandTemplateViewModel) {
val format = downloadViewModel.generateCommandFormat(it)
items.forEach { f ->
f.format = format

@ -51,7 +51,6 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel
private lateinit var resultViewModel: ResultViewModel
private lateinit var uiUtil : UiUtil
private lateinit var title : TextInputLayout
private lateinit var author : TextInputLayout
@ -70,8 +69,6 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
activity = getActivity()
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
resultViewModel = ViewModelProvider(this@DownloadVideoFragment)[ResultViewModel::class.java]
uiUtil = UiUtil()
return fragmentView
}
@ -146,7 +143,7 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
val formatCard = view.findViewById<MaterialCardView>(R.id.format_card_constraintLayout)
val chosenFormat = downloadItem.format
uiUtil.populateFormatCard(formatCard, chosenFormat, downloadItem.allFormats.filter { downloadItem.videoPreferences.audioFormatIDs.contains(it.format_id) })
UiUtil.populateFormatCard(formatCard, chosenFormat, downloadItem.allFormats.filter { downloadItem.videoPreferences.audioFormatIDs.contains(it.format_id) })
val listener = object : OnFormatClickListener {
override fun onFormatClick(allFormats: List<List<Format>>, item: List<Format>) {
downloadItem.format = item.first()
@ -159,7 +156,7 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
}
}
formats = allFormats.first().toMutableList()
uiUtil.populateFormatCard(formatCard, item.first(), item.drop(1))
UiUtil.populateFormatCard(formatCard, item.first(), item.drop(1))
}
}
formatCard.setOnClickListener{
@ -170,7 +167,7 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
}
formatCard.setOnLongClickListener {
uiUtil.showFormatDetails(downloadItem.format, requireActivity())
UiUtil.showFormatDetails(downloadItem.format, requireActivity())
true
}
@ -367,7 +364,7 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
}
subtitleLanguages.setOnClickListener {
uiUtil.showSubtitleLanguagesDialog(requireActivity(), downloadItem.videoPreferences.subsLanguages){
UiUtil.showSubtitleLanguagesDialog(requireActivity(), downloadItem.videoPreferences.subsLanguages){
downloadItem.videoPreferences.subsLanguages = it
}
}

@ -32,7 +32,6 @@ import java.util.*
class FormatSelectionBottomSheetDialog(private val items: List<DownloadItem?>, private var formats: List<List<Format>>, private val listener: OnFormatClickListener) : BottomSheetDialogFragment() {
private lateinit var behavior: BottomSheetBehavior<View>
private lateinit var infoUtil: InfoUtil
private lateinit var uiUtil: UiUtil
private lateinit var sharedPreferences: SharedPreferences
private lateinit var formatCollection: MutableList<List<Format>>
private lateinit var chosenFormats: List<Format>
@ -47,7 +46,6 @@ class FormatSelectionBottomSheetDialog(private val items: List<DownloadItem?>, p
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
uiUtil = UiUtil()
infoUtil = InfoUtil(requireActivity().applicationContext)
formatCollection = mutableListOf()
chosenFormats = listOf()
@ -230,7 +228,7 @@ class FormatSelectionBottomSheetDialog(private val items: List<DownloadItem?>, p
val format = chosenFormats[i]
val formatItem = LayoutInflater.from(context).inflate(R.layout.format_item, null)
formatItem.tag = "${format.format_id}${format.format_note}"
uiUtil.populateFormatCard(formatItem as MaterialCardView, format, null)
UiUtil.populateFormatCard(formatItem as MaterialCardView, format, null)
formatItem.setOnClickListener{ clickedformat ->
//if the context is behind a single download card and its a video, allow the ability to multiselect audio formats
if (canMultiSelectAudio){
@ -273,7 +271,7 @@ class FormatSelectionBottomSheetDialog(private val items: List<DownloadItem?>, p
}
}
formatItem.setOnLongClickListener {
uiUtil.showFormatDetails(format, requireActivity())
UiUtil.showFormatDetails(format, requireActivity())
true
}

@ -52,7 +52,6 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
private var selectedObjects: ArrayList<DownloadItem>? = null
private var actionMode : ActionMode? = null
private lateinit var items : MutableList<DownloadItem>
private lateinit var uiUtil : UiUtil
override fun onCreateView(
inflater: LayoutInflater,
@ -65,7 +64,6 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
selectedObjects = arrayListOf()
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
items = mutableListOf()
uiUtil = UiUtil()
return fragmentView
}
@ -170,10 +168,10 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
link!!.text = url
link.tag = itemID
link.setOnClickListener{
uiUtil.openLinkIntent(requireContext(), item.url, bottomSheet)
UiUtil.openLinkIntent(requireContext(), item.url, bottomSheet)
}
link.setOnLongClickListener{
uiUtil.copyLinkToClipBoard(requireContext(), item.url, bottomSheet)
UiUtil.copyLinkToClipBoard(requireContext(), item.url, bottomSheet)
true
}
val remove = bottomSheet.findViewById<Button>(R.id.bottomsheet_remove_button)

@ -55,7 +55,6 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
private lateinit var items : MutableList<DownloadItem>
private var selectedObjects: ArrayList<DownloadItem>? = null
private var actionMode : ActionMode? = null
private lateinit var uiUtil : UiUtil
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -67,7 +66,6 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
items = mutableListOf()
selectedObjects = arrayListOf()
uiUtil = UiUtil()
return fragmentView
}
@ -173,10 +171,10 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
link!!.text = url
link.tag = itemID
link.setOnClickListener{
uiUtil.openLinkIntent(requireContext(), item.url, bottomSheet)
UiUtil.openLinkIntent(requireContext(), item.url, bottomSheet)
}
link.setOnLongClickListener{
uiUtil.copyLinkToClipBoard(requireContext(), item.url, bottomSheet)
UiUtil.copyLinkToClipBoard(requireContext(), item.url, bottomSheet)
true
}
val remove = bottomSheet.findViewById<Button>(R.id.bottomsheet_remove_button)

@ -87,7 +87,6 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
private var historyList: List<HistoryItem?>? = null
private var allhistoryList: List<HistoryItem?>? = null
private var selectedObjects: ArrayList<HistoryItem>? = null
private var uiUtil: UiUtil? = null
private var _binding : FragmentHistoryBinding? = null
private var actionMode : ActionMode? = null
@ -112,7 +111,6 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
noResults = view.findViewById(R.id.no_results)
selectionChips = view.findViewById(R.id.history_selection_chips)
websiteGroup = view.findViewById(R.id.website_chip_group)
uiUtil = UiUtil()
uiHandler = Handler(Looper.getMainLooper())
selectedObjects = ArrayList()
@ -424,7 +422,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
if (isPresent){
btn.setOnClickListener {
uiUtil!!.shareFileIntent(requireContext(), listOf(item.downloadPath))
UiUtil!!.shareFileIntent(requireContext(), listOf(item.downloadPath))
}
}
@ -469,10 +467,10 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
link!!.text = url
link.tag = itemID
link.setOnClickListener{
uiUtil!!.openLinkIntent(requireContext(), item.url, bottomSheet)
UiUtil.openLinkIntent(requireContext(), item.url, bottomSheet)
}
link.setOnLongClickListener{
uiUtil!!.copyLinkToClipBoard(requireContext(), item.url, bottomSheet)
UiUtil.copyLinkToClipBoard(requireContext(), item.url, bottomSheet)
true
}
val remove = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_remove_button)
@ -483,7 +481,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
val openFile = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_open_file_button)
openFile!!.tag = itemID
openFile.setOnClickListener{
uiUtil!!.openFileIntent(requireContext(), item.downloadPath)
UiUtil.openFileIntent(requireContext(), item.downloadPath)
}
val redownload = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_redownload_button)
@ -582,7 +580,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
true
}
R.id.share -> {
uiUtil?.shareFileIntent(requireContext(), selectedObjects!!.map { it.downloadPath })
UiUtil.shareFileIntent(requireContext(), selectedObjects!!.map { it.downloadPath })
clearCheckedItems()
actionMode?.finish()
true

@ -63,7 +63,6 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
private var selectedObjects: ArrayList<DownloadItem>? = null
private var actionMode : ActionMode? = null
private lateinit var items : MutableList<DownloadItem>
private lateinit var uiUtil: UiUtil
override fun onCreateView(
inflater: LayoutInflater,
@ -77,7 +76,6 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
items = mutableListOf()
selectedObjects = arrayListOf()
uiUtil = UiUtil()
return fragmentView
}
@ -148,7 +146,7 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
time!!.text = SimpleDateFormat(DateFormat.getBestDateTimePattern(Locale.getDefault(), "ddMMMyyyy - HHmm"), Locale.getDefault()).format(calendar.time)
time.setOnClickListener {
uiUtil.showDatePicker(parentFragmentManager) {
UiUtil.showDatePicker(parentFragmentManager) {
bottomSheet.dismiss()
Toast.makeText(context, getString(R.string.download_rescheduled_to) + " " + it.time, Toast.LENGTH_LONG).show()
downloadViewModel.deleteDownload(item)
@ -192,10 +190,10 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
link!!.text = url
link.tag = itemID
link.setOnClickListener{
uiUtil.openLinkIntent(requireContext(), item.url, bottomSheet)
UiUtil.openLinkIntent(requireContext(), item.url, bottomSheet)
}
link.setOnLongClickListener{
uiUtil.copyLinkToClipBoard(requireContext(), item.url, bottomSheet)
UiUtil.copyLinkToClipBoard(requireContext(), item.url, bottomSheet)
true
}
val remove = bottomSheet.findViewById<Button>(R.id.bottomsheet_remove_button)

@ -38,7 +38,6 @@ class CommandTemplatesFragment : Fragment(), TemplatesAdapter.OnItemClickListene
private lateinit var templatesAdapter: TemplatesAdapter
private lateinit var topAppBar: MaterialToolbar
private lateinit var commandTemplateViewModel: CommandTemplateViewModel
private lateinit var uiUtil: UiUtil
private lateinit var templatesList: List<CommandTemplate>
private lateinit var noResults: RelativeLayout
private lateinit var mainActivity: MainActivity
@ -75,7 +74,6 @@ class CommandTemplatesFragment : Fragment(), TemplatesAdapter.OnItemClickListene
itemTouchHelper.attachToRecyclerView(recyclerView)
}
uiUtil = UiUtil()
commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
commandTemplateViewModel.items.observe(viewLifecycleOwner) {
@ -116,11 +114,11 @@ class CommandTemplatesFragment : Fragment(), TemplatesAdapter.OnItemClickListene
private fun initChips() {
val new = view?.findViewById<Chip>(R.id.newTemplate)
new?.setOnClickListener {
uiUtil.showCommandTemplateCreationOrUpdatingSheet(null,mainActivity, this, commandTemplateViewModel) {}
UiUtil.showCommandTemplateCreationOrUpdatingSheet(null,mainActivity, this, commandTemplateViewModel) {}
}
val shortcuts = view?.findViewById<Chip>(R.id.shortcuts)
shortcuts?.setOnClickListener {
uiUtil.showShortcutsSheet(mainActivity,this, commandTemplateViewModel)
UiUtil.showShortcutsSheet(mainActivity,this, commandTemplateViewModel)
}
}
@ -129,7 +127,7 @@ class CommandTemplatesFragment : Fragment(), TemplatesAdapter.OnItemClickListene
}
override fun onItemClick(commandTemplate: CommandTemplate, index: Int) {
uiUtil.showCommandTemplateCreationOrUpdatingSheet(commandTemplate,mainActivity, this, commandTemplateViewModel) {
UiUtil.showCommandTemplateCreationOrUpdatingSheet(commandTemplate,mainActivity, this, commandTemplateViewModel) {
templatesAdapter.notifyItemChanged(index)
}

@ -45,7 +45,6 @@ class CookiesFragment : Fragment(), CookieAdapter.OnItemClickListener {
private lateinit var listAdapter: CookieAdapter
private lateinit var topAppBar: MaterialToolbar
private lateinit var cookiesViewModel: CookieViewModel
private lateinit var uiUtil: UiUtil
private lateinit var cookiesList: List<CookieItem>
private lateinit var noResults : RelativeLayout
private lateinit var mainActivity: MainActivity
@ -79,7 +78,6 @@ class CookiesFragment : Fragment(), CookieAdapter.OnItemClickListener {
val itemTouchHelper = ItemTouchHelper(simpleCallback)
itemTouchHelper.attachToRecyclerView(recyclerView)
}
uiUtil = UiUtil()
cookiesViewModel = ViewModelProvider(this)[CookieViewModel::class.java]
cookiesViewModel.items.observe(viewLifecycleOwner) {

@ -63,7 +63,6 @@ class TerminalActivity : BaseActivity() {
private lateinit var downloadFile : File
private lateinit var observer: FileObserver
private lateinit var imm : InputMethodManager
private lateinit var uiUtil: UiUtil
var context: Context? = null
public override fun onCreate(savedInstanceState: Bundle?) {
@ -74,7 +73,6 @@ class TerminalActivity : BaseActivity() {
downloadFile = File(cacheDir.absolutePath + "/$downloadID.txt")
if (! downloadFile.exists()) downloadFile.createNewFile()
imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
uiUtil = UiUtil()
context = baseContext
scrollView = findViewById(R.id.custom_command_scrollview)
@ -114,7 +112,7 @@ class TerminalActivity : BaseActivity() {
Toast.makeText(context, getString(R.string.add_template_first), Toast.LENGTH_SHORT).show()
}else{
lifecycleScope.launch {
uiUtil.showCommandTemplates(this@TerminalActivity, commandTemplateViewModel){ template ->
UiUtil.showCommandTemplates(this@TerminalActivity, commandTemplateViewModel){ template ->
input!!.text.insert(input!!.selectionStart, template.content + " ")
input!!.postDelayed({
input!!.requestFocus()

@ -8,12 +8,21 @@ import android.os.Bundle
import android.os.Environment
import android.provider.Settings
import androidx.activity.result.contract.ActivityResultContracts
import androidx.preference.EditTextPreference
import androidx.preference.Preference
import androidx.preference.PreferenceManager
import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkInfo
import androidx.work.WorkManager
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.util.FileUtil
import com.deniscerri.ytdlnis.work.DownloadWorker
import com.deniscerri.ytdlnis.work.MoveCacheFilesWorker
import com.google.android.material.snackbar.Snackbar
import java.io.File
import java.util.concurrent.TimeUnit
class FolderSettingsFragment : BaseSettingsFragment() {
@ -23,7 +32,10 @@ class FolderSettingsFragment : BaseSettingsFragment() {
private var videoPath: Preference? = null
private var commandPath: Preference? = null
private var accessAllFiles : Preference? = null
private var audioFilenameTemplate : EditTextPreference? = null
private var videoFilenameTemplate : EditTextPreference? = null
private var clearCache: Preference? = null
private var moveCache: Preference? = null
private var activeDownloadCount = 0
@ -37,7 +49,10 @@ class FolderSettingsFragment : BaseSettingsFragment() {
videoPath = findPreference("video_path")
commandPath = findPreference("command_path")
accessAllFiles = findPreference("access_all_files")
videoFilenameTemplate = findPreference("file_name_template")
audioFilenameTemplate = findPreference("file_name_template_audio")
clearCache = findPreference("clear_cache")
moveCache = findPreference("move_cache")
if (preferences.getString("music_path", "")!!.isEmpty()) {
editor.putString("music_path", FileUtil.getDefautAudioPath())
@ -95,6 +110,12 @@ class FolderSettingsFragment : BaseSettingsFragment() {
true
}
videoFilenameTemplate?.title = "${getString(R.string.file_name_template)} [${getString(R.string.video)}]"
videoFilenameTemplate?.dialogTitle = "${getString(R.string.file_name_template)} [${getString(R.string.video)}]"
audioFilenameTemplate?.title = "${getString(R.string.file_name_template)} [${getString(R.string.audio)}]"
audioFilenameTemplate?.dialogTitle = "${getString(R.string.file_name_template)} [${getString(R.string.audio)}]"
var cacheSize = File(requireContext().cacheDir.absolutePath + "/downloads").walkBottomUp().fold(0L) { acc, file -> acc + file.length() }
clearCache!!.summary = "(${FileUtil.convertFileSize(cacheSize)}) ${resources.getString(R.string.clear_temporary_files_summary)}"
clearCache!!.onPreferenceClickListener =
@ -110,6 +131,34 @@ class FolderSettingsFragment : BaseSettingsFragment() {
true
}
moveCache!!.onPreferenceClickListener =
Preference.OnPreferenceClickListener {
val workRequest = OneTimeWorkRequestBuilder<MoveCacheFilesWorker>()
.addTag("cacheFiles")
.build()
WorkManager.getInstance(requireContext()).beginUniqueWork(
System.currentTimeMillis().toString(),
ExistingWorkPolicy.KEEP,
workRequest
).enqueue()
WorkManager.getInstance(requireContext())
.getWorkInfosByTagLiveData("cacheFiles")
.observe(viewLifecycleOwner){ list ->
if (list == null) return@observe
if (list.first() == null) return@observe
if (list.first().state == WorkInfo.State.SUCCEEDED){
cacheSize = File(requireContext().cacheDir.absolutePath + "/downloads").walkBottomUp().fold(0L) { acc, file -> acc + file.length() }
clearCache!!.summary = "(${FileUtil.convertFileSize(cacheSize)}) ${resources.getString(R.string.clear_temporary_files_summary)}"
}
}
true
}
}
private var musicPathResultLauncher = registerForActivityResult(

@ -9,11 +9,6 @@ class ProcessingSettingsFragment : BaseSettingsFragment() {
override val title: Int = R.string.processing
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.processing_preferences, rootKey)
findPreference<EditTextPreference>("file_name_template")?.title = "${getString(R.string.file_name_template)} [${getString(R.string.video)}]"
findPreference<EditTextPreference>("file_name_template")?.dialogTitle = "${getString(R.string.file_name_template)} [${getString(R.string.video)}]"
findPreference<EditTextPreference>("file_name_template_audio")?.title = "${getString(R.string.file_name_template)} [${getString(R.string.audio)}]"
findPreference<EditTextPreference>("file_name_template_audio")?.dialogTitle = "${getString(R.string.file_name_template)} [${getString(R.string.audio)}]"
}
}

@ -70,7 +70,7 @@ object FileUtil {
@Throws(Exception::class)
fun moveFile(originDir: File, context: Context, destDir: String, keepCache: Boolean, progress: (p: Int) -> Unit) : String {
fun moveFile(originDir: File, context: Context, destDir: String, keepCache: Boolean, progress: (p: Int) -> Unit) : List<String> {
val fileList = mutableListOf<File>()
val dir = File(formatPath(destDir))
if (!dir.exists()) dir.mkdirs()
@ -159,17 +159,17 @@ object FileUtil {
}
return scanMedia(fileList, context)
}
private fun scanMedia(files: List<File>, context: Context) : String {
private fun scanMedia(files: List<File>, context: Context) : List<String> {
try {
val paths = files.map { it.absolutePath }.toTypedArray()
MediaScannerConnection.scanFile(context, paths, null, null)
return files.reduce(Compare::max).absolutePath
return files.sortedByDescending { it.length() }.map { it.absolutePath }
}catch (e: Exception){
e.printStackTrace()
}
return context.getString(R.string.unfound_file);
return listOf(context.getString(R.string.unfound_file))
}
fun getLogFile(context: Context, item: DownloadItem) : File {

@ -56,13 +56,18 @@ class InfoUtil(private val context: Context) {
}
}
@Throws(JSONException::class)
fun search(query: String): ArrayList<ResultItem?> {
init()
items = ArrayList()
val searchEngine = sharedPreferences.getString("search_engine", "ytsearch")
return if (searchEngine == "ytsearch"){
if (key!!.isNotEmpty()) searchFromKey(query) else if (useInvidous) searchFromInvidous(query) else getFromYTDL(query)
if (key!!.isNotEmpty()) searchFromKey(query) else {
try{
searchFromPiped(query)
}catch (e: Exception){
getFromYTDL(query)
}
}
}else getFromYTDL(query)
}
@ -116,22 +121,15 @@ class InfoUtil(private val context: Context) {
}
@Throws(JSONException::class)
fun searchFromInvidous(query: String): ArrayList<ResultItem?> {
val dataArray = genericArrayRequest(invidousURL + "search?q=" + query + "?type=video")
fun searchFromPiped(query: String): ArrayList<ResultItem?> {
val data = genericRequest(pipedURL + "search?q=" + query + "?filter=videos")
val dataArray = data.getJSONArray("items")
if (dataArray.length() == 0) return getFromYTDL(query)
for (i in 0 until dataArray.length()) {
val element = dataArray.getJSONObject(i)
if (!element.getString("type").equals("video")) continue
val duration = formatIntegerDuration(element.getInt("lengthSeconds"), Locale.getDefault())
if (duration == "0:00") {
continue
}
element.put("duration", duration)
element.put(
"thumb",
element.getJSONArray("videoThumbnails").getJSONObject(0).getString("url")
)
val v = createVideoFromInvidiousJSON(element)
if (element.getInt("duration") == -1) continue
element.put("uploader", element.getString("uploaderName"))
val v = createVideoFromPipedJSON(element, element.getString("url").removePrefix("/watch?v="))
if (v == null || v.thumb.isEmpty()) {
continue
}
@ -511,7 +509,7 @@ class InfoUtil(private val context: Context) {
init()
items = ArrayList()
return if (key!!.isEmpty()) {
if (useInvidous) getTrendingFromInvidous(context) else ArrayList()
getTrendingFromPiped()
} else getTrendingFromKey(context)
}
@ -545,14 +543,15 @@ class InfoUtil(private val context: Context) {
return items
}
private fun getTrendingFromInvidous(context: Context): ArrayList<ResultItem?> {
val url = invidousURL + "trending?type=music&region=" + countryCODE
private fun getTrendingFromPiped(): ArrayList<ResultItem?> {
val url = pipedURL + "trending?region=" + countryCODE
val res = genericArrayRequest(url)
try {
for (i in 0 until res.length()) {
val element = res.getJSONObject(i)
if (element.getString("type") != "video") continue
val v = createVideoFromInvidiousJSON(element)
if (element.getInt("duration") < 0) continue
element.put("uploader", element.getString("uploaderName"))
val v = createVideoFromPipedJSON(element, element.getString("url").removePrefix("/watch?v="))
if (v == null || v.thumb.isEmpty()) continue
v.playlistTitle = context.getString(R.string.trendingPlaylist)
items.add(v)

@ -11,12 +11,12 @@ import android.graphics.BitmapFactory
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.content.FileProvider
import com.deniscerri.ytdlnis.MainActivity
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.receiver.CancelDownloadNotificationReceiver
import com.deniscerri.ytdlnis.receiver.PauseDownloadNotificationReceiver
import com.deniscerri.ytdlnis.receiver.ResumeActivity
import com.deniscerri.ytdlnis.receiver.SharedDownloadNotificationReceiver
import com.deniscerri.ytdlnis.ui.more.downloadLogs.DownloadLogFragment
import com.deniscerri.ytdlnis.receiver.ShareFileService
import java.io.File
@ -55,6 +55,13 @@ class NotificationUtil(var context: Context) {
channel = NotificationChannel(DOWNLOAD_FINISHED_CHANNEL_ID, name, NotificationManager.IMPORTANCE_HIGH)
channel.description = description
notificationManager.createNotificationChannel(channel)
//misc
name = context.getString(R.string.misc)
description = ""
channel = NotificationChannel(DOWNLOAD_MISC_CHANNEL_ID, name, NotificationManager.IMPORTANCE_HIGH)
channel.description = description
notificationManager.createNotificationChannel(channel)
}
}
@ -166,7 +173,7 @@ class NotificationUtil(var context: Context) {
}
fun createDownloadFinished(title: String?,
filepath: String?,
filepath: List<String>?,
channel: String
) {
val notificationBuilder = getBuilder(channel)
@ -185,7 +192,7 @@ class NotificationUtil(var context: Context) {
.clearActions()
if (filepath != null){
try{
val file = File(filepath)
val file = File(filepath.first())
val uri = FileProvider.getUriForFile(
context,
"com.deniscerri.ytdl.fileprovider",
@ -204,15 +211,15 @@ class NotificationUtil(var context: Context) {
}
//share intent
val shareIntent = Intent(context, SharedDownloadNotificationReceiver::class.java)
shareIntent.putExtra("share", "")
shareIntent.putExtra("path", filepath)
val shareIntent = Intent(context, ShareFileService::class.java)
shareIntent.putExtra("path", filepath.toTypedArray())
shareIntent.putExtra("notificationID", DOWNLOAD_FINISHED_NOTIFICATION_ID)
val shareNotificationPendingIntent: PendingIntent = TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(shareIntent)
getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
val shareNotificationPendingIntent: PendingIntent = PendingIntent.getService(
context,
0,
shareIntent,
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)
notificationBuilder.addAction(0, context.getString(R.string.Open_File), openNotificationPendingIntent)
notificationBuilder.addAction(0, context.getString(R.string.share), shareNotificationPendingIntent)
@ -228,7 +235,7 @@ class NotificationUtil(var context: Context) {
) {
val notificationBuilder = getBuilder(channel)
val intent = Intent(context, DownloadLogFragment::class.java)
val intent = Intent(context, MainActivity::class.java)
intent.putExtra("logpath", logFile?.absolutePath)
val errorPendingIntent: PendingIntent = TaskStackBuilder.create(context).run {
@ -283,6 +290,43 @@ class NotificationUtil(var context: Context) {
notificationManager.cancel(id)
}
fun createMoveCacheFilesNotification(pendingIntent: PendingIntent?, downloadMiscChannelId: String): Notification {
val notificationBuilder = getBuilder(downloadMiscChannelId)
return notificationBuilder
.setContentTitle(context.getString(R.string.move_temporary_files))
.setOngoing(true)
.setCategory(Notification.CATEGORY_PROGRESS)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setLargeIcon(
BitmapFactory.decodeResource(
context.resources,
android.R.drawable.stat_sys_download
)
)
.setContentText("")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setProgress(PROGRESS_MAX, PROGRESS_CURR, false)
.setContentIntent(pendingIntent)
.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
.clearActions()
.build()
}
fun updateCacheMovingNotification(id: Int, progress: Int, totalFiles: Int) {
val notificationBuilder = getBuilder(DOWNLOAD_MISC_CHANNEL_ID)
val contentText = "${progress}/${totalFiles}"
try {
notificationBuilder.setProgress(100, progress, false)
.setContentTitle(context.getString(R.string.move_temporary_files))
.setStyle(NotificationCompat.BigTextStyle().bigText(contentText))
notificationManager.notify(id, notificationBuilder.build())
} catch (e: Exception) {
e.printStackTrace()
}
}
companion object {
const val DOWNLOAD_SERVICE_CHANNEL_ID = "1"
const val COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID = "2"
@ -290,6 +334,8 @@ class NotificationUtil(var context: Context) {
const val DOWNLOAD_FINISHED_NOTIFICATION_ID = 3
const val DOWNLOAD_RESUME_NOTIFICATION_ID = 4
const val DOWNLOAD_UPDATING_NOTIFICATION_ID = 5
const val DOWNLOAD_MISC_CHANNEL_ID = "4"
const val DOWNLOAD_MISC_NOTIFICATION_ID = 4
private const val PROGRESS_MAX = 100
private const val PROGRESS_CURR = 0
}

@ -52,7 +52,7 @@ import kotlinx.coroutines.withContext
import java.io.File
import java.util.Calendar
class UiUtil() {
object UiUtil {
@SuppressLint("SetTextI18n")
fun populateFormatCard(formatCard : MaterialCardView, chosenFormat: Format, audioFormats: List<Format>?){
formatCard.findViewById<TextView>(R.id.container).text = chosenFormat.container.uppercase()
@ -276,9 +276,9 @@ class UiUtil() {
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
}
try {
fragmentContext.startActivity(Intent.createChooser(shareIntent, null))
fragmentContext.startActivity(Intent.createChooser(shareIntent, fragmentContext.getString(R.string.share)))
}catch (e: Exception){
val intent = Intent.createChooser(shareIntent, null)
val intent = Intent.createChooser(shareIntent, fragmentContext.getString(R.string.share))
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
fragmentContext.startActivity(intent)
}

@ -73,6 +73,7 @@ class DownloadWorker(
}
val intent = Intent(context, MainActivity::class.java)
intent.putExtra("activedownload", "")
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val notification = notificationUtil.createDownloadServiceNotification(pendingIntent, downloadItem.title, downloadItem.id.toInt(), NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID)
val foregroundInfo = ForegroundInfo(downloadItem.id.toInt(), notification)
@ -316,14 +317,14 @@ class DownloadWorker(
}.onSuccess {
//move file from internal to set download directory
setProgressAsync(workDataOf("progress" to 100, "output" to "Moving file to ${FileUtil.formatPath(downloadLocation)}", "id" to downloadItem.id, "log" to logDownloads))
var finalPath : String?
var finalPaths : List<String>?
try {
finalPath = FileUtil.moveFile(tempFileDir.absoluteFile,context, downloadLocation, keepCache){ p ->
finalPaths = FileUtil.moveFile(tempFileDir.absoluteFile,context, downloadLocation, keepCache){ p ->
setProgressAsync(workDataOf("progress" to p, "output" to "Moving file to ${FileUtil.formatPath(downloadLocation)}", "id" to downloadItem.id, "log" to logDownloads))
}
setProgressAsync(workDataOf("progress" to 100, "output" to "Moved file to $finalPath", "id" to downloadItem.id, "log" to logDownloads))
setProgressAsync(workDataOf("progress" to 100, "output" to "Moved file to $downloadLocation", "id" to downloadItem.id, "log" to logDownloads))
}catch (e: Exception){
finalPath = context.getString(R.string.unfound_file)
finalPaths = listOf(context.getString(R.string.unfound_file))
e.printStackTrace()
handler.postDelayed({
Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show()
@ -336,9 +337,9 @@ class DownloadWorker(
val incognito = sharedPreferences.getBoolean("incognito", false)
if (!incognito) {
val unixtime = System.currentTimeMillis() / 1000
val file = File(finalPath!!)
val file = File(finalPaths?.first()!!)
downloadItem.format.filesize = if (file.exists()) file.length() else 0L
val historyItem = HistoryItem(0, downloadItem.url, downloadItem.title, downloadItem.author, downloadItem.duration, downloadItem.thumb, downloadItem.type, unixtime, finalPath, downloadItem.website, downloadItem.format, downloadItem.id)
val historyItem = HistoryItem(0, downloadItem.url, downloadItem.title, downloadItem.author, downloadItem.duration, downloadItem.thumb, downloadItem.type, unixtime, finalPaths.first(), downloadItem.website, downloadItem.format, downloadItem.id)
runBlocking {
historyDao.insert(historyItem)
}
@ -346,7 +347,7 @@ class DownloadWorker(
notificationUtil.cancelDownloadNotification(downloadItem.id.toInt())
notificationUtil.createDownloadFinished(
downloadItem.title, if (finalPath.equals(context.getString(R.string.unfound_file))) null else finalPath,
downloadItem.title, if (finalPaths?.first().equals(context.getString(R.string.unfound_file))) null else finalPaths,
NotificationUtil.DOWNLOAD_FINISHED_CHANNEL_ID
)

@ -0,0 +1,88 @@
package com.deniscerri.ytdlnis.work
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Environment
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.widget.Toast
import androidx.preference.PreferenceManager
import androidx.work.Data
import androidx.work.ForegroundInfo
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import com.deniscerri.ytdlnis.MainActivity
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.DBManager
import com.deniscerri.ytdlnis.database.dao.DownloadDao
import com.deniscerri.ytdlnis.database.dao.ResultDao
import com.deniscerri.ytdlnis.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.HistoryItem
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.util.FileUtil
import com.deniscerri.ytdlnis.util.InfoUtil
import com.deniscerri.ytdlnis.util.NotificationUtil
import com.yausername.youtubedl_android.YoutubeDL
import com.yausername.youtubedl_android.YoutubeDLRequest
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.io.File
import java.nio.file.Files
import java.nio.file.StandardCopyOption
class MoveCacheFilesWorker(
private val context: Context,
workerParams: WorkerParameters
) : Worker(context, workerParams) {
override fun doWork(): Result {
val notificationUtil = NotificationUtil(context)
val id = System.currentTimeMillis().toInt()
val downloadFolders = File(context.cacheDir.absolutePath + "/downloads")
val allContent = downloadFolders.walk()
allContent.drop(1)
val totalFiles = allContent.count()
val destination = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath + File.separator + "YTDLnis/CACHE_IMPORT")
val intent = Intent(context, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val notification = notificationUtil.createMoveCacheFilesNotification(pendingIntent, NotificationUtil.DOWNLOAD_MISC_CHANNEL_ID)
val foregroundInfo = ForegroundInfo(id, notification)
setForegroundAsync(foregroundInfo)
var progress = 0
allContent.forEach {
progress++
notificationUtil.updateCacheMovingNotification(id, progress, totalFiles)
val destFile = File(destination.absolutePath + "/${it.absolutePath.removePrefix(context.cacheDir.absolutePath + "/downloads")}")
if (it.isDirectory) {
destFile.mkdirs()
return@forEach
}
if (Build.VERSION.SDK_INT >= 26 ){
Files.move(it.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
}else{
it.renameTo(destFile)
}
}
val handler = Handler(Looper.getMainLooper())
handler.post {
Toast.makeText(context, context.getString(R.string.ok), Toast.LENGTH_SHORT).show()
}
return Result.success()
}
companion object {
const val TAG = "MoveCacheFilesWorker"
}
}

@ -14,6 +14,7 @@ import androidx.work.WorkerParameters
import androidx.work.workDataOf
import com.deniscerri.ytdlnis.MainActivity
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.ui.more.TerminalActivity
import com.deniscerri.ytdlnis.util.FileUtil
import com.deniscerri.ytdlnis.util.NotificationUtil
import com.yausername.youtubedl_android.YoutubeDL
@ -34,7 +35,7 @@ class TerminalDownloadWorker(
val notificationUtil = NotificationUtil(context)
val handler = Handler(Looper.getMainLooper())
val intent = Intent(context, MainActivity::class.java)
val intent = Intent(context, TerminalActivity::class.java)
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val notification = notificationUtil.createDownloadServiceNotification(pendingIntent, command.take(65), itemId, NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID)
val foregroundInfo = ForegroundInfo(itemId, notification)

@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:colorAccent" android:pathData="M20,6h-8l-2,-2L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,8c0,-1.1 -0.9,-2 -2,-2zM14,18v-3h-4v-4h4L14,8l5,5 -5,5z"/>
</vector>

@ -273,4 +273,6 @@
<string name="crop_thumb_summary">Crop the thumbnail into a square for audio downloads</string>
<string name="locale">Locale</string>
<string name="audio_only_item">This item only contains audio formats</string>
<string name="move_temporary_files">Move Temporary Files</string>
<string name="move_temporary_files_summary">Transfer cached files to the downloads folder</string>
</resources>

@ -23,6 +23,35 @@
android:summary="@string/access_all_directories_summary"
app:title="@string/access_all_directories" />
<EditTextPreference
android:icon="@drawable/ic_textformat"
app:key="file_name_template"
app:useSimpleSummaryProvider="true"
app:defaultValue="%(uploader)s - %(title)s"
app:title="@string/file_name_template" />
<EditTextPreference
android:icon="@drawable/ic_textformat"
app:key="file_name_template_audio"
app:useSimpleSummaryProvider="true"
app:defaultValue="%(uploader)s - %(title)s"
app:title="@string/file_name_template" />
<SwitchPreferenceCompat
android:widgetLayout="@layout/preferece_material_switch"
app:defaultValue="false"
app:icon="@drawable/if_file_rename"
app:key="restrict_filenames"
app:summary="@string/restrict_filenames_summary"
app:title="@string/restrict_filenames" />
<Preference
app:icon="@drawable/baseline_drive_file_move_24"
app:key="move_cache"
android:summary="@string/move_temporary_files_summary"
app:title="@string/move_temporary_files" />
<Preference
app:icon="@drawable/ic_folder_delete"
app:key="clear_cache"

@ -11,27 +11,6 @@
app:summary="@string/select_sponsorblock_filtering"
app:title="SponsorBlock" />
<EditTextPreference
android:icon="@drawable/ic_textformat"
app:key="file_name_template"
app:useSimpleSummaryProvider="true"
app:defaultValue="%(uploader)s - %(title)s"
app:title="@string/file_name_template" />
<EditTextPreference
android:icon="@drawable/ic_textformat"
app:key="file_name_template_audio"
app:useSimpleSummaryProvider="true"
app:defaultValue="%(uploader)s - %(title)s"
app:title="@string/file_name_template" />
<SwitchPreferenceCompat
android:widgetLayout="@layout/preferece_material_switch"
app:defaultValue="false"
app:icon="@drawable/if_file_rename"
app:key="restrict_filenames"
app:summary="@string/restrict_filenames_summary"
app:title="@string/restrict_filenames" />
<SwitchPreferenceCompat
android:widgetLayout="@layout/preferece_material_switch"

Loading…
Cancel
Save