This commit is contained in:
deniscerri 2023-04-29 17:57:07 +02:00
parent 794f591652
commit 98c1e20d51
No known key found for this signature in database
GPG key ID: 95C43D517D830350
17 changed files with 121 additions and 54 deletions

View file

@ -77,7 +77,7 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
if (title.length > 100) {
title = title.substring(0, 40) + "..."
}
itemTitle.text = title.ifEmpty { "`${activity.getString(R.string.defaultValue)}`" }
itemTitle.text = title.ifEmpty { "<${activity.getString(R.string.defaultValue)}>" }
// Author ----------------------------------
val author = card.findViewById<TextView>(R.id.author)
@ -86,7 +86,7 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
if (item.author.isNotEmpty()) info += ""
info += item.duration
}
author.text = info.ifEmpty { "`${activity.getString(R.string.defaultValue)}`" }
author.text = info.ifEmpty { "<${activity.getString(R.string.defaultValue)}>" }
val type = card.findViewById<MaterialButton>(R.id.download_type)
when(item.type){

View file

@ -73,7 +73,7 @@ class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
if (title.length > 100) {
title = title.substring(0, 40) + "..."
}
itemTitle.text = title.ifEmpty { "`${activity.getString(R.string.defaultValue)}`" }
itemTitle.text = title.ifEmpty { "<${activity.getString(R.string.defaultValue)}>" }
val formatNote = card.findViewById<TextView>(R.id.format_note)
if (item.format.format_note == "?" || item.format.format_note == "") formatNote!!.visibility =

View file

@ -20,7 +20,7 @@ data class DownloadItem(
var downloadSections: String,
val allFormats: ArrayList<Format>,
var downloadPath: String,
val website: String,
var website: String,
val downloadSize: String,
val playlistTitle: String,
val audioPreferences : AudioPreferences,

View file

@ -193,6 +193,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
if (arguments?.getString("url") != null){
val url = requireArguments().getString("url")
arguments?.remove("url")
if (inputQueries == null) inputQueries = mutableListOf()
searchBar?.text = url
inputQueries!!.add(url!!)
@ -202,6 +203,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
resultViewModel.deleteAll()
lifecycleScope.launch(Dispatchers.IO){
resultViewModel.parseQueries(inputQueries!!)
inputQueries = null
}
}
}

View file

@ -71,7 +71,7 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
behavior = BottomSheetBehavior.from(view.parent as View)
val displayMetrics = DisplayMetrics()
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
behavior.peekHeight = displayMetrics.heightPixels - 700
behavior.peekHeight = displayMetrics.heightPixels
}
@ -159,9 +159,9 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
scheduleBtn.setOnClickListener{
scheduleBtn.isEnabled = false
download.isEnabled = false
uiUtil.showDatePicker(fragmentManager) {
scheduleBtn.isEnabled = false
download.isEnabled = false
val item: DownloadItem = getDownloadItem();
item.downloadStartTime = it.timeInMillis
runBlocking {
@ -197,13 +197,13 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
(updateItem.parent as LinearLayout).visibility = View.VISIBLE
updateItem.setOnClickListener {
if (activity is ShareActivity) {
dismiss()
val intent = Intent(context, ShareActivity::class.java)
intent.action = Intent.ACTION_SEND
intent.type = "text/plain"
intent.putExtra(Intent.EXTRA_TEXT, resultItem.url)
intent.putExtra("quick_download", false)
startActivity(intent)
dismiss()
}else{
dismiss()
val bundle = Bundle()

View file

@ -106,9 +106,9 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
scheduleBtn.setOnClickListener{
scheduleBtn.isEnabled = false
download.isEnabled = false
uiUtil.showDatePicker(parentFragmentManager) {
scheduleBtn.isEnabled = false
download.isEnabled = false
items.forEach { item ->
item.downloadStartTime = it.timeInMillis
}

View file

@ -88,13 +88,13 @@ class SelectPlaylistItemsBottomSheetDialog(private val items: List<ResultItem?>,
val end = toTextInput.editText!!.text.toString()
if (checkRanges(start, end)) {
if (start < end){
if (start.toInt() < end.toInt()){
var startNr = Integer.parseInt(start)
startNr--
var endNr = Integer.parseInt(end)
endNr--
if (startNr <= 0) startNr = 0
if (endNr > items.size) endNr = items.size
if (endNr > items.size) endNr = items.size - 1
listAdapter.checkRange(startNr, endNr)
selectedText.text = "${listAdapter.getCheckedItems().size} ${resources.getString(R.string.selected)}"
}
@ -108,13 +108,13 @@ class SelectPlaylistItemsBottomSheetDialog(private val items: List<ResultItem?>,
val end = _text.toString()
if (checkRanges(start, end)) {
if (start < end){
if (start.toInt() < end.toInt()){
var startNr = Integer.parseInt(start)
startNr--
var endNr = Integer.parseInt(end)
endNr--
if (startNr <= 0) startNr = 0
if (endNr > items.size) endNr = items.size
if (endNr > items.size) endNr = items.size -1
listAdapter.checkRange(startNr, endNr)
selectedText.text = "${listAdapter.getCheckedItems().size} ${resources.getString(R.string.selected)}"
}

View file

@ -120,7 +120,7 @@ class ActiveDownloadsFragment() : Fragment(), ActiveDownloadAdapter.OnItemClickL
val logFile = fileUtil.getLogFile(requireContext(), item)
if (logFile.exists()) {
val intent = Intent(requireContext(), DownloadLogActivity::class.java)
intent.putExtra("path", logFile.absolutePath)
intent.putExtra("logpath", logFile.absolutePath)
startActivity(intent)
}
}

View file

@ -105,7 +105,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
val item = items.find { it.id == itemID } ?: return
val file = fileUtil.getLogFile(requireContext(), item)
val intent = Intent(requireContext(), DownloadLogActivity::class.java)
intent.putExtra("path", file.absolutePath)
intent.putExtra("logpath", file.absolutePath)
startActivity(intent)
}

View file

@ -45,7 +45,7 @@ class DownloadLogActivity : BaseActivity() {
clipboard.setText(content.text)
}
val path = intent.getStringExtra("path")
val path = intent.getStringExtra("logpath")
if (path == null) {
onBackPressedDispatcher.onBackPressed()
}

View file

@ -125,7 +125,7 @@ class DownloadLogListActivity : BaseActivity(), DownloadLogsAdapter.OnItemClickL
override fun onItemClick(file: File) {
val intent = Intent(this, DownloadLogActivity::class.java)
intent.putExtra("path", file.absolutePath)
intent.putExtra("logpath", file.absolutePath)
startActivity(intent)
}

View file

@ -7,6 +7,7 @@ import android.os.Looper
import android.util.Log
import android.widget.Toast
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.Format
import com.deniscerri.ytdlnis.database.models.ResultItem
import com.google.gson.Gson
@ -674,6 +675,51 @@ class InfoUtil(private val context: Context) {
return items
}
fun getMissingInfo(url: String): ResultItem? {
try {
val request = YoutubeDLRequest(url)
request.addOption("--flat-playlist")
request.addOption("-J")
request.addOption("--skip-download")
request.addOption("-R", "1")
request.addOption("--socket-timeout", "5")
val cookiesFile = File(context.cacheDir, "cookies.txt")
if (cookiesFile.exists()){
request.addOption("--cookies", cookiesFile.absolutePath)
}
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
val jsonObject = JSONObject(youtubeDLResponse.out)
val thumbs = jsonObject.getJSONArray("thumbnails")
val thumb = thumbs.getJSONObject(thumbs.length() - 1).getString("url")
val isPlaylist = jsonObject.has("playlist_count")
return ResultItem(
0,
url,
if (isPlaylist){
"[${jsonObject.getInt("playlist_count")} Items] ${jsonObject.getString("title")}"
}else{
jsonObject.getString("title")
},
jsonObject.getString("uploader"),
if (jsonObject.has("duration")) formatIntegerDuration(jsonObject.getInt("duration"), Locale.US) else "",
thumb,
jsonObject.getString("extractor"),
if (isPlaylist) jsonObject.getString("title") else "",
arrayListOf(),
System.currentTimeMillis()
)
} catch (e: Exception) {
Looper.prepare().run {
Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
}
e.printStackTrace()
}
return null
}
fun getSearchSuggestions(query: String): ArrayList<String> {
val url = "https://suggestqueries.google.com/complete/search?client=youtube&ds=yt&client=firefox&q=$query"
// invidousURL + "search/suggestions?q=" + query

View file

@ -1,9 +1,6 @@
package com.deniscerri.ytdlnis.util
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.*
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
@ -140,16 +137,22 @@ class NotificationUtil(var context: Context) {
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)
val openNotificationPendingIntent: PendingIntent = TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(intent)
getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT or 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)
val shareNotificationPendingIntent: PendingIntent = TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(shareIntent)
getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
notificationBuilder.addAction(0, context.getString(R.string.Open_File), openNotificationPendingIntent)
notificationBuilder.addAction(0, context.getString(R.string.share), shareNotificationPendingIntent)
@ -160,31 +163,34 @@ class NotificationUtil(var context: Context) {
fun createDownloadErrored(title: String?,
error: String?,
logFilePath: String?,
logFile: File?,
channel: String
) {
val notificationBuilder = getBuilder(channel)
val intent = Intent(context, DownloadLogActivity::class.java)
intent.putExtra("path", logFilePath)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
val errorPendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
intent.putExtra("logpath", logFile?.absolutePath)
val errorPendingIntent: PendingIntent = TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(intent)
getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
notificationBuilder
.setContentTitle("${context.getString(R.string.failed_download)}: $title")
.setContentText(error)
.setContentIntent(errorPendingIntent)
.setSmallIcon(R.drawable.ic_app_icon)
.setSmallIcon(R.drawable.ic_launcher_foreground_large)
.setLargeIcon(
BitmapFactory.decodeResource(
context.resources,
R.drawable.ic_app_icon
R.drawable.ic_launcher_foreground_large
)
)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.clearActions()
if (logFilePath != null){
if (logFile != null){
notificationBuilder.setContentIntent(errorPendingIntent)
notificationBuilder.addAction(0, context.getString(R.string.logs), errorPendingIntent)
}
notificationManager.notify(DOWNLOAD_FINISHED_NOTIFICATION_ID, notificationBuilder.build())

View file

@ -268,6 +268,22 @@ class DownloadWorker(
}
}
//update item if its incomplete
if (downloadItem.title.isEmpty() || downloadItem.author.isEmpty() || downloadItem.thumb.isEmpty()){
runCatching {
setProgressAsync(workDataOf("progress" to 0, "output" to "Updating Download Item Data", "id" to downloadItem.id, "log" to false))
val info = infoUtil.getMissingInfo(downloadItem.url)
if (downloadItem.title.isEmpty()) downloadItem.title = info?.title.toString()
if (downloadItem.author.isEmpty()) downloadItem.author = info?.author.toString()
if (downloadItem.thumb.isEmpty()) downloadItem.thumb = info?.thumb.toString()
downloadItem.duration = info?.duration.toString()
downloadItem.website = info?.website.toString()
runBlocking {
dao.update(downloadItem)
}
}
}
val logDownloads = sharedPreferences.getBoolean("log_downloads", false) && !sharedPreferences.getBoolean("incognito", false)
val logFolder = File(context.filesDir.absolutePath + "/logs")
val logFile = fileUtil.getLogFile(context, downloadItem)
@ -282,21 +298,6 @@ class DownloadWorker(
"Format: ${downloadItem.format}\n\n")
}
//update item if its incomplete
if (downloadItem.title.isEmpty() || downloadItem.author.isEmpty() || downloadItem.thumb.isEmpty()){
runCatching {
setProgressAsync(workDataOf("progress" to 0, "output" to "Updating Download Item Data", "id" to downloadItem.id, "log" to logDownloads))
val info = YoutubeDL.getInfo(downloadItem.url)
if (downloadItem.title.isEmpty()) downloadItem.title = info.title.toString()
if (downloadItem.author.isEmpty()) downloadItem.author = info.uploader.toString()
if (downloadItem.thumb.isEmpty()) downloadItem.thumb = info.thumbnail.toString()
downloadItem.duration = infoUtil.formatIntegerDuration(info.duration, Locale.US)
runBlocking {
dao.update(downloadItem)
}
}
}
runCatching {
YoutubeDL.getInstance().execute(request, downloadItem.id.toString()){ progress, _, line ->
setProgressAsync(workDataOf("progress" to progress.toInt(), "output" to line.chunked(5000).first().toString(), "id" to downloadItem.id, "log" to logDownloads))
@ -376,7 +377,7 @@ class DownloadWorker(
notificationUtil.createDownloadErrored(
downloadItem.title, it.message,
if (logDownloads) logFile.absolutePath else null,
if (logDownloads) logFile else null,
NotificationUtil.DOWNLOAD_FINISHED_CHANNEL_ID
)

View file

@ -15,7 +15,7 @@
android:checkable="true"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:backgroundTint="@android:color/transparent"
app:cardPreventCornerOverlap="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@ -178,12 +178,13 @@
<com.google.android.material.button.MaterialButton
android:id="@+id/action_button"
style="?attr/materialIconButtonStyle"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:padding="0dp"
android:minHeight="0dp"
android:layout_height="wrap_content"
app:cornerRadius="10dp"
app:iconTint="?attr/colorAccent"
app:icon="@drawable/ic_video"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />

View file

@ -5,7 +5,7 @@ buildscript {
def versionMajor = 1
def versionMinor = 6
def versionPatch = 0
def versionPatch = 1
def versionBuild = 0 // bump for dogfood builds, public betas, etc.
ext {

View file

@ -0,0 +1,11 @@
## Introducing Quick Download Mode
You can launch a download (or card) immediately without fetching data at first.
Added Theme Picker, Accents and High Contrast Mode
Added swipe actions on history,downloads,cookies,templates cards
Added finished download notification with actions
Fixed Tiktok videos not creating result cards
Added active downloads badge in the navigation bar
Added remove audio feature for videos
Added check for present downloads
Added preferred Format ID