fixed download logs text not being highlightable, fixed app not deleting some cached files, filed filenames being too short, fixed sometimes error output not being shown in terminal output, added keyboard focus when adding template in the terminal, made the loading of video player faster when you are cutting it

This commit is contained in:
deniscerri 2023-04-03 22:12:30 +02:00
parent daac3fd241
commit f88bfab70e
No known key found for this signature in database
GPG key ID: 95C43D517D830350
12 changed files with 92 additions and 106 deletions

View file

@ -94,7 +94,7 @@ class HistoryAdapter(onItemClickListener: OnItemClickListener, activity: Activit
// System.currentTimeMillis(),
// DateUtils.MINUTE_IN_MILLIS
// )
datetime.text = SimpleDateFormat(DateFormat.getBestDateTimePattern(Locale.getDefault(), "ddMMMyyyy - HHmm"), Locale.getDefault()).format(item.time * 1000L)
datetime.text = SimpleDateFormat(android.text.format.DateFormat.getBestDateTimePattern(Locale.getDefault(), "ddMMMyyyy - HHmm"), Locale.getDefault()).format(item.time * 1000L)
// BUTTON ----------------------------------
val btn = card.findViewById<MaterialButton>(R.id.downloads_download_button_type)

View file

@ -24,6 +24,7 @@ import com.deniscerri.ytdlnis.work.DownloadWorker
import com.google.gson.Gson
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.sql.Date
import java.text.SimpleDateFormat
import java.util.*
@ -310,7 +311,9 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
).enqueue()
}
items.forEach {
it.id = repository.checkIfReDownloadingErroredOrCancelled(it)
it.id = withContext(Dispatchers.IO){
repository.checkIfReDownloadingErroredOrCancelled(it)
}
if (it.id != 0L){
repository.delete(it)
}

View file

@ -107,21 +107,20 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
}
if (url.isBlank()) throw Exception("No Streaming URL found!")
Log.e("aa", url.split("\n")[0])
Log.e("aa", url.split("\n")[1])
val urls = url.split("\n")
if (urls.size == 2){
val audioSource: MediaSource =
DefaultMediaSourceFactory(requireContext())
.createMediaSource(fromUri(Uri.parse(urls[0])))
val videoSource: MediaSource =
DefaultMediaSourceFactory(requireContext())
.createMediaSource(fromUri(Uri.parse(urls[1])))
(player as ExoPlayer).setMediaSource(MergingMediaSource(videoSource, audioSource))
}else{
player.addMediaItem(fromUri(Uri.parse(urls[0])))
}
// val urls = url.split("\n")
// if (urls.size == 2){
// val audioSource: MediaSource =
// DefaultMediaSourceFactory(requireContext())
// .createMediaSource(fromUri(Uri.parse(urls[0])))
// val videoSource: MediaSource =
// DefaultMediaSourceFactory(requireContext())
// .createMediaSource(fromUri(Uri.parse(urls[1])))
// (player as ExoPlayer).setMediaSource(MergingMediaSource(videoSource, audioSource))
// }else{
// player.addMediaItem(fromUri(Uri.parse(urls[0])))
// }
player.addMediaItem(fromUri(Uri.parse(url)))
progress.visibility = View.GONE

View file

@ -9,6 +9,7 @@ import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.ScrollView
@ -17,11 +18,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.*
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel
import com.deniscerri.ytdlnis.util.NotificationUtil
@ -109,9 +106,7 @@ class TerminalActivity : AppCompatActivity() {
input!!.requestFocus()
hideCancelFab()
}
val line = work.progress.getString("output") ?: return@observe
val id = work.progress.getInt("id", 0)
if(id == 0) return@observe
val line = work.progress.getString("output") ?: (work.outputData.getString("output") ?: return@observe)
runOnUiThread {
try {
output!!.text = "${output!!.text}\n$line"
@ -168,6 +163,11 @@ class TerminalActivity : AppCompatActivity() {
item.setOnClickListener {
input!!.text.insert(input!!.selectionStart, template.content + " ")
bottomSheet.cancel()
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
input!!.postDelayed({
input!!.requestFocus()
imm.showSoftInput(input!!, 0)
}, 200)
}
linearLayout.addView(item)
}

View file

@ -34,6 +34,7 @@ class DownloadLogActivity : AppCompatActivity() {
}
content = findViewById(R.id.content)
content.setTextIsSelectable(true)
contentScrollView = findViewById(R.id.content_scrollview)
copyLog = findViewById(R.id.copy_log)

View file

@ -28,6 +28,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.yausername.youtubedl_android.YoutubeDL
import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json
import java.io.File
import java.util.*
@ -135,15 +136,11 @@ class SettingsFragment : PreferenceFragmentCompat() {
version!!.summary = BuildConfig.VERSION_NAME
val values = resources.getStringArray(R.array.language_values)
if (Build.VERSION.SDK_INT >= 33 || Build.VERSION.SDK_INT < 24){
language!!.isVisible = false
}else{
val entries = mutableListOf<String>()
values.forEach {
entries.add(Locale(it).getDisplayName(Locale(it)))
}
language!!.entries = entries.toTypedArray()
val entries = mutableListOf<String>()
values.forEach {
entries.add(Locale(it).getDisplayName(Locale(it)))
}
language!!.entries = entries.toTypedArray()
val lang = if (values.contains(Locale.getDefault().language)) Locale.getDefault().language else "en"
editor.putString("app_language", lang)
@ -258,14 +255,14 @@ class SettingsFragment : PreferenceFragmentCompat() {
true
}
var cacheSize = requireContext().cacheDir.walkBottomUp().fold(0L) { acc, file -> acc + file.length() }
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 =
Preference.OnPreferenceClickListener {
if (activeDownloadCount == 0){
requireContext().cacheDir.deleteRecursively()
File(requireContext().cacheDir.absolutePath + "/downloads").deleteRecursively()
Toast.makeText(requireContext(), getString(R.string.cache_cleared), Toast.LENGTH_SHORT).show()
cacheSize = requireContext().cacheDir.walkBottomUp().fold(0L) { acc, file -> acc + file.length() }
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)}"
}else{
Toast.makeText(requireContext(), getString(R.string.downloads_running_try_later), Toast.LENGTH_SHORT).show()

View file

@ -132,13 +132,13 @@ class FileUtil() {
}
}
originDir.delete()
originDir.deleteRecursively()
return scanMedia(fileList, context)
}
fun getLogFile(context: Context, item: DownloadItem) : File {
val titleRegex = Regex("[^A-Za-z\\d ]")
return File(context.filesDir.absolutePath + """/logs/${item.id} - ${titleRegex.replace(item.title, "")}##${item.type}##${item.format.format_id}.log""")
return File(context.filesDir.absolutePath + """/logs/${item.id} - ${titleRegex.replace(item.title, "").take(150)}##${item.type}##${item.format.format_id}.log""")
}
fun getLogFileForTerminal(context: Context, command: String) : File {
val titleRegex = Regex("[^A-Za-z\\d ]")

View file

@ -630,23 +630,13 @@ class InfoUtil(context: Context) {
}
fun getStreamingUrl(url: String) : String {
try {
return try {
val request = YoutubeDLRequest(url)
request.addOption("-j")
request.addOption("--skip-download")
request.addOption("-R", "1")
request.addOption("--socket-timeout", "5")
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
val results: Array<String?> = try {
val lineSeparator = System.getProperty("line.separator")
youtubeDLResponse.out.split(lineSeparator!!).toTypedArray()
} catch (e: Exception) {
arrayOf(youtubeDLResponse.out)
}
val jsonObject = JSONObject(results[0]!!)
return jsonObject.getString("urls")
request.addOption("-f", "best")
val youtubeDlInfo = YoutubeDL.getInstance().getInfo(request)
youtubeDlInfo.url ?: ""
} catch (e: Exception) {
return ""
""
}
}

View file

@ -8,10 +8,7 @@ import android.os.Handler
import android.os.Looper
import android.util.Log
import android.widget.Toast
import androidx.work.ForegroundInfo
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import androidx.work.*
import com.deniscerri.ytdlnis.MainActivity
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.DBManager
@ -69,9 +66,9 @@ class DownloadWorker(
val type = downloadItem.type
val downloadLocation = downloadItem.downloadPath
val tempFileDir = File(context.cacheDir.absolutePath + "/" + downloadItem.id)
val tempFileDir = File(context.cacheDir.absolutePath + "/downloads/" + downloadItem.id)
tempFileDir.delete()
tempFileDir.mkdir()
tempFileDir.mkdirs()
val sharedPreferences = context.getSharedPreferences("root_preferences",
Service.MODE_PRIVATE
@ -111,10 +108,10 @@ class DownloadWorker(
}
if(downloadItem.title.isNotBlank()){
request.addCommands(listOf("--replace-in-metadata","title",".*.",downloadItem.title))
request.addCommands(listOf("--replace-in-metadata","title",".*.",downloadItem.title.take(200)))
}
if (downloadItem.author.isNotBlank()){
request.addCommands(listOf("--replace-in-metadata","uploader",".*.",downloadItem.author))
request.addCommands(listOf("--replace-in-metadata","uploader",".*.",downloadItem.author.take(25)))
}
if (downloadItem.customFileNameTemplate.isBlank()) downloadItem.customFileNameTemplate = "%(uploader)s - %(title)s"
@ -127,8 +124,6 @@ class DownloadWorker(
request.addOption("--restrict-filenames")
}
request.addOption("--trim-filenames", 100)
when(type){
DownloadViewModel.Type.audio -> {
request.addOption("-x")
@ -150,7 +145,7 @@ class DownloadWorker(
request.addOption("--embed-thumbnail")
request.addOption("--convert-thumbnails", "png")
try {
val config = File(context.cacheDir, "config" + downloadItem.title + "##" + downloadItem.format.format_id + ".txt")
val config = File(context.cacheDir.absolutePath + "/downloads/config" + downloadItem.title + "##" + downloadItem.format.format_id + ".txt")
val configData =
"--ppa \"ffmpeg: -c:v png -vf crop=\\\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\\\"\""
config.writeText(configData)
@ -177,6 +172,7 @@ class DownloadWorker(
DownloadViewModel.Type.video -> {
if (downloadItem.videoPreferences.addChapters) {
request.addOption("--sponsorblock-mark", "all")
request.addOption("--embed-chapters")
}
if (downloadItem.videoPreferences.embedSubs) {
request.addOption("--embed-subs", "")
@ -216,7 +212,7 @@ class DownloadWorker(
DownloadViewModel.Type.command -> {
request.addOption(
"--config-locations",
File(context.cacheDir, "config${System.currentTimeMillis()}.txt").apply {
File(context.cacheDir.absolutePath + "/downloads/config${System.currentTimeMillis()}.txt").apply {
writeText(downloadItem.format.format_note)
}.absolutePath
)
@ -255,12 +251,13 @@ class DownloadWorker(
}
}.onSuccess {
//move file from internal to set download directory
setProgressAsync(workDataOf("progress" to 100, "output" to "Moving file to $downloadLocation", "id" to downloadItem.id, "log" to logDownloads))
var finalPath : String?
try {
finalPath = moveFile(tempFileDir.absoluteFile, downloadLocation){ progress ->
setProgressAsync(workDataOf("progress" to progress))
setProgressAsync(workDataOf("progress" to progress, "output" to "Moving file to $downloadLocation", "id" to downloadItem.id, "log" to logDownloads))
}
setProgressAsync(workDataOf("progress" to 1000, "output" to "Moved file to $finalPath", "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))
}catch (e: Exception){
finalPath = context.getString(R.string.unfound_file)
e.printStackTrace()
@ -288,7 +285,9 @@ class DownloadWorker(
runBlocking {
dao.update(downloadItem)
}
return Result.failure()
return Result.failure(
Data.Builder().putString("output", "Download has been cancelled!").build()
)
}else{
if (logDownloads && logFile.exists()){
logFile.appendText("${it.message}\n")
@ -310,7 +309,9 @@ class DownloadWorker(
runBlocking {
dao.update(downloadItem)
}
return Result.failure()
return Result.failure(
Data.Builder().putString("output", it.toString()).build()
)
}
}

View file

@ -8,10 +8,7 @@ import android.os.Handler
import android.os.Looper
import android.util.Log
import android.widget.Toast
import androidx.work.ForegroundInfo
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import androidx.work.*
import com.deniscerri.ytdlnis.MainActivity
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.util.FileUtil
@ -48,13 +45,13 @@ class TerminalDownloadWorker(
)
val downloadLocation = sharedPreferences.getString("command_path", context.getString(R.string.command_path))
val tempFileDir = File(context.cacheDir.absolutePath + "/" + itemId)
val tempFileDir = File(context.cacheDir.absolutePath + "/downloads/" + itemId)
tempFileDir.delete()
tempFileDir.mkdir()
tempFileDir.mkdirs()
request.addOption(
"--config-locations",
File(context.cacheDir, "config${System.currentTimeMillis()}.txt").apply {
File(context.cacheDir.absolutePath + "/downloads/config${System.currentTimeMillis()}.txt").apply {
writeText(command)
}.absolutePath
)
@ -93,7 +90,6 @@ class TerminalDownloadWorker(
finalPath = moveFile(tempFileDir.absoluteFile, downloadLocation!!){ progress ->
setProgressAsync(workDataOf("progress" to progress))
}
setProgressAsync(workDataOf("progress" to 100, "output" to "Moved file to $finalPath", "id" to itemId, "log" to logDownloads))
}catch (e: Exception){
finalPath = context.getString(R.string.unfound_file)
e.printStackTrace()
@ -101,20 +97,7 @@ class TerminalDownloadWorker(
Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show()
}, 1000)
}
//put download in history
// val incognito = sharedPreferences.getBoolean("incognito", false)
// if (!incognito) {
// val unixtime = System.currentTimeMillis() / 1000
// val file = File(finalPath!!)
// 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)
// runBlocking {
// historyDao.insert(historyItem)
// }
// }
// runBlocking {
// dao.delete(downloadItem.id)
// }
}.onFailure {
if (it is YoutubeDL.CanceledException) {
return Result.failure()
@ -123,8 +106,6 @@ class TerminalDownloadWorker(
if (logDownloads && logFile.exists()){
logFile.appendText("${it.message}\n")
}
setProgressAsync(workDataOf("progress" to -1, "output" to it.message, "id" to itemId, "log" to logDownloads))
tempFileDir.delete()
Log.e(TAG, context.getString(R.string.failed_download), it)
@ -133,7 +114,14 @@ class TerminalDownloadWorker(
context.getString(R.string.failed_download), 0, 0, command.take(20),
NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID
)
return Result.failure()
if (logDownloads && logFile.exists()){
logFile.appendText("${it.message}\n")
}
return Result.failure(
Data.Builder().putString("output", it.message.toString()).build()
)
}
return Result.success()

View file

@ -105,13 +105,13 @@
<HorizontalScrollView
android:id="@+id/linearlayout2_horizontalscrollview"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:scrollbars="none"
android:paddingTop="10dp"
android:scrollbars="none"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/barrier"
app:layout_constraintVertical_bias="1.0">
app:layout_constraintTop_toBottomOf="@+id/barrier">
<com.google.android.material.chip.ChipGroup
android:id="@+id/linearLayout2"

View file

@ -27,7 +27,6 @@
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
android:orientation="vertical">
<ScrollView
@ -38,15 +37,23 @@
android:paddingBottom="150dp"
>
<TextView
android:id="@+id/content"
android:padding="10dp"
android:fontFamily="monospace"
android:textSize="15sp"
android:gravity="bottom"
<LinearLayout
android:layout_width="match_parent"
android:textIsSelectable="true"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:orientation="vertical">
<TextView
android:id="@+id/content"
android:padding="10dp"
android:fontFamily="monospace"
android:textSize="15sp"
android:gravity="bottom"
android:layout_width="match_parent"
android:textIsSelectable="true"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>