...
This commit is contained in:
parent
1b55784839
commit
c30285133b
52 changed files with 533 additions and 365 deletions
|
|
@ -4,13 +4,14 @@ plugins {
|
||||||
id 'org.jetbrains.kotlin.android'
|
id 'org.jetbrains.kotlin.android'
|
||||||
id 'com.google.devtools.ksp'
|
id 'com.google.devtools.ksp'
|
||||||
id "org.jetbrains.kotlin.plugin.serialization" version "1.8.10"
|
id "org.jetbrains.kotlin.plugin.serialization" version "1.8.10"
|
||||||
|
id "org.jetbrains.kotlin.plugin.parcelize" version "1.8.10"
|
||||||
}
|
}
|
||||||
|
|
||||||
def properties = new Properties()
|
def properties = new Properties()
|
||||||
def versionMajor = 1
|
def versionMajor = 1
|
||||||
def versionMinor = 6
|
def versionMinor = 6
|
||||||
def versionPatch = 8
|
def versionPatch = 8
|
||||||
def versionBuild = 0 // bump for dogfood builds, public betas, etc.
|
def versionBuild = 1 // bump for dogfood builds, public betas, etc.
|
||||||
def versionExt = ""
|
def versionExt = ""
|
||||||
|
|
||||||
if (versionBuild > 0){
|
if (versionBuild > 0){
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:configChanges="locale"
|
android:configChanges="locale"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
android:launchMode="singleTask"
|
||||||
android:windowSoftInputMode="adjustPan">
|
android:windowSoftInputMode="adjustPan">
|
||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
@ -53,6 +54,7 @@
|
||||||
android:configChanges="smallestScreenSize|layoutDirection|locale|orientation|screenSize"
|
android:configChanges="smallestScreenSize|layoutDirection|locale|orientation|screenSize"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
android:launchMode="singleInstance"
|
||||||
android:theme="@style/Theme.BottomSheet">
|
android:theme="@style/Theme.BottomSheet">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEND" />
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
|
@ -125,6 +127,7 @@
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:configChanges="locale"
|
android:configChanges="locale"
|
||||||
|
android:launchMode="singleTask"
|
||||||
android:targetActivity=".MainActivity"
|
android:targetActivity=".MainActivity"
|
||||||
android:windowSoftInputMode="adjustPan"
|
android:windowSoftInputMode="adjustPan"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
|
|
@ -147,6 +150,7 @@
|
||||||
android:icon="@mipmap/ic_launcher_dark"
|
android:icon="@mipmap/ic_launcher_dark"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round_dark"
|
android:roundIcon="@mipmap/ic_launcher_round_dark"
|
||||||
android:configChanges="locale"
|
android:configChanges="locale"
|
||||||
|
android:launchMode="singleTask"
|
||||||
android:targetActivity=".MainActivity"
|
android:targetActivity=".MainActivity"
|
||||||
android:windowSoftInputMode="adjustPan">
|
android:windowSoftInputMode="adjustPan">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
@ -167,6 +171,7 @@
|
||||||
android:icon="@mipmap/ic_launcher_light"
|
android:icon="@mipmap/ic_launcher_light"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round_light"
|
android:roundIcon="@mipmap/ic_launcher_round_light"
|
||||||
android:configChanges="locale"
|
android:configChanges="locale"
|
||||||
|
android:launchMode="singleTask"
|
||||||
android:targetActivity=".MainActivity"
|
android:targetActivity=".MainActivity"
|
||||||
android:windowSoftInputMode="adjustPan">
|
android:windowSoftInputMode="adjustPan">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
@ -184,6 +189,7 @@
|
||||||
android:name=".ui.more.WebViewActivity"
|
android:name=".ui.more.WebViewActivity"
|
||||||
android:configChanges="locale"
|
android:configChanges="locale"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
android:launchMode="singleTask"
|
||||||
android:parentActivityName=".MainActivity"
|
android:parentActivityName=".MainActivity"
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import androidx.fragment.app.FragmentContainerView
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import androidx.navigation.findNavController
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.ui.setupWithNavController
|
import androidx.navigation.ui.setupWithNavController
|
||||||
|
|
@ -48,6 +49,7 @@ import com.deniscerri.ytdlnis.util.ThemeUtil
|
||||||
import com.deniscerri.ytdlnis.util.UpdateUtil
|
import com.deniscerri.ytdlnis.util.UpdateUtil
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.google.android.material.elevation.SurfaceColors
|
||||||
import com.google.android.material.navigation.NavigationBarView
|
import com.google.android.material.navigation.NavigationBarView
|
||||||
import com.google.android.material.navigation.NavigationView
|
import com.google.android.material.navigation.NavigationView
|
||||||
import com.google.android.material.navigationrail.NavigationRailView
|
import com.google.android.material.navigationrail.NavigationRailView
|
||||||
|
|
@ -82,6 +84,7 @@ class MainActivity : BaseActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
ThemeUtil.updateTheme(this)
|
ThemeUtil.updateTheme(this)
|
||||||
|
window.navigationBarColor = SurfaceColors.SURFACE_2.getColor(this)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
context = baseContext
|
context = baseContext
|
||||||
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
||||||
|
|
@ -362,8 +365,10 @@ class MainActivity : BaseActivity() {
|
||||||
Toast.makeText(context, "Couldn't read file", Toast.LENGTH_LONG).show()
|
Toast.makeText(context, "Couldn't read file", Toast.LENGTH_LONG).show()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val bottomSheet = DownloadBottomSheetDialog(type = DownloadViewModel.Type.command, result = downloadViewModel.createEmptyResultItem(f.absolutePath))
|
val bundle = Bundle()
|
||||||
bottomSheet.show(supportFragmentManager, "downloadSingleSheet")
|
bundle.putParcelable("result", downloadViewModel.createEmptyResultItem(f.absolutePath))
|
||||||
|
bundle.putSerializable("type", DownloadViewModel.Type.command)
|
||||||
|
navController.navigate(R.id.downloadBottomSheetDialog, bundle)
|
||||||
}else{
|
}else{
|
||||||
val `is` = contentResolver.openInputStream(uri!!)
|
val `is` = contentResolver.openInputStream(uri!!)
|
||||||
val textBuilder = StringBuilder()
|
val textBuilder = StringBuilder()
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@ interface DownloadDao {
|
||||||
@Query("SELECT * FROM downloads ORDER BY status")
|
@Query("SELECT * FROM downloads ORDER BY status")
|
||||||
fun getAllDownloads() : PagingSource<Int, DownloadItem>
|
fun getAllDownloads() : PagingSource<Int, DownloadItem>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Active' or status='Paused'")
|
@Query("SELECT * FROM downloads WHERE status in ('Active', 'ActivePaused', 'PausedReQueued')")
|
||||||
fun getActiveDownloads() : Flow<List<DownloadItem>>
|
fun getActiveDownloads() : Flow<List<DownloadItem>>
|
||||||
|
|
||||||
@Query("SELECT COUNT(*) FROM downloads WHERE status='Active' or status='Paused'")
|
@Query("SELECT COUNT(*) FROM downloads WHERE status in ('Active', 'ActivePaused', 'PausedReQueued')")
|
||||||
fun getActiveDownloadsCountFlow() : Flow<Int>
|
fun getActiveDownloadsCountFlow() : Flow<Int>
|
||||||
|
|
||||||
@Query("SELECT COUNT(*) FROM downloads WHERE status in (:status)")
|
@Query("SELECT COUNT(*) FROM downloads WHERE status in (:status)")
|
||||||
|
|
@ -25,34 +25,34 @@ interface DownloadDao {
|
||||||
@Query("SELECT COUNT(*) FROM downloads WHERE status in (:status)")
|
@Query("SELECT COUNT(*) FROM downloads WHERE status in (:status)")
|
||||||
fun getDownloadsCountByStatus(status : List<String>) : Int
|
fun getDownloadsCountByStatus(status : List<String>) : Int
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Active' or status='Paused'")
|
@Query("SELECT * FROM downloads WHERE status in('Active','ActivePaused','PausedReQueued')")
|
||||||
fun getActiveAndPausedDownloadsList() : List<DownloadItem>
|
fun getActiveAndPausedDownloadsList() : List<DownloadItem>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Active'")
|
@Query("SELECT * FROM downloads WHERE status='Active'")
|
||||||
fun getActiveDownloadsList() : List<DownloadItem>
|
fun getActiveDownloadsList() : List<DownloadItem>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Active' or status='Queued' or status='QueuedPaused' or status='Paused'")
|
@Query("SELECT * FROM downloads WHERE status in('Active','Queued','QueuedPaused','ActivePaused','PausedReQueued')")
|
||||||
fun getActiveAndQueuedDownloadsList() : List<DownloadItem>
|
fun getActiveAndQueuedDownloadsList() : List<DownloadItem>
|
||||||
|
|
||||||
@Query("SELECT id FROM downloads WHERE status='Active' or status='Queued' or status='QueuedPaused' or status='Paused'")
|
@Query("SELECT id FROM downloads WHERE status in('Active','Queued','QueuedPaused','ActivePaused','PausedReQueued')")
|
||||||
fun getActiveAndQueuedDownloadIDs() : List<Long>
|
fun getActiveAndQueuedDownloadIDs() : List<Long>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Active' or status='Queued' or status='QueuedPaused' or status='Paused'")
|
@Query("SELECT * FROM downloads WHERE status in('Active','Queued','QueuedPaused','ActivePaused','PausedReQueued')")
|
||||||
fun getActiveAndQueuedDownloads() : Flow<List<DownloadItem>>
|
fun getActiveAndQueuedDownloads() : Flow<List<DownloadItem>>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Queued' or status='QueuedPaused' ORDER BY downloadStartTime, id")
|
@Query("SELECT * FROM downloads WHERE status in('Queued','QueuedPaused') ORDER BY downloadStartTime, id")
|
||||||
fun getQueuedDownloads() : PagingSource<Int, DownloadItemSimple>
|
fun getQueuedDownloads() : PagingSource<Int, DownloadItemSimple>
|
||||||
|
|
||||||
@Query("SELECT format FROM downloads WHERE status='Queued' or status='QueuedPaused'")
|
@Query("SELECT format FROM downloads WHERE status in('Queued','QueuedPaused')")
|
||||||
fun getSelectedFormatFromQueued() : List<Format>
|
fun getSelectedFormatFromQueued() : List<Format>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE downloadStartTime <= :currentTime and status='Queued' ORDER BY downloadStartTime, id LIMIT 20")
|
@Query("SELECT * FROM downloads WHERE downloadStartTime <= :currentTime and status in ('Queued', 'PausedReQueued') ORDER BY downloadStartTime, id LIMIT 20")
|
||||||
fun getQueuedDownloadsThatAreNotScheduledChunked(currentTime: Long) : Flow<List<DownloadItem>>
|
fun getQueuedDownloadsThatAreNotScheduledChunked(currentTime: Long) : Flow<List<DownloadItem>>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Queued' or status='QueuedPaused' or status='Paused' ORDER BY downloadStartTime, id")
|
@Query("SELECT * FROM downloads WHERE status in ('Queued','QueuedPaused','ActivePaused','PausedReQueued') ORDER BY downloadStartTime, id")
|
||||||
fun getQueuedAndPausedDownloads() : Flow<List<DownloadItem>>
|
fun getQueuedAndPausedDownloads() : Flow<List<DownloadItem>>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Queued' or status='QueuedPaused' ORDER BY downloadStartTime, id")
|
@Query("SELECT * FROM downloads WHERE status in('Queued','QueuedPaused') ORDER BY downloadStartTime, id")
|
||||||
fun getQueuedDownloadsList() : List<DownloadItem>
|
fun getQueuedDownloadsList() : List<DownloadItem>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Cancelled' ORDER BY id DESC")
|
@Query("SELECT * FROM downloads WHERE status='Cancelled' ORDER BY id DESC")
|
||||||
|
|
@ -87,7 +87,7 @@ interface DownloadDao {
|
||||||
|
|
||||||
@Query("UPDATE downloads " +
|
@Query("UPDATE downloads " +
|
||||||
"SET status = CASE " +
|
"SET status = CASE " +
|
||||||
" WHEN status = 'Active' THEN 'Paused' " +
|
" WHEN status = 'Active' THEN 'ActivePaused' " +
|
||||||
" WHEN status = 'Queued' THEN 'QueuedPaused' " +
|
" WHEN status = 'Queued' THEN 'QueuedPaused' " +
|
||||||
" ELSE status " +
|
" ELSE status " +
|
||||||
" END;")
|
" END;")
|
||||||
|
|
@ -95,7 +95,7 @@ interface DownloadDao {
|
||||||
|
|
||||||
@Query("UPDATE downloads " +
|
@Query("UPDATE downloads " +
|
||||||
"SET status = CASE " +
|
"SET status = CASE " +
|
||||||
" WHEN status = 'Paused' THEN 'Active' " +
|
" WHEN status = 'ActivePaused' THEN 'Active' " +
|
||||||
" WHEN status = 'QueuedPaused' THEN 'Queued' " +
|
" WHEN status = 'QueuedPaused' THEN 'Queued' " +
|
||||||
" ELSE status " +
|
" ELSE status " +
|
||||||
" END;")
|
" END;")
|
||||||
|
|
@ -125,7 +125,7 @@ interface DownloadDao {
|
||||||
@Query("DELETE FROM downloads WHERE id in (:list)")
|
@Query("DELETE FROM downloads WHERE id in (:list)")
|
||||||
suspend fun deleteAllWithIDs(list: List<Long>)
|
suspend fun deleteAllWithIDs(list: List<Long>)
|
||||||
|
|
||||||
@Query("UPDATE downloads SET status='Cancelled' WHERE status='Queued' or status='QueuedPaused' or status='Active' or status='Paused'")
|
@Query("UPDATE downloads SET status='Cancelled' WHERE status in('Queued','QueuedPaused','Active','ActivePaused','PausedReQueued')")
|
||||||
suspend fun cancelActiveQueued()
|
suspend fun cancelActiveQueued()
|
||||||
|
|
||||||
@Query("DELETE FROM downloads WHERE status='Processing' AND id=:id")
|
@Query("DELETE FROM downloads WHERE status='Processing' AND id=:id")
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
package com.deniscerri.ytdlnis.database.models
|
package com.deniscerri.ytdlnis.database.models
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
data class AudioPreferences(
|
data class AudioPreferences(
|
||||||
var embedThumb: Boolean = true,
|
var embedThumb: Boolean = true,
|
||||||
var splitByChapters: Boolean = false,
|
var splitByChapters: Boolean = false,
|
||||||
var sponsorBlockFilters: ArrayList<String> = arrayListOf()
|
var sponsorBlockFilters: ArrayList<String> = arrayListOf()
|
||||||
)
|
) : Parcelable
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
package com.deniscerri.ytdlnis.database.models
|
package com.deniscerri.ytdlnis.database.models
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
data class ChapterItem(
|
data class ChapterItem(
|
||||||
@SerializedName(value = "start_time")
|
@SerializedName(value = "start_time")
|
||||||
var start_time: Long,
|
var start_time: Long,
|
||||||
|
|
@ -9,4 +12,4 @@ data class ChapterItem(
|
||||||
var end_time: Long,
|
var end_time: Long,
|
||||||
@SerializedName(value = "title")
|
@SerializedName(value = "title")
|
||||||
var title: String,
|
var title: String,
|
||||||
)
|
) : Parcelable
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
package com.deniscerri.ytdlnis.database.models
|
package com.deniscerri.ytdlnis.database.models
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
import androidx.room.ColumnInfo
|
import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
@Entity(tableName = "downloads")
|
@Entity(tableName = "downloads")
|
||||||
|
@Parcelize
|
||||||
data class DownloadItem(
|
data class DownloadItem(
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Long,
|
var id: Long,
|
||||||
|
|
@ -24,7 +27,7 @@ data class DownloadItem(
|
||||||
var downloadPath: String,
|
var downloadPath: String,
|
||||||
var website: String,
|
var website: String,
|
||||||
val downloadSize: String,
|
val downloadSize: String,
|
||||||
val playlistTitle: String,
|
var playlistTitle: String,
|
||||||
val audioPreferences : AudioPreferences,
|
val audioPreferences : AudioPreferences,
|
||||||
val videoPreferences: VideoPreferences,
|
val videoPreferences: VideoPreferences,
|
||||||
@ColumnInfo(defaultValue = "")
|
@ColumnInfo(defaultValue = "")
|
||||||
|
|
@ -36,4 +39,4 @@ data class DownloadItem(
|
||||||
@ColumnInfo(defaultValue = "0")
|
@ColumnInfo(defaultValue = "0")
|
||||||
var downloadStartTime: Long,
|
var downloadStartTime: Long,
|
||||||
var logID: Long?
|
var logID: Long?
|
||||||
)
|
) : Parcelable
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
package com.deniscerri.ytdlnis.database.models
|
package com.deniscerri.ytdlnis.database.models
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
data class Format(
|
data class Format(
|
||||||
@SerializedName(value = "format_id", alternate = ["itag"])
|
@SerializedName(value = "format_id", alternate = ["itag"])
|
||||||
var format_id: String = "",
|
var format_id: String = "",
|
||||||
|
|
@ -23,4 +26,4 @@ data class Format(
|
||||||
var asr: String? = "",
|
var asr: String? = "",
|
||||||
@SerializedName(value = "url")
|
@SerializedName(value = "url")
|
||||||
var url: String? = ""
|
var url: String? = ""
|
||||||
)
|
) : Parcelable
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
package com.deniscerri.ytdlnis.database.models
|
package com.deniscerri.ytdlnis.database.models
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
import androidx.room.ColumnInfo
|
import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
@Entity(tableName = "results")
|
@Entity(tableName = "results")
|
||||||
|
@Parcelize
|
||||||
data class ResultItem(
|
data class ResultItem(
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Long,
|
var id: Long,
|
||||||
|
|
@ -20,4 +23,4 @@ data class ResultItem(
|
||||||
var urls: String,
|
var urls: String,
|
||||||
var chapters: MutableList<ChapterItem>?,
|
var chapters: MutableList<ChapterItem>?,
|
||||||
var creationTime: Long = System.currentTimeMillis() / 1000,
|
var creationTime: Long = System.currentTimeMillis() / 1000,
|
||||||
)
|
) : Parcelable
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
package com.deniscerri.ytdlnis.database.models
|
package com.deniscerri.ytdlnis.database.models
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
data class VideoPreferences (
|
data class VideoPreferences (
|
||||||
var embedSubs: Boolean = true,
|
var embedSubs: Boolean = true,
|
||||||
var addChapters: Boolean = true,
|
var addChapters: Boolean = true,
|
||||||
|
|
@ -9,4 +13,4 @@ data class VideoPreferences (
|
||||||
var subsLanguages: String = "en.*,.*-orig",
|
var subsLanguages: String = "en.*,.*-orig",
|
||||||
var audioFormatIDs : ArrayList<String> = arrayListOf(),
|
var audioFormatIDs : ArrayList<String> = arrayListOf(),
|
||||||
var removeAudio: Boolean = false
|
var removeAudio: Boolean = false
|
||||||
)
|
) : Parcelable
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
|
||||||
val activeDownloadsCount : Flow<Int> = downloadDao.getActiveDownloadsCountFlow()
|
val activeDownloadsCount : Flow<Int> = downloadDao.getActiveDownloadsCountFlow()
|
||||||
|
|
||||||
enum class Status {
|
enum class Status {
|
||||||
Active, Paused, Queued, QueuedPaused, Error, Cancelled, Saved
|
Active, ActivePaused, PausedReQueued, Queued, QueuedPaused, Error, Cancelled, Saved
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun insert(item: DownloadItem) : Long {
|
suspend fun insert(item: DownloadItem) : Long {
|
||||||
|
|
|
||||||
|
|
@ -612,7 +612,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
}
|
}
|
||||||
|
|
||||||
items.forEach {
|
items.forEach {
|
||||||
if (it.status != DownloadRepository.Status.Paused.toString()) it.status = DownloadRepository.Status.Queued.toString()
|
if (it.status != DownloadRepository.Status.ActivePaused.toString()) it.status = DownloadRepository.Status.Queued.toString()
|
||||||
val currentCommand = infoUtil.buildYoutubeDLRequest(it)
|
val currentCommand = infoUtil.buildYoutubeDLRequest(it)
|
||||||
val parsedCurrentCommand = infoUtil.parseYTDLRequestString(currentCommand)
|
val parsedCurrentCommand = infoUtil.parseYTDLRequestString(currentCommand)
|
||||||
val existingDownload = activeAndQueuedDownloads.firstOrNull{d ->
|
val existingDownload = activeAndQueuedDownloads.firstOrNull{d ->
|
||||||
|
|
@ -640,7 +640,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
existing.add(it)
|
existing.add(it)
|
||||||
}else{
|
}else{
|
||||||
if (it.id == 0L){
|
if (it.id == 0L){
|
||||||
val id = withContext(Dispatchers.IO){
|
val id = runBlocking {
|
||||||
repository.insert(it)
|
repository.insert(it)
|
||||||
}
|
}
|
||||||
it.id = id
|
it.id = id
|
||||||
|
|
@ -665,6 +665,13 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (items.any { it.playlistTitle.isEmpty() }){
|
||||||
|
items.forEachIndexed { index, it -> it.playlistTitle = "Various[${index+1}]" }
|
||||||
|
withContext(Dispatchers.IO){
|
||||||
|
dao.updateMultiple(items)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!useScheduler || alarmScheduler.isDuringTheScheduledTime() || items.any { it.downloadStartTime > 0L } ){
|
if (!useScheduler || alarmScheduler.isDuringTheScheduledTime() || items.any { it.downloadStartTime > 0L } ){
|
||||||
startDownloadWorker(queuedItems)
|
startDownloadWorker(queuedItems)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ class PauseDownloadNotificationReceiver : BroadcastReceiver() {
|
||||||
CoroutineScope(Dispatchers.IO).launch{
|
CoroutineScope(Dispatchers.IO).launch{
|
||||||
runCatching {
|
runCatching {
|
||||||
val item = dbManager.downloadDao.getDownloadById(id.toLong())
|
val item = dbManager.downloadDao.getDownloadById(id.toLong())
|
||||||
item.status = DownloadRepository.Status.Paused.toString()
|
item.status = DownloadRepository.Status.ActivePaused.toString()
|
||||||
dbManager.downloadDao.update(item)
|
dbManager.downloadDao.update(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.deniscerri.ytdlnis.receiver
|
package com.deniscerri.ytdlnis.receiver
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
|
@ -16,10 +17,16 @@ import android.util.Log
|
||||||
import android.util.Patterns
|
import android.util.Patterns
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.core.content.IntentSanitizer
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import androidx.navigation.NavDestination
|
||||||
|
import androidx.navigation.findNavController
|
||||||
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.deniscerri.ytdlnis.MainActivity
|
import com.deniscerri.ytdlnis.MainActivity
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
|
|
@ -34,6 +41,7 @@ import com.deniscerri.ytdlnis.ui.downloadcard.SelectPlaylistItemsDialog
|
||||||
import com.deniscerri.ytdlnis.util.ThemeUtil
|
import com.deniscerri.ytdlnis.util.ThemeUtil
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
|
@ -46,6 +54,7 @@ class ShareActivity : BaseActivity() {
|
||||||
private lateinit var downloadViewModel: DownloadViewModel
|
private lateinit var downloadViewModel: DownloadViewModel
|
||||||
private lateinit var cookieViewModel: CookieViewModel
|
private lateinit var cookieViewModel: CookieViewModel
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
|
private lateinit var navController: NavController
|
||||||
private var quickDownload by Delegates.notNull<Boolean>()
|
private var quickDownload by Delegates.notNull<Boolean>()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -83,6 +92,28 @@ class ShareActivity : BaseActivity() {
|
||||||
handleIntents(intent)
|
handleIntents(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
navController.addOnDestinationChangedListener(object: NavController.OnDestinationChangedListener{
|
||||||
|
override fun onDestinationChanged(
|
||||||
|
controller: NavController,
|
||||||
|
destination: NavDestination,
|
||||||
|
arguments: Bundle?
|
||||||
|
) {
|
||||||
|
if (navController.currentBackStack.value.isEmpty()) return
|
||||||
|
navController.removeOnDestinationChangedListener(this)
|
||||||
|
lifecycleScope.launch {
|
||||||
|
navController.currentBackStack.collectLatest {
|
||||||
|
if (it.isEmpty()){
|
||||||
|
this@ShareActivity.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent) {
|
override fun onNewIntent(intent: Intent) {
|
||||||
super.onNewIntent(intent)
|
super.onNewIntent(intent)
|
||||||
handleIntents(intent)
|
handleIntents(intent)
|
||||||
|
|
@ -91,6 +122,9 @@ class ShareActivity : BaseActivity() {
|
||||||
private fun handleIntents(intent: Intent) {
|
private fun handleIntents(intent: Intent) {
|
||||||
askPermissions()
|
askPermissions()
|
||||||
|
|
||||||
|
val navHostFragment = supportFragmentManager.findFragmentById(R.id.frame_layout) as NavHostFragment
|
||||||
|
navController = navHostFragment.findNavController()
|
||||||
|
|
||||||
val action = intent.action
|
val action = intent.action
|
||||||
Log.e("aa", intent.toString())
|
Log.e("aa", intent.toString())
|
||||||
if (Intent.ACTION_SEND == action || Intent.ACTION_VIEW == action) {
|
if (Intent.ACTION_SEND == action || Intent.ACTION_VIEW == action) {
|
||||||
|
|
@ -129,10 +163,10 @@ class ShareActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
val downloadType = DownloadViewModel.Type.valueOf(type ?: downloadViewModel.getDownloadType(url = result.url).toString())
|
val downloadType = DownloadViewModel.Type.valueOf(type ?: downloadViewModel.getDownloadType(url = result.url).toString())
|
||||||
if (sharedPreferences.getBoolean("download_card", true) && !background){
|
if (sharedPreferences.getBoolean("download_card", true) && !background){
|
||||||
val bottomSheet = DownloadBottomSheetDialog(
|
val bundle = Bundle()
|
||||||
result = result,
|
bundle.putParcelable("result", result)
|
||||||
type = downloadType)
|
bundle.putSerializable("type", downloadType)
|
||||||
bottomSheet.show(supportFragmentManager, "downloadSingleSheet")
|
navController.setGraph(R.navigation.share_nav_graph, bundle)
|
||||||
}else{
|
}else{
|
||||||
lifecycleScope.launch(Dispatchers.IO){
|
lifecycleScope.launch(Dispatchers.IO){
|
||||||
val downloadItem = downloadViewModel.createDownloadItemFromResult(
|
val downloadItem = downloadViewModel.createDownloadItemFromResult(
|
||||||
|
|
@ -152,32 +186,6 @@ class ShareActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showDownloadSheet(it: ResultItem){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showSelectPlaylistItems(it: List<ResultItem?>){
|
|
||||||
if (sharedPreferences.getBoolean("download_card", true)){
|
|
||||||
val bottomSheet = SelectPlaylistItemsDialog(it, DownloadViewModel.Type.valueOf(sharedPreferences.getString("preferred_download_type", "video")!!))
|
|
||||||
bottomSheet.show(supportFragmentManager, "downloadPlaylistSheet")
|
|
||||||
}else{
|
|
||||||
lifecycleScope.launch(Dispatchers.IO){
|
|
||||||
val downloadItems = mutableListOf<DownloadItem>()
|
|
||||||
lifecycleScope.launch(Dispatchers.IO){
|
|
||||||
it.forEach { res ->
|
|
||||||
val i = downloadViewModel.createDownloadItemFromResult(
|
|
||||||
result = res!!,
|
|
||||||
givenType = DownloadViewModel.Type.valueOf(sharedPreferences.getString("preferred_download_type", "video")!!))
|
|
||||||
i.format = downloadViewModel.getLatestCommandTemplateAsFormat()
|
|
||||||
downloadItems.add(i)
|
|
||||||
}
|
|
||||||
downloadViewModel.queueDownloads(downloadItems)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun askPermissions() {
|
private fun askPermissions() {
|
||||||
val permissions = arrayListOf<String>()
|
val permissions = arrayListOf<String>()
|
||||||
if (!checkFilePermission()) {
|
if (!checkFilePermission()) {
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,14 @@ import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
import androidx.core.view.forEach
|
import androidx.core.view.forEach
|
||||||
import androidx.core.widget.doAfterTextChanged
|
import androidx.core.widget.doAfterTextChanged
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
|
@ -158,28 +160,30 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
||||||
recyclerView?.enableFastScroll()
|
recyclerView?.enableFastScroll()
|
||||||
|
|
||||||
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
||||||
resultViewModel.items.observe(viewLifecycleOwner) {
|
resultViewModel.items.observe(requireActivity()) {
|
||||||
homeAdapter!!.submitList(it)
|
kotlin.runCatching {
|
||||||
resultsList = it
|
homeAdapter!!.submitList(it)
|
||||||
if(resultViewModel.repository.itemCount.value > 1 || resultViewModel.repository.itemCount.value == -1){
|
resultsList = it
|
||||||
if (it.size > 1 && it[0].playlistTitle.isNotEmpty() && !loadingItems){
|
if(resultViewModel.repository.itemCount.value > 1 || resultViewModel.repository.itemCount.value == -1){
|
||||||
downloadAllFabCoordinator!!.visibility = VISIBLE
|
if (it.size > 1 && it[0].playlistTitle.isNotEmpty() && !loadingItems){
|
||||||
|
downloadAllFabCoordinator!!.visibility = VISIBLE
|
||||||
|
}else{
|
||||||
|
downloadAllFabCoordinator!!.visibility = GONE
|
||||||
|
}
|
||||||
|
}else if (resultViewModel.repository.itemCount.value == 1){
|
||||||
|
if (sharedPreferences!!.getBoolean("download_card", true)){
|
||||||
|
if(it.size == 1 && quickLaunchSheet && parentFragmentManager.findFragmentByTag("downloadSingleSheet") == null){
|
||||||
|
showSingleDownloadSheet(
|
||||||
|
it[0],
|
||||||
|
DownloadViewModel.Type.valueOf(sharedPreferences!!.getString("preferred_download_type", "video")!!)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
downloadAllFabCoordinator!!.visibility = GONE
|
downloadAllFabCoordinator!!.visibility = GONE
|
||||||
}
|
}
|
||||||
}else if (resultViewModel.repository.itemCount.value == 1){
|
quickLaunchSheet = true
|
||||||
if (sharedPreferences!!.getBoolean("download_card", true)){
|
|
||||||
if(it.size == 1 && quickLaunchSheet && parentFragmentManager.findFragmentByTag("downloadSingleSheet") == null){
|
|
||||||
showSingleDownloadSheet(
|
|
||||||
it[0],
|
|
||||||
DownloadViewModel.Type.valueOf(sharedPreferences!!.getString("preferred_download_type", "video")!!)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
downloadAllFabCoordinator!!.visibility = GONE
|
|
||||||
}
|
}
|
||||||
quickLaunchSheet = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initMenu()
|
initMenu()
|
||||||
|
|
@ -271,8 +275,9 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
||||||
ids?.forEach {
|
ids?.forEach {
|
||||||
items.add(downloadViewModel.getItemByID(it))
|
items.add(downloadViewModel.getItemByID(it))
|
||||||
}
|
}
|
||||||
val bottomSheet = DownloadMultipleBottomSheetDialog(items.toMutableList())
|
findNavController().navigate(R.id.downloadMultipleBottomSheetDialog2, bundleOf(
|
||||||
bottomSheet.show(parentFragmentManager, "downloadMultipleSheet")
|
Pair("downloads", items)
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -560,20 +565,18 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
||||||
if(sharedPreferences!!.getBoolean("quick_download", false) || sharedPreferences!!.getString("preferred_download_type", "video") == "command"){
|
if(sharedPreferences!!.getBoolean("quick_download", false) || sharedPreferences!!.getString("preferred_download_type", "video") == "command"){
|
||||||
if (queryList.size == 1 && Patterns.WEB_URL.matcher(queryList.first()).matches()){
|
if (queryList.size == 1 && Patterns.WEB_URL.matcher(queryList.first()).matches()){
|
||||||
if (sharedPreferences!!.getBoolean("download_card", true)) {
|
if (sharedPreferences!!.getBoolean("download_card", true)) {
|
||||||
showSingleDownloadSheet(
|
withContext(Dispatchers.Main){
|
||||||
resultItem = downloadViewModel.createEmptyResultItem(queryList.first()),
|
showSingleDownloadSheet(
|
||||||
type = DownloadViewModel.Type.valueOf(sharedPreferences!!.getString("preferred_download_type", "video")!!)
|
resultItem = downloadViewModel.createEmptyResultItem(queryList.first()),
|
||||||
)
|
type = DownloadViewModel.Type.valueOf(sharedPreferences!!.getString("preferred_download_type", "video")!!)
|
||||||
} else {
|
)
|
||||||
lifecycleScope.launch{
|
|
||||||
val downloadItem = withContext(Dispatchers.IO){
|
|
||||||
downloadViewModel.createDownloadItemFromResult(
|
|
||||||
result = downloadViewModel.createEmptyResultItem(queryList.first()),
|
|
||||||
givenType = DownloadViewModel.Type.valueOf(sharedPreferences!!.getString("preferred_download_type", "video")!!)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
downloadViewModel.queueDownloads(listOf(downloadItem))
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
val downloadItem = downloadViewModel.createDownloadItemFromResult(
|
||||||
|
result = downloadViewModel.createEmptyResultItem(queryList.first()),
|
||||||
|
givenType = DownloadViewModel.Type.valueOf(sharedPreferences!!.getString("preferred_download_type", "video")!!)
|
||||||
|
)
|
||||||
|
downloadViewModel.queueDownloads(listOf(downloadItem))
|
||||||
}
|
}
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
|
|
@ -620,8 +623,13 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
||||||
resultItem: ResultItem,
|
resultItem: ResultItem,
|
||||||
type: DownloadViewModel.Type
|
type: DownloadViewModel.Type
|
||||||
){
|
){
|
||||||
val bottomSheet = DownloadBottomSheetDialog(resultItem, downloadViewModel.getDownloadType(type, resultItem.url))
|
if(findNavController().currentBackStack.value.firstOrNull {it.destination.id == R.id.downloadBottomSheetDialog} == null){
|
||||||
bottomSheet.show(parentFragmentManager, "downloadSingleSheet")
|
//show the fragment if its not in the backstack
|
||||||
|
val bundle = Bundle()
|
||||||
|
bundle.putParcelable("result", resultItem)
|
||||||
|
bundle.putSerializable("type", downloadViewModel.getDownloadType(type, resultItem.url))
|
||||||
|
findNavController().navigate(R.id.downloadBottomSheetDialog, bundle)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCardClick(videoURL: String, add: Boolean) {
|
override fun onCardClick(videoURL: String, add: Boolean) {
|
||||||
|
|
@ -646,8 +654,9 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
||||||
|
|
||||||
override fun onCardDetailsClick(videoURL: String) {
|
override fun onCardDetailsClick(videoURL: String) {
|
||||||
if (parentFragmentManager.findFragmentByTag("resultDetails") == null && resultsList != null && resultsList!!.isNotEmpty()){
|
if (parentFragmentManager.findFragmentByTag("resultDetails") == null && resultsList != null && resultsList!!.isNotEmpty()){
|
||||||
val bottomSheet = ResultCardDetailsDialog(resultsList!!.first{it!!.url == videoURL}!!)
|
val bundle = Bundle()
|
||||||
bottomSheet.show(parentFragmentManager, "cutVideoSheet")
|
bundle.putParcelable("result", resultsList!!.first{it!!.url == videoURL}!!)
|
||||||
|
findNavController().navigate(R.id.resultCardDetailsDialog, bundle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -662,8 +671,9 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
||||||
downloadViewModel.turnResultItemsToDownloadItems(resultsList!!)
|
downloadViewModel.turnResultItemsToDownloadItems(resultsList!!)
|
||||||
}
|
}
|
||||||
if (sharedPreferences!!.getBoolean("download_card", true)) {
|
if (sharedPreferences!!.getBoolean("download_card", true)) {
|
||||||
val bottomSheet = DownloadMultipleBottomSheetDialog(downloadList.toMutableList())
|
findNavController().navigate(R.id.downloadMultipleBottomSheetDialog2, bundleOf(
|
||||||
bottomSheet.show(parentFragmentManager, "downloadMultipleSheet")
|
Pair("downloads", downloadList)
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
downloadViewModel.queueDownloads(downloadList)
|
downloadViewModel.queueDownloads(downloadList)
|
||||||
}
|
}
|
||||||
|
|
@ -723,8 +733,9 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sharedPreferences!!.getBoolean("download_card", true)) {
|
if (sharedPreferences!!.getBoolean("download_card", true)) {
|
||||||
val bottomSheet = DownloadMultipleBottomSheetDialog(downloadList.toMutableList())
|
findNavController().navigate(R.id.downloadMultipleBottomSheetDialog2, bundleOf(
|
||||||
bottomSheet.show(parentFragmentManager, "downloadMultipleSheet")
|
Pair("downloads", downloadList)
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
downloadViewModel.queueDownloads(downloadList)
|
downloadViewModel.queueDownloads(downloadList)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -133,25 +133,37 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
|
||||||
if (cancelButton.hasOnClickListeners()) cancelButton.setOnClickListener(null)
|
if (cancelButton.hasOnClickListeners()) cancelButton.setOnClickListener(null)
|
||||||
cancelButton.setOnClickListener {onItemClickListener.onCancelClick(item.id)}
|
cancelButton.setOnClickListener {onItemClickListener.onCancelClick(item.id)}
|
||||||
|
|
||||||
if (item.status == DownloadRepository.Status.Paused.toString()){
|
|
||||||
progressBar.isIndeterminate = false
|
when(DownloadRepository.Status.valueOf(item.status)){
|
||||||
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_play_arrow_white)
|
DownloadRepository.Status.Active -> {
|
||||||
pauseButton.tag = ActiveDownloadAction.Resume
|
progressBar.isIndeterminate = true
|
||||||
cancelButton.visibility = View.VISIBLE
|
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_pause_white)
|
||||||
}else{
|
cancelButton.visibility = View.GONE
|
||||||
progressBar.isIndeterminate = true
|
pauseButton.isEnabled = true
|
||||||
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_pause_white)
|
pauseButton.tag = ActiveDownloadAction.Pause
|
||||||
cancelButton.visibility = View.GONE
|
}
|
||||||
pauseButton.tag = ActiveDownloadAction.Pause
|
DownloadRepository.Status.ActivePaused -> {
|
||||||
|
progressBar.isIndeterminate = false
|
||||||
|
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_play_arrow_white)
|
||||||
|
pauseButton.tag = ActiveDownloadAction.Resume
|
||||||
|
pauseButton.isEnabled = true
|
||||||
|
cancelButton.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
DownloadRepository.Status.PausedReQueued -> {
|
||||||
|
progressBar.isIndeterminate = true
|
||||||
|
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.ic_refresh)
|
||||||
|
pauseButton.tag = null
|
||||||
|
pauseButton.isEnabled = false
|
||||||
|
cancelButton.visibility = View.GONE
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pauseButton.setOnClickListener {
|
pauseButton.setOnClickListener {
|
||||||
if (pauseButton.tag == ActiveDownloadAction.Pause){
|
if (pauseButton.tag == ActiveDownloadAction.Pause){
|
||||||
onItemClickListener.onPauseClick(item.id, ActiveDownloadAction.Pause, position)
|
onItemClickListener.onPauseClick(item.id, ActiveDownloadAction.Pause, position)
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
onItemClickListener.onPauseClick(item.id, ActiveDownloadAction.Resume, position)
|
onItemClickListener.onPauseClick(item.id, ActiveDownloadAction.Resume, position)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ class ActiveDownloadMinifiedAdapter(onItemClickListener: OnItemClickListener, ac
|
||||||
if (cancelButton.hasOnClickListeners()) cancelButton.setOnClickListener(null)
|
if (cancelButton.hasOnClickListeners()) cancelButton.setOnClickListener(null)
|
||||||
cancelButton.setOnClickListener {onItemClickListener.onCancelClick(item.id)}
|
cancelButton.setOnClickListener {onItemClickListener.onCancelClick(item.id)}
|
||||||
|
|
||||||
if (item.status == DownloadRepository.Status.Paused.toString()){
|
if (item.status == DownloadRepository.Status.ActivePaused.toString()){
|
||||||
progressBar.isIndeterminate = false
|
progressBar.isIndeterminate = false
|
||||||
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_play_arrow_white)
|
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_play_arrow_white)
|
||||||
pauseButton.tag = ActiveDownloadAdapter.ActiveDownloadAction.Resume
|
pauseButton.tag = ActiveDownloadAdapter.ActiveDownloadAction.Resume
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ import android.app.Dialog
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Looper
|
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.util.Patterns
|
import android.util.Patterns
|
||||||
|
|
@ -17,13 +17,16 @@ import android.widget.Button
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import androidx.navigation.NavDestination
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
|
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
|
||||||
import com.deniscerri.ytdlnis.MainActivity
|
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.DBManager
|
import com.deniscerri.ytdlnis.database.DBManager
|
||||||
import com.deniscerri.ytdlnis.database.dao.CommandTemplateDao
|
import com.deniscerri.ytdlnis.database.dao.CommandTemplateDao
|
||||||
|
|
@ -44,14 +47,20 @@ import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.Locale
|
||||||
|
|
||||||
|
|
||||||
class DownloadBottomSheetDialog(private var result: ResultItem, private val type: Type, private var currentDownloadItem: DownloadItem? = null) : BottomSheetDialogFragment() {
|
class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
|
||||||
private lateinit var tabLayout: TabLayout
|
private lateinit var tabLayout: TabLayout
|
||||||
private lateinit var viewPager2: ViewPager2
|
private lateinit var viewPager2: ViewPager2
|
||||||
private lateinit var fragmentAdapter : DownloadFragmentAdapter
|
private lateinit var fragmentAdapter : DownloadFragmentAdapter
|
||||||
|
|
@ -64,6 +73,18 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type
|
||||||
private lateinit var sharedPreferences : SharedPreferences
|
private lateinit var sharedPreferences : SharedPreferences
|
||||||
private lateinit var updateItem : Button
|
private lateinit var updateItem : Button
|
||||||
private lateinit var view: View
|
private lateinit var view: View
|
||||||
|
private lateinit var shimmerLoading :ShimmerFrameLayout
|
||||||
|
private lateinit var title : View
|
||||||
|
private lateinit var shimmerLoadingSubtitle : ShimmerFrameLayout
|
||||||
|
private lateinit var subtitle : View
|
||||||
|
|
||||||
|
private var updateJob : Job? = null
|
||||||
|
private var updateFormatsJob : Job? = null
|
||||||
|
|
||||||
|
|
||||||
|
private lateinit var result: ResultItem
|
||||||
|
private lateinit var type: Type
|
||||||
|
private var currentDownloadItem: DownloadItem? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
@ -81,6 +102,26 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type
|
||||||
view = LayoutInflater.from(context).inflate(R.layout.download_bottom_sheet, null)
|
view = LayoutInflater.from(context).inflate(R.layout.download_bottom_sheet, null)
|
||||||
dialog.setContentView(view)
|
dialog.setContentView(view)
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 33){
|
||||||
|
arguments?.getParcelable("result", ResultItem::class.java)
|
||||||
|
}else{
|
||||||
|
arguments?.getParcelable<ResultItem>("result")
|
||||||
|
}.apply {
|
||||||
|
if (this == null){
|
||||||
|
dismiss()
|
||||||
|
return
|
||||||
|
}else{
|
||||||
|
result = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type = arguments?.getSerializable("type") as Type
|
||||||
|
currentDownloadItem = if (Build.VERSION.SDK_INT >= 33){
|
||||||
|
arguments?.getParcelable("downloadItem", DownloadItem::class.java)
|
||||||
|
}else{
|
||||||
|
arguments?.getParcelable<DownloadItem>("downloadItem")
|
||||||
|
}
|
||||||
|
|
||||||
dialog.setOnShowListener {
|
dialog.setOnShowListener {
|
||||||
behavior = BottomSheetBehavior.from(view.parent as View)
|
behavior = BottomSheetBehavior.from(view.parent as View)
|
||||||
val displayMetrics = DisplayMetrics()
|
val displayMetrics = DisplayMetrics()
|
||||||
|
|
@ -95,6 +136,13 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type
|
||||||
viewPager2 = view.findViewById(R.id.download_viewpager)
|
viewPager2 = view.findViewById(R.id.download_viewpager)
|
||||||
updateItem = view.findViewById(R.id.update_item)
|
updateItem = view.findViewById(R.id.update_item)
|
||||||
|
|
||||||
|
|
||||||
|
//loading shimmers
|
||||||
|
shimmerLoading = view.findViewById(R.id.shimmer_loading_title)
|
||||||
|
title = view.findViewById(R.id.bottom_sheet_title)
|
||||||
|
shimmerLoadingSubtitle = view.findViewById(R.id.shimmer_loading_subtitle)
|
||||||
|
subtitle = view.findViewById(R.id.bottom_sheet_subtitle)
|
||||||
|
|
||||||
(viewPager2.getChildAt(0) as? RecyclerView)?.apply {
|
(viewPager2.getChildAt(0) as? RecyclerView)?.apply {
|
||||||
isNestedScrollingEnabled = false
|
isNestedScrollingEnabled = false
|
||||||
overScrollMode = View.OVER_SCROLL_NEVER
|
overScrollMode = View.OVER_SCROLL_NEVER
|
||||||
|
|
@ -224,6 +272,8 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type
|
||||||
|
|
||||||
scheduleBtn.setOnClickListener{
|
scheduleBtn.setOnClickListener{
|
||||||
UiUtil.showDatePicker(fragmentManager) {
|
UiUtil.showDatePicker(fragmentManager) {
|
||||||
|
updateJob?.cancel()
|
||||||
|
updateFormatsJob?.cancel()
|
||||||
scheduleBtn.isEnabled = false
|
scheduleBtn.isEnabled = false
|
||||||
download.isEnabled = false
|
download.isEnabled = false
|
||||||
val item: DownloadItem = getDownloadItem()
|
val item: DownloadItem = getDownloadItem()
|
||||||
|
|
@ -237,6 +287,8 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
download!!.setOnClickListener {
|
download!!.setOnClickListener {
|
||||||
|
updateJob?.cancel()
|
||||||
|
updateFormatsJob?.cancel()
|
||||||
scheduleBtn.isEnabled = false
|
scheduleBtn.isEnabled = false
|
||||||
download.isEnabled = false
|
download.isEnabled = false
|
||||||
val item: DownloadItem = getDownloadItem()
|
val item: DownloadItem = getDownloadItem()
|
||||||
|
|
@ -285,7 +337,7 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type
|
||||||
(updateItem.parent as LinearLayout).visibility = View.VISIBLE
|
(updateItem.parent as LinearLayout).visibility = View.VISIBLE
|
||||||
updateItem.setOnClickListener {
|
updateItem.setOnClickListener {
|
||||||
(updateItem.parent as LinearLayout).visibility = View.GONE
|
(updateItem.parent as LinearLayout).visibility = View.GONE
|
||||||
initUpdateData(view)
|
initUpdateData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
|
@ -300,7 +352,7 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type
|
||||||
|
|
||||||
//update in the background if there is no data
|
//update in the background if there is no data
|
||||||
if(result.title.isEmpty() && currentDownloadItem == null && !sharedPreferences.getBoolean("quick_download", false) && type != Type.command){
|
if(result.title.isEmpty() && currentDownloadItem == null && !sharedPreferences.getBoolean("quick_download", false) && type != Type.command){
|
||||||
initUpdateData(view)
|
initUpdateData()
|
||||||
}else {
|
}else {
|
||||||
val usingGenericFormatsOrEmpty = result.formats.isEmpty() || result.formats.any { it.format_note.contains("ytdlnisgeneric") }
|
val usingGenericFormatsOrEmpty = result.formats.isEmpty() || result.formats.any { it.format_note.contains("ytdlnisgeneric") }
|
||||||
if (usingGenericFormatsOrEmpty && sharedPreferences.getBoolean("update_formats", false) && !sharedPreferences.getBoolean("quick_download", false)){
|
if (usingGenericFormatsOrEmpty && sharedPreferences.getBoolean("update_formats", false) && !sharedPreferences.getBoolean("quick_download", false)){
|
||||||
|
|
@ -377,48 +429,83 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initUpdateData(v: View){
|
private fun initUpdateData() {
|
||||||
val shimmerLoading = v.findViewById<ShimmerFrameLayout>(R.id.shimmer_loading_title)
|
updateJob = CoroutineScope(SupervisorJob()).launch(Dispatchers.IO){
|
||||||
val title = v.findViewById<View>(R.id.bottom_sheet_title)
|
findNavController().saveState()
|
||||||
val shimmerLoadingSubtitle = v.findViewById<ShimmerFrameLayout>(R.id.shimmer_loading_subtitle)
|
kotlin.runCatching {
|
||||||
val subtitle = v.findViewById<View>(R.id.bottom_sheet_subtitle)
|
|
||||||
|
|
||||||
val updateJob = CoroutineScope(SupervisorJob()).launch(Dispatchers.IO){
|
|
||||||
withContext(Dispatchers.Main){
|
|
||||||
title.visibility = View.GONE
|
|
||||||
subtitle.visibility = View.GONE
|
|
||||||
shimmerLoading.visibility = View.VISIBLE
|
|
||||||
shimmerLoadingSubtitle.visibility = View.VISIBLE
|
|
||||||
shimmerLoading.startShimmer()
|
|
||||||
shimmerLoadingSubtitle.startShimmer()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (result.url.isBlank()){
|
|
||||||
withContext(Dispatchers.Main){dismiss()}
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
|
|
||||||
val result = resultViewModel.parseQueries(listOf(result.url))
|
|
||||||
if (result.isEmpty()){
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.size == 1 && result[0] != null){
|
|
||||||
fragmentAdapter.setResultItem(result[0]!!)
|
|
||||||
withContext(Dispatchers.Main){
|
withContext(Dispatchers.Main){
|
||||||
runCatching {
|
title.visibility = View.GONE
|
||||||
val f = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment
|
subtitle.visibility = View.GONE
|
||||||
f.updateUI(result[0])
|
shimmerLoading.visibility = View.VISIBLE
|
||||||
}
|
shimmerLoadingSubtitle.visibility = View.VISIBLE
|
||||||
|
shimmerLoading.startShimmer()
|
||||||
runCatching {
|
shimmerLoadingSubtitle.startShimmer()
|
||||||
val f1 = fragmentManager?.findFragmentByTag("f1") as DownloadVideoFragment
|
|
||||||
f1.updateUI(result[0])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
withContext(Dispatchers.Main){
|
if (result.url.isBlank()){
|
||||||
|
withContext(Dispatchers.Main){dismiss()}
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = resultViewModel.parseQueries(listOf(result.url))
|
||||||
|
if (result.isEmpty()){
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.size == 1 && result[0] != null){
|
||||||
|
fragmentAdapter.setResultItem(result[0]!!)
|
||||||
|
withContext(Dispatchers.Main){
|
||||||
|
runCatching {
|
||||||
|
val f = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment
|
||||||
|
f.updateUI(result[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
runCatching {
|
||||||
|
val f1 = fragmentManager?.findFragmentByTag("f1") as DownloadVideoFragment
|
||||||
|
f1.updateUI(result[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main){
|
||||||
|
title.visibility = View.VISIBLE
|
||||||
|
subtitle.visibility = View.VISIBLE
|
||||||
|
shimmerLoading.visibility = View.GONE
|
||||||
|
shimmerLoadingSubtitle.visibility = View.GONE
|
||||||
|
shimmerLoading.stopShimmer()
|
||||||
|
shimmerLoadingSubtitle.stopShimmer()
|
||||||
|
}
|
||||||
|
|
||||||
|
val usingGenericFormatsOrEmpty = result[0]!!.formats.isEmpty() || result[0]!!.formats.any { it.format_note.contains("ytdlnisgeneric") }
|
||||||
|
|
||||||
|
if (usingGenericFormatsOrEmpty && sharedPreferences.getBoolean("update_formats", false)){
|
||||||
|
initUpdateFormats(result[0]!!.url)
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
//open multi download card instead
|
||||||
|
if (activity is ShareActivity){
|
||||||
|
val preferredType = DownloadViewModel.Type.valueOf(sharedPreferences.getString("preferred_download_type", "video")!!)
|
||||||
|
withContext(Dispatchers.Main){
|
||||||
|
findNavController().navigate(R.id.action_downloadBottomSheetDialog_to_selectPlaylistItemsDialog, bundleOf(
|
||||||
|
Pair("results", result),
|
||||||
|
Pair("type", preferredType),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shimmerLoading.setOnClickListener {
|
||||||
|
updateJob?.cancel()
|
||||||
|
(updateItem.parent as LinearLayout).visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
updateJob?.invokeOnCompletion {
|
||||||
|
kotlin.runCatching {
|
||||||
|
requireActivity().runOnUiThread {
|
||||||
title.visibility = View.VISIBLE
|
title.visibility = View.VISIBLE
|
||||||
subtitle.visibility = View.VISIBLE
|
subtitle.visibility = View.VISIBLE
|
||||||
shimmerLoading.visibility = View.GONE
|
shimmerLoading.visibility = View.GONE
|
||||||
|
|
@ -426,48 +513,13 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type
|
||||||
shimmerLoading.stopShimmer()
|
shimmerLoading.stopShimmer()
|
||||||
shimmerLoadingSubtitle.stopShimmer()
|
shimmerLoadingSubtitle.stopShimmer()
|
||||||
}
|
}
|
||||||
|
|
||||||
val usingGenericFormatsOrEmpty = result[0]!!.formats.isEmpty() || result[0]!!.formats.any { it.format_note.contains("ytdlnisgeneric") }
|
|
||||||
|
|
||||||
if (usingGenericFormatsOrEmpty && sharedPreferences.getBoolean("update_formats", false)){
|
|
||||||
initUpdateFormats(result[0]!!.url)
|
|
||||||
}
|
|
||||||
|
|
||||||
}else{
|
|
||||||
//open multi download card instead
|
|
||||||
if (activity is ShareActivity){
|
|
||||||
val preferredType = DownloadViewModel.Type.valueOf(sharedPreferences.getString("preferred_download_type", "video")!!)
|
|
||||||
withContext(Dispatchers.Main){
|
|
||||||
val playlistSelect = SelectPlaylistItemsDialog(items = result, type = preferredType)
|
|
||||||
parentFragmentManager.addFragmentOnAttachListener { fragmentManager, fragment ->
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
playlistSelect.show(parentFragmentManager, "downloadPlaylistSheet")
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shimmerLoading.setOnClickListener {
|
updateJob?.start()
|
||||||
updateJob.cancel()
|
|
||||||
(updateItem.parent as LinearLayout).visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
updateJob.invokeOnCompletion {
|
|
||||||
requireActivity().runOnUiThread {
|
|
||||||
title.visibility = View.VISIBLE
|
|
||||||
subtitle.visibility = View.VISIBLE
|
|
||||||
shimmerLoading.visibility = View.GONE
|
|
||||||
shimmerLoadingSubtitle.visibility = View.GONE
|
|
||||||
shimmerLoading.stopShimmer()
|
|
||||||
shimmerLoadingSubtitle.stopShimmer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateJob.start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initUpdateFormats(url: String){
|
private fun initUpdateFormats(url: String){
|
||||||
CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) {
|
updateFormatsJob = CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) {
|
||||||
withContext(Dispatchers.Main){
|
withContext(Dispatchers.Main){
|
||||||
runCatching {
|
runCatching {
|
||||||
val f1 = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment
|
val f1 = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment
|
||||||
|
|
@ -510,25 +562,7 @@ class DownloadBottomSheetDialog(private var result: ResultItem, private val type
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
updateFormatsJob?.start()
|
||||||
|
|
||||||
override fun onCancel(dialog: DialogInterface) {
|
|
||||||
super.onCancel(dialog)
|
|
||||||
cleanUp()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDismiss(dialog: DialogInterface) {
|
|
||||||
super.onDismiss(dialog)
|
|
||||||
cleanUp()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun cleanUp(){
|
|
||||||
kotlin.runCatching {
|
|
||||||
if (activity is ShareActivity && !parentFragmentManager.fragments.map { it.tag }.contains("downloadPlaylistSheet")){
|
|
||||||
(activity as ShareActivity).finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import android.content.SharedPreferences
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
|
|
@ -37,6 +38,7 @@ import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.ui.adapter.ConfigureMultipleDownloadsAdapter
|
import com.deniscerri.ytdlnis.ui.adapter.ConfigureMultipleDownloadsAdapter
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
import com.deniscerri.ytdlnis.database.models.Format
|
import com.deniscerri.ytdlnis.database.models.Format
|
||||||
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
|
|
@ -66,7 +68,7 @@ import kotlinx.coroutines.withContext
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
class DownloadMultipleBottomSheetDialog(private var items: MutableList<DownloadItem>) : BottomSheetDialogFragment(), ConfigureMultipleDownloadsAdapter.OnItemClickListener, View.OnClickListener,
|
class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), ConfigureMultipleDownloadsAdapter.OnItemClickListener, View.OnClickListener,
|
||||||
ConfigureDownloadBottomSheetDialog.OnDownloadItemUpdateListener {
|
ConfigureDownloadBottomSheetDialog.OnDownloadItemUpdateListener {
|
||||||
private lateinit var downloadViewModel: DownloadViewModel
|
private lateinit var downloadViewModel: DownloadViewModel
|
||||||
private lateinit var historyViewModel: HistoryViewModel
|
private lateinit var historyViewModel: HistoryViewModel
|
||||||
|
|
@ -80,6 +82,8 @@ class DownloadMultipleBottomSheetDialog(private var items: MutableList<DownloadI
|
||||||
private lateinit var filesize : TextView
|
private lateinit var filesize : TextView
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
|
|
||||||
|
private lateinit var items: MutableList<DownloadItem>
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
@ -97,6 +101,19 @@ class DownloadMultipleBottomSheetDialog(private var items: MutableList<DownloadI
|
||||||
val view = LayoutInflater.from(context).inflate(R.layout.download_multiple_bottom_sheet, null)
|
val view = LayoutInflater.from(context).inflate(R.layout.download_multiple_bottom_sheet, null)
|
||||||
dialog.setContentView(view)
|
dialog.setContentView(view)
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 33){
|
||||||
|
arguments?.getParcelableArrayList("downloads", DownloadItem::class.java)
|
||||||
|
}else{
|
||||||
|
arguments?.getParcelableArrayList<DownloadItem>("downloads")
|
||||||
|
}.apply {
|
||||||
|
if (this == null){
|
||||||
|
dismiss()
|
||||||
|
return
|
||||||
|
}else{
|
||||||
|
items = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (items.isEmpty()) dismiss()
|
if (items.isEmpty()) dismiss()
|
||||||
|
|
||||||
dialog.setOnShowListener {
|
dialog.setOnShowListener {
|
||||||
|
|
@ -138,10 +155,7 @@ class DownloadMultipleBottomSheetDialog(private var items: MutableList<DownloadI
|
||||||
item.downloadStartTime = it.timeInMillis
|
item.downloadStartTime = it.timeInMillis
|
||||||
}
|
}
|
||||||
runBlocking {
|
runBlocking {
|
||||||
val chunks = items.chunked(10)
|
downloadViewModel.queueDownloads(items)
|
||||||
for (c in chunks) {
|
|
||||||
downloadViewModel.queueDownloads(c)
|
|
||||||
}
|
|
||||||
val first = items.first()
|
val first = items.first()
|
||||||
val date = SimpleDateFormat(DateFormat.getBestDateTimePattern(Locale.getDefault(), "ddMMMyyyy - HHmm"), Locale.getDefault()).format(first.downloadStartTime)
|
val date = SimpleDateFormat(DateFormat.getBestDateTimePattern(Locale.getDefault(), "ddMMMyyyy - HHmm"), Locale.getDefault()).format(first.downloadStartTime)
|
||||||
Toast.makeText(context, getString(R.string.download_rescheduled_to) + " " + date, Toast.LENGTH_LONG).show()
|
Toast.makeText(context, getString(R.string.download_rescheduled_to) + " " + date, Toast.LENGTH_LONG).show()
|
||||||
|
|
@ -154,11 +168,7 @@ class DownloadMultipleBottomSheetDialog(private var items: MutableList<DownloadI
|
||||||
scheduleBtn.isEnabled = false
|
scheduleBtn.isEnabled = false
|
||||||
download.isEnabled = false
|
download.isEnabled = false
|
||||||
runBlocking {
|
runBlocking {
|
||||||
val chunks = items.chunked(10)
|
downloadViewModel.queueDownloads(items)
|
||||||
for (c in chunks) {
|
|
||||||
downloadViewModel.queueDownloads(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|
@ -559,24 +569,6 @@ class DownloadMultipleBottomSheetDialog(private var items: MutableList<DownloadI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCancel(dialog: DialogInterface) {
|
|
||||||
super.onCancel(dialog)
|
|
||||||
cleanup()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDismiss(dialog: DialogInterface) {
|
|
||||||
super.onDismiss(dialog)
|
|
||||||
cleanup()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun cleanup(){
|
|
||||||
kotlin.runCatching {
|
|
||||||
if (activity is ShareActivity){
|
|
||||||
(activity as ShareActivity).finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onButtonClick(itemURL: String) {
|
override fun onButtonClick(itemURL: String) {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val item = items.find { it.url == itemURL } ?: return@launch
|
val item = items.find { it.url == itemURL } ?: return@launch
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import android.content.res.Configuration
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
|
|
@ -70,7 +71,7 @@ import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogFragment(), GenericDownloadAdapter.OnItemClickListener, ActiveDownloadMinifiedAdapter.OnItemClickListener {
|
class ResultCardDetailsDialog : BottomSheetDialogFragment(), GenericDownloadAdapter.OnItemClickListener, ActiveDownloadMinifiedAdapter.OnItemClickListener {
|
||||||
private lateinit var infoUtil: InfoUtil
|
private lateinit var infoUtil: InfoUtil
|
||||||
private lateinit var notificationUtil: NotificationUtil
|
private lateinit var notificationUtil: NotificationUtil
|
||||||
private lateinit var videoView: PlayerView
|
private lateinit var videoView: PlayerView
|
||||||
|
|
@ -85,6 +86,7 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF
|
||||||
|
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
private lateinit var dialogView : View
|
private lateinit var dialogView : View
|
||||||
|
private lateinit var item: ResultItem
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
@ -136,6 +138,19 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
val i = if (Build.VERSION.SDK_INT >= 33){
|
||||||
|
arguments?.getParcelable("result", ResultItem::class.java)
|
||||||
|
}else{
|
||||||
|
arguments?.getParcelable<ResultItem>("result")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == null) {
|
||||||
|
dismiss()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
item = i
|
||||||
|
|
||||||
//remove outdated player url of 1hr so it can refetch it in the player
|
//remove outdated player url of 1hr so it can refetch it in the player
|
||||||
if (item.creationTime > System.currentTimeMillis() - 3600000) item.urls = ""
|
if (item.creationTime > System.currentTimeMillis() - 3600000) item.urls = ""
|
||||||
|
|
||||||
|
|
@ -293,10 +308,12 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onButtonClick(type: DownloadViewModel.Type){
|
private fun onButtonClick(type: DownloadViewModel.Type){
|
||||||
this.dismiss()
|
|
||||||
if (sharedPreferences.getBoolean("download_card", true)) {
|
if (sharedPreferences.getBoolean("download_card", true)) {
|
||||||
val bottomSheet = DownloadBottomSheetDialog(item, type)
|
val bundle = Bundle()
|
||||||
bottomSheet.show(parentFragmentManager, "downloadSingleSheet")
|
bundle.putParcelable("result", item)
|
||||||
|
bundle.putSerializable("type", type)
|
||||||
|
findNavController().navigateUp()
|
||||||
|
findNavController().navigate(R.id.downloadBottomSheetDialog, bundle)
|
||||||
} else {
|
} else {
|
||||||
lifecycleScope.launch{
|
lifecycleScope.launch{
|
||||||
val downloadItem = withContext(Dispatchers.IO){
|
val downloadItem = withContext(Dispatchers.IO){
|
||||||
|
|
@ -305,6 +322,7 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF
|
||||||
givenType = type)
|
givenType = type)
|
||||||
}
|
}
|
||||||
downloadViewModel.queueDownloads(listOf(downloadItem))
|
downloadViewModel.queueDownloads(listOf(downloadItem))
|
||||||
|
findNavController().navigateUp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -324,7 +342,6 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
videoView.player?.stop()
|
videoView.player?.stop()
|
||||||
videoView.player?.release()
|
videoView.player?.release()
|
||||||
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("resultDetails")!!).commit()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -582,7 +599,7 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF
|
||||||
ActiveDownloadAdapter.ActiveDownloadAction.Pause -> {
|
ActiveDownloadAdapter.ActiveDownloadAction.Pause -> {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
cancelItem(itemID.toInt())
|
cancelItem(itemID.toInt())
|
||||||
item.status = DownloadRepository.Status.Paused.toString()
|
item.status = DownloadRepository.Status.ActivePaused.toString()
|
||||||
withContext(Dispatchers.IO){
|
withContext(Dispatchers.IO){
|
||||||
downloadViewModel.updateDownload(item)
|
downloadViewModel.updateDownload(item)
|
||||||
}
|
}
|
||||||
|
|
@ -591,7 +608,7 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF
|
||||||
}
|
}
|
||||||
ActiveDownloadAdapter.ActiveDownloadAction.Resume -> {
|
ActiveDownloadAdapter.ActiveDownloadAction.Resume -> {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
item.status = DownloadRepository.Status.Active.toString()
|
item.status = DownloadRepository.Status.PausedReQueued.toString()
|
||||||
withContext(Dispatchers.IO){
|
withContext(Dispatchers.IO){
|
||||||
downloadViewModel.updateDownload(item)
|
downloadViewModel.updateDownload(item)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,19 @@ package com.deniscerri.ytdlnis.ui.downloadcard
|
||||||
import android.app.ActionBar.LayoutParams
|
import android.app.ActionBar.LayoutParams
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.Window
|
import android.view.Window
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.widget.doAfterTextChanged
|
import androidx.core.widget.doAfterTextChanged
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
|
|
@ -30,8 +33,9 @@ import com.google.android.material.floatingactionbutton.ExtendedFloatingActionBu
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class SelectPlaylistItemsDialog(private val items: List<ResultItem?>, private val type: DownloadViewModel.Type) : DialogFragment(), PlaylistAdapter.OnItemClickListener {
|
class SelectPlaylistItemsDialog : DialogFragment(), PlaylistAdapter.OnItemClickListener {
|
||||||
private lateinit var downloadViewModel: DownloadViewModel
|
private lateinit var downloadViewModel: DownloadViewModel
|
||||||
private lateinit var resultViewModel: ResultViewModel
|
private lateinit var resultViewModel: ResultViewModel
|
||||||
private lateinit var listAdapter : PlaylistAdapter
|
private lateinit var listAdapter : PlaylistAdapter
|
||||||
|
|
@ -41,6 +45,10 @@ class SelectPlaylistItemsDialog(private val items: List<ResultItem?>, private va
|
||||||
private lateinit var fromTextInput: TextInputLayout
|
private lateinit var fromTextInput: TextInputLayout
|
||||||
private lateinit var toTextInput: TextInputLayout
|
private lateinit var toTextInput: TextInputLayout
|
||||||
|
|
||||||
|
|
||||||
|
private lateinit var items: List<ResultItem?>
|
||||||
|
private lateinit var type: DownloadViewModel.Type
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setStyle(STYLE_NORMAL, R.style.FullScreenDialogTheme)
|
setStyle(STYLE_NORMAL, R.style.FullScreenDialogTheme)
|
||||||
|
|
@ -65,6 +73,21 @@ class SelectPlaylistItemsDialog(private val items: List<ResultItem?>, private va
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 33){
|
||||||
|
arguments?.getParcelableArrayList("results", ResultItem::class.java)
|
||||||
|
}else{
|
||||||
|
arguments?.getParcelableArrayList<ResultItem>("results")
|
||||||
|
}.apply {
|
||||||
|
if (this == null){
|
||||||
|
dismiss()
|
||||||
|
return
|
||||||
|
}else{
|
||||||
|
items = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type = arguments?.getSerializable("type") as DownloadViewModel.Type
|
||||||
|
|
||||||
|
|
||||||
dialog?.window?.setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
|
dialog?.window?.setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
|
||||||
|
|
||||||
toolbar = view.findViewById<MaterialToolbar>(R.id.toolbar)
|
toolbar = view.findViewById<MaterialToolbar>(R.id.toolbar)
|
||||||
|
|
@ -156,11 +179,12 @@ class SelectPlaylistItemsDialog(private val items: List<ResultItem?>, private va
|
||||||
val checkedResultItems = items.filter { item -> checkedItems.contains(item!!.url) }
|
val checkedResultItems = items.filter { item -> checkedItems.contains(item!!.url) }
|
||||||
if (checkedResultItems.size == 1){
|
if (checkedResultItems.size == 1){
|
||||||
val resultItem = resultViewModel.getItemByURL(checkedResultItems[0]!!.url)
|
val resultItem = resultViewModel.getItemByURL(checkedResultItems[0]!!.url)
|
||||||
val bottomSheet = DownloadBottomSheetDialog(resultItem, type)
|
withContext(Dispatchers.Main){
|
||||||
parentFragmentManager.addFragmentOnAttachListener { fragmentManager, fragment ->
|
findNavController().navigate(R.id.action_selectPlaylistItemsDialog_to_downloadBottomSheetDialog, bundleOf(
|
||||||
dismiss()
|
Pair("result", resultItem),
|
||||||
|
Pair("type", downloadViewModel.getDownloadType(type, resultItem.url)),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
bottomSheet.show(parentFragmentManager, "downloadSingleSheet")
|
|
||||||
}else{
|
}else{
|
||||||
val downloadItems = mutableListOf<DownloadItem>()
|
val downloadItems = mutableListOf<DownloadItem>()
|
||||||
checkedResultItems.forEach { c ->
|
checkedResultItems.forEach { c ->
|
||||||
|
|
@ -173,11 +197,11 @@ class SelectPlaylistItemsDialog(private val items: List<ResultItem?>, private va
|
||||||
downloadItems.add(i)
|
downloadItems.add(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
val bottomSheet = DownloadMultipleBottomSheetDialog(downloadItems)
|
withContext(Dispatchers.Main){
|
||||||
parentFragmentManager.addFragmentOnAttachListener { fragmentManager, fragment ->
|
findNavController().navigate(R.id.action_selectPlaylistItemsDialog_to_downloadMultipleBottomSheetDialog, bundleOf(
|
||||||
dismiss()
|
Pair("downloads", downloadItems)
|
||||||
|
))
|
||||||
}
|
}
|
||||||
bottomSheet.show(parentFragmentManager, "downloadMultipleSheet")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dismiss()
|
dismiss()
|
||||||
|
|
@ -210,25 +234,6 @@ class SelectPlaylistItemsDialog(private val items: List<ResultItem?>, private va
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCancel(dialog: DialogInterface) {
|
|
||||||
super.onCancel(dialog)
|
|
||||||
cleanup()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDismiss(dialog: DialogInterface) {
|
|
||||||
super.onDismiss(dialog)
|
|
||||||
cleanup()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun cleanup(){
|
|
||||||
kotlin.runCatching {
|
|
||||||
val movedToMultipleOrSingleSheet = parentFragmentManager.fragments.map { it.tag }.contains("downloadMultipleSheet") || parentFragmentManager.fragments.map { it.tag }.contains("downloadSingleSheet")
|
|
||||||
if (activity is ShareActivity && !movedToMultipleOrSingleSheet){
|
|
||||||
(activity as ShareActivity).finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkRanges(start: String, end: String) : Boolean {
|
private fun checkRanges(start: String, end: String) : Boolean {
|
||||||
return start.isNotBlank() && end.isNotBlank()
|
return start.isNotBlank() && end.isNotBlank()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis
|
||||||
downloadViewModel.getActiveDownloads()
|
downloadViewModel.getActiveDownloads()
|
||||||
}.forEach {
|
}.forEach {
|
||||||
cancelItem(it.id.toInt())
|
cancelItem(it.id.toInt())
|
||||||
it.status = DownloadRepository.Status.Paused.toString()
|
it.status = DownloadRepository.Status.ActivePaused.toString()
|
||||||
downloadViewModel.updateDownload(it)
|
downloadViewModel.updateDownload(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,7 +111,7 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis
|
||||||
downloadViewModel.getActiveDownloads()
|
downloadViewModel.getActiveDownloads()
|
||||||
}
|
}
|
||||||
|
|
||||||
val toQueue = active.filter { it.status == DownloadRepository.Status.Paused.toString() }.toMutableList()
|
val toQueue = active.filter { it.status == DownloadRepository.Status.ActivePaused.toString() }.toMutableList()
|
||||||
toQueue.forEach {
|
toQueue.forEach {
|
||||||
it.status = DownloadRepository.Status.Queued.toString()
|
it.status = DownloadRepository.Status.Queued.toString()
|
||||||
downloadViewModel.updateDownload(it)
|
downloadViewModel.updateDownload(it)
|
||||||
|
|
@ -162,7 +162,7 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis
|
||||||
|
|
||||||
if (it.size > 1){
|
if (it.size > 1){
|
||||||
pauseResume.visibility = View.VISIBLE
|
pauseResume.visibility = View.VISIBLE
|
||||||
if (it.all { l -> l.status == DownloadRepository.Status.Paused.toString() }){
|
if (it.all { l -> l.status == DownloadRepository.Status.ActivePaused.toString() }){
|
||||||
pauseResume.text = requireContext().getString(R.string.resume)
|
pauseResume.text = requireContext().getString(R.string.resume)
|
||||||
}else{
|
}else{
|
||||||
pauseResume.text = requireContext().getString(R.string.pause)
|
pauseResume.text = requireContext().getString(R.string.pause)
|
||||||
|
|
@ -208,7 +208,7 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis
|
||||||
ActiveDownloadAdapter.ActiveDownloadAction.Pause -> {
|
ActiveDownloadAdapter.ActiveDownloadAction.Pause -> {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
cancelItem(itemID.toInt())
|
cancelItem(itemID.toInt())
|
||||||
item.status = DownloadRepository.Status.Paused.toString()
|
item.status = DownloadRepository.Status.ActivePaused.toString()
|
||||||
withContext(Dispatchers.IO){
|
withContext(Dispatchers.IO){
|
||||||
downloadViewModel.updateDownload(item)
|
downloadViewModel.updateDownload(item)
|
||||||
}
|
}
|
||||||
|
|
@ -217,7 +217,7 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis
|
||||||
}
|
}
|
||||||
ActiveDownloadAdapter.ActiveDownloadAction.Resume -> {
|
ActiveDownloadAdapter.ActiveDownloadAction.Resume -> {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
item.status = DownloadRepository.Status.Active.toString()
|
item.status = DownloadRepository.Status.PausedReQueued.toString()
|
||||||
withContext(Dispatchers.IO){
|
withContext(Dispatchers.IO){
|
||||||
downloadViewModel.updateDownload(item)
|
downloadViewModel.updateDownload(item)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,11 @@ import android.widget.RelativeLayout
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
|
|
@ -131,12 +133,12 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
longClickDownloadButton = {
|
longClickDownloadButton = {
|
||||||
val sheet = DownloadBottomSheetDialog(
|
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
|
||||||
currentDownloadItem = it,
|
Pair("downloadItem", it),
|
||||||
result = downloadViewModel.createResultItemFromDownload(it),
|
Pair("result", downloadViewModel.createResultItemFromDownload(it)),
|
||||||
type = it.type
|
Pair("type", it.type)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
sheet.show(parentFragmentManager, "downloadSingleSheet")
|
|
||||||
},
|
},
|
||||||
scheduleButtonClick = {}
|
scheduleButtonClick = {}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ import android.widget.Toast
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import androidx.navigation.ui.setupWithNavController
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import android.widget.AdapterView.OnItemClickListener
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
|
@ -134,12 +135,11 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
longClickDownloadButton = {
|
longClickDownloadButton = {
|
||||||
val sheet = DownloadBottomSheetDialog(
|
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
|
||||||
currentDownloadItem = it,
|
Pair("downloadItem", it),
|
||||||
result = downloadViewModel.createResultItemFromDownload(it),
|
Pair("result", downloadViewModel.createResultItemFromDownload(it)),
|
||||||
type = it.type
|
Pair("type", it.type)
|
||||||
)
|
))
|
||||||
sheet.show(parentFragmentManager, "downloadSingleSheet")
|
|
||||||
},
|
},
|
||||||
scheduleButtonClick = {}
|
scheduleButtonClick = {}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.forEach
|
import androidx.core.view.forEach
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
|
@ -411,11 +412,10 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
historyViewModel.delete(it, false)
|
historyViewModel.delete(it, false)
|
||||||
},
|
},
|
||||||
redownloadShowDownloadCard = {
|
redownloadShowDownloadCard = {
|
||||||
val sheet = DownloadBottomSheetDialog(
|
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
|
||||||
result = downloadViewModel.createResultItemFromHistory(it),
|
Pair("result", downloadViewModel.createResultItemFromHistory(it)),
|
||||||
type = it.type
|
Pair("type", it.type),
|
||||||
)
|
))
|
||||||
sheet.show(parentFragmentManager, "downloadSingleSheet")
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -547,10 +547,10 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
ItemTouchHelper.RIGHT -> {
|
ItemTouchHelper.RIGHT -> {
|
||||||
val item = historyList!![position]!!
|
val item = historyList!![position]!!
|
||||||
historyAdapter!!.notifyItemChanged(position)
|
historyAdapter!!.notifyItemChanged(position)
|
||||||
val sheet = DownloadBottomSheetDialog(type = item.type,
|
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
|
||||||
result = downloadViewModel.createResultItemFromHistory(item)
|
Pair("result", downloadViewModel.createResultItemFromHistory(item)),
|
||||||
)
|
Pair("type", item.type)
|
||||||
sheet.show(parentFragmentManager, "downloadSingleSheet")
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,11 @@ import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
|
|
@ -154,12 +156,11 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
longClickDownloadButton = {
|
longClickDownloadButton = {
|
||||||
val sheet = DownloadBottomSheetDialog(
|
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
|
||||||
currentDownloadItem = it,
|
Pair("downloadItem", it),
|
||||||
result = downloadViewModel.createResultItemFromDownload(it),
|
Pair("result", downloadViewModel.createResultItemFromDownload(it)),
|
||||||
type = it.type
|
Pair("type", it.type)
|
||||||
)
|
))
|
||||||
sheet.show(parentFragmentManager, "downloadSingleSheet")
|
|
||||||
},
|
},
|
||||||
scheduleButtonClick = {downloadItem ->
|
scheduleButtonClick = {downloadItem ->
|
||||||
UiUtil.showDatePicker(parentFragmentManager) {
|
UiUtil.showDatePicker(parentFragmentManager) {
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,11 @@ import android.widget.RelativeLayout
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
|
|
@ -131,12 +133,11 @@ class SavedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLis
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
longClickDownloadButton = { it: DownloadItem ->
|
longClickDownloadButton = { it: DownloadItem ->
|
||||||
val sheet = DownloadBottomSheetDialog(
|
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
|
||||||
currentDownloadItem = it,
|
Pair("downloadItem", it),
|
||||||
result = downloadViewModel.createResultItemFromDownload(it),
|
Pair("result", downloadViewModel.createResultItemFromDownload(it)),
|
||||||
type = it.type
|
Pair("type", it.type),
|
||||||
)
|
))
|
||||||
sheet.show(parentFragmentManager, "downloadSingleSheet")
|
|
||||||
},
|
},
|
||||||
scheduleButtonClick = {}
|
scheduleButtonClick = {}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,6 @@ class DownloadLogFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
content = view.findViewById(R.id.content)
|
content = view.findViewById(R.id.content)
|
||||||
content.movementMethod = ScrollingMovementMethod()
|
|
||||||
content.setTextIsSelectable(true)
|
content.setTextIsSelectable(true)
|
||||||
contentScrollView = view.findViewById(R.id.content_scrollview)
|
contentScrollView = view.findViewById(R.id.content_scrollview)
|
||||||
val bottomAppBar = view.findViewById<BottomAppBar>(R.id.bottomAppBar)
|
val bottomAppBar = view.findViewById<BottomAppBar>(R.id.bottomAppBar)
|
||||||
|
|
@ -89,7 +88,7 @@ class DownloadLogFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val id = arguments?.getLong("logID")
|
val id = arguments?.getLong("logID")
|
||||||
if (id == null) {
|
if (id == null || id == 0L) {
|
||||||
mainActivity.onBackPressedDispatcher.onBackPressed()
|
mainActivity.onBackPressedDispatcher.onBackPressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,19 +154,11 @@ class DownloadLogFragment : Fragment() {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
// contentScrollView.setOnScrollChangeListener { view, sx, sy, osx, osy ->
|
contentScrollView.setOnScrollChangeListener { view, sx, sy, osx, osy ->
|
||||||
// if (sy < osy){
|
if (sy < osy){
|
||||||
// if (contentScrollView.canScrollVertically(1)){
|
bottomAppBar?.menu?.get(1)?.isVisible = contentScrollView.canScrollVertically(1)
|
||||||
// shouldScroll = false
|
}
|
||||||
// content.movementMethod = LinkMovementMethod.getInstance()
|
}
|
||||||
// bottomAppBar?.menu?.get(1)?.isVisible = true
|
|
||||||
// }else{
|
|
||||||
// shouldScroll = true
|
|
||||||
// content.movementMethod = ScrollingMovementMethod()
|
|
||||||
// bottomAppBar?.menu?.get(1)?.isVisible = false
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
logViewModel.getLogFlowByID(id!!).observe(viewLifecycleOwner){logItem ->
|
logViewModel.getLogFlowByID(id!!).observe(viewLifecycleOwner){logItem ->
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ class NotificationUtil(var context: Context) {
|
||||||
val importance = NotificationManager.IMPORTANCE_LOW
|
val importance = NotificationManager.IMPORTANCE_LOW
|
||||||
var channel = NotificationChannel(DOWNLOAD_WORKER_CHANNEL_ID, name, importance)
|
var channel = NotificationChannel(DOWNLOAD_WORKER_CHANNEL_ID, name, importance)
|
||||||
channel.description = description
|
channel.description = description
|
||||||
|
channel.setSound(null, null)
|
||||||
notificationManager.createNotificationChannel(channel)
|
notificationManager.createNotificationChannel(channel)
|
||||||
|
|
||||||
//gui downloads
|
//gui downloads
|
||||||
|
|
|
||||||
|
|
@ -611,7 +611,7 @@ object UiUtil {
|
||||||
|
|
||||||
if (item.format.format_note == "?" || item.format.format_note == "") formatNote!!.visibility =
|
if (item.format.format_note == "?" || item.format.format_note == "") formatNote!!.visibility =
|
||||||
View.GONE
|
View.GONE
|
||||||
else formatNote!!.text = item.format.format_note.uppercase()
|
else formatNote!!.text = item.format.format_note
|
||||||
|
|
||||||
if (item.format.container != "") {
|
if (item.format.container != "") {
|
||||||
container!!.text = if (file.exists()) file.extension.uppercase() else item.format.container.uppercase()
|
container!!.text = if (file.exists()) file.extension.uppercase() else item.format.container.uppercase()
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,6 @@ import com.yausername.youtubedl_android.YoutubeDL.UpdateStatus
|
||||||
import io.noties.markwon.AbstractMarkwonPlugin
|
import io.noties.markwon.AbstractMarkwonPlugin
|
||||||
import io.noties.markwon.Markwon
|
import io.noties.markwon.Markwon
|
||||||
import io.noties.markwon.MarkwonConfiguration
|
import io.noties.markwon.MarkwonConfiguration
|
||||||
import io.noties.markwon.MarkwonSpansFactory
|
|
||||||
import io.noties.markwon.core.MarkwonTheme
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
@ -94,7 +92,7 @@ class UpdateUtil(var context: Context) {
|
||||||
.setTitle(v.tag_name)
|
.setTitle(v.tag_name)
|
||||||
.setMessage(v.body)
|
.setMessage(v.body)
|
||||||
.setIcon(R.drawable.ic_update_app)
|
.setIcon(R.drawable.ic_update_app)
|
||||||
.setNeutralButton(R.string.skip){ d: DialogInterface?, _:Int ->
|
.setNeutralButton(R.string.ignore){ d: DialogInterface?, _:Int ->
|
||||||
skippedVersions.add(v.tag_name)
|
skippedVersions.add(v.tag_name)
|
||||||
sharedPreferences.edit().putString("skip_updates", skippedVersions.joinToString(",")).apply()
|
sharedPreferences.edit().putString("skip_updates", skippedVersions.joinToString(",")).apply()
|
||||||
d?.dismiss()
|
d?.dismiss()
|
||||||
|
|
|
||||||
|
|
@ -259,7 +259,10 @@ class DownloadWorker(
|
||||||
}else{
|
}else{
|
||||||
logString.append("${it.message}\n")
|
logString.append("${it.message}\n")
|
||||||
logItem.content = logString.toString()
|
logItem.content = logString.toString()
|
||||||
logRepo.insert(logItem)
|
val logID = withContext(Dispatchers.IO){
|
||||||
|
logRepo.insert(logItem)
|
||||||
|
}
|
||||||
|
downloadItem.logID = logID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -277,8 +280,8 @@ class DownloadWorker(
|
||||||
}
|
}
|
||||||
|
|
||||||
notificationUtil.createDownloadErrored(
|
notificationUtil.createDownloadErrored(
|
||||||
downloadItem.title, it.message,
|
downloadItem.title.ifEmpty { downloadItem.url }, it.message,
|
||||||
if (logDownloads) logItem.id else null,
|
downloadItem.logID,
|
||||||
NotificationUtil.DOWNLOAD_FINISHED_CHANNEL_ID
|
NotificationUtil.DOWNLOAD_FINISHED_CHANNEL_ID
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,15 @@ class TerminalDownloadWorker(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
request.addOption("-P", FileUtil.getDefaultCommandPath() + "/" + itemId)
|
val commandPath = sharedPreferences.getString("command_path", FileUtil.getDefaultCommandPath())!!
|
||||||
|
val noCache = !sharedPreferences.getBoolean("cache_downloads", true) && File(FileUtil.formatPath(commandPath)).canWrite()
|
||||||
|
|
||||||
|
if (!noCache){
|
||||||
|
request.addOption("-P", FileUtil.getCachePath(context) + "/TERMINAL/" + itemId)
|
||||||
|
}else if (!request.hasOption("-P")){
|
||||||
|
request.addOption("-P", FileUtil.formatPath(commandPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
val logDownloads = sharedPreferences.getBoolean("log_downloads", false) && !sharedPreferences.getBoolean("incognito", false)
|
val logDownloads = sharedPreferences.getBoolean("log_downloads", false) && !sharedPreferences.getBoolean("incognito", false)
|
||||||
|
|
||||||
|
|
@ -120,16 +128,18 @@ class TerminalDownloadWorker(
|
||||||
}
|
}
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
//move file from internal to set download directory
|
if(!noCache){
|
||||||
try {
|
//move file from internal to set download directory
|
||||||
FileUtil.moveFile(File(FileUtil.getDefaultCommandPath() + "/" + itemId),context, downloadLocation!!, false){ p ->
|
try {
|
||||||
setProgressAsync(workDataOf("progress" to p))
|
FileUtil.moveFile(File(FileUtil.getCachePath(context) + "/TERMINAL/" + itemId),context, downloadLocation!!, false){ p ->
|
||||||
|
setProgressAsync(workDataOf("progress" to p))
|
||||||
|
}
|
||||||
|
}catch (e: Exception){
|
||||||
|
e.printStackTrace()
|
||||||
|
handler.postDelayed({
|
||||||
|
Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show()
|
||||||
|
}, 1000)
|
||||||
}
|
}
|
||||||
}catch (e: Exception){
|
|
||||||
e.printStackTrace()
|
|
||||||
handler.postDelayed({
|
|
||||||
Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show()
|
|
||||||
}, 1000)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,21 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:context=".receiver.ShareActivity"
|
tools:context=".receiver.ShareActivity"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/frame_layout"
|
||||||
|
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:defaultNavHost="true"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -27,6 +27,12 @@
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_homeFragment_to_resultCardDetailsDialog"
|
android:id="@+id/action_homeFragment_to_resultCardDetailsDialog"
|
||||||
app:destination="@id/resultCardDetailsDialog" />
|
app:destination="@id/resultCardDetailsDialog" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_homeFragment_to_downloadBottomSheetDialog"
|
||||||
|
app:destination="@id/downloadBottomSheetDialog" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_homeFragment_to_downloadMultipleBottomSheetDialog2"
|
||||||
|
app:destination="@id/downloadMultipleBottomSheetDialog2" />
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/historyFragment"
|
android:id="@+id/historyFragment"
|
||||||
|
|
@ -96,7 +102,7 @@
|
||||||
android:id="@+id/downloadLogFragment"
|
android:id="@+id/downloadLogFragment"
|
||||||
android:name="com.deniscerri.ytdlnis.ui.more.downloadLogs.DownloadLogFragment"
|
android:name="com.deniscerri.ytdlnis.ui.more.downloadLogs.DownloadLogFragment"
|
||||||
android:label="DownloadLogFragment" />
|
android:label="DownloadLogFragment" />
|
||||||
<fragment
|
<dialog
|
||||||
android:id="@+id/resultCardDetailsDialog"
|
android:id="@+id/resultCardDetailsDialog"
|
||||||
android:name="com.deniscerri.ytdlnis.ui.downloadcard.ResultCardDetailsDialog"
|
android:name="com.deniscerri.ytdlnis.ui.downloadcard.ResultCardDetailsDialog"
|
||||||
android:label="ResultCardDetailsDialog" />
|
android:label="ResultCardDetailsDialog" />
|
||||||
|
|
@ -142,4 +148,12 @@
|
||||||
android:name="com.deniscerri.ytdlnis.ui.more.settings.GeneralSettingsFragment"
|
android:name="com.deniscerri.ytdlnis.ui.more.settings.GeneralSettingsFragment"
|
||||||
android:label="AppearanceSettingsFragment" />
|
android:label="AppearanceSettingsFragment" />
|
||||||
</navigation>
|
</navigation>
|
||||||
|
<dialog
|
||||||
|
android:id="@+id/downloadBottomSheetDialog"
|
||||||
|
android:name="com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog"
|
||||||
|
android:label="DownloadBottomSheetDialog" />
|
||||||
|
<dialog
|
||||||
|
android:id="@+id/downloadMultipleBottomSheetDialog2"
|
||||||
|
android:name="com.deniscerri.ytdlnis.ui.downloadcard.DownloadMultipleBottomSheetDialog"
|
||||||
|
android:label="DownloadMultipleBottomSheetDialog" />
|
||||||
</navigation>
|
</navigation>
|
||||||
|
|
@ -8,14 +8,27 @@
|
||||||
android:label="DownloadBottomSheetDialog" >
|
android:label="DownloadBottomSheetDialog" >
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_downloadBottomSheetDialog_to_selectPlaylistItemsDialog"
|
android:id="@+id/action_downloadBottomSheetDialog_to_selectPlaylistItemsDialog"
|
||||||
app:destination="@id/selectPlaylistItemsDialog" />
|
app:destination="@id/selectPlaylistItemsDialog"
|
||||||
|
app:launchSingleTop="true"
|
||||||
|
app:popUpTo="@id/downloadBottomSheetDialog"
|
||||||
|
app:popUpToInclusive="true" />
|
||||||
</dialog>
|
</dialog>
|
||||||
<dialog
|
<dialog
|
||||||
|
android:id="@+id/selectPlaylistItemsDialog"
|
||||||
android:name="com.deniscerri.ytdlnis.ui.downloadcard.SelectPlaylistItemsDialog"
|
android:name="com.deniscerri.ytdlnis.ui.downloadcard.SelectPlaylistItemsDialog"
|
||||||
android:label="SelectPlaylistItemsDialog">
|
android:label="SelectPlaylistItemsDialog">
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_selectPlaylistItemsDialog_to_downloadMultipleBottomSheetDialog"
|
android:id="@+id/action_selectPlaylistItemsDialog_to_downloadMultipleBottomSheetDialog"
|
||||||
app:destination="@id/downloadMultipleBottomSheetDialog" />
|
app:destination="@id/downloadMultipleBottomSheetDialog"
|
||||||
|
app:launchSingleTop="true"
|
||||||
|
app:popUpTo="@id/selectPlaylistItemsDialog"
|
||||||
|
app:popUpToInclusive="true" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_selectPlaylistItemsDialog_to_downloadBottomSheetDialog"
|
||||||
|
app:destination="@id/downloadBottomSheetDialog"
|
||||||
|
app:launchSingleTop="true"
|
||||||
|
app:popUpTo="@id/selectPlaylistItemsDialog"
|
||||||
|
app:popUpToInclusive="true" />
|
||||||
</dialog>
|
</dialog>
|
||||||
<dialog
|
<dialog
|
||||||
android:id="@+id/downloadMultipleBottomSheetDialog"
|
android:id="@+id/downloadMultipleBottomSheetDialog"
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,7 @@
|
||||||
<string name="remember_download_type_summary">تعيين نوع التحميل اللاحق بناءً على آخر نوع تحميل تم الوصول اليه</string>
|
<string name="remember_download_type_summary">تعيين نوع التحميل اللاحق بناءً على آخر نوع تحميل تم الوصول اليه</string>
|
||||||
<string name="schedule">توقيت</string>
|
<string name="schedule">توقيت</string>
|
||||||
<string name="search_command_hint">بحث في قوالب الأوامر</string>
|
<string name="search_command_hint">بحث في قوالب الأوامر</string>
|
||||||
<string name="skip">تخطي</string>
|
<string name="ignore">تخطي</string>
|
||||||
<string name="license">الترخيص</string>
|
<string name="license">الترخيص</string>
|
||||||
<string name="download_already_exists_summary">المضي بالتحميل على أي حال؟</string>
|
<string name="download_already_exists_summary">المضي بالتحميل على أي حال؟</string>
|
||||||
<string name="modify_download_card">تحرير بطاقة التحميل</string>
|
<string name="modify_download_card">تحرير بطاقة التحميل</string>
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,7 @@
|
||||||
<string name="remember_download_type_summary">Selecciona el último tipo de la descarga abierto para el elemento actual</string>
|
<string name="remember_download_type_summary">Selecciona el último tipo de la descarga abierto para el elemento actual</string>
|
||||||
<string name="schedule">Horario</string>
|
<string name="schedule">Horario</string>
|
||||||
<string name="search_command_hint">Búsqueda a partir de comandos</string>
|
<string name="search_command_hint">Búsqueda a partir de comandos</string>
|
||||||
<string name="skip">Omitir</string>
|
<string name="ignore">Omitir</string>
|
||||||
<string name="license">Licencia</string>
|
<string name="license">Licencia</string>
|
||||||
<string name="download_already_exists_summary">¿Todavía quieres descargar\?</string>
|
<string name="download_already_exists_summary">¿Todavía quieres descargar\?</string>
|
||||||
<string name="modify_download_card">Modificar la tarjeta de descarga</string>
|
<string name="modify_download_card">Modificar la tarjeta de descarga</string>
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,7 @@
|
||||||
<string name="remember_download_type_summary">वर्तमान आइटम के लिए अंतिम बार खोला गया डाउनलोड टाईप चुनें</string>
|
<string name="remember_download_type_summary">वर्तमान आइटम के लिए अंतिम बार खोला गया डाउनलोड टाईप चुनें</string>
|
||||||
<string name="schedule">शडिऊल</string>
|
<string name="schedule">शडिऊल</string>
|
||||||
<string name="search_command_hint">कमांड में से खोजें</string>
|
<string name="search_command_hint">कमांड में से खोजें</string>
|
||||||
<string name="skip">छोड़ें</string>
|
<string name="ignore">छोड़ें</string>
|
||||||
<string name="license">लाइसेंस</string>
|
<string name="license">लाइसेंस</string>
|
||||||
<string name="download_already_exists_summary">क्या आप अब भी डाउनलोड करना चाहते हैं\?</string>
|
<string name="download_already_exists_summary">क्या आप अब भी डाउनलोड करना चाहते हैं\?</string>
|
||||||
<string name="modify_download_card">डाउनलोड कार्ड संशोधित करें</string>
|
<string name="modify_download_card">डाउनलोड कार्ड संशोधित करें</string>
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,7 @@
|
||||||
<string name="couldnt_parse_file">לא ניתן לנתח את הקובץ</string>
|
<string name="couldnt_parse_file">לא ניתן לנתח את הקובץ</string>
|
||||||
<string name="schedule">תזמון</string>
|
<string name="schedule">תזמון</string>
|
||||||
<string name="search_command_hint">חפש מתוך פקודות</string>
|
<string name="search_command_hint">חפש מתוך פקודות</string>
|
||||||
<string name="skip">דילוג</string>
|
<string name="ignore">דילוג</string>
|
||||||
<string name="license">רישיון</string>
|
<string name="license">רישיון</string>
|
||||||
<string name="download_already_exists_summary">האם תרצה להמשיך להוריד\?</string>
|
<string name="download_already_exists_summary">האם תרצה להמשיך להוריד\?</string>
|
||||||
<string name="modify_download_card">התאמת כרטיס הורדה</string>
|
<string name="modify_download_card">התאמת כרטיס הורדה</string>
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,7 @@
|
||||||
<string name="remember_download_type_summary">ਮੌਜੂਦਾ ਆਈਟਮ ਲਈ ਆਖਰੀ ਵਾਰ ਖੋਲ੍ਹੀ ਗਈ ਡਾਊਨਲੋਡ ਕਿਸਮ ਚੁਣੋ</string>
|
<string name="remember_download_type_summary">ਮੌਜੂਦਾ ਆਈਟਮ ਲਈ ਆਖਰੀ ਵਾਰ ਖੋਲ੍ਹੀ ਗਈ ਡਾਊਨਲੋਡ ਕਿਸਮ ਚੁਣੋ</string>
|
||||||
<string name="schedule">ਸ਼ਡਿਊਲ</string>
|
<string name="schedule">ਸ਼ਡਿਊਲ</string>
|
||||||
<string name="search_command_hint">ਕਮਾਂਡਾਂ ਤੋਂ ਖੋਜ ਕਰੋ</string>
|
<string name="search_command_hint">ਕਮਾਂਡਾਂ ਤੋਂ ਖੋਜ ਕਰੋ</string>
|
||||||
<string name="skip">ਸਕਿੱਪ ਕਰੋ</string>
|
<string name="ignore">ਸਕਿੱਪ ਕਰੋ</string>
|
||||||
<string name="license">ਲਾਈਸੈਂਸ</string>
|
<string name="license">ਲਾਈਸੈਂਸ</string>
|
||||||
<string name="download_already_exists_summary">ਕੀ ਤੁਸੀਂ ਅਜੇ ਵੀ ਡਾਊਨਲੋਡ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ\?</string>
|
<string name="download_already_exists_summary">ਕੀ ਤੁਸੀਂ ਅਜੇ ਵੀ ਡਾਊਨਲੋਡ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ\?</string>
|
||||||
<string name="modify_download_card">ਡਾਊਨਲੋਡ ਕਾਰਡ ਨੂੰ ਸੋਧੋ</string>
|
<string name="modify_download_card">ਡਾਊਨਲੋਡ ਕਾਰਡ ਨੂੰ ਸੋਧੋ</string>
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,7 @@
|
||||||
<string name="remember_download_type_summary">Selecione o último tipo de download aberto para o item atual</string>
|
<string name="remember_download_type_summary">Selecione o último tipo de download aberto para o item atual</string>
|
||||||
<string name="schedule">Agendar</string>
|
<string name="schedule">Agendar</string>
|
||||||
<string name="search_command_hint">Pesquisar a partir dos comandos</string>
|
<string name="search_command_hint">Pesquisar a partir dos comandos</string>
|
||||||
<string name="skip">Pular</string>
|
<string name="ignore">Pular</string>
|
||||||
<string name="license">Licença</string>
|
<string name="license">Licença</string>
|
||||||
<string name="download_already_exists_summary">Você ainda quer fazer o download\?</string>
|
<string name="download_already_exists_summary">Você ainda quer fazer o download\?</string>
|
||||||
<string name="modify_download_card">Modificar cartão de download</string>
|
<string name="modify_download_card">Modificar cartão de download</string>
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,7 @@
|
||||||
<string name="remember_download_type_summary">Selecionar o último tipo de download aberto para o item atual</string>
|
<string name="remember_download_type_summary">Selecionar o último tipo de download aberto para o item atual</string>
|
||||||
<string name="schedule">Agendar</string>
|
<string name="schedule">Agendar</string>
|
||||||
<string name="search_command_hint">Pesquisar a partir de comandos</string>
|
<string name="search_command_hint">Pesquisar a partir de comandos</string>
|
||||||
<string name="skip">Saltar</string>
|
<string name="ignore">Saltar</string>
|
||||||
<string name="license">Licença</string>
|
<string name="license">Licença</string>
|
||||||
<string name="download_already_exists_summary">Ainda queres descarregar\?</string>
|
<string name="download_already_exists_summary">Ainda queres descarregar\?</string>
|
||||||
<string name="modify_download_card">Modificar o cartão de descarregamento</string>
|
<string name="modify_download_card">Modificar o cartão de descarregamento</string>
|
||||||
|
|
|
||||||
|
|
@ -307,7 +307,7 @@
|
||||||
<string name="schedule">Расписание</string>
|
<string name="schedule">Расписание</string>
|
||||||
<string name="user_agent_header">Заголовок User-Agent</string>
|
<string name="user_agent_header">Заголовок User-Agent</string>
|
||||||
<string name="search_command_hint">Поиск по командам</string>
|
<string name="search_command_hint">Поиск по командам</string>
|
||||||
<string name="skip">Пропустить</string>
|
<string name="ignore">Пропустить</string>
|
||||||
<string name="license">Лицензия</string>
|
<string name="license">Лицензия</string>
|
||||||
<string name="download_already_exists_summary">Вы все еще хотите скачать\?</string>
|
<string name="download_already_exists_summary">Вы все еще хотите скачать\?</string>
|
||||||
<string name="modify_download_card">Изменить карту загрузки</string>
|
<string name="modify_download_card">Изменить карту загрузки</string>
|
||||||
|
|
|
||||||
|
|
@ -310,7 +310,7 @@
|
||||||
<string name="remember_download_type_summary">Zgjidh llojin e fundit të shkarkimit për shkarkimin aktual</string>
|
<string name="remember_download_type_summary">Zgjidh llojin e fundit të shkarkimit për shkarkimin aktual</string>
|
||||||
<string name="length">Gjatësia</string>
|
<string name="length">Gjatësia</string>
|
||||||
<string name="schedule">Orar</string>
|
<string name="schedule">Orar</string>
|
||||||
<string name="skip">Injoro</string>
|
<string name="ignore">Injoro</string>
|
||||||
<string name="license">Liçensa</string>
|
<string name="license">Liçensa</string>
|
||||||
<string name="download_already_exists_summary">Do sërisht ta shkarkosh\?</string>
|
<string name="download_already_exists_summary">Do sërisht ta shkarkosh\?</string>
|
||||||
<string name="modify_download_card">Modifiko Kartën e Shkarkimit</string>
|
<string name="modify_download_card">Modifiko Kartën e Shkarkimit</string>
|
||||||
|
|
|
||||||
|
|
@ -307,7 +307,7 @@
|
||||||
<string name="schedule">Розклад</string>
|
<string name="schedule">Розклад</string>
|
||||||
<string name="user_agent_header">Заголовок User-Agent</string>
|
<string name="user_agent_header">Заголовок User-Agent</string>
|
||||||
<string name="search_command_hint">Пошук з команд</string>
|
<string name="search_command_hint">Пошук з команд</string>
|
||||||
<string name="skip">Пропустити</string>
|
<string name="ignore">Пропустити</string>
|
||||||
<string name="license">Ліцензія</string>
|
<string name="license">Ліцензія</string>
|
||||||
<string name="download_already_exists_summary">Ви все ще хочете завантажити\?</string>
|
<string name="download_already_exists_summary">Ви все ще хочете завантажити\?</string>
|
||||||
<string name="modify_download_card">Змінити картку завантаження</string>
|
<string name="modify_download_card">Змінити картку завантаження</string>
|
||||||
|
|
|
||||||
|
|
@ -307,7 +307,7 @@
|
||||||
<string name="schedule">Lịch trình</string>
|
<string name="schedule">Lịch trình</string>
|
||||||
<string name="user_agent_header">Tiêu đề tác nhân người dùng</string>
|
<string name="user_agent_header">Tiêu đề tác nhân người dùng</string>
|
||||||
<string name="search_command_hint">Tìm kiếm từ lệnh</string>
|
<string name="search_command_hint">Tìm kiếm từ lệnh</string>
|
||||||
<string name="skip">Bỏ qua</string>
|
<string name="ignore">Bỏ qua</string>
|
||||||
<string name="license">Giấy phép</string>
|
<string name="license">Giấy phép</string>
|
||||||
<string name="download_already_exists_summary">Bạn vẫn muốn tải xuống\?</string>
|
<string name="download_already_exists_summary">Bạn vẫn muốn tải xuống\?</string>
|
||||||
<string name="modify_download_card">Sửa đổi thẻ tải xuống</string>
|
<string name="modify_download_card">Sửa đổi thẻ tải xuống</string>
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,7 @@
|
||||||
<string name="remember_download_type_summary">为当前项目选择上次打开的下载类型</string>
|
<string name="remember_download_type_summary">为当前项目选择上次打开的下载类型</string>
|
||||||
<string name="schedule">安排时间</string>
|
<string name="schedule">安排时间</string>
|
||||||
<string name="search_command_hint">搜索命令行模板</string>
|
<string name="search_command_hint">搜索命令行模板</string>
|
||||||
<string name="skip">跳过</string>
|
<string name="ignore">跳过</string>
|
||||||
<string name="license">许可证</string>
|
<string name="license">许可证</string>
|
||||||
<string name="download_already_exists_summary">你仍要下载吗?</string>
|
<string name="download_already_exists_summary">你仍要下载吗?</string>
|
||||||
<string name="modify_download_card">修改下载卡片</string>
|
<string name="modify_download_card">修改下载卡片</string>
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,7 @@
|
||||||
<string name="remember_download_type_summary">使用上次的下載類型</string>
|
<string name="remember_download_type_summary">使用上次的下載類型</string>
|
||||||
<string name="schedule">排程設定</string>
|
<string name="schedule">排程設定</string>
|
||||||
<string name="search_command_hint">指令搜尋</string>
|
<string name="search_command_hint">指令搜尋</string>
|
||||||
<string name="skip">略過此項</string>
|
<string name="ignore">略過此項</string>
|
||||||
<string name="license">使用授權</string>
|
<string name="license">使用授權</string>
|
||||||
<string name="download_already_exists_summary">是否繼續進行下載?</string>
|
<string name="download_already_exists_summary">是否繼續進行下載?</string>
|
||||||
<string name="modify_download_card">編輯下載資訊卡片</string>
|
<string name="modify_download_card">編輯下載資訊卡片</string>
|
||||||
|
|
|
||||||
|
|
@ -293,7 +293,7 @@
|
||||||
<string name="extra_command">Extra Command</string>
|
<string name="extra_command">Extra Command</string>
|
||||||
<string name="use_cookies">Use Cookies</string>
|
<string name="use_cookies">Use Cookies</string>
|
||||||
<string name="embed_metadata">Embed Metadata</string>
|
<string name="embed_metadata">Embed Metadata</string>
|
||||||
<string name="embed_metadata_summary">Embed and parse metadata to the audio file</string>
|
<string name="embed_metadata_summary">Parse and embed metadata to the audio file</string>
|
||||||
<string name="update_formats_background">Update Formats in Background</string>
|
<string name="update_formats_background">Update Formats in Background</string>
|
||||||
<string name="auto_update_ytdlp">Auto-Update yt-dlp</string>
|
<string name="auto_update_ytdlp">Auto-Update yt-dlp</string>
|
||||||
<string name="use_sponsorblock">Use SponsorBlock</string>
|
<string name="use_sponsorblock">Use SponsorBlock</string>
|
||||||
|
|
@ -316,7 +316,7 @@
|
||||||
<string name="license">License</string>
|
<string name="license">License</string>
|
||||||
<string name="download_already_exists_summary">Do you still want to download?</string>
|
<string name="download_already_exists_summary">Do you still want to download?</string>
|
||||||
<string name="schedule">Schedule</string>
|
<string name="schedule">Schedule</string>
|
||||||
<string name="skip">Skip</string>
|
<string name="ignore">Ignore</string>
|
||||||
<string name="modify_download_card">Modify Download Card</string>
|
<string name="modify_download_card">Modify Download Card</string>
|
||||||
<string name="export_file">Export File</string>
|
<string name="export_file">Export File</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -39,6 +39,7 @@ plugins {
|
||||||
id 'com.android.library' version '8.1.1' apply false
|
id 'com.android.library' version '8.1.1' apply false
|
||||||
id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
|
id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
|
||||||
id "org.jetbrains.kotlin.plugin.serialization" version "1.8.10" apply false
|
id "org.jetbrains.kotlin.plugin.serialization" version "1.8.10" apply false
|
||||||
|
id "org.jetbrains.kotlin.plugin.parcelize" version "1.8.10" apply false
|
||||||
id 'com.android.test' version '8.1.1' apply false
|
id 'com.android.test' version '8.1.1' apply false
|
||||||
id 'com.google.devtools.ksp' version '1.8.10-1.0.9' apply false
|
id 'com.google.devtools.ksp' version '1.8.10-1.0.9' apply false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue