more more fixes lol
fixed Snackbar overlapping with buttons on settings fixed locale not translating right in download card fixed format updating the container when re-selecting it made the video tab disabled when the item only has audio formats made the app fetch streaming url and chapters from the start so it loads faster when trying to cut a video added url in format item
This commit is contained in:
parent
bfdc7df88a
commit
0f6d1fa765
46 changed files with 1056 additions and 459 deletions
448
app/schemas/com.deniscerri.ytdlnis.database.DBManager/6.json
Normal file
448
app/schemas/com.deniscerri.ytdlnis.database.DBManager/6.json
Normal file
|
|
@ -0,0 +1,448 @@
|
||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 6,
|
||||||
|
"identityHash": "d34711f8239a4a966885543cd5454eab",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "results",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `website` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `formats` TEXT NOT NULL, `urls` TEXT NOT NULL DEFAULT '', `chapters` TEXT, `creationTime` INTEGER NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "title",
|
||||||
|
"columnName": "title",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "author",
|
||||||
|
"columnName": "author",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "duration",
|
||||||
|
"columnName": "duration",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumb",
|
||||||
|
"columnName": "thumb",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "website",
|
||||||
|
"columnName": "website",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistTitle",
|
||||||
|
"columnName": "playlistTitle",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "formats",
|
||||||
|
"columnName": "formats",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "urls",
|
||||||
|
"columnName": "urls",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "''"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "chapters",
|
||||||
|
"columnName": "chapters",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "creationTime",
|
||||||
|
"columnName": "creationTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "history",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `type` TEXT NOT NULL, `time` INTEGER NOT NULL, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `format` TEXT NOT NULL, `downloadId` INTEGER NOT NULL DEFAULT 0)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "title",
|
||||||
|
"columnName": "title",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "author",
|
||||||
|
"columnName": "author",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "duration",
|
||||||
|
"columnName": "duration",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumb",
|
||||||
|
"columnName": "thumb",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "time",
|
||||||
|
"columnName": "time",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadPath",
|
||||||
|
"columnName": "downloadPath",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "website",
|
||||||
|
"columnName": "website",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "format",
|
||||||
|
"columnName": "format",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadId",
|
||||||
|
"columnName": "downloadId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "downloads",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `thumb` TEXT NOT NULL, `duration` TEXT NOT NULL, `type` TEXT NOT NULL, `format` TEXT NOT NULL, `container` TEXT NOT NULL DEFAULT 'Default', `downloadSections` TEXT NOT NULL DEFAULT '', `allFormats` TEXT NOT NULL, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `downloadSize` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `audioPreferences` TEXT NOT NULL, `videoPreferences` TEXT NOT NULL, `customFileNameTemplate` TEXT NOT NULL, `SaveThumb` INTEGER NOT NULL, `status` TEXT NOT NULL DEFAULT 'Queued', `downloadStartTime` INTEGER NOT NULL DEFAULT 0)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "title",
|
||||||
|
"columnName": "title",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "author",
|
||||||
|
"columnName": "author",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumb",
|
||||||
|
"columnName": "thumb",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "duration",
|
||||||
|
"columnName": "duration",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "format",
|
||||||
|
"columnName": "format",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "container",
|
||||||
|
"columnName": "container",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "'Default'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadSections",
|
||||||
|
"columnName": "downloadSections",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "''"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "allFormats",
|
||||||
|
"columnName": "allFormats",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadPath",
|
||||||
|
"columnName": "downloadPath",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "website",
|
||||||
|
"columnName": "website",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadSize",
|
||||||
|
"columnName": "downloadSize",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistTitle",
|
||||||
|
"columnName": "playlistTitle",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "audioPreferences",
|
||||||
|
"columnName": "audioPreferences",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "videoPreferences",
|
||||||
|
"columnName": "videoPreferences",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "customFileNameTemplate",
|
||||||
|
"columnName": "customFileNameTemplate",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "SaveThumb",
|
||||||
|
"columnName": "SaveThumb",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "status",
|
||||||
|
"columnName": "status",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "'Queued'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadStartTime",
|
||||||
|
"columnName": "downloadStartTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "commandTemplates",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "title",
|
||||||
|
"columnName": "title",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "content",
|
||||||
|
"columnName": "content",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "searchHistory",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `query` TEXT NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "query",
|
||||||
|
"columnName": "query",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "templateShortcuts",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `content` TEXT NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "content",
|
||||||
|
"columnName": "content",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "cookies",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `content` TEXT NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "content",
|
||||||
|
"columnName": "content",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"views": [],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd34711f8239a4a966885543cd5454eab')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -38,6 +38,7 @@ import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||||
import com.deniscerri.ytdlnis.ui.BaseActivity
|
import com.deniscerri.ytdlnis.ui.BaseActivity
|
||||||
import com.deniscerri.ytdlnis.ui.HomeFragment
|
import com.deniscerri.ytdlnis.ui.HomeFragment
|
||||||
import com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity
|
import com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity
|
||||||
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
import com.deniscerri.ytdlnis.util.ThemeUtil
|
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
|
||||||
|
|
@ -67,7 +68,6 @@ class MainActivity : BaseActivity() {
|
||||||
private lateinit var navHostFragment : NavHostFragment
|
private lateinit var navHostFragment : NavHostFragment
|
||||||
private lateinit var navController : NavController
|
private lateinit var navController : NavController
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
ThemeUtil.updateTheme(this)
|
ThemeUtil.updateTheme(this)
|
||||||
|
|
@ -338,9 +338,9 @@ class MainActivity : BaseActivity() {
|
||||||
|
|
||||||
|
|
||||||
private fun createDefaultFolders(){
|
private fun createDefaultFolders(){
|
||||||
val audio = File(getString(R.string.music_path))
|
val audio = File(FileUtil.getDefautAudioPath())
|
||||||
val video = File(getString(R.string.video_path))
|
val video = File(FileUtil.getDefautVideoPath())
|
||||||
val command = File(getString(R.string.command_path))
|
val command = File(FileUtil.getDefaultCommandPath())
|
||||||
|
|
||||||
audio.mkdirs()
|
audio.mkdirs()
|
||||||
video.mkdirs()
|
video.mkdirs()
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,10 @@ import com.squareup.picasso.Picasso
|
||||||
class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, ActiveDownloadAdapter.ViewHolder>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) {
|
class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, ActiveDownloadAdapter.ViewHolder>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) {
|
||||||
private val onItemClickListener: OnItemClickListener
|
private val onItemClickListener: OnItemClickListener
|
||||||
private val activity: Activity
|
private val activity: Activity
|
||||||
private val fileUtil: FileUtil
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.onItemClickListener = onItemClickListener
|
this.onItemClickListener = onItemClickListener
|
||||||
this.activity = activity
|
this.activity = activity
|
||||||
fileUtil = FileUtil()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
|
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
|
@ -113,7 +111,7 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
|
||||||
}
|
}
|
||||||
|
|
||||||
val fileSize = card.findViewById<Chip>(R.id.file_size)
|
val fileSize = card.findViewById<Chip>(R.id.file_size)
|
||||||
fileSize.text = fileUtil.convertFileSize(item.format.filesize)
|
fileSize.text = FileUtil.convertFileSize(item.format.filesize)
|
||||||
if (fileSize.text == "?") fileSize.visibility = View.GONE
|
if (fileSize.text == "?") fileSize.visibility = View.GONE
|
||||||
|
|
||||||
if (fileSize.visibility == View.VISIBLE && codec.visibility == View.GONE){
|
if (fileSize.visibility == View.VISIBLE && codec.visibility == View.GONE){
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,10 @@ import java.util.Locale
|
||||||
class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, ConfigureMultipleDownloadsAdapter.ViewHolder>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) {
|
class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, ConfigureMultipleDownloadsAdapter.ViewHolder>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) {
|
||||||
private val onItemClickListener: OnItemClickListener
|
private val onItemClickListener: OnItemClickListener
|
||||||
private val activity: Activity
|
private val activity: Activity
|
||||||
private var fileUtil: FileUtil
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.onItemClickListener = onItemClickListener
|
this.onItemClickListener = onItemClickListener
|
||||||
this.activity = activity
|
this.activity = activity
|
||||||
fileUtil = FileUtil()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
|
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
|
@ -96,7 +94,7 @@ class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener
|
||||||
}
|
}
|
||||||
|
|
||||||
val fileSize = card.findViewById<TextView>(R.id.file_size)
|
val fileSize = card.findViewById<TextView>(R.id.file_size)
|
||||||
val fileSizeReadable = fileUtil.convertFileSize(item.format.filesize)
|
val fileSizeReadable = FileUtil.convertFileSize(item.format.filesize)
|
||||||
if (fileSizeReadable == "?") fileSize.visibility = View.GONE
|
if (fileSizeReadable == "?") fileSize.visibility = View.GONE
|
||||||
else {
|
else {
|
||||||
fileSize.text = fileSizeReadable
|
fileSize.text = fileSizeReadable
|
||||||
|
|
|
||||||
|
|
@ -24,14 +24,12 @@ import com.squareup.picasso.Picasso
|
||||||
class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, GenericDownloadAdapter.ViewHolder>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) {
|
class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, GenericDownloadAdapter.ViewHolder>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) {
|
||||||
private val onItemClickListener: OnItemClickListener
|
private val onItemClickListener: OnItemClickListener
|
||||||
private val activity: Activity
|
private val activity: Activity
|
||||||
private var fileUtil: FileUtil
|
|
||||||
private val checkedItems: ArrayList<Long>
|
private val checkedItems: ArrayList<Long>
|
||||||
|
|
||||||
init {
|
init {
|
||||||
checkedItems = ArrayList()
|
checkedItems = ArrayList()
|
||||||
this.onItemClickListener = onItemClickListener
|
this.onItemClickListener = onItemClickListener
|
||||||
this.activity = activity
|
this.activity = activity
|
||||||
fileUtil = FileUtil()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
|
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
|
@ -94,7 +92,7 @@ class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
|
||||||
}
|
}
|
||||||
|
|
||||||
val fileSize = card.findViewById<TextView>(R.id.file_size)
|
val fileSize = card.findViewById<TextView>(R.id.file_size)
|
||||||
val fileSizeReadable = fileUtil.convertFileSize(item.format.filesize)
|
val fileSizeReadable = FileUtil.convertFileSize(item.format.filesize)
|
||||||
if (fileSizeReadable == "?") fileSize.visibility = View.GONE
|
if (fileSizeReadable == "?") fileSize.visibility = View.GONE
|
||||||
else fileSize.text = fileSizeReadable
|
else fileSize.text = fileSizeReadable
|
||||||
|
|
||||||
|
|
@ -107,7 +105,7 @@ class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
|
||||||
DownloadRepository.Status.Queued.toString() -> actionButton.setIconResource(R.drawable.ic_baseline_delete_outline_24)
|
DownloadRepository.Status.Queued.toString() -> actionButton.setIconResource(R.drawable.ic_baseline_delete_outline_24)
|
||||||
else -> {
|
else -> {
|
||||||
actionButton.setIconResource(R.drawable.ic_baseline_file_open_24)
|
actionButton.setIconResource(R.drawable.ic_baseline_file_open_24)
|
||||||
val logFile = fileUtil.getLogFile(activity, item)
|
val logFile = FileUtil.getLogFile(activity, item)
|
||||||
if (!logFile.exists()){
|
if (!logFile.exists()){
|
||||||
actionButton.visibility = View.GONE
|
actionButton.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.deniscerri.ytdlnis.database
|
||||||
|
|
||||||
import androidx.room.TypeConverter
|
import androidx.room.TypeConverter
|
||||||
import com.deniscerri.ytdlnis.database.models.AudioPreferences
|
import com.deniscerri.ytdlnis.database.models.AudioPreferences
|
||||||
|
import com.deniscerri.ytdlnis.database.models.ChapterItem
|
||||||
import com.deniscerri.ytdlnis.database.models.Format
|
import com.deniscerri.ytdlnis.database.models.Format
|
||||||
import com.deniscerri.ytdlnis.database.models.VideoPreferences
|
import com.deniscerri.ytdlnis.database.models.VideoPreferences
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
|
|
@ -50,4 +51,16 @@ class Converters {
|
||||||
fun videoPreferencesToString(videoPreferences: VideoPreferences): String = Gson().toJson(videoPreferences)
|
fun videoPreferencesToString(videoPreferences: VideoPreferences): String = Gson().toJson(videoPreferences)
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun stringToVideoPreferences(string: String): VideoPreferences = Gson().fromJson(string, VideoPreferences::class.java)
|
fun stringToVideoPreferences(string: String): VideoPreferences = Gson().fromJson(string, VideoPreferences::class.java)
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun stringToListOfChapters(value: String?): ArrayList<ChapterItem>? {
|
||||||
|
val listType: Type = object : TypeToken<ArrayList<ChapterItem?>?>() {}.type
|
||||||
|
return Gson().fromJson(value, listType)
|
||||||
|
}
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
fun listOfChaptersToString(list: ArrayList<ChapterItem?>?): String {
|
||||||
|
val gson = Gson()
|
||||||
|
return gson.toJson(list)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,12 +8,13 @@ import com.deniscerri.ytdlnis.database.models.*
|
||||||
@TypeConverters(Converters::class)
|
@TypeConverters(Converters::class)
|
||||||
@Database(
|
@Database(
|
||||||
entities = [ResultItem::class, HistoryItem::class, DownloadItem::class, CommandTemplate::class, SearchHistoryItem::class, TemplateShortcut::class, CookieItem::class],
|
entities = [ResultItem::class, HistoryItem::class, DownloadItem::class, CommandTemplate::class, SearchHistoryItem::class, TemplateShortcut::class, CookieItem::class],
|
||||||
version = 5,
|
version = 6,
|
||||||
autoMigrations = [
|
autoMigrations = [
|
||||||
AutoMigration (from = 1, to = 2),
|
AutoMigration (from = 1, to = 2),
|
||||||
AutoMigration (from = 2, to = 3),
|
AutoMigration (from = 2, to = 3),
|
||||||
AutoMigration (from = 3, to = 4),
|
AutoMigration (from = 3, to = 4),
|
||||||
AutoMigration (from = 4, to = 5)
|
AutoMigration (from = 4, to = 5),
|
||||||
|
AutoMigration (from = 5, to = 6)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
abstract class DBManager : RoomDatabase(){
|
abstract class DBManager : RoomDatabase(){
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ data class DownloadItem(
|
||||||
var duration: String,
|
var duration: String,
|
||||||
var type: DownloadViewModel.Type,
|
var type: DownloadViewModel.Type,
|
||||||
var format: Format,
|
var format: Format,
|
||||||
|
@ColumnInfo(defaultValue = "Default")
|
||||||
|
var container: String,
|
||||||
@ColumnInfo(defaultValue = "")
|
@ColumnInfo(defaultValue = "")
|
||||||
var downloadSections: String,
|
var downloadSections: String,
|
||||||
val allFormats: ArrayList<Format>,
|
val allFormats: ArrayList<Format>,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ data class Format(
|
||||||
var acodec: String = "",
|
var acodec: String = "",
|
||||||
@SerializedName(value = "encoding")
|
@SerializedName(value = "encoding")
|
||||||
var encoding: String = "",
|
var encoding: String = "",
|
||||||
@SerializedName(value = "filesize", alternate = ["clen", "filesize_approx"])
|
@SerializedName(value = "filesize", alternate = ["clen", "filesize_approx", "contentLength"])
|
||||||
var filesize: Long = 0,
|
var filesize: Long = 0,
|
||||||
@SerializedName(value = "format_note", alternate = ["resolution", "audioQuality", "quality"])
|
@SerializedName(value = "format_note", alternate = ["resolution", "audioQuality", "quality"])
|
||||||
var format_note: String = "",
|
var format_note: String = "",
|
||||||
|
|
@ -21,5 +21,6 @@ data class Format(
|
||||||
var fps: String? = "",
|
var fps: String? = "",
|
||||||
@SerializedName(value = "asr", alternate = ["audioSampleRate"])
|
@SerializedName(value = "asr", alternate = ["audioSampleRate"])
|
||||||
var asr: String? = "",
|
var asr: String? = "",
|
||||||
|
@SerializedName(value = "url")
|
||||||
|
var url: String? = ""
|
||||||
)
|
)
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.deniscerri.ytdlnis.database.models
|
package com.deniscerri.ytdlnis.database.models
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
|
@ -15,5 +16,8 @@ data class ResultItem(
|
||||||
val website: String,
|
val website: String,
|
||||||
var playlistTitle: String,
|
var playlistTitle: String,
|
||||||
var formats: ArrayList<Format>,
|
var formats: ArrayList<Format>,
|
||||||
|
@ColumnInfo(defaultValue = "")
|
||||||
|
var urls: String,
|
||||||
|
var chapters: ArrayList<ChapterItem>?,
|
||||||
var creationTime: Long = System.currentTimeMillis() / 1000,
|
var creationTime: Long = System.currentTimeMillis() / 1000,
|
||||||
)
|
)
|
||||||
|
|
@ -10,7 +10,7 @@ class CommandTemplateRepository(private val commandDao: CommandTemplateDao) {
|
||||||
val shortcuts : LiveData<List<TemplateShortcut>> = commandDao.getAllShortcutsLiveData()
|
val shortcuts : LiveData<List<TemplateShortcut>> = commandDao.getAllShortcutsLiveData()
|
||||||
|
|
||||||
fun getAll() : List<CommandTemplate> {
|
fun getAll() : List<CommandTemplate> {
|
||||||
return commandDao.getAllTemplates();
|
return commandDao.getAllTemplates()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTotalNumber() : Int {
|
fun getTotalNumber() : Int {
|
||||||
|
|
@ -34,7 +34,7 @@ class CommandTemplateRepository(private val commandDao: CommandTemplateDao) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllShortCuts() : List<TemplateShortcut> {
|
fun getAllShortCuts() : List<TemplateShortcut> {
|
||||||
return commandDao.getAllShortcuts();
|
return commandDao.getAllShortcuts()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun insertShortcut(item: TemplateShortcut){
|
suspend fun insertShortcut(item: TemplateShortcut){
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,8 @@ class HistoryRepository(private val historyDao: HistoryDao) {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun clearDeletedHistory(){
|
suspend fun clearDeletedHistory(){
|
||||||
val fileUtil = FileUtil()
|
|
||||||
items.value?.forEach { item ->
|
items.value?.forEach { item ->
|
||||||
if (!fileUtil.exists(item.downloadPath)){
|
if (!FileUtil.exists(item.downloadPath)){
|
||||||
historyDao.delete(item.id)
|
historyDao.delete(item.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ import com.deniscerri.ytdlnis.database.models.HistoryItem
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
import com.deniscerri.ytdlnis.database.models.VideoPreferences
|
import com.deniscerri.ytdlnis.database.models.VideoPreferences
|
||||||
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
||||||
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
import com.deniscerri.ytdlnis.util.InfoUtil
|
import com.deniscerri.ytdlnis.util.InfoUtil
|
||||||
import com.deniscerri.ytdlnis.work.DownloadWorker
|
import com.deniscerri.ytdlnis.work.DownloadWorker
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
|
|
@ -46,7 +47,7 @@ import java.util.Locale
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
|
||||||
class DownloadViewModel(private val application: Application) : AndroidViewModel(application) {
|
class DownloadViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
private val repository : DownloadRepository
|
private val repository : DownloadRepository
|
||||||
private val sharedPreferences: SharedPreferences
|
private val sharedPreferences: SharedPreferences
|
||||||
private val commandTemplateDao: CommandTemplateDao
|
private val commandTemplateDao: CommandTemplateDao
|
||||||
|
|
@ -152,9 +153,9 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
val downloadPath = when(type){
|
val downloadPath = when(type){
|
||||||
Type.audio -> sharedPreferences.getString("music_path", File(Environment.DIRECTORY_DOWNLOADS, "YTDLnis/Audio").absolutePath)
|
Type.audio -> sharedPreferences.getString("music_path", FileUtil.getDefautAudioPath())
|
||||||
Type.video -> sharedPreferences.getString("video_path", File(Environment.DIRECTORY_DOWNLOADS, "YTDLnis/Video").absolutePath)
|
Type.video -> sharedPreferences.getString("video_path", FileUtil.getDefautVideoPath())
|
||||||
else -> sharedPreferences.getString("command_path", File(Environment.DIRECTORY_DOWNLOADS, "YTDLnis/Command").absolutePath)
|
else -> sharedPreferences.getString("command_path", FileUtil.getDefaultCommandPath())
|
||||||
}
|
}
|
||||||
|
|
||||||
val sponsorblock = sharedPreferences.getStringSet("sponsorblock_filters", emptySet())
|
val sponsorblock = sharedPreferences.getStringSet("sponsorblock_filters", emptySet())
|
||||||
|
|
@ -170,6 +171,7 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
resultItem.duration,
|
resultItem.duration,
|
||||||
type,
|
type,
|
||||||
getFormat(resultItem.formats, type),
|
getFormat(resultItem.formats, type),
|
||||||
|
sharedPreferences.getString("video_format", "Default")!!,
|
||||||
"",
|
"",
|
||||||
resultItem.formats,
|
resultItem.formats,
|
||||||
downloadPath!!, resultItem.website, "", resultItem.playlistTitle, audioPreferences, videoPreferences,customFileNameTemplate!!, saveThumb, DownloadRepository.Status.Processing.toString(), 0
|
downloadPath!!, resultItem.website, "", resultItem.playlistTitle, audioPreferences, videoPreferences,customFileNameTemplate!!, saveThumb, DownloadRepository.Status.Processing.toString(), 0
|
||||||
|
|
@ -188,6 +190,8 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
downloadItem.website,
|
downloadItem.website,
|
||||||
downloadItem.playlistTitle,
|
downloadItem.playlistTitle,
|
||||||
downloadItem.allFormats,
|
downloadItem.allFormats,
|
||||||
|
"",
|
||||||
|
arrayListOf(),
|
||||||
System.currentTimeMillis()
|
System.currentTimeMillis()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -204,6 +208,8 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
downloadItem.website,
|
downloadItem.website,
|
||||||
"",
|
"",
|
||||||
arrayListOf(),
|
arrayListOf(),
|
||||||
|
"",
|
||||||
|
arrayListOf(),
|
||||||
System.currentTimeMillis()
|
System.currentTimeMillis()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -220,6 +226,8 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
arrayListOf(),
|
arrayListOf(),
|
||||||
|
"",
|
||||||
|
arrayListOf(),
|
||||||
System.currentTimeMillis()
|
System.currentTimeMillis()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -247,9 +255,15 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
val downloadPath = when(historyItem.type){
|
val downloadPath = when(historyItem.type){
|
||||||
Type.audio -> sharedPreferences.getString("music_path", File(Environment.DIRECTORY_DOWNLOADS, "YTDLnis/Audio").absolutePath)
|
Type.audio -> sharedPreferences.getString("music_path", FileUtil.getDefautAudioPath())
|
||||||
Type.video -> sharedPreferences.getString("video_path", File(Environment.DIRECTORY_DOWNLOADS, "YTDLnis/Video").absolutePath)
|
Type.video -> sharedPreferences.getString("video_path", FileUtil.getDefautVideoPath())
|
||||||
else -> sharedPreferences.getString("command_path", File(Environment.DIRECTORY_DOWNLOADS, "YTDLnis/Command").absolutePath)
|
else -> sharedPreferences.getString("command_path", FileUtil.getDefaultCommandPath())
|
||||||
|
}
|
||||||
|
|
||||||
|
val container = when(historyItem.type){
|
||||||
|
Type.audio -> sharedPreferences.getString("audio_format", "Default")!!
|
||||||
|
Type.video -> sharedPreferences.getString("video_format", "Default")!!
|
||||||
|
else -> ""
|
||||||
}
|
}
|
||||||
|
|
||||||
val sponsorblock = sharedPreferences.getStringSet("sponsorblock_filters", emptySet())
|
val sponsorblock = sharedPreferences.getStringSet("sponsorblock_filters", emptySet())
|
||||||
|
|
@ -265,6 +279,7 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
historyItem.duration,
|
historyItem.duration,
|
||||||
historyItem.type,
|
historyItem.type,
|
||||||
historyItem.format,
|
historyItem.format,
|
||||||
|
container,
|
||||||
"",
|
"",
|
||||||
ArrayList(),
|
ArrayList(),
|
||||||
downloadPath!!, historyItem.website, "", "", audioPreferences, videoPreferences,customFileNameTemplate!!, saveThumb, DownloadRepository.Status.Processing.toString(), 0
|
downloadPath!!, historyItem.website, "", "", audioPreferences, videoPreferences,customFileNameTemplate!!, saveThumb, DownloadRepository.Status.Processing.toString(), 0
|
||||||
|
|
@ -438,24 +453,6 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if the download was quick downloaded and are incomplete
|
|
||||||
if (queuedItems.count() == 1){
|
|
||||||
val item = queuedItems.first()
|
|
||||||
if (item.title.isEmpty() || item.author.isEmpty() || item.thumb.isEmpty()){
|
|
||||||
runCatching {
|
|
||||||
val info = infoUtil.getMissingInfo(item.url)
|
|
||||||
if (item.title.isEmpty()) item.title = info?.title.toString()
|
|
||||||
if (item.author.isEmpty()) item.author = info?.author.toString()
|
|
||||||
item.duration = info?.duration.toString()
|
|
||||||
item.website = info?.website.toString()
|
|
||||||
if (item.thumb.isEmpty()) item.thumb = info?.thumb.toString()
|
|
||||||
repository.update(item)
|
|
||||||
}.onFailure { err ->
|
|
||||||
Log.e("error", err.message.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
queuedItems.forEach {
|
queuedItems.forEach {
|
||||||
val currentTime = System.currentTimeMillis()
|
val currentTime = System.currentTimeMillis()
|
||||||
var delay = if (it.downloadStartTime != 0L){
|
var delay = if (it.downloadStartTime != 0L){
|
||||||
|
|
|
||||||
|
|
@ -90,8 +90,7 @@ class HistoryViewModel(application: Application) : AndroidViewModel(application)
|
||||||
fun delete(item: HistoryItem, deleteFile: Boolean) = viewModelScope.launch(Dispatchers.IO){
|
fun delete(item: HistoryItem, deleteFile: Boolean) = viewModelScope.launch(Dispatchers.IO){
|
||||||
repository.delete(item)
|
repository.delete(item)
|
||||||
if (deleteFile){
|
if (deleteFile){
|
||||||
val fileUtil = FileUtil()
|
FileUtil.deleteFile(item.downloadPath)
|
||||||
fileUtil.deleteFile(item.downloadPath)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class SharedDownloadNotificationReceiver : AppCompatActivity() {
|
||||||
val notificationId = intent.getIntExtra("notificationID", 0)
|
val notificationId = intent.getIntExtra("notificationID", 0)
|
||||||
if (message != null && path != null) {
|
if (message != null && path != null) {
|
||||||
if (notificationId != 0) NotificationUtil(this).cancelDownloadNotification(notificationId)
|
if (notificationId != 0) NotificationUtil(this).cancelDownloadNotification(notificationId)
|
||||||
val uiUtil = UiUtil(FileUtil())
|
val uiUtil = UiUtil()
|
||||||
uiUtil.shareFileIntent(this, listOf(path))
|
uiUtil.shareFileIntent(this, listOf(path))
|
||||||
this.finishAffinity()
|
this.finishAffinity()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,5 @@ open class BaseActivity : AppCompatActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
ThemeUtil.updateTheme(this)
|
ThemeUtil.updateTheme(this)
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(window.decorView) { v, insets ->
|
|
||||||
v.setPadding(0, 0, 0, 0)
|
|
||||||
insets
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +37,6 @@ import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||||
import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
|
import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
|
||||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
|
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
|
||||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadMultipleBottomSheetDialog
|
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadMultipleBottomSheetDialog
|
||||||
import com.deniscerri.ytdlnis.util.FileUtil
|
|
||||||
import com.deniscerri.ytdlnis.util.InfoUtil
|
import com.deniscerri.ytdlnis.util.InfoUtil
|
||||||
import com.facebook.shimmer.ShimmerFrameLayout
|
import com.facebook.shimmer.ShimmerFrameLayout
|
||||||
import com.google.android.material.appbar.AppBarLayout
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
|
|
@ -88,7 +87,6 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
||||||
private var uiHandler: Handler? = null
|
private var uiHandler: Handler? = null
|
||||||
private var resultsList: List<ResultItem?>? = null
|
private var resultsList: List<ResultItem?>? = null
|
||||||
private var selectedObjects: ArrayList<ResultItem>? = null
|
private var selectedObjects: ArrayList<ResultItem>? = null
|
||||||
private var fileUtil: FileUtil? = null
|
|
||||||
private var quickLaunchSheet = false
|
private var quickLaunchSheet = false
|
||||||
private var sharedPreferences: SharedPreferences? = null
|
private var sharedPreferences: SharedPreferences? = null
|
||||||
private var _binding : FragmentHomeBinding? = null
|
private var _binding : FragmentHomeBinding? = null
|
||||||
|
|
@ -114,7 +112,6 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
||||||
|
|
||||||
fragmentContext = context
|
fragmentContext = context
|
||||||
layoutinflater = LayoutInflater.from(context)
|
layoutinflater = LayoutInflater.from(context)
|
||||||
fileUtil = FileUtil()
|
|
||||||
uiHandler = Handler(Looper.getMainLooper())
|
uiHandler = Handler(Looper.getMainLooper())
|
||||||
selectedObjects = ArrayList()
|
selectedObjects = ArrayList()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
||||||
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
||||||
commandTemplateDao = DBManager.getInstance(requireContext()).commandTemplateDao
|
commandTemplateDao = DBManager.getInstance(requireContext()).commandTemplateDao
|
||||||
onDownloadItemUpdateListener = listener
|
onDownloadItemUpdateListener = listener
|
||||||
uiUtil = UiUtil(FileUtil())
|
uiUtil = UiUtil()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
|
@ -94,6 +94,13 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//check if the item has formats and its audio-only
|
||||||
|
val isAudioOnly = resultItem.formats.isNotEmpty() && resultItem.formats.none { !it.format_note.contains("audio") }
|
||||||
|
if (isAudioOnly){
|
||||||
|
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(1)?.isClickable = true
|
||||||
|
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(1)?.alpha = 0.3f
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
val fragmentManager = parentFragmentManager
|
val fragmentManager = parentFragmentManager
|
||||||
fragmentAdapter = DownloadFragmentAdapter(
|
fragmentAdapter = DownloadFragmentAdapter(
|
||||||
|
|
@ -111,8 +118,14 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
||||||
viewPager2.setCurrentItem(0, false)
|
viewPager2.setCurrentItem(0, false)
|
||||||
}
|
}
|
||||||
Type.video -> {
|
Type.video -> {
|
||||||
tabLayout.selectTab(tabLayout.getTabAt(1))
|
if (isAudioOnly){
|
||||||
viewPager2.setCurrentItem(1, false)
|
tabLayout.getTabAt(0)!!.select()
|
||||||
|
viewPager2.setCurrentItem(0, false)
|
||||||
|
Toast.makeText(context, getString(R.string.audio_only_item), Toast.LENGTH_SHORT).show()
|
||||||
|
}else{
|
||||||
|
tabLayout.getTabAt(1)!!.select()
|
||||||
|
viewPager2.setCurrentItem(1, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
tabLayout.selectTab(tabLayout.getTabAt(2))
|
tabLayout.selectTab(tabLayout.getTabAt(2))
|
||||||
|
|
@ -127,6 +140,9 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
||||||
if (tab!!.position == 2 && commandTemplateNr == 0){
|
if (tab!!.position == 2 && commandTemplateNr == 0){
|
||||||
tabLayout.selectTab(tabLayout.getTabAt(1))
|
tabLayout.selectTab(tabLayout.getTabAt(1))
|
||||||
Toast.makeText(context, getString(R.string.add_template_first), Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, getString(R.string.add_template_first), Toast.LENGTH_SHORT).show()
|
||||||
|
}else if (tab.position == 1 && isAudioOnly){
|
||||||
|
tabLayout.selectTab(tabLayout.getTabAt(0))
|
||||||
|
Toast.makeText(context, getString(R.string.audio_only_item), Toast.LENGTH_SHORT).show()
|
||||||
}else{
|
}else{
|
||||||
viewPager2.setCurrentItem(tab.position, false)
|
viewPager2.setCurrentItem(tab.position, false)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,9 +60,8 @@ import java.util.*
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
|
|
||||||
class CutVideoBottomSheetDialog(private val item: DownloadItem, private val listener: VideoCutListener) : BottomSheetDialogFragment() {
|
class CutVideoBottomSheetDialog(private val item: DownloadItem, private val urls : String?, private var chapters: List<ChapterItem>?, private val listener: VideoCutListener) : BottomSheetDialogFragment() {
|
||||||
private lateinit var behavior: BottomSheetBehavior<View>
|
private lateinit var behavior: BottomSheetBehavior<View>
|
||||||
private lateinit var fileUtil: FileUtil
|
|
||||||
private lateinit var infoUtil: InfoUtil
|
private lateinit var infoUtil: InfoUtil
|
||||||
private lateinit var uiUtil: UiUtil
|
private lateinit var uiUtil: UiUtil
|
||||||
private lateinit var player: Player
|
private lateinit var player: Player
|
||||||
|
|
@ -86,14 +85,12 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
private lateinit var chipGroup : ChipGroup
|
private lateinit var chipGroup : ChipGroup
|
||||||
|
|
||||||
private var timeSeconds by Delegates.notNull<Int>()
|
private var timeSeconds by Delegates.notNull<Int>()
|
||||||
private lateinit var chapters: List<ChapterItem>
|
|
||||||
private lateinit var selectedCuts: MutableList<String>
|
private lateinit var selectedCuts: MutableList<String>
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
fileUtil = FileUtil()
|
uiUtil = UiUtil()
|
||||||
uiUtil = UiUtil(fileUtil)
|
|
||||||
infoUtil = InfoUtil(requireActivity().applicationContext)
|
infoUtil = InfoUtil(requireActivity().applicationContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,7 +147,7 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
val videoView = view.findViewById<StyledPlayerView>(R.id.video_view)
|
val videoView = view.findViewById<StyledPlayerView>(R.id.video_view)
|
||||||
videoView.player = player
|
videoView.player = player
|
||||||
timeSeconds = convertStringToTimestamp(item.duration)
|
timeSeconds = convertStringToTimestamp(item.duration)
|
||||||
chapters = emptyList()
|
if (chapters == null) chapters = emptyList()
|
||||||
|
|
||||||
//cut section
|
//cut section
|
||||||
cutSection = view.findViewById(R.id.cut_section)
|
cutSection = view.findViewById(R.id.cut_section)
|
||||||
|
|
@ -166,7 +163,7 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
okBtn = view.findViewById(R.id.okButton)
|
okBtn = view.findViewById(R.id.okButton)
|
||||||
suggestedChips = view.findViewById(R.id.chapters)
|
suggestedChips = view.findViewById(R.id.chapters)
|
||||||
suggestedChapters = view.findViewById(R.id.suggested_cuts)
|
suggestedChapters = view.findViewById(R.id.suggested_cuts)
|
||||||
initCutSection()
|
|
||||||
|
|
||||||
//cut list section
|
//cut list section
|
||||||
cutListSection = view.findViewById(R.id.list_section)
|
cutListSection = view.findViewById(R.id.list_section)
|
||||||
|
|
@ -174,6 +171,7 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
resetBtn = view.findViewById(R.id.reset_all)
|
resetBtn = view.findViewById(R.id.reset_all)
|
||||||
chipGroup = view.findViewById(R.id.cut_list_chip_group)
|
chipGroup = view.findViewById(R.id.cut_list_chip_group)
|
||||||
|
|
||||||
|
|
||||||
selectedCuts = if (chipGroup.childCount == 0){
|
selectedCuts = if (chipGroup.childCount == 0){
|
||||||
mutableListOf()
|
mutableListOf()
|
||||||
}else {
|
}else {
|
||||||
|
|
@ -183,6 +181,7 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
chipGroup.children.map { (it as Chip).text.toString() }.toMutableList()
|
chipGroup.children.map { (it as Chip).text.toString() }.toMutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initCutSection()
|
||||||
initCutListSection()
|
initCutListSection()
|
||||||
|
|
||||||
if (item.downloadSections.isBlank()) cutSection.visibility = View.VISIBLE
|
if (item.downloadSections.isBlank()) cutSection.visibility = View.VISIBLE
|
||||||
|
|
@ -190,16 +189,22 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
try {
|
try {
|
||||||
val data = withContext(Dispatchers.IO){
|
val data : MutableList<String?> = withContext(Dispatchers.IO){
|
||||||
infoUtil.getStreamingUrlAndChapters(item.url)
|
if (urls.isNullOrEmpty() || chapters.isNullOrEmpty()) {
|
||||||
|
infoUtil.getStreamingUrlAndChapters(item.url)
|
||||||
|
}else {
|
||||||
|
urls.split("\n").toMutableList()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (data.isEmpty()) throw Exception("No Data found!")
|
|
||||||
try{
|
|
||||||
val listType: Type = object : TypeToken<List<ChapterItem>>() {}.type
|
|
||||||
chapters = Gson().fromJson(data.first().toString(), listType)
|
|
||||||
}catch (ignored: Exception) {}
|
|
||||||
data.removeFirst()
|
|
||||||
|
|
||||||
|
if (data.isEmpty()) throw Exception("No Data found!")
|
||||||
|
if (chapters!!.isEmpty()){
|
||||||
|
try{
|
||||||
|
val listType: Type = object : TypeToken<List<ChapterItem>>() {}.type
|
||||||
|
chapters = Gson().fromJson(data.first().toString(), listType)
|
||||||
|
}catch (ignored: Exception) {}
|
||||||
|
data.removeFirst()
|
||||||
|
}
|
||||||
|
|
||||||
if (data.isEmpty()) throw Exception("No Streaming URL found!")
|
if (data.isEmpty()) throw Exception("No Streaming URL found!")
|
||||||
if (data.size == 2){
|
if (data.size == 2){
|
||||||
|
|
@ -375,11 +380,11 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun populateSuggestedChapters(){
|
private fun populateSuggestedChapters(){
|
||||||
if (chapters.isEmpty()) suggestedChapters.visibility = View.GONE
|
if (chapters!!.isEmpty()) suggestedChapters.visibility = View.GONE
|
||||||
else {
|
else {
|
||||||
suggestedChapters.visibility = View.VISIBLE
|
suggestedChapters.visibility = View.VISIBLE
|
||||||
suggestedChips.removeAllViews()
|
suggestedChips.removeAllViews()
|
||||||
chapters.forEach {
|
chapters!!.forEach {
|
||||||
val chip = layoutInflater.inflate(R.layout.suggestion_chip, chipGroup, false) as Chip
|
val chip = layoutInflater.inflate(R.layout.suggestion_chip, chipGroup, false) as Chip
|
||||||
chip.text = it.title
|
chip.text = it.title
|
||||||
chip.chipBackgroundColor = ColorStateList.valueOf(MaterialColors.getColor(requireContext(), R.attr.colorSecondaryContainer, Color.BLACK))
|
chip.chipBackgroundColor = ColorStateList.valueOf(MaterialColors.getColor(requireContext(), R.attr.colorSecondaryContainer, Color.BLACK))
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
|
||||||
private var activity: Activity? = null
|
private var activity: Activity? = null
|
||||||
private lateinit var downloadViewModel : DownloadViewModel
|
private lateinit var downloadViewModel : DownloadViewModel
|
||||||
private lateinit var resultViewModel : ResultViewModel
|
private lateinit var resultViewModel : ResultViewModel
|
||||||
private lateinit var fileUtil : FileUtil
|
|
||||||
private lateinit var uiUtil : UiUtil
|
private lateinit var uiUtil : UiUtil
|
||||||
|
|
||||||
private lateinit var title : TextInputLayout
|
private lateinit var title : TextInputLayout
|
||||||
|
|
@ -71,8 +70,7 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
|
||||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
||||||
|
|
||||||
fileUtil = FileUtil()
|
uiUtil = UiUtil()
|
||||||
uiUtil = UiUtil(fileUtil)
|
|
||||||
return fragmentView
|
return fragmentView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,7 +110,7 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
|
||||||
})
|
})
|
||||||
saveDir = view.findViewById(R.id.outputPath)
|
saveDir = view.findViewById(R.id.outputPath)
|
||||||
saveDir.editText!!.setText(
|
saveDir.editText!!.setText(
|
||||||
fileUtil.formatPath(downloadItem.downloadPath)
|
FileUtil.formatPath(downloadItem.downloadPath)
|
||||||
)
|
)
|
||||||
saveDir.editText!!.isFocusable = false
|
saveDir.editText!!.isFocusable = false
|
||||||
saveDir.editText!!.isClickable = true
|
saveDir.editText!!.isClickable = true
|
||||||
|
|
@ -124,8 +122,8 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
|
||||||
audioPathResultLauncher.launch(intent)
|
audioPathResultLauncher.launch(intent)
|
||||||
}
|
}
|
||||||
freeSpace = view.findViewById(R.id.freespace)
|
freeSpace = view.findViewById(R.id.freespace)
|
||||||
val free = fileUtil.convertFileSize(
|
val free = FileUtil.convertFileSize(
|
||||||
File(fileUtil.formatPath(downloadItem.downloadPath)).freeSpace)
|
File(FileUtil.formatPath(downloadItem.downloadPath)).freeSpace)
|
||||||
freeSpace.text = String.format( getString(R.string.freespace) + ": " + free)
|
freeSpace.text = String.format( getString(R.string.freespace) + ": " + free)
|
||||||
if (free == "?") freeSpace.visibility = View.GONE
|
if (free == "?") freeSpace.visibility = View.GONE
|
||||||
|
|
||||||
|
|
@ -157,7 +155,6 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
formats = allFormats.first().toMutableList()
|
formats = allFormats.first().toMutableList()
|
||||||
downloadItem.format.container = container.editText?.text.toString()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
formatCard.setOnClickListener{
|
formatCard.setOnClickListener{
|
||||||
|
|
@ -181,13 +178,13 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
downloadItem.format.container = if (containerPreference == getString(R.string.defaultValue)) "" else containerPreference!!
|
downloadItem.container = if (containerPreference == getString(R.string.defaultValue)) "" else containerPreference!!
|
||||||
containerAutoCompleteTextView.setText(downloadItem.format.container.ifEmpty { getString(R.string.defaultValue) }, false)
|
containerAutoCompleteTextView.setText(downloadItem.container.ifEmpty { getString(R.string.defaultValue) }, false)
|
||||||
|
|
||||||
(container!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
|
(container!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
|
||||||
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
|
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
|
||||||
downloadItem.format.container = containers[index]
|
downloadItem.container = containers[index]
|
||||||
if (containers[index] == getString(R.string.defaultValue)) downloadItem.format.container = ""
|
if (containers[index] == getString(R.string.defaultValue)) downloadItem.container = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
val embedThumb = view.findViewById<Chip>(R.id.embed_thumb)
|
val embedThumb = view.findViewById<Chip>(R.id.embed_thumb)
|
||||||
|
|
@ -313,7 +310,7 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
|
||||||
}
|
}
|
||||||
cut.setOnClickListener {
|
cut.setOnClickListener {
|
||||||
if (parentFragmentManager.findFragmentByTag("cutVideoSheet") == null){
|
if (parentFragmentManager.findFragmentByTag("cutVideoSheet") == null){
|
||||||
val bottomSheet = CutVideoBottomSheetDialog(downloadItem, cutVideoListener)
|
val bottomSheet = CutVideoBottomSheetDialog(downloadItem, resultItem.urls, resultItem.chapters, cutVideoListener)
|
||||||
bottomSheet.show(parentFragmentManager, "cutVideoSheet")
|
bottomSheet.show(parentFragmentManager, "cutVideoSheet")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -340,10 +337,10 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
|
||||||
}
|
}
|
||||||
downloadItem.downloadPath = result.data?.data.toString()
|
downloadItem.downloadPath = result.data?.data.toString()
|
||||||
//downloadViewModel.updateDownload(downloadItem)
|
//downloadViewModel.updateDownload(downloadItem)
|
||||||
saveDir.editText?.setText(fileUtil.formatPath(result.data?.data.toString()), TextView.BufferType.EDITABLE)
|
saveDir.editText?.setText(FileUtil.formatPath(result.data?.data.toString()), TextView.BufferType.EDITABLE)
|
||||||
|
|
||||||
val free = fileUtil.convertFileSize(
|
val free = FileUtil.convertFileSize(
|
||||||
File(fileUtil.formatPath(downloadItem.downloadPath)).freeSpace)
|
File(FileUtil.formatPath(downloadItem.downloadPath)).freeSpace)
|
||||||
freeSpace.text = String.format( getString(R.string.freespace) + ": " + free)
|
freeSpace.text = String.format( getString(R.string.freespace) + ": " + free)
|
||||||
if (free == "?") freeSpace.visibility = View.GONE
|
if (free == "?") freeSpace.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
|
||||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
||||||
commandTemplateDao = DBManager.getInstance(requireContext()).commandTemplateDao
|
commandTemplateDao = DBManager.getInstance(requireContext()).commandTemplateDao
|
||||||
uiUtil = UiUtil(FileUtil())
|
uiUtil = UiUtil()
|
||||||
infoUtil = InfoUtil(requireContext())
|
infoUtil = InfoUtil(requireContext())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,6 +103,13 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//check if the item has formats and its audio-only
|
||||||
|
val isAudioOnly = resultItem.formats.isNotEmpty() && resultItem.formats.none { !it.format_note.contains("audio") }
|
||||||
|
if (isAudioOnly){
|
||||||
|
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(1)?.isClickable = true
|
||||||
|
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(1)?.alpha = 0.3f
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
val fragmentManager = parentFragmentManager
|
val fragmentManager = parentFragmentManager
|
||||||
fragmentAdapter = DownloadFragmentAdapter(
|
fragmentAdapter = DownloadFragmentAdapter(
|
||||||
|
|
@ -121,8 +128,14 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
|
||||||
viewPager2.setCurrentItem(0, false)
|
viewPager2.setCurrentItem(0, false)
|
||||||
}
|
}
|
||||||
Type.video -> {
|
Type.video -> {
|
||||||
tabLayout.getTabAt(1)!!.select()
|
if (isAudioOnly){
|
||||||
viewPager2.setCurrentItem(1, false)
|
tabLayout.getTabAt(0)!!.select()
|
||||||
|
viewPager2.setCurrentItem(0, false)
|
||||||
|
Toast.makeText(context, getString(R.string.audio_only_item), Toast.LENGTH_SHORT).show()
|
||||||
|
}else{
|
||||||
|
tabLayout.getTabAt(1)!!.select()
|
||||||
|
viewPager2.setCurrentItem(1, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
tabLayout.getTabAt(2)!!.select()
|
tabLayout.getTabAt(2)!!.select()
|
||||||
|
|
@ -138,7 +151,11 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
|
||||||
if (tab!!.position == 2 && commandTemplateNr == 0){
|
if (tab!!.position == 2 && commandTemplateNr == 0){
|
||||||
tabLayout.selectTab(tabLayout.getTabAt(1))
|
tabLayout.selectTab(tabLayout.getTabAt(1))
|
||||||
Toast.makeText(context, getString(R.string.add_template_first), Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, getString(R.string.add_template_first), Toast.LENGTH_SHORT).show()
|
||||||
}else{
|
}else if (tab.position == 1 && isAudioOnly){
|
||||||
|
tabLayout.selectTab(tabLayout.getTabAt(0))
|
||||||
|
Toast.makeText(context, getString(R.string.audio_only_item), Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
else{
|
||||||
viewPager2.setCurrentItem(tab.position, false)
|
viewPager2.setCurrentItem(tab.position, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,6 @@ class DownloadCommandFragment(private val resultItem: ResultItem, private var cu
|
||||||
private var activity: Activity? = null
|
private var activity: Activity? = null
|
||||||
private lateinit var downloadViewModel : DownloadViewModel
|
private lateinit var downloadViewModel : DownloadViewModel
|
||||||
private lateinit var commandTemplateViewModel : CommandTemplateViewModel
|
private lateinit var commandTemplateViewModel : CommandTemplateViewModel
|
||||||
private lateinit var fileUtil : FileUtil
|
|
||||||
private lateinit var uiUtil : UiUtil
|
private lateinit var uiUtil : UiUtil
|
||||||
private lateinit var saveDir : TextInputLayout
|
private lateinit var saveDir : TextInputLayout
|
||||||
private lateinit var freeSpace : TextView
|
private lateinit var freeSpace : TextView
|
||||||
|
|
@ -59,8 +58,7 @@ class DownloadCommandFragment(private val resultItem: ResultItem, private var cu
|
||||||
activity = getActivity()
|
activity = getActivity()
|
||||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
|
commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
|
||||||
fileUtil = FileUtil()
|
uiUtil = UiUtil()
|
||||||
uiUtil = UiUtil(fileUtil)
|
|
||||||
return fragmentView
|
return fragmentView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,7 +136,7 @@ class DownloadCommandFragment(private val resultItem: ResultItem, private var cu
|
||||||
|
|
||||||
saveDir = view.findViewById(R.id.outputPath)
|
saveDir = view.findViewById(R.id.outputPath)
|
||||||
saveDir.editText!!.setText(
|
saveDir.editText!!.setText(
|
||||||
fileUtil.formatPath(downloadItem.downloadPath)
|
FileUtil.formatPath(downloadItem.downloadPath)
|
||||||
)
|
)
|
||||||
saveDir.editText!!.isFocusable = false
|
saveDir.editText!!.isFocusable = false
|
||||||
saveDir.editText!!.isClickable = true
|
saveDir.editText!!.isClickable = true
|
||||||
|
|
@ -151,8 +149,8 @@ class DownloadCommandFragment(private val resultItem: ResultItem, private var cu
|
||||||
}
|
}
|
||||||
|
|
||||||
freeSpace = view.findViewById(R.id.freespace)
|
freeSpace = view.findViewById(R.id.freespace)
|
||||||
freeSpace.text = String.format(getString(R.string.freespace) + ": " + fileUtil.convertFileSize(
|
freeSpace.text = String.format(getString(R.string.freespace) + ": " + FileUtil.convertFileSize(
|
||||||
File(fileUtil.formatPath(downloadItem.downloadPath)).freeSpace
|
File(FileUtil.formatPath(downloadItem.downloadPath)).freeSpace
|
||||||
))
|
))
|
||||||
|
|
||||||
val newTemplate : Chip = view.findViewById(R.id.newTemplate)
|
val newTemplate : Chip = view.findViewById(R.id.newTemplate)
|
||||||
|
|
@ -226,10 +224,10 @@ class DownloadCommandFragment(private val resultItem: ResultItem, private var cu
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
downloadItem.downloadPath = result.data?.data.toString()
|
downloadItem.downloadPath = result.data?.data.toString()
|
||||||
saveDir.editText?.setText(fileUtil.formatPath(result.data?.data.toString()), TextView.BufferType.EDITABLE)
|
saveDir.editText?.setText(FileUtil.formatPath(result.data?.data.toString()), TextView.BufferType.EDITABLE)
|
||||||
|
|
||||||
freeSpace.text = String.format(getString(R.string.freespace) + ": " + fileUtil.convertFileSize(
|
freeSpace.text = String.format(getString(R.string.freespace) + ": " + FileUtil.convertFileSize(
|
||||||
File(fileUtil.formatPath(downloadItem.downloadPath)).freeSpace
|
File(FileUtil.formatPath(downloadItem.downloadPath)).freeSpace
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,6 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
private lateinit var listAdapter : ConfigureMultipleDownloadsAdapter
|
private lateinit var listAdapter : ConfigureMultipleDownloadsAdapter
|
||||||
private lateinit var recyclerView: RecyclerView
|
private lateinit var recyclerView: RecyclerView
|
||||||
private lateinit var behavior: BottomSheetBehavior<View>
|
private lateinit var behavior: BottomSheetBehavior<View>
|
||||||
private lateinit var fileUtil: FileUtil
|
|
||||||
private lateinit var uiUtil: UiUtil
|
private lateinit var uiUtil: UiUtil
|
||||||
private lateinit var bottomAppBar: BottomAppBar
|
private lateinit var bottomAppBar: BottomAppBar
|
||||||
|
|
||||||
|
|
@ -69,8 +68,7 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
||||||
commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
|
commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
|
||||||
fileUtil = FileUtil()
|
uiUtil = UiUtil()
|
||||||
uiUtil = UiUtil(fileUtil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("RestrictedApi", "NotifyDataSetChanged")
|
@SuppressLint("RestrictedApi", "NotifyDataSetChanged")
|
||||||
|
|
@ -291,7 +289,7 @@ class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>,
|
||||||
items.forEach {
|
items.forEach {
|
||||||
it.downloadPath = result.data?.data.toString()
|
it.downloadPath = result.data?.data.toString()
|
||||||
}
|
}
|
||||||
Toast.makeText(requireContext(), "Changed every item's download path to: ${fileUtil.formatPath(result.data!!.data.toString())}", Toast.LENGTH_LONG).show()
|
Toast.makeText(requireContext(), "Changed every item's download path to: ${FileUtil.formatPath(result.data!!.data.toString())}", Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
private var activity: Activity? = null
|
private var activity: Activity? = null
|
||||||
private lateinit var downloadViewModel : DownloadViewModel
|
private lateinit var downloadViewModel : DownloadViewModel
|
||||||
private lateinit var resultViewModel: ResultViewModel
|
private lateinit var resultViewModel: ResultViewModel
|
||||||
private lateinit var fileUtil : FileUtil
|
|
||||||
private lateinit var uiUtil : UiUtil
|
private lateinit var uiUtil : UiUtil
|
||||||
|
|
||||||
private lateinit var title : TextInputLayout
|
private lateinit var title : TextInputLayout
|
||||||
|
|
@ -72,8 +71,7 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
resultViewModel = ViewModelProvider(this@DownloadVideoFragment)[ResultViewModel::class.java]
|
resultViewModel = ViewModelProvider(this@DownloadVideoFragment)[ResultViewModel::class.java]
|
||||||
|
|
||||||
fileUtil = FileUtil()
|
uiUtil = UiUtil()
|
||||||
uiUtil = UiUtil(fileUtil)
|
|
||||||
return fragmentView
|
return fragmentView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,7 +112,7 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
|
|
||||||
saveDir = view.findViewById(R.id.outputPath)
|
saveDir = view.findViewById(R.id.outputPath)
|
||||||
saveDir.editText!!.setText(
|
saveDir.editText!!.setText(
|
||||||
fileUtil.formatPath(downloadItem.downloadPath)
|
FileUtil.formatPath(downloadItem.downloadPath)
|
||||||
)
|
)
|
||||||
saveDir.editText!!.isFocusable = false
|
saveDir.editText!!.isFocusable = false
|
||||||
saveDir.editText!!.isClickable = true
|
saveDir.editText!!.isClickable = true
|
||||||
|
|
@ -127,8 +125,8 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
}
|
}
|
||||||
|
|
||||||
freeSpace = view.findViewById(R.id.freespace)
|
freeSpace = view.findViewById(R.id.freespace)
|
||||||
val free = fileUtil.convertFileSize(
|
val free = FileUtil.convertFileSize(
|
||||||
File(fileUtil.formatPath(downloadItem.downloadPath)).freeSpace)
|
File(FileUtil.formatPath(downloadItem.downloadPath)).freeSpace)
|
||||||
freeSpace.text = String.format( getString(R.string.freespace) + ": " + free)
|
freeSpace.text = String.format( getString(R.string.freespace) + ": " + free)
|
||||||
if (free == "?") freeSpace.visibility = View.GONE
|
if (free == "?") freeSpace.visibility = View.GONE
|
||||||
|
|
||||||
|
|
@ -148,7 +146,7 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
val formatCard = view.findViewById<MaterialCardView>(R.id.format_card_constraintLayout)
|
val formatCard = view.findViewById<MaterialCardView>(R.id.format_card_constraintLayout)
|
||||||
|
|
||||||
val chosenFormat = downloadItem.format
|
val chosenFormat = downloadItem.format
|
||||||
uiUtil.populateFormatCard(formatCard, chosenFormat, null)
|
uiUtil.populateFormatCard(formatCard, chosenFormat, downloadItem.allFormats.filter { downloadItem.videoPreferences.audioFormatIDs.contains(it.format_id) })
|
||||||
val listener = object : OnFormatClickListener {
|
val listener = object : OnFormatClickListener {
|
||||||
override fun onFormatClick(allFormats: List<List<Format>>, item: List<Format>) {
|
override fun onFormatClick(allFormats: List<List<Format>>, item: List<Format>) {
|
||||||
downloadItem.format = item.first()
|
downloadItem.format = item.first()
|
||||||
|
|
@ -162,7 +160,6 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
}
|
}
|
||||||
formats = allFormats.first().toMutableList()
|
formats = allFormats.first().toMutableList()
|
||||||
uiUtil.populateFormatCard(formatCard, item.first(), item.drop(1))
|
uiUtil.populateFormatCard(formatCard, item.first(), item.drop(1))
|
||||||
downloadItem.format.container = container.editText?.text.toString()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
formatCard.setOnClickListener{
|
formatCard.setOnClickListener{
|
||||||
|
|
@ -185,15 +182,15 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
containers
|
containers
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
downloadItem.format.container = if (containerPreference == getString(R.string.defaultValue)) "" else containerPreference!!
|
downloadItem.container = if (containerPreference == getString(R.string.defaultValue)) "" else containerPreference!!
|
||||||
containerAutoCompleteTextView!!.setText(
|
containerAutoCompleteTextView!!.setText(
|
||||||
downloadItem.format.container.ifEmpty { getString(R.string.defaultValue) },
|
downloadItem.container.ifEmpty { getString(R.string.defaultValue) },
|
||||||
false)
|
false)
|
||||||
|
|
||||||
(container!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
|
(container!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
|
||||||
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
|
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
|
||||||
downloadItem.format.container = containers[index]
|
downloadItem.container = containers[index]
|
||||||
if (containers[index] == getString(R.string.defaultValue)) downloadItem.format.container = ""
|
if (containers[index] == getString(R.string.defaultValue)) downloadItem.container = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -312,7 +309,7 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
}
|
}
|
||||||
cut.setOnClickListener {
|
cut.setOnClickListener {
|
||||||
if (parentFragmentManager.findFragmentByTag("cutVideoSheet") == null){
|
if (parentFragmentManager.findFragmentByTag("cutVideoSheet") == null){
|
||||||
val bottomSheet = CutVideoBottomSheetDialog(downloadItem, cutVideoListener)
|
val bottomSheet = CutVideoBottomSheetDialog(downloadItem, resultItem.urls, resultItem.chapters, cutVideoListener)
|
||||||
bottomSheet.show(parentFragmentManager, "cutVideoSheet")
|
bottomSheet.show(parentFragmentManager, "cutVideoSheet")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -332,17 +329,17 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
builder.setView(inputLayout)
|
builder.setView(inputLayout)
|
||||||
builder.setPositiveButton(
|
builder.setPositiveButton(
|
||||||
getString(R.string.ok)
|
getString(R.string.ok)
|
||||||
) { dialog: DialogInterface?, which: Int ->
|
) { _: DialogInterface?, _: Int ->
|
||||||
downloadItem.customFileNameTemplate = editText.text.toString()
|
downloadItem.customFileNameTemplate = editText.text.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle the negative button of the alert dialog
|
// handle the negative button of the alert dialog
|
||||||
builder.setNegativeButton(
|
builder.setNegativeButton(
|
||||||
getString(R.string.cancel)
|
getString(R.string.cancel)
|
||||||
) { dialog: DialogInterface?, which: Int -> }
|
) { _: DialogInterface?, _: Int -> }
|
||||||
|
|
||||||
val dialog = builder.create()
|
val dialog = builder.create()
|
||||||
editText.doOnTextChanged { text, start, before, count ->
|
editText.doOnTextChanged { _, _, _, _ ->
|
||||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = editText.text.isNotEmpty()
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = editText.text.isNotEmpty()
|
||||||
}
|
}
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
|
@ -363,7 +360,7 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
subtitleLanguages.visibility = View.VISIBLE
|
subtitleLanguages.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
saveSubtitles.setOnCheckedChangeListener { compoundButton, b ->
|
saveSubtitles.setOnCheckedChangeListener { _, _ ->
|
||||||
if (saveSubtitles.isChecked) subtitleLanguages.visibility = View.VISIBLE
|
if (saveSubtitles.isChecked) subtitleLanguages.visibility = View.VISIBLE
|
||||||
else subtitleLanguages.visibility = View.GONE
|
else subtitleLanguages.visibility = View.GONE
|
||||||
downloadItem.videoPreferences.writeSubs = saveSubtitles.isChecked
|
downloadItem.videoPreferences.writeSubs = saveSubtitles.isChecked
|
||||||
|
|
@ -376,7 +373,7 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
}
|
}
|
||||||
|
|
||||||
val removeAudio = view.findViewById<Chip>(R.id.remove_audio)
|
val removeAudio = view.findViewById<Chip>(R.id.remove_audio)
|
||||||
removeAudio.setOnCheckedChangeListener { compoundButton, b ->
|
removeAudio.setOnCheckedChangeListener { _, _ ->
|
||||||
downloadItem.videoPreferences.removeAudio = removeAudio.isChecked
|
downloadItem.videoPreferences.removeAudio = removeAudio.isChecked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -398,11 +395,10 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
downloadItem.downloadPath = result.data?.data.toString()
|
downloadItem.downloadPath = result.data?.data.toString()
|
||||||
//downloadviewmodel.updateDownload(downloadItem)
|
saveDir.editText?.setText(FileUtil.formatPath(result.data?.data.toString()), TextView.BufferType.EDITABLE)
|
||||||
saveDir.editText?.setText(fileUtil.formatPath(result.data?.data.toString()), TextView.BufferType.EDITABLE)
|
|
||||||
|
|
||||||
val free = fileUtil.convertFileSize(
|
val free = FileUtil.convertFileSize(
|
||||||
File(fileUtil.formatPath(downloadItem.downloadPath)).freeSpace)
|
File(FileUtil.formatPath(downloadItem.downloadPath)).freeSpace)
|
||||||
freeSpace.text = String.format( getString(R.string.freespace) + ": " + free)
|
freeSpace.text = String.format( getString(R.string.freespace) + ": " + free)
|
||||||
if (free == "?") freeSpace.visibility = View.GONE
|
if (free == "?") freeSpace.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ import java.util.*
|
||||||
|
|
||||||
class FormatSelectionBottomSheetDialog(private val items: List<DownloadItem?>, private var formats: List<List<Format>>, private val listener: OnFormatClickListener) : BottomSheetDialogFragment() {
|
class FormatSelectionBottomSheetDialog(private val items: List<DownloadItem?>, private var formats: List<List<Format>>, private val listener: OnFormatClickListener) : BottomSheetDialogFragment() {
|
||||||
private lateinit var behavior: BottomSheetBehavior<View>
|
private lateinit var behavior: BottomSheetBehavior<View>
|
||||||
private lateinit var fileUtil: FileUtil
|
|
||||||
private lateinit var infoUtil: InfoUtil
|
private lateinit var infoUtil: InfoUtil
|
||||||
private lateinit var uiUtil: UiUtil
|
private lateinit var uiUtil: UiUtil
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
|
|
@ -48,8 +47,7 @@ class FormatSelectionBottomSheetDialog(private val items: List<DownloadItem?>, p
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
fileUtil = FileUtil()
|
uiUtil = UiUtil()
|
||||||
uiUtil = UiUtil(fileUtil)
|
|
||||||
infoUtil = InfoUtil(requireActivity().applicationContext)
|
infoUtil = InfoUtil(requireActivity().applicationContext)
|
||||||
formatCollection = mutableListOf()
|
formatCollection = mutableListOf()
|
||||||
chosenFormats = listOf()
|
chosenFormats = listOf()
|
||||||
|
|
@ -116,11 +114,12 @@ class FormatSelectionBottomSheetDialog(private val items: List<DownloadItem?>, p
|
||||||
}
|
}
|
||||||
|
|
||||||
val refreshBtn = view.findViewById<Button>(R.id.format_refresh)
|
val refreshBtn = view.findViewById<Button>(R.id.format_refresh)
|
||||||
if (formats.flatten().none { it.filesize == 0L } || items.isEmpty()) refreshBtn.visibility = View.GONE
|
if (!hasGenericFormats || items.isEmpty()) refreshBtn.visibility = View.GONE
|
||||||
|
|
||||||
|
|
||||||
refreshBtn.setOnClickListener {
|
refreshBtn.setOnClickListener {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
|
chosenFormats = emptyList()
|
||||||
try {
|
try {
|
||||||
refreshBtn.isEnabled = false
|
refreshBtn.isEnabled = false
|
||||||
formatListLinearLayout.visibility = View.GONE
|
formatListLinearLayout.visibility = View.GONE
|
||||||
|
|
@ -132,9 +131,11 @@ class FormatSelectionBottomSheetDialog(private val items: List<DownloadItem?>, p
|
||||||
val res = withContext(Dispatchers.IO){
|
val res = withContext(Dispatchers.IO){
|
||||||
infoUtil.getFormats(items.first()!!.url)
|
infoUtil.getFormats(items.first()!!.url)
|
||||||
}
|
}
|
||||||
chosenFormats = res.formats.filter { it.filesize != 0L }
|
res.filter { it.format_note != "storyboard" }
|
||||||
if(items.first()?.type == Type.audio){
|
if(items.first()?.type == Type.audio){
|
||||||
chosenFormats = chosenFormats.filter { it.format_note.contains("audio", ignoreCase = true) }
|
chosenFormats = res.filter { it.format_note.contains("audio", ignoreCase = true) }
|
||||||
|
}else{
|
||||||
|
chosenFormats = res
|
||||||
}
|
}
|
||||||
if (chosenFormats.isEmpty()) throw Exception()
|
if (chosenFormats.isEmpty()) throw Exception()
|
||||||
//playlist format filtering
|
//playlist format filtering
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
import com.yausername.youtubedl_android.YoutubeDL
|
import com.yausername.youtubedl_android.YoutubeDL
|
||||||
|
|
||||||
|
|
||||||
class ActiveDownloadsFragment() : Fragment(), ActiveDownloadAdapter.OnItemClickListener, OnClickListener {
|
class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickListener, OnClickListener {
|
||||||
private var _binding : FragmentHomeBinding? = null
|
private var _binding : FragmentHomeBinding? = null
|
||||||
private var fragmentView: View? = null
|
private var fragmentView: View? = null
|
||||||
private var activity: Activity? = null
|
private var activity: Activity? = null
|
||||||
|
|
@ -34,7 +34,6 @@ class ActiveDownloadsFragment() : Fragment(), ActiveDownloadAdapter.OnItemClickL
|
||||||
private lateinit var activeDownloads : ActiveDownloadAdapter
|
private lateinit var activeDownloads : ActiveDownloadAdapter
|
||||||
lateinit var downloadItem: DownloadItem
|
lateinit var downloadItem: DownloadItem
|
||||||
private lateinit var notificationUtil: NotificationUtil
|
private lateinit var notificationUtil: NotificationUtil
|
||||||
private lateinit var fileUtil: FileUtil
|
|
||||||
private lateinit var list: List<DownloadItem>
|
private lateinit var list: List<DownloadItem>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -47,7 +46,6 @@ class ActiveDownloadsFragment() : Fragment(), ActiveDownloadAdapter.OnItemClickL
|
||||||
fragmentView = inflater.inflate(R.layout.fragment_generic_download_queue, container, false)
|
fragmentView = inflater.inflate(R.layout.fragment_generic_download_queue, container, false)
|
||||||
activity = getActivity()
|
activity = getActivity()
|
||||||
notificationUtil = NotificationUtil(requireContext())
|
notificationUtil = NotificationUtil(requireContext())
|
||||||
fileUtil = FileUtil()
|
|
||||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
list = listOf()
|
list = listOf()
|
||||||
return fragmentView
|
return fragmentView
|
||||||
|
|
@ -102,7 +100,7 @@ class ActiveDownloadsFragment() : Fragment(), ActiveDownloadAdapter.OnItemClickL
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOutputClick(item: DownloadItem) {
|
override fun onOutputClick(item: DownloadItem) {
|
||||||
val logFile = fileUtil.getLogFile(requireContext(), item)
|
val logFile = FileUtil.getLogFile(requireContext(), item)
|
||||||
if (logFile.exists()) {
|
if (logFile.exists()) {
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putString("logpath", logFile.absolutePath)
|
bundle.putString("logpath", logFile.absolutePath)
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
|
||||||
private var selectedObjects: ArrayList<DownloadItem>? = null
|
private var selectedObjects: ArrayList<DownloadItem>? = null
|
||||||
private var actionMode : ActionMode? = null
|
private var actionMode : ActionMode? = null
|
||||||
private lateinit var items : MutableList<DownloadItem>
|
private lateinit var items : MutableList<DownloadItem>
|
||||||
private lateinit var fileUtil: FileUtil
|
|
||||||
private lateinit var uiUtil : UiUtil
|
private lateinit var uiUtil : UiUtil
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
|
@ -66,8 +65,7 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
|
||||||
selectedObjects = arrayListOf()
|
selectedObjects = arrayListOf()
|
||||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
items = mutableListOf()
|
items = mutableListOf()
|
||||||
fileUtil = FileUtil()
|
uiUtil = UiUtil()
|
||||||
uiUtil = UiUtil(fileUtil)
|
|
||||||
return fragmentView
|
return fragmentView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -163,7 +161,7 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
|
||||||
codec.text = codecText
|
codec.text = codecText
|
||||||
}
|
}
|
||||||
|
|
||||||
val fileSizeReadable = fileUtil.convertFileSize(item.format.filesize)
|
val fileSizeReadable = FileUtil.convertFileSize(item.format.filesize)
|
||||||
if (fileSizeReadable == "?") fileSize!!.visibility = View.GONE
|
if (fileSizeReadable == "?") fileSize!!.visibility = View.GONE
|
||||||
else fileSize!!.text = fileSizeReadable
|
else fileSize!!.text = fileSizeReadable
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import it.xabaras.android.recyclerview.swipedecorator.RecyclerViewSwipeDecorator
|
import it.xabaras.android.recyclerview.swipedecorator.RecyclerViewSwipeDecorator
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickListener, OnItemClickListener {
|
class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickListener, OnItemClickListener {
|
||||||
|
|
@ -54,7 +55,6 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
||||||
private lateinit var items : MutableList<DownloadItem>
|
private lateinit var items : MutableList<DownloadItem>
|
||||||
private var selectedObjects: ArrayList<DownloadItem>? = null
|
private var selectedObjects: ArrayList<DownloadItem>? = null
|
||||||
private var actionMode : ActionMode? = null
|
private var actionMode : ActionMode? = null
|
||||||
private lateinit var fileUtil: FileUtil
|
|
||||||
private lateinit var uiUtil : UiUtil
|
private lateinit var uiUtil : UiUtil
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
|
|
@ -67,8 +67,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
||||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
items = mutableListOf()
|
items = mutableListOf()
|
||||||
selectedObjects = arrayListOf()
|
selectedObjects = arrayListOf()
|
||||||
fileUtil = FileUtil()
|
uiUtil = UiUtil()
|
||||||
uiUtil = UiUtil(fileUtil)
|
|
||||||
return fragmentView
|
return fragmentView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,7 +97,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
||||||
|
|
||||||
override fun onActionButtonClick(itemID: Long) {
|
override fun onActionButtonClick(itemID: Long) {
|
||||||
val item = items.find { it.id == itemID } ?: return
|
val item = items.find { it.id == itemID } ?: return
|
||||||
val logFile = fileUtil.getLogFile(requireContext(), item)
|
val logFile = FileUtil.getLogFile(requireContext(), item)
|
||||||
if (logFile.exists()) {
|
if (logFile.exists()) {
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putString("logpath", logFile.absolutePath)
|
bundle.putString("logpath", logFile.absolutePath)
|
||||||
|
|
@ -165,7 +164,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
||||||
codec.text = codecText
|
codec.text = codecText
|
||||||
}
|
}
|
||||||
|
|
||||||
val fileSizeReadable = fileUtil.convertFileSize(item.format.filesize)
|
val fileSizeReadable = FileUtil.convertFileSize(item.format.filesize)
|
||||||
if (fileSizeReadable == "?") fileSize!!.visibility = View.GONE
|
if (fileSizeReadable == "?") fileSize!!.visibility = View.GONE
|
||||||
else fileSize!!.text = fileSizeReadable
|
else fileSize!!.text = fileSizeReadable
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,6 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
private var historyList: List<HistoryItem?>? = null
|
private var historyList: List<HistoryItem?>? = null
|
||||||
private var allhistoryList: List<HistoryItem?>? = null
|
private var allhistoryList: List<HistoryItem?>? = null
|
||||||
private var selectedObjects: ArrayList<HistoryItem>? = null
|
private var selectedObjects: ArrayList<HistoryItem>? = null
|
||||||
private var fileUtil: FileUtil? = null
|
|
||||||
private var uiUtil: UiUtil? = null
|
private var uiUtil: UiUtil? = null
|
||||||
private var _binding : FragmentHistoryBinding? = null
|
private var _binding : FragmentHistoryBinding? = null
|
||||||
private var actionMode : ActionMode? = null
|
private var actionMode : ActionMode? = null
|
||||||
|
|
@ -113,8 +112,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
noResults = view.findViewById(R.id.no_results)
|
noResults = view.findViewById(R.id.no_results)
|
||||||
selectionChips = view.findViewById(R.id.history_selection_chips)
|
selectionChips = view.findViewById(R.id.history_selection_chips)
|
||||||
websiteGroup = view.findViewById(R.id.website_chip_group)
|
websiteGroup = view.findViewById(R.id.website_chip_group)
|
||||||
fileUtil = FileUtil()
|
uiUtil = UiUtil()
|
||||||
uiUtil = UiUtil(FileUtil())
|
|
||||||
uiHandler = Handler(Looper.getMainLooper())
|
uiHandler = Handler(Looper.getMainLooper())
|
||||||
selectedObjects = ArrayList()
|
selectedObjects = ArrayList()
|
||||||
|
|
||||||
|
|
@ -462,7 +460,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
codec.text = codecText
|
codec.text = codecText
|
||||||
}
|
}
|
||||||
|
|
||||||
val fileSizeReadable = fileUtil!!.convertFileSize(item.format.filesize)
|
val fileSizeReadable = FileUtil.convertFileSize(item.format.filesize)
|
||||||
if (fileSizeReadable == "?") fileSize!!.visibility = GONE
|
if (fileSizeReadable == "?") fileSize!!.visibility = GONE
|
||||||
else fileSize!!.text = fileSizeReadable
|
else fileSize!!.text = fileSizeReadable
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,6 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
||||||
private var selectedObjects: ArrayList<DownloadItem>? = null
|
private var selectedObjects: ArrayList<DownloadItem>? = null
|
||||||
private var actionMode : ActionMode? = null
|
private var actionMode : ActionMode? = null
|
||||||
private lateinit var items : MutableList<DownloadItem>
|
private lateinit var items : MutableList<DownloadItem>
|
||||||
private lateinit var fileUtil: FileUtil
|
|
||||||
private lateinit var uiUtil: UiUtil
|
private lateinit var uiUtil: UiUtil
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
|
@ -78,8 +77,7 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
||||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
items = mutableListOf()
|
items = mutableListOf()
|
||||||
selectedObjects = arrayListOf()
|
selectedObjects = arrayListOf()
|
||||||
fileUtil = FileUtil()
|
uiUtil = UiUtil()
|
||||||
uiUtil = UiUtil(fileUtil)
|
|
||||||
return fragmentView
|
return fragmentView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -185,7 +183,7 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
||||||
codec.text = codecText
|
codec.text = codecText
|
||||||
}
|
}
|
||||||
|
|
||||||
val fileSizeReadable = fileUtil.convertFileSize(item.format.filesize)
|
val fileSizeReadable = FileUtil.convertFileSize(item.format.filesize)
|
||||||
if (fileSizeReadable == "?") fileSize!!.visibility = View.GONE
|
if (fileSizeReadable == "?") fileSize!!.visibility = View.GONE
|
||||||
else fileSize!!.text = fileSizeReadable
|
else fileSize!!.text = fileSizeReadable
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ class CommandTemplatesFragment : Fragment(), TemplatesAdapter.OnItemClickListene
|
||||||
itemTouchHelper.attachToRecyclerView(recyclerView)
|
itemTouchHelper.attachToRecyclerView(recyclerView)
|
||||||
}
|
}
|
||||||
|
|
||||||
uiUtil = UiUtil(FileUtil())
|
uiUtil = UiUtil()
|
||||||
|
|
||||||
commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
|
commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
|
||||||
commandTemplateViewModel.items.observe(viewLifecycleOwner) {
|
commandTemplateViewModel.items.observe(viewLifecycleOwner) {
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ class CookiesFragment : Fragment(), CookieAdapter.OnItemClickListener {
|
||||||
val itemTouchHelper = ItemTouchHelper(simpleCallback)
|
val itemTouchHelper = ItemTouchHelper(simpleCallback)
|
||||||
itemTouchHelper.attachToRecyclerView(recyclerView)
|
itemTouchHelper.attachToRecyclerView(recyclerView)
|
||||||
}
|
}
|
||||||
uiUtil = UiUtil(FileUtil())
|
uiUtil = UiUtil()
|
||||||
|
|
||||||
cookiesViewModel = ViewModelProvider(this)[CookieViewModel::class.java]
|
cookiesViewModel = ViewModelProvider(this)[CookieViewModel::class.java]
|
||||||
cookiesViewModel.items.observe(viewLifecycleOwner) {
|
cookiesViewModel.items.observe(viewLifecycleOwner) {
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,6 @@ class TerminalActivity : BaseActivity() {
|
||||||
private lateinit var observer: FileObserver
|
private lateinit var observer: FileObserver
|
||||||
private lateinit var imm : InputMethodManager
|
private lateinit var imm : InputMethodManager
|
||||||
private lateinit var uiUtil: UiUtil
|
private lateinit var uiUtil: UiUtil
|
||||||
private lateinit var fileUtil: FileUtil
|
|
||||||
var context: Context? = null
|
var context: Context? = null
|
||||||
|
|
||||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
@ -75,8 +74,7 @@ class TerminalActivity : BaseActivity() {
|
||||||
downloadFile = File(cacheDir.absolutePath + "/$downloadID.txt")
|
downloadFile = File(cacheDir.absolutePath + "/$downloadID.txt")
|
||||||
if (! downloadFile.exists()) downloadFile.createNewFile()
|
if (! downloadFile.exists()) downloadFile.createNewFile()
|
||||||
imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
fileUtil = FileUtil()
|
uiUtil = UiUtil()
|
||||||
uiUtil = UiUtil(fileUtil)
|
|
||||||
|
|
||||||
context = baseContext
|
context = baseContext
|
||||||
scrollView = findViewById(R.id.custom_command_scrollview)
|
scrollView = findViewById(R.id.custom_command_scrollview)
|
||||||
|
|
@ -311,7 +309,7 @@ class TerminalActivity : BaseActivity() {
|
||||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
input!!.text.insert(input!!.selectionStart, fileUtil.formatPath(result.data?.data.toString()))
|
input!!.text.insert(input!!.selectionStart, FileUtil.formatPath(result.data?.data.toString()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
||||||
private var accessAllFiles : Preference? = null
|
private var accessAllFiles : Preference? = null
|
||||||
private var clearCache: Preference? = null
|
private var clearCache: Preference? = null
|
||||||
|
|
||||||
private var fileUtil: FileUtil? = null
|
|
||||||
private var activeDownloadCount = 0
|
private var activeDownloadCount = 0
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
|
@ -33,7 +32,6 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
||||||
|
|
||||||
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||||
val editor = preferences.edit()
|
val editor = preferences.edit()
|
||||||
fileUtil = FileUtil()
|
|
||||||
|
|
||||||
musicPath = findPreference("music_path")
|
musicPath = findPreference("music_path")
|
||||||
videoPath = findPreference("video_path")
|
videoPath = findPreference("video_path")
|
||||||
|
|
@ -42,13 +40,13 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
||||||
clearCache = findPreference("clear_cache")
|
clearCache = findPreference("clear_cache")
|
||||||
|
|
||||||
if (preferences.getString("music_path", "")!!.isEmpty()) {
|
if (preferences.getString("music_path", "")!!.isEmpty()) {
|
||||||
editor.putString("music_path", getString(R.string.music_path))
|
editor.putString("music_path", FileUtil.getDefautAudioPath())
|
||||||
}
|
}
|
||||||
if (preferences.getString("video_path", "")!!.isEmpty()) {
|
if (preferences.getString("video_path", "")!!.isEmpty()) {
|
||||||
editor.putString("video_path", getString(R.string.video_path))
|
editor.putString("video_path", FileUtil.getDefautVideoPath())
|
||||||
}
|
}
|
||||||
if (preferences.getString("command_path", "")!!.isEmpty()) {
|
if (preferences.getString("command_path", "")!!.isEmpty()) {
|
||||||
editor.putString("command_path", getString(R.string.command_path))
|
editor.putString("command_path", FileUtil.getDefaultCommandPath())
|
||||||
}
|
}
|
||||||
|
|
||||||
if((VERSION.SDK_INT >= 30 && Environment.isExternalStorageManager()) ||
|
if((VERSION.SDK_INT >= 30 && Environment.isExternalStorageManager()) ||
|
||||||
|
|
@ -58,7 +56,7 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
||||||
|
|
||||||
editor.apply()
|
editor.apply()
|
||||||
|
|
||||||
musicPath!!.summary = fileUtil?.formatPath(preferences.getString("music_path", "")!!)
|
musicPath!!.summary = FileUtil.formatPath(preferences.getString("music_path", "")!!)
|
||||||
musicPath!!.onPreferenceClickListener =
|
musicPath!!.onPreferenceClickListener =
|
||||||
Preference.OnPreferenceClickListener {
|
Preference.OnPreferenceClickListener {
|
||||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||||
|
|
@ -68,7 +66,7 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
||||||
musicPathResultLauncher.launch(intent)
|
musicPathResultLauncher.launch(intent)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
videoPath!!.summary = fileUtil?.formatPath(preferences.getString("video_path", "")!!)
|
videoPath!!.summary = FileUtil.formatPath(preferences.getString("video_path", "")!!)
|
||||||
videoPath!!.onPreferenceClickListener =
|
videoPath!!.onPreferenceClickListener =
|
||||||
Preference.OnPreferenceClickListener {
|
Preference.OnPreferenceClickListener {
|
||||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||||
|
|
@ -78,7 +76,7 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
||||||
videoPathResultLauncher.launch(intent)
|
videoPathResultLauncher.launch(intent)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
commandPath!!.summary = fileUtil?.formatPath(preferences.getString("command_path", "")!!)
|
commandPath!!.summary = FileUtil.formatPath(preferences.getString("command_path", "")!!)
|
||||||
commandPath!!.onPreferenceClickListener =
|
commandPath!!.onPreferenceClickListener =
|
||||||
Preference.OnPreferenceClickListener {
|
Preference.OnPreferenceClickListener {
|
||||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||||
|
|
@ -98,14 +96,14 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var cacheSize = File(requireContext().cacheDir.absolutePath + "/downloads").walkBottomUp().fold(0L) { acc, file -> acc + file.length() }
|
var cacheSize = File(requireContext().cacheDir.absolutePath + "/downloads").walkBottomUp().fold(0L) { acc, file -> acc + file.length() }
|
||||||
clearCache!!.summary = "(${fileUtil!!.convertFileSize(cacheSize)}) ${resources.getString(R.string.clear_temporary_files_summary)}"
|
clearCache!!.summary = "(${FileUtil.convertFileSize(cacheSize)}) ${resources.getString(R.string.clear_temporary_files_summary)}"
|
||||||
clearCache!!.onPreferenceClickListener =
|
clearCache!!.onPreferenceClickListener =
|
||||||
Preference.OnPreferenceClickListener {
|
Preference.OnPreferenceClickListener {
|
||||||
if (activeDownloadCount == 0){
|
if (activeDownloadCount == 0){
|
||||||
File(requireContext().cacheDir.absolutePath + "/downloads").deleteRecursively()
|
File(requireContext().cacheDir.absolutePath + "/downloads").deleteRecursively()
|
||||||
Snackbar.make(requireView(), getString(R.string.cache_cleared), Snackbar.LENGTH_SHORT).show()
|
Snackbar.make(requireView(), getString(R.string.cache_cleared), Snackbar.LENGTH_SHORT).show()
|
||||||
cacheSize = File(requireContext().cacheDir.absolutePath + "/downloads").walkBottomUp().fold(0L) { acc, file -> acc + file.length() }
|
cacheSize = File(requireContext().cacheDir.absolutePath + "/downloads").walkBottomUp().fold(0L) { acc, file -> acc + file.length() }
|
||||||
clearCache!!.summary = "(${fileUtil!!.convertFileSize(cacheSize)}) ${resources.getString(R.string.clear_temporary_files_summary)}"
|
clearCache!!.summary = "(${FileUtil.convertFileSize(cacheSize)}) ${resources.getString(R.string.clear_temporary_files_summary)}"
|
||||||
}else{
|
}else{
|
||||||
Snackbar.make(requireView(), getString(R.string.downloads_running_try_later), Snackbar.LENGTH_SHORT).show()
|
Snackbar.make(requireView(), getString(R.string.downloads_running_try_later), Snackbar.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +157,7 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
||||||
|
|
||||||
private fun changePath(p: Preference?, data: Intent?, requestCode: Int) {
|
private fun changePath(p: Preference?, data: Intent?, requestCode: Int) {
|
||||||
val path = data!!.data.toString()
|
val path = data!!.data.toString()
|
||||||
p!!.summary = fileUtil?.formatPath(data.data.toString())
|
p!!.summary = FileUtil.formatPath(data.data.toString())
|
||||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||||
val editor = sharedPreferences.edit()
|
val editor = sharedPreferences.edit()
|
||||||
when (requestCode) {
|
when (requestCode) {
|
||||||
|
|
|
||||||
|
|
@ -30,13 +30,11 @@ class GeneralSettingsFragment : BaseSettingsFragment() {
|
||||||
private var locale: ListPreference? = null
|
private var locale: ListPreference? = null
|
||||||
|
|
||||||
private var updateUtil: UpdateUtil? = null
|
private var updateUtil: UpdateUtil? = null
|
||||||
private var fileUtil: FileUtil? = null
|
|
||||||
private var activeDownloadCount = 0
|
private var activeDownloadCount = 0
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
setPreferencesFromResource(R.xml.general_preferences, rootKey)
|
setPreferencesFromResource(R.xml.general_preferences, rootKey)
|
||||||
updateUtil = UpdateUtil(requireContext())
|
updateUtil = UpdateUtil(requireContext())
|
||||||
fileUtil = FileUtil()
|
|
||||||
|
|
||||||
WorkManager.getInstance(requireContext()).getWorkInfosByTagLiveData("download").observe(this){
|
WorkManager.getInstance(requireContext()).getWorkInfosByTagLiveData("download").observe(this){
|
||||||
activeDownloadCount = 0
|
activeDownloadCount = 0
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
|
||||||
private var restore : Preference? = null
|
private var restore : Preference? = null
|
||||||
|
|
||||||
private var updateUtil: UpdateUtil? = null
|
private var updateUtil: UpdateUtil? = null
|
||||||
private var fileUtil: FileUtil? = null
|
|
||||||
private var activeDownloadCount = 0
|
private var activeDownloadCount = 0
|
||||||
|
|
||||||
private lateinit var resultViewModel: ResultViewModel
|
private lateinit var resultViewModel: ResultViewModel
|
||||||
|
|
@ -105,7 +104,6 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
|
||||||
|
|
||||||
//about section -------------------------
|
//about section -------------------------
|
||||||
updateUtil = UpdateUtil(requireContext())
|
updateUtil = UpdateUtil(requireContext())
|
||||||
fileUtil = FileUtil()
|
|
||||||
|
|
||||||
WorkManager.getInstance(requireContext()).getWorkInfosByTagLiveData("download").observe(this){
|
WorkManager.getInstance(requireContext()).getWorkInfosByTagLiveData("download").observe(this){
|
||||||
activeDownloadCount = 0
|
activeDownloadCount = 0
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.content.Context
|
||||||
import android.media.MediaScannerConnection
|
import android.media.MediaScannerConnection
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Environment
|
||||||
import android.provider.DocumentsContract
|
import android.provider.DocumentsContract
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
|
|
@ -21,7 +22,7 @@ import kotlin.math.log10
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
|
|
||||||
class FileUtil() {
|
object FileUtil {
|
||||||
fun deleteFile(path: String){
|
fun deleteFile(path: String){
|
||||||
val file = File(path)
|
val file = File(path)
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
|
|
@ -144,13 +145,26 @@ class FileUtil() {
|
||||||
|
|
||||||
fun getLogFile(context: Context, item: DownloadItem) : File {
|
fun getLogFile(context: Context, item: DownloadItem) : File {
|
||||||
val titleRegex = Regex("[^A-Za-z\\d ]")
|
val titleRegex = Regex("[^A-Za-z\\d ]")
|
||||||
return File(context.filesDir.absolutePath + """/logs/${item.id} - ${titleRegex.replace(item.title, "").take(150)}##${item.type}##${item.format.format_id}.log""")
|
val title = item.title.ifEmpty { item.url }
|
||||||
|
return File(context.filesDir.absolutePath + """/logs/${item.id} - ${titleRegex.replace(title, "").take(150)}##${item.type}##${item.format.format_id}.log""")
|
||||||
}
|
}
|
||||||
fun getLogFileForTerminal(context: Context, command: String) : File {
|
fun getLogFileForTerminal(context: Context, command: String) : File {
|
||||||
val titleRegex = Regex("[^A-Za-z\\d ]")
|
val titleRegex = Regex("[^A-Za-z\\d ]")
|
||||||
return File(context.filesDir.absolutePath + """/logs/Terminal - ${titleRegex.replace(command.take(30), "")}##terminal.log""")
|
return File(context.filesDir.absolutePath + """/logs/Terminal - ${titleRegex.replace(command.take(30), "")}##terminal.log""")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getDefautAudioPath() : String{
|
||||||
|
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath + File.separator + "YTDLnis/Audio"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDefautVideoPath() : String{
|
||||||
|
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath + File.separator + "YTDLnis/Video"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDefaultCommandPath() : String {
|
||||||
|
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath + File.separator + "YTDLnis/Command"
|
||||||
|
}
|
||||||
|
|
||||||
fun convertFileSize(s: Long): String{
|
fun convertFileSize(s: Long): String{
|
||||||
if (s <= 0) return "?"
|
if (s <= 0) return "?"
|
||||||
val units = arrayOf("B", "kB", "MB", "GB", "TB")
|
val units = arrayOf("B", "kB", "MB", "GB", "TB")
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,11 @@ import android.widget.Toast
|
||||||
import androidx.core.text.HtmlCompat
|
import androidx.core.text.HtmlCompat
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.database.models.ChapterItem
|
||||||
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.models.ResultItem
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
import com.yausername.youtubedl_android.YoutubeDL
|
import com.yausername.youtubedl_android.YoutubeDL
|
||||||
import com.yausername.youtubedl_android.YoutubeDLRequest
|
import com.yausername.youtubedl_android.YoutubeDLRequest
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
|
|
@ -20,6 +22,7 @@ import org.json.JSONObject
|
||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
|
import java.lang.reflect.Type
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
@ -272,7 +275,9 @@ class InfoUtil(private val context: Context) {
|
||||||
thumb,
|
thumb,
|
||||||
"youtube",
|
"youtube",
|
||||||
"",
|
"",
|
||||||
ArrayList()
|
ArrayList(),
|
||||||
|
"",
|
||||||
|
ArrayList()
|
||||||
)
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, e.toString())
|
Log.e(TAG, e.toString())
|
||||||
|
|
@ -326,7 +331,9 @@ class InfoUtil(private val context: Context) {
|
||||||
thumb,
|
thumb,
|
||||||
"youtube",
|
"youtube",
|
||||||
"",
|
"",
|
||||||
formats
|
formats,
|
||||||
|
"",
|
||||||
|
ArrayList()
|
||||||
)
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, e.toString())
|
Log.e(TAG, e.toString())
|
||||||
|
|
@ -337,13 +344,8 @@ class InfoUtil(private val context: Context) {
|
||||||
private fun createVideoFromPipedJSON(obj: JSONObject, id: String): ResultItem? {
|
private fun createVideoFromPipedJSON(obj: JSONObject, id: String): ResultItem? {
|
||||||
var video: ResultItem? = null
|
var video: ResultItem? = null
|
||||||
try {
|
try {
|
||||||
val title = obj.getString("title").toString()
|
val title = Html.fromHtml(obj.getString("title").toString()).toString()
|
||||||
title.replace("'s", "'")
|
val author = Html.fromHtml(obj.getString("uploader").toString()).toString()
|
||||||
title.replace("&", "&")
|
|
||||||
val author = obj.getString("uploader").toString()
|
|
||||||
author.replace("'s", "'")
|
|
||||||
author.replace("&", "&")
|
|
||||||
|
|
||||||
if (author.isBlank()) throw Exception()
|
if (author.isBlank()) throw Exception()
|
||||||
|
|
||||||
val duration = formatIntegerDuration(obj.getInt("duration"), Locale.getDefault())
|
val duration = formatIntegerDuration(obj.getInt("duration"), Locale.getDefault())
|
||||||
|
|
@ -360,7 +362,6 @@ class InfoUtil(private val context: Context) {
|
||||||
formatObj.acodec = format.getString("codec")
|
formatObj.acodec = format.getString("codec")
|
||||||
val streamURL = format.getString("url")
|
val streamURL = format.getString("url")
|
||||||
formatObj.format_id = streamURL.substringAfter("itag=").substringBefore("&")
|
formatObj.format_id = streamURL.substringAfter("itag=").substringBefore("&")
|
||||||
formatObj.filesize = (format.getInt("bitrate") / 8 * obj.getInt("duration")).toLong()
|
|
||||||
formatObj.asr = format.getString("quality")
|
formatObj.asr = format.getString("quality")
|
||||||
if (! format.getString("audioTrackName").equals("null", ignoreCase = true)){
|
if (! format.getString("audioTrackName").equals("null", ignoreCase = true)){
|
||||||
formatObj.format_note = format.getString("audioTrackName") + " Audio, " + formatObj.format_note
|
formatObj.format_note = format.getString("audioTrackName") + " Audio, " + formatObj.format_note
|
||||||
|
|
@ -385,7 +386,6 @@ class InfoUtil(private val context: Context) {
|
||||||
formatObj.vcodec = format.getString("codec")
|
formatObj.vcodec = format.getString("codec")
|
||||||
val streamURL = format.getString("url")
|
val streamURL = format.getString("url")
|
||||||
formatObj.format_id = streamURL.substringAfter("itag=").substringBefore("&")
|
formatObj.format_id = streamURL.substringAfter("itag=").substringBefore("&")
|
||||||
formatObj.filesize = (format.getInt("bitrate") / 8 * obj.getInt("duration")).toLong()
|
|
||||||
}catch (e: Exception) {
|
}catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
@ -394,6 +394,17 @@ class InfoUtil(private val context: Context) {
|
||||||
}
|
}
|
||||||
formats.sortBy { it.filesize }
|
formats.sortBy { it.filesize }
|
||||||
|
|
||||||
|
val chapters = ArrayList<ChapterItem>()
|
||||||
|
if (obj.has("chapters") && obj.getJSONArray("chapters").length() > 0){
|
||||||
|
val chaptersJArray = obj.getJSONArray("chapters")
|
||||||
|
for (c in 0 until chaptersJArray.length()){
|
||||||
|
val chapter = chaptersJArray.getJSONObject(c)
|
||||||
|
val end = if (c == chaptersJArray.length() - 1) obj.getInt("duration") else chaptersJArray.getJSONObject(c+1).getInt("start")
|
||||||
|
val item = ChapterItem(chapter.getInt("start").toLong(), end.toLong(), chapter.getString("title"))
|
||||||
|
chapters.add(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
video = ResultItem(0,
|
video = ResultItem(0,
|
||||||
url,
|
url,
|
||||||
title,
|
title,
|
||||||
|
|
@ -402,7 +413,9 @@ class InfoUtil(private val context: Context) {
|
||||||
thumb,
|
thumb,
|
||||||
"youtube",
|
"youtube",
|
||||||
"",
|
"",
|
||||||
formats
|
formats,
|
||||||
|
if (obj.has("hls")) obj.getString("hls") else "",
|
||||||
|
chapters
|
||||||
)
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, e.toString())
|
Log.e(TAG, e.toString())
|
||||||
|
|
@ -567,7 +580,7 @@ class InfoUtil(private val context: Context) {
|
||||||
return query!!
|
return query!!
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFormats(url: String) : ResultItem {
|
fun getFormats(url: String) : List<Format> {
|
||||||
init()
|
init()
|
||||||
val p = Pattern.compile("^(https?)://(www.)?youtu(.be)?")
|
val p = Pattern.compile("^(https?)://(www.)?youtu(.be)?")
|
||||||
val m = p.matcher(url)
|
val m = p.matcher(url)
|
||||||
|
|
@ -576,14 +589,70 @@ class InfoUtil(private val context: Context) {
|
||||||
val id = getIDFromYoutubeURL(url)
|
val id = getIDFromYoutubeURL(url)
|
||||||
val res = genericRequest(pipedURL + "streams/" + id)
|
val res = genericRequest(pipedURL + "streams/" + id)
|
||||||
if (res.length() == 0) getFromYTDL(url)[0]!!
|
if (res.length() == 0) getFromYTDL(url)[0]!!
|
||||||
else createVideoFromPipedJSON(
|
val item = createVideoFromPipedJSON(res, id)
|
||||||
res, id
|
item!!.formats
|
||||||
)!!
|
|
||||||
}else{
|
}else{
|
||||||
getFromYTDL(url)[0]!!
|
getFormatsFromYTDL(url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getFormatsFromYTDL(url: String) : List<Format> {
|
||||||
|
try {
|
||||||
|
val request = YoutubeDLRequest(url)
|
||||||
|
request.addOption("--print", "%(formats)s")
|
||||||
|
request.addOption("--skip-download")
|
||||||
|
request.addOption("-R", "1")
|
||||||
|
request.addOption("--socket-timeout", "5")
|
||||||
|
val cookiesFile = File(context.cacheDir, "cookies.txt")
|
||||||
|
if (cookiesFile.exists()){
|
||||||
|
request.addOption("--cookies", cookiesFile.absolutePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
val proxy = sharedPreferences.getString("proxy", "")
|
||||||
|
if (proxy!!.isNotBlank()){
|
||||||
|
request.addOption("--proxy", proxy)
|
||||||
|
}
|
||||||
|
|
||||||
|
val res = YoutubeDL.getInstance().execute(request)
|
||||||
|
val results: Array<String?> = try {
|
||||||
|
val lineSeparator = System.getProperty("line.separator")
|
||||||
|
res.out.split(lineSeparator!!).toTypedArray()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
arrayOf(res.out)
|
||||||
|
}
|
||||||
|
val json = results[0]
|
||||||
|
val jsonArray = JSONArray(json)
|
||||||
|
|
||||||
|
val formats : ArrayList<Format> = ArrayList()
|
||||||
|
for (f in 0 until jsonArray.length()){
|
||||||
|
val format = jsonArray.getJSONObject(f)
|
||||||
|
if (format.has("filesize") && format.get("filesize") == "None"){
|
||||||
|
format.remove("filesize")
|
||||||
|
format.put("filesize", 0)
|
||||||
|
}
|
||||||
|
val formatProper = Gson().fromJson(format.toString(), Format::class.java)
|
||||||
|
if (format.has("format_note")){
|
||||||
|
if (!formatProper!!.format_note.contains("audio only", true)) {
|
||||||
|
formatProper.format_note = format.getString("format_note")
|
||||||
|
}else{
|
||||||
|
formatProper.format_note = "${format.getString("format_note")} audio"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (formatProper!!.format_note == "storyboard") continue
|
||||||
|
formatProper.container = format.getString("ext")
|
||||||
|
formats.add(formatProper)
|
||||||
|
}
|
||||||
|
|
||||||
|
return formats
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Looper.prepare().run {
|
||||||
|
Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
fun getFormatsMultiple(urls: List<String>, progress: (progress: List<Format>) -> Unit){
|
fun getFormatsMultiple(urls: List<String>, progress: (progress: List<Format>) -> Unit){
|
||||||
init()
|
init()
|
||||||
val urlsFile = File(context.cacheDir, "urls.txt")
|
val urlsFile = File(context.cacheDir, "urls.txt")
|
||||||
|
|
@ -623,16 +692,19 @@ class InfoUtil(private val context: Context) {
|
||||||
try{
|
try{
|
||||||
if (format.getString("filesize") == "None") continue
|
if (format.getString("filesize") == "None") continue
|
||||||
}catch (e: Exception) { continue }
|
}catch (e: Exception) { continue }
|
||||||
val formatProper = Gson().fromJson(format.toString(), Format::class.java)
|
if (format.has("filesize") && format.get("filesize") == "None"){
|
||||||
if (formatProper.filesize > 0){
|
format.remove("filesize")
|
||||||
if ( !formatProper!!.format_note!!.contains("audio only", true)) {
|
format.put("filesize", 0)
|
||||||
formatProper.format_note = format.getString("format_note")
|
|
||||||
}else{
|
|
||||||
formatProper.format_note = "${format.getString("format_note")} audio"
|
|
||||||
}
|
|
||||||
formatProper.container = format.getString("ext")
|
|
||||||
formats.add(formatProper)
|
|
||||||
}
|
}
|
||||||
|
val formatProper = Gson().fromJson(format.toString(), Format::class.java)
|
||||||
|
if ( !formatProper!!.format_note.contains("audio only", true)) {
|
||||||
|
formatProper.format_note = format.getString("format_note")
|
||||||
|
}else{
|
||||||
|
formatProper.format_note = "${format.getString("format_note")} audio"
|
||||||
|
}
|
||||||
|
if (formatProper.format_note == "storyboard") continue
|
||||||
|
formatProper.container = format.getString("ext")
|
||||||
|
formats.add(formatProper)
|
||||||
}
|
}
|
||||||
progress(formats)
|
progress(formats)
|
||||||
}catch (e: Exception){
|
}catch (e: Exception){
|
||||||
|
|
@ -725,20 +797,28 @@ class InfoUtil(private val context: Context) {
|
||||||
if (formatsInJSON != null) {
|
if (formatsInJSON != null) {
|
||||||
for (f in 0 until formatsInJSON.length()){
|
for (f in 0 until formatsInJSON.length()){
|
||||||
val format = formatsInJSON.getJSONObject(f)
|
val format = formatsInJSON.getJSONObject(f)
|
||||||
val formatProper = Gson().fromJson(format.toString(), Format::class.java)
|
if (format.has("filesize") && format.get("filesize") == "None"){
|
||||||
if (formatProper.filesize > 0){
|
format.remove("filesize")
|
||||||
if (format.has("format_note") && formatProper.format_note != null){
|
format.put("filesize", 0)
|
||||||
if (!formatProper!!.format_note.contains("audio only", true)) {
|
|
||||||
formatProper.format_note = format.getString("format_note")
|
|
||||||
}else{
|
|
||||||
formatProper.format_note = "${format.getString("format_note")} audio"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
formatProper.container = format.getString("ext")
|
|
||||||
formats.add(formatProper)
|
|
||||||
}
|
}
|
||||||
|
val formatProper = Gson().fromJson(format.toString(), Format::class.java)
|
||||||
|
if (format.has("format_note") && formatProper.format_note != null){
|
||||||
|
if (!formatProper!!.format_note.contains("audio only", true)) {
|
||||||
|
formatProper.format_note = format.getString("format_note")
|
||||||
|
}else{
|
||||||
|
formatProper.format_note = "${format.getString("format_note")} audio"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (formatProper.format_note == "storyboard") continue
|
||||||
|
formatProper.container = format.getString("ext")
|
||||||
|
formats.add(formatProper)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val chaptersInJSON = if (jsonObject.has("formats") && jsonObject.get("formats") is JSONArray) jsonObject.getJSONArray("formats") else null
|
||||||
|
val listType: Type = object : TypeToken<List<ChapterItem>>() {}.type
|
||||||
|
val chapters : ArrayList<ChapterItem> = Gson().fromJson(chaptersInJSON?.toString(), listType)
|
||||||
|
|
||||||
Log.e("aa", formats.toString())
|
Log.e("aa", formats.toString())
|
||||||
items.add(ResultItem(0,
|
items.add(ResultItem(0,
|
||||||
url,
|
url,
|
||||||
|
|
@ -748,7 +828,9 @@ class InfoUtil(private val context: Context) {
|
||||||
thumb!!,
|
thumb!!,
|
||||||
website,
|
website,
|
||||||
playlistTitle!!,
|
playlistTitle!!,
|
||||||
formats
|
formats,
|
||||||
|
jsonObject.getString("urls") ?: "",
|
||||||
|
chapters
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -821,6 +903,8 @@ class InfoUtil(private val context: Context) {
|
||||||
jsonObject.getString("extractor"),
|
jsonObject.getString("extractor"),
|
||||||
if (isPlaylist) jsonObject.getString("title") else "",
|
if (isPlaylist) jsonObject.getString("title") else "",
|
||||||
arrayListOf(),
|
arrayListOf(),
|
||||||
|
"",
|
||||||
|
arrayListOf(),
|
||||||
System.currentTimeMillis()
|
System.currentTimeMillis()
|
||||||
)
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|
@ -945,7 +1029,7 @@ class InfoUtil(private val context: Context) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "API MANAGER"
|
private const val TAG = "API MANAGER"
|
||||||
private const val invidousURL = "https://invidious.nerdvpn.de/api/v1/"
|
private const val invidousURL = "https://invidious.baczek.me/api/v1/"
|
||||||
private const val pipedURL = "https://pipedapi.kavin.rocks/"
|
private const val pipedURL = "https://pipedapi.kavin.rocks/"
|
||||||
private var countryCODE: String = ""
|
private var countryCODE: String = ""
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ import kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
|
|
||||||
class UiUtil(private val fileUtil: FileUtil) {
|
class UiUtil() {
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun populateFormatCard(formatCard : MaterialCardView, chosenFormat: Format, audioFormats: List<Format>?){
|
fun populateFormatCard(formatCard : MaterialCardView, chosenFormat: Format, audioFormats: List<Format>?){
|
||||||
formatCard.findViewById<TextView>(R.id.container).text = chosenFormat.container.uppercase()
|
formatCard.findViewById<TextView>(R.id.container).text = chosenFormat.container.uppercase()
|
||||||
|
|
@ -79,7 +79,7 @@ class UiUtil(private val fileUtil: FileUtil) {
|
||||||
}
|
}
|
||||||
var filesize = chosenFormat.filesize
|
var filesize = chosenFormat.filesize
|
||||||
if (!audioFormats.isNullOrEmpty()) filesize += audioFormats.sumOf { it.filesize }
|
if (!audioFormats.isNullOrEmpty()) filesize += audioFormats.sumOf { it.filesize }
|
||||||
formatCard.findViewById<TextView>(R.id.file_size).text = fileUtil.convertFileSize(filesize)
|
formatCard.findViewById<TextView>(R.id.file_size).text = FileUtil.convertFileSize(filesize)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,7 +139,7 @@ class UiUtil(private val fileUtil: FileUtil) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
commandTemplateViewModel.shortcuts.observe(lifeCycle){ it ->
|
commandTemplateViewModel.shortcuts.observe(lifeCycle){
|
||||||
shortcutsChipGroup.removeAllViews()
|
shortcutsChipGroup.removeAllViews()
|
||||||
it.forEach {shortcut ->
|
it.forEach {shortcut ->
|
||||||
val chip = context.layoutInflater.inflate(R.layout.suggestion_chip, shortcutsChipGroup, false) as Chip
|
val chip = context.layoutInflater.inflate(R.layout.suggestion_chip, shortcutsChipGroup, false) as Chip
|
||||||
|
|
@ -200,7 +200,7 @@ class UiUtil(private val fileUtil: FileUtil) {
|
||||||
title.isEndIconVisible = false
|
title.isEndIconVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
commandTemplateViewModel.shortcuts.observe(lifeCycle){ it ->
|
commandTemplateViewModel.shortcuts.observe(lifeCycle){
|
||||||
shortcutsChipGroup.removeAllViews()
|
shortcutsChipGroup.removeAllViews()
|
||||||
it.forEach {shortcut ->
|
it.forEach {shortcut ->
|
||||||
val chip = context.layoutInflater.inflate(R.layout.input_chip, shortcutsChipGroup, false) as Chip
|
val chip = context.layoutInflater.inflate(R.layout.input_chip, shortcutsChipGroup, false) as Chip
|
||||||
|
|
@ -324,6 +324,7 @@ class UiUtil(private val fileUtil: FileUtil) {
|
||||||
bottomSheet.setContentView(R.layout.format_details_sheet)
|
bottomSheet.setContentView(R.layout.format_details_sheet)
|
||||||
|
|
||||||
val formatIdParent = bottomSheet.findViewById<LinearLayout>(R.id.format_id_parent)
|
val formatIdParent = bottomSheet.findViewById<LinearLayout>(R.id.format_id_parent)
|
||||||
|
val formatURLParent = bottomSheet.findViewById<LinearLayout>(R.id.format_url_parent)
|
||||||
val containerParent = bottomSheet.findViewById<LinearLayout>(R.id.container_parent)
|
val containerParent = bottomSheet.findViewById<LinearLayout>(R.id.container_parent)
|
||||||
val codecParent = bottomSheet.findViewById<LinearLayout>(R.id.codec_parent)
|
val codecParent = bottomSheet.findViewById<LinearLayout>(R.id.codec_parent)
|
||||||
val filesizeParent = bottomSheet.findViewById<LinearLayout>(R.id.filesize_parent)
|
val filesizeParent = bottomSheet.findViewById<LinearLayout>(R.id.filesize_parent)
|
||||||
|
|
@ -339,6 +340,14 @@ class UiUtil(private val fileUtil: FileUtil) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (format.url.isNullOrBlank()) formatURLParent?.visibility = View.GONE
|
||||||
|
else {
|
||||||
|
formatURLParent?.findViewById<TextView>(R.id.format_url_value)?.text = format.url
|
||||||
|
formatURLParent?.setOnClickListener {
|
||||||
|
copyToClipboard(format.url!!, activity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (format.container.isBlank()) containerParent?.visibility = View.GONE
|
if (format.container.isBlank()) containerParent?.visibility = View.GONE
|
||||||
else {
|
else {
|
||||||
|
|
@ -367,9 +376,9 @@ class UiUtil(private val fileUtil: FileUtil) {
|
||||||
|
|
||||||
if (format.filesize != 0L) filesizeParent?.visibility = View.GONE
|
if (format.filesize != 0L) filesizeParent?.visibility = View.GONE
|
||||||
else {
|
else {
|
||||||
filesizeParent?.findViewById<TextView>(R.id.filesize_value)?.text = fileUtil.convertFileSize(format.filesize)
|
filesizeParent?.findViewById<TextView>(R.id.filesize_value)?.text = FileUtil.convertFileSize(format.filesize)
|
||||||
filesizeParent?.setOnClickListener {
|
filesizeParent?.setOnClickListener {
|
||||||
copyToClipboard(fileUtil.convertFileSize(format.filesize), activity)
|
copyToClipboard(FileUtil.convertFileSize(format.filesize), activity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,6 @@ class DownloadWorker(
|
||||||
if (itemId == 0L) return Result.failure()
|
if (itemId == 0L) return Result.failure()
|
||||||
|
|
||||||
val notificationUtil = NotificationUtil(context)
|
val notificationUtil = NotificationUtil(context)
|
||||||
val fileUtil = FileUtil()
|
|
||||||
val infoUtil = InfoUtil(context)
|
val infoUtil = InfoUtil(context)
|
||||||
val dbManager = DBManager.getInstance(context)
|
val dbManager = DBManager.getInstance(context)
|
||||||
val dao = dbManager.downloadDao
|
val dao = dbManager.downloadDao
|
||||||
|
|
@ -68,13 +67,9 @@ class DownloadWorker(
|
||||||
}
|
}
|
||||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
if (sharedPreferences.getBoolean("log_downloads", false)){
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
updateDownloadItem(downloadItem, infoUtil, dao, resultDao, true, notificationUtil)
|
//update item if its incomplete
|
||||||
}else{
|
updateDownloadItem(downloadItem, infoUtil, dao, resultDao, false, notificationUtil)
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
|
||||||
//update item if its incomplete
|
|
||||||
updateDownloadItem(downloadItem, infoUtil, dao, resultDao, false, notificationUtil)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val intent = Intent(context, MainActivity::class.java)
|
val intent = Intent(context, MainActivity::class.java)
|
||||||
|
|
@ -174,13 +169,13 @@ class DownloadWorker(
|
||||||
if (audioQualityId.isBlank() || audioQualityId == "0" || audioQualityId == context.getString(R.string.best_quality) || audioQualityId == "best") audioQualityId = ""
|
if (audioQualityId.isBlank() || audioQualityId == "0" || audioQualityId == context.getString(R.string.best_quality) || audioQualityId == "best") audioQualityId = ""
|
||||||
else if (audioQualityId == context.getString(R.string.worst_quality) || audioQualityId == "worst") audioQualityId = "worstaudio"
|
else if (audioQualityId == context.getString(R.string.worst_quality) || audioQualityId == "worst") audioQualityId = "worstaudio"
|
||||||
|
|
||||||
val ext = downloadItem.format.container
|
val ext = downloadItem.container
|
||||||
if (audioQualityId.isNotBlank()) request.addOption("-f", audioQualityId)
|
if (audioQualityId.isNotBlank()) request.addOption("-f", audioQualityId)
|
||||||
request.addOption("-x")
|
request.addOption("-x")
|
||||||
|
|
||||||
if(ext.isNotBlank()){
|
if(ext.isNotBlank()){
|
||||||
if(!ext.matches("(webm)|(Default)|(${context.getString(R.string.defaultValue)})".toRegex())){
|
if(!ext.matches("(webm)|(Default)|(${context.getString(R.string.defaultValue)})".toRegex())){
|
||||||
request.addOption("--audio-format", downloadItem.format.container)
|
request.addOption("--audio-format", ext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -246,10 +241,10 @@ class DownloadWorker(
|
||||||
}
|
}
|
||||||
Log.e(TAG, formatArgument)
|
Log.e(TAG, formatArgument)
|
||||||
request.addOption("-f", formatArgument)
|
request.addOption("-f", formatArgument)
|
||||||
val format = downloadItem.format.container
|
val outputFormat = downloadItem.container
|
||||||
if(format.isNotEmpty() && format != "Default" && format != context.getString(R.string.defaultValue)){
|
if(outputFormat.isNotEmpty() && outputFormat != "Default" && outputFormat != context.getString(R.string.defaultValue)){
|
||||||
request.addOption("--merge-output-format", format.lowercase())
|
request.addOption("--merge-output-format", outputFormat.lowercase())
|
||||||
if (format != "webm") {
|
if (outputFormat != "webm") {
|
||||||
val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false)
|
val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false)
|
||||||
if (embedThumb) {
|
if (embedThumb) {
|
||||||
request.addOption("--embed-thumbnail")
|
request.addOption("--embed-thumbnail")
|
||||||
|
|
@ -293,7 +288,7 @@ class DownloadWorker(
|
||||||
|
|
||||||
val logDownloads = sharedPreferences.getBoolean("log_downloads", false) && !sharedPreferences.getBoolean("incognito", false)
|
val logDownloads = sharedPreferences.getBoolean("log_downloads", false) && !sharedPreferences.getBoolean("incognito", false)
|
||||||
val logFolder = File(context.filesDir.absolutePath + "/logs")
|
val logFolder = File(context.filesDir.absolutePath + "/logs")
|
||||||
val logFile = fileUtil.getLogFile(context, downloadItem)
|
val logFile = FileUtil.getLogFile(context, downloadItem)
|
||||||
|
|
||||||
if (logDownloads){
|
if (logDownloads){
|
||||||
logFolder.mkdirs()
|
logFolder.mkdirs()
|
||||||
|
|
@ -320,11 +315,11 @@ class DownloadWorker(
|
||||||
}
|
}
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
//move file from internal to set download directory
|
//move file from internal to set download directory
|
||||||
setProgressAsync(workDataOf("progress" to 100, "output" to "Moving file to ${fileUtil.formatPath(downloadLocation)}", "id" to downloadItem.id, "log" to logDownloads))
|
setProgressAsync(workDataOf("progress" to 100, "output" to "Moving file to ${FileUtil.formatPath(downloadLocation)}", "id" to downloadItem.id, "log" to logDownloads))
|
||||||
var finalPath : String?
|
var finalPath : String?
|
||||||
try {
|
try {
|
||||||
finalPath = fileUtil.moveFile(tempFileDir.absoluteFile,context, downloadLocation, keepCache){ p ->
|
finalPath = FileUtil.moveFile(tempFileDir.absoluteFile,context, downloadLocation, keepCache){ p ->
|
||||||
setProgressAsync(workDataOf("progress" to p, "output" to "Moving file to ${fileUtil.formatPath(downloadLocation)}", "id" to downloadItem.id, "log" to logDownloads))
|
setProgressAsync(workDataOf("progress" to p, "output" to "Moving file to ${FileUtil.formatPath(downloadLocation)}", "id" to downloadItem.id, "log" to logDownloads))
|
||||||
}
|
}
|
||||||
setProgressAsync(workDataOf("progress" to 100, "output" to "Moved file to $finalPath", "id" to downloadItem.id, "log" to logDownloads))
|
setProgressAsync(workDataOf("progress" to 100, "output" to "Moved file to $finalPath", "id" to downloadItem.id, "log" to logDownloads))
|
||||||
}catch (e: Exception){
|
}catch (e: Exception){
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ class TerminalDownloadWorker(
|
||||||
if (command!!.isEmpty()) return Result.failure()
|
if (command!!.isEmpty()) return Result.failure()
|
||||||
|
|
||||||
val notificationUtil = NotificationUtil(context)
|
val notificationUtil = NotificationUtil(context)
|
||||||
val fileUtil = FileUtil()
|
|
||||||
val handler = Handler(Looper.getMainLooper())
|
val handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
val intent = Intent(context, MainActivity::class.java)
|
val intent = Intent(context, MainActivity::class.java)
|
||||||
|
|
@ -68,7 +67,7 @@ class TerminalDownloadWorker(
|
||||||
|
|
||||||
val logDownloads = sharedPreferences.getBoolean("log_downloads", false) && !sharedPreferences.getBoolean("incognito", false)
|
val logDownloads = sharedPreferences.getBoolean("log_downloads", false) && !sharedPreferences.getBoolean("incognito", false)
|
||||||
val logFolder = File(context.filesDir.absolutePath + "/logs")
|
val logFolder = File(context.filesDir.absolutePath + "/logs")
|
||||||
val logFile = fileUtil.getLogFileForTerminal(context, command)
|
val logFile = FileUtil.getLogFileForTerminal(context, command)
|
||||||
|
|
||||||
runCatching {
|
runCatching {
|
||||||
if (logDownloads){
|
if (logDownloads){
|
||||||
|
|
@ -94,7 +93,7 @@ class TerminalDownloadWorker(
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
//move file from internal to set download directory
|
//move file from internal to set download directory
|
||||||
try {
|
try {
|
||||||
fileUtil.moveFile(tempFileDir.absoluteFile,context, downloadLocation!!, false){ p ->
|
FileUtil.moveFile(tempFileDir.absoluteFile,context, downloadLocation!!, false){ p ->
|
||||||
setProgressAsync(workDataOf("progress" to p))
|
setProgressAsync(workDataOf("progress" to p))
|
||||||
}
|
}
|
||||||
}catch (e: Exception){
|
}catch (e: Exception){
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
|
||||||
android:fitsSystemWindows="true"
|
android:fitsSystemWindows="true"
|
||||||
tools:context="com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity">
|
tools:context="com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity">
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,217 +1,254 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout android:layout_width="match_parent"
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:orientation="vertical"
|
android:layout_height="wrap_content">
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<TextView
|
<LinearLayout android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:text="@string/format"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:layout_margin="20dp"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/format_id_parent"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
android:orientation="vertical">
|
||||||
android:paddingHorizontal="10dp"
|
|
||||||
android:weightSum="100"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:orientation="horizontal" >
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_weight="50"
|
android:text="@string/format"
|
||||||
android:text="@string/format_id"
|
android:textSize="12sp"
|
||||||
android:textSize="18sp"
|
android:layout_margin="20dp"
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:id="@+id/format_id_value"
|
android:id="@+id/format_id_parent"
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_weight="50"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="18sp"
|
android:gravity="center"
|
||||||
android:layout_margin="10dp"
|
android:paddingHorizontal="10dp"
|
||||||
android:gravity="end"
|
android:weightSum="100"
|
||||||
android:layout_height="wrap_content"/>
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:text="@string/format_id"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/format_id_value"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:gravity="end"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/format_url_parent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
|
android:weightSum="100"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:text="@string/url"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/format_url_value"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:gravity="end"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/container_parent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:weightSum="100"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:text="@string/container"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/container_value"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:gravity="end"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/codec_parent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:weightSum="100"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:text="@string/codec"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/codec_value"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:gravity="end"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/filesize_parent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:weightSum="100"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:text="@string/file_size"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/filesize_value"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:gravity="end"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/format_note_parent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:weightSum="100"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:text="@string/quality"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/format_note_value"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:gravity="end"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/fps_parent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:weightSum="100"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:text="FPS"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/fps_value"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:gravity="end"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/asr_parent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:weightSum="100"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:text="@string/audio_samplerate"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/asr_value"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="50"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:gravity="end"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
</ScrollView>
|
||||||
android:id="@+id/container_parent"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:weightSum="100"
|
|
||||||
android:paddingHorizontal="10dp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:orientation="horizontal" >
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="50"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:text="@string/container"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/container_value"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="50"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:gravity="end"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/codec_parent"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:weightSum="100"
|
|
||||||
android:paddingHorizontal="10dp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:orientation="horizontal" >
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="50"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:text="@string/codec"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/codec_value"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="50"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:gravity="end"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/filesize_parent"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:weightSum="100"
|
|
||||||
android:paddingHorizontal="10dp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:orientation="horizontal" >
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="50"
|
|
||||||
android:text="@string/file_size"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/filesize_value"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="50"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:gravity="end"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/format_note_parent"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:weightSum="100"
|
|
||||||
android:paddingHorizontal="10dp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:orientation="horizontal" >
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:text="@string/quality"
|
|
||||||
android:layout_weight="50"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/format_note_value"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="50"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:gravity="end"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/fps_parent"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:weightSum="100"
|
|
||||||
android:paddingHorizontal="10dp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:orientation="horizontal" >
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="50"
|
|
||||||
android:text="FPS"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/fps_value"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="50"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:gravity="end"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/asr_parent"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:weightSum="100"
|
|
||||||
android:paddingHorizontal="10dp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:orientation="horizontal" >
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="50"
|
|
||||||
android:text="@string/audio_samplerate"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/asr_value"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="50"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:gravity="end"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
@ -271,4 +271,6 @@
|
||||||
<string name="swipe_gestures_summary">Swipe items for certain actions</string>
|
<string name="swipe_gestures_summary">Swipe items for certain actions</string>
|
||||||
<string name="crop_thumb">Crop Thumbnail</string>
|
<string name="crop_thumb">Crop Thumbnail</string>
|
||||||
<string name="crop_thumb_summary">Crop the thumbnail into a square for audio downloads</string>
|
<string name="crop_thumb_summary">Crop the thumbnail into a square for audio downloads</string>
|
||||||
|
<string name="locale">Locale</string>
|
||||||
|
<string name="audio_only_item">This item only contains audio formats</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -5,19 +5,16 @@
|
||||||
<Preference
|
<Preference
|
||||||
app:icon="@drawable/ic_music_downloaded"
|
app:icon="@drawable/ic_music_downloaded"
|
||||||
app:key="music_path"
|
app:key="music_path"
|
||||||
app:defaultValue="@string/music_path"
|
|
||||||
app:title="@string/music_directory" />
|
app:title="@string/music_directory" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
app:icon="@drawable/ic_video_downloaded"
|
app:icon="@drawable/ic_video_downloaded"
|
||||||
app:key="video_path"
|
app:key="video_path"
|
||||||
app:defaultValue="@string/video_path"
|
|
||||||
app:title="@string/video_directory" />
|
app:title="@string/video_directory" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
app:icon="@drawable/ic_terminal"
|
app:icon="@drawable/ic_terminal"
|
||||||
app:key="command_path"
|
app:key="command_path"
|
||||||
app:defaultValue="@string/command_path"
|
|
||||||
app:title="@string/command_directory" />
|
app:title="@string/command_directory" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<PreferenceCategory android:title="Locale">
|
<PreferenceCategory android:title="@string/locale">
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:entries="@array/language_values"
|
android:entries="@array/language_values"
|
||||||
android:entryValues="@array/language_values"
|
android:entryValues="@array/language_values"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue