reverted terminal mode to rxjava for simplicity sake
This commit is contained in:
parent
5482105a18
commit
3937dd6e4c
6 changed files with 142 additions and 99 deletions
|
|
@ -38,8 +38,7 @@ class Converters {
|
||||||
return when(string){
|
return when(string){
|
||||||
"audio" -> DownloadViewModel.Type.audio
|
"audio" -> DownloadViewModel.Type.audio
|
||||||
"video" -> DownloadViewModel.Type.video
|
"video" -> DownloadViewModel.Type.video
|
||||||
"command" -> DownloadViewModel.Type.command
|
else -> DownloadViewModel.Type.command
|
||||||
else -> DownloadViewModel.Type.terminal
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,4 @@ interface DownloadDao {
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE url=:url AND format=:format AND (status='Error' OR status='Cancelled') LIMIT 1")
|
@Query("SELECT * FROM downloads WHERE url=:url AND format=:format AND (status='Error' OR status='Cancelled') LIMIT 1")
|
||||||
fun getUnfinishedByURLAndFormat(url: String, format: String) : DownloadItem
|
fun getUnfinishedByURLAndFormat(url: String, format: String) : DownloadItem
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE type='terminal' ORDER BY id DESC LIMIT 1")
|
|
||||||
fun getTerminalDownload() : DownloadItem
|
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +65,4 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTerminalDownload() : Long {
|
|
||||||
return downloadDao.getTerminalDownload().id
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +37,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
private var bestVideoFormat : Format
|
private var bestVideoFormat : Format
|
||||||
private var bestAudioFormat : Format
|
private var bestAudioFormat : Format
|
||||||
enum class Type {
|
enum class Type {
|
||||||
audio, video, command, terminal
|
audio, video, command
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
@ -204,39 +204,4 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startTerminalDownload(command: String) = viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
val downloadPath = sharedPreferences.getString("command_path", getApplication<App>().resources.getString(R.string.command_path))
|
|
||||||
val downloadItem = DownloadItem(0,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
Type.terminal,
|
|
||||||
Format("", "", 0, command),
|
|
||||||
downloadPath!!, "", "", "", AudioPreferences(), VideoPreferences(), "", false, DownloadRepository.Status.Processing.toString(), 0
|
|
||||||
)
|
|
||||||
|
|
||||||
downloadItem.status = DownloadRepository.Status.Queued.toString()
|
|
||||||
Log.e("aaaaaaaa", downloadItem.toString())
|
|
||||||
val id = repository.insert(downloadItem)
|
|
||||||
downloadItem.id = id
|
|
||||||
|
|
||||||
val workRequest = OneTimeWorkRequestBuilder<DownloadWorker>()
|
|
||||||
.setInputData(Data.Builder().putLong("id", downloadItem.id).build())
|
|
||||||
.addTag("terminal")
|
|
||||||
.build()
|
|
||||||
val context = getApplication<App>().applicationContext
|
|
||||||
WorkManager.getInstance(context).beginUniqueWork(
|
|
||||||
downloadItem.id.toString(),
|
|
||||||
ExistingWorkPolicy.KEEP,
|
|
||||||
workRequest
|
|
||||||
).enqueue()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun getTerminalDownload(): Long {
|
|
||||||
return repository.getTerminalDownload();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package com.deniscerri.ytdlnis.ui
|
package com.deniscerri.ytdlnis.ui
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
|
import android.app.Notification
|
||||||
|
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.PackageManager
|
||||||
|
|
@ -10,36 +12,36 @@ import android.view.View
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.ScrollView
|
import android.widget.ScrollView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.lifecycle.Observer
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.work.WorkInfo
|
|
||||||
import androidx.work.WorkManager
|
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
import com.deniscerri.ytdlnis.service.IDownloaderService
|
|
||||||
import com.deniscerri.ytdlnis.util.NotificationUtil
|
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||||
|
import com.deniscerri.ytdlnis.work.DownloadWorker
|
||||||
import com.google.android.material.appbar.MaterialToolbar
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
import com.yausername.youtubedl_android.YoutubeDL
|
import com.yausername.youtubedl_android.YoutubeDL
|
||||||
import kotlinx.coroutines.Dispatchers
|
import com.yausername.youtubedl_android.YoutubeDLRequest
|
||||||
|
import io.reactivex.Observable
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
|
import io.reactivex.disposables.Disposable
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import java.io.File
|
||||||
import kotlinx.coroutines.withContext
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
|
||||||
class CustomCommandActivity : AppCompatActivity() {
|
class CustomCommandActivity : AppCompatActivity() {
|
||||||
private var topAppBar: MaterialToolbar? = null
|
private var topAppBar: MaterialToolbar? = null
|
||||||
private lateinit var downloadViewModel: DownloadViewModel
|
|
||||||
private lateinit var notificationUtil: NotificationUtil
|
private lateinit var notificationUtil: NotificationUtil
|
||||||
private lateinit var workManager: WorkManager
|
|
||||||
private var isDownloadServiceRunning = false
|
|
||||||
private var output: TextView? = null
|
private var output: TextView? = null
|
||||||
private var input: EditText? = null
|
private var input: EditText? = null
|
||||||
private var fab: ExtendedFloatingActionButton? = null
|
private var fab: ExtendedFloatingActionButton? = null
|
||||||
private var cancelFab: ExtendedFloatingActionButton? = null
|
private var cancelFab: ExtendedFloatingActionButton? = null
|
||||||
private var iDownloaderService: IDownloaderService? = null
|
|
||||||
private var scrollView: ScrollView? = null
|
private var scrollView: ScrollView? = null
|
||||||
var context: Context? = null
|
var context: Context? = null
|
||||||
|
|
||||||
|
|
@ -56,6 +58,9 @@ class CustomCommandActivity : AppCompatActivity() {
|
||||||
input!!.requestFocus()
|
input!!.requestFocus()
|
||||||
fab = findViewById(R.id.command_fab)
|
fab = findViewById(R.id.command_fab)
|
||||||
fab!!.setOnClickListener {
|
fab!!.setOnClickListener {
|
||||||
|
input!!.isEnabled = false
|
||||||
|
output!!.text = ""
|
||||||
|
swapFabs()
|
||||||
startDownload(
|
startDownload(
|
||||||
input!!.text.toString()
|
input!!.text.toString()
|
||||||
)
|
)
|
||||||
|
|
@ -65,9 +70,7 @@ class CustomCommandActivity : AppCompatActivity() {
|
||||||
cancelDownload()
|
cancelDownload()
|
||||||
input!!.isEnabled = true
|
input!!.isEnabled = true
|
||||||
}
|
}
|
||||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
|
||||||
notificationUtil = NotificationUtil(this)
|
notificationUtil = NotificationUtil(this)
|
||||||
workManager = WorkManager.getInstance(this)
|
|
||||||
handleIntent(intent)
|
handleIntent(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,33 +91,141 @@ class CustomCommandActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun swapFabs() {
|
||||||
|
val cancel = cancelFab!!.visibility
|
||||||
|
val start = fab!!.visibility
|
||||||
|
cancelFab!!.visibility = start
|
||||||
|
fab!!.visibility = cancel
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun startDownload(command: String?) {
|
private fun startDownload(command: String?) {
|
||||||
if (isDownloadServiceRunning) return
|
downloadID = System.currentTimeMillis().toInt()
|
||||||
downloadViewModel.startTerminalDownload(command!!)
|
|
||||||
output!!.text = ""
|
val theIntent = Intent(this, CustomCommandActivity::class.java)
|
||||||
workManager.getWorkInfosByTagLiveData("terminal")
|
val pendingIntent = PendingIntent.getActivity(this, 0, theIntent, PendingIntent.FLAG_IMMUTABLE)
|
||||||
.observe(this){ list ->
|
|
||||||
list.forEach {
|
val commandNotification: Notification =
|
||||||
if(it.progress.getString("output") != null){
|
notificationUtil.createDownloadServiceNotification(
|
||||||
output?.append("\n" + it.progress.getString("output") + "\n")
|
pendingIntent,
|
||||||
output?.scrollTo(0, output!!.height)
|
getString(R.string.terminal),
|
||||||
scrollView?.fullScroll(View.FOCUS_DOWN)
|
downloadID,
|
||||||
|
NotificationUtil.COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID
|
||||||
|
)
|
||||||
|
with(NotificationManagerCompat.from(this)){
|
||||||
|
if (ActivityCompat.checkSelfPermission(
|
||||||
|
context!!,
|
||||||
|
Manifest.permission.POST_NOTIFICATIONS
|
||||||
|
) == PackageManager.PERMISSION_GRANTED
|
||||||
|
) {
|
||||||
|
notify(downloadID, commandNotification)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val commandRegex = "\"([^\"]*)\"|(\\S+)"
|
||||||
|
val request = YoutubeDLRequest(emptyList())
|
||||||
|
|
||||||
|
val tempFolder = StringBuilder(context!!.cacheDir.absolutePath + """/${command}##terminal""")
|
||||||
|
val tempFileDir = File(tempFolder.toString())
|
||||||
|
tempFileDir.delete()
|
||||||
|
tempFileDir.mkdir()
|
||||||
|
|
||||||
|
|
||||||
|
val m = Pattern.compile(commandRegex).matcher(command!!)
|
||||||
|
while (m.find()) {
|
||||||
|
if (m.group(1) != null) {
|
||||||
|
request.addOption(m.group(1)!!)
|
||||||
|
} else {
|
||||||
|
request.addOption(m.group(2)!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request.addOption("-o", tempFileDir.absolutePath + "/%(uploader)s - %(title)s.%(ext)s")
|
||||||
|
|
||||||
|
cancelFab!!.visibility = View.VISIBLE
|
||||||
|
fab!!.visibility = View.GONE
|
||||||
|
|
||||||
|
val disposable: Disposable = Observable.fromCallable {
|
||||||
|
try{
|
||||||
|
YoutubeDL.getInstance().execute(request, downloadID.toString()){ progress, _, line ->
|
||||||
|
runOnUiThread {
|
||||||
|
output!!.append("\n" + line)
|
||||||
|
output!!.scrollTo(0, output!!.height)
|
||||||
|
scrollView!!.fullScroll(View.FOCUS_DOWN)
|
||||||
|
|
||||||
|
val title: String = getString(R.string.terminal)
|
||||||
|
notificationUtil.updateDownloadNotification(
|
||||||
|
downloadID,
|
||||||
|
line, progress.toInt(), 0, title,
|
||||||
|
NotificationUtil.COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}catch (e: Exception){
|
||||||
|
e.printStackTrace()
|
||||||
|
runOnUiThread {
|
||||||
|
input!!.isEnabled = true
|
||||||
|
|
||||||
|
cancelFab!!.visibility = View.GONE
|
||||||
|
fab!!.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.subscribeOn(Schedulers.newThread())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({
|
||||||
|
scrollView!!.scrollTo(0, scrollView!!.maxScrollAmount);
|
||||||
|
input!!.setText("yt-dlp ");
|
||||||
|
input!!.isEnabled = true;
|
||||||
|
|
||||||
|
cancelFab!!.visibility = View.GONE
|
||||||
|
fab!!.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
//move file from internal to set download directory
|
||||||
|
try {
|
||||||
|
moveFile(tempFileDir.absoluteFile, getString(R.string.command_path)){ }
|
||||||
|
}catch (e: Exception){
|
||||||
|
Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
notificationUtil.cancelDownloadNotification(downloadID)
|
||||||
|
}) { e ->
|
||||||
|
scrollView!!.scrollTo(0, scrollView!!.maxScrollAmount)
|
||||||
|
input!!.setText("yt-dlp ")
|
||||||
|
input!!.isEnabled = true
|
||||||
|
|
||||||
|
cancelFab!!.visibility = View.GONE
|
||||||
|
fab!!.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
tempFileDir.delete()
|
||||||
|
Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show()
|
||||||
|
|
||||||
|
Log.e(DownloadWorker.TAG, context?.getString(R.string.failed_download), e)
|
||||||
|
notificationUtil.cancelDownloadNotification(downloadID)
|
||||||
|
}
|
||||||
|
compositeDisposable.add(disposable)
|
||||||
|
|
||||||
|
}
|
||||||
|
@Throws(Exception::class)
|
||||||
|
private fun moveFile(originDir: File, downLocation: String, progress: (progress: Int) -> Unit){
|
||||||
|
val fileUtil = FileUtil()
|
||||||
|
fileUtil.moveFile(originDir, context!!, downLocation){ p ->
|
||||||
|
progress(p)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cancelDownload() {
|
private fun cancelDownload() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val id = withContext(Dispatchers.IO){ downloadViewModel.getTerminalDownload(); }
|
compositeDisposable.dispose()
|
||||||
YoutubeDL.getInstance().destroyProcessById(id.toString())
|
YoutubeDL.getInstance().destroyProcessById(downloadID.toString())
|
||||||
WorkManager.getInstance(this@CustomCommandActivity).cancelUniqueWork(id.toString())
|
notificationUtil.cancelDownloadNotification(downloadID)
|
||||||
notificationUtil.cancelDownloadNotification(id.toInt())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "CustomCommandActivity"
|
private const val TAG = "CustomCommandActivity"
|
||||||
|
private var downloadID = System.currentTimeMillis().toInt()
|
||||||
|
private val compositeDisposable = CompositeDisposable()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -190,32 +190,6 @@ class DownloadWorker(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DownloadViewModel.Type.terminal -> {
|
|
||||||
if(downloadItem.format.format_note.startsWith("yt-dlp ")){
|
|
||||||
downloadItem.format.format_note = downloadItem.format.format_note.substring(6).trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
val commandRegex = "\"([^\"]*)\"|(\\S+)"
|
|
||||||
request = YoutubeDLRequest(emptyList())
|
|
||||||
|
|
||||||
tempFolder = StringBuilder(context.cacheDir.absolutePath + """/${downloadItem.format.format_id}##terminal""")
|
|
||||||
tempFileDir = File(tempFolder.toString())
|
|
||||||
tempFileDir.delete()
|
|
||||||
tempFileDir.mkdir()
|
|
||||||
|
|
||||||
|
|
||||||
val m = Pattern.compile(commandRegex).matcher(downloadItem.format.format_note)
|
|
||||||
while (m.find()) {
|
|
||||||
if (m.group(1) != null) {
|
|
||||||
request.addOption(m.group(1)!!)
|
|
||||||
} else {
|
|
||||||
request.addOption(m.group(2)!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
request.addOption("-o", tempFileDir.absolutePath + "/${downloadItem.customFileNameTemplate}.%(ext)s")
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
runCatching {
|
runCatching {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue