stuff
- added hungarian - added serbian - added ability to enable/disable swipe gestures on any screen - added ability to choose whether extra command applies to audio video or both - hide search providers if the user has typed out an url in the searchview
This commit is contained in:
parent
715120dd59
commit
17d6a87e49
54 changed files with 1304 additions and 389 deletions
572
app/schemas/com.deniscerri.ytdlnis.database.DBManager/12.json
Normal file
572
app/schemas/com.deniscerri.ytdlnis.database.DBManager/12.json
Normal file
|
|
@ -0,0 +1,572 @@
|
|||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 12,
|
||||
"identityHash": "d56ec0fdb461aabd551c64b826f0f8ea",
|
||||
"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, `command` TEXT NOT NULL DEFAULT '')",
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"fieldPath": "command",
|
||||
"columnName": "command",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true,
|
||||
"defaultValue": "''"
|
||||
}
|
||||
],
|
||||
"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, `extraCommands` TEXT NOT NULL DEFAULT '', `customFileNameTemplate` TEXT NOT NULL, `SaveThumb` INTEGER NOT NULL, `status` TEXT NOT NULL DEFAULT 'Queued', `downloadStartTime` INTEGER NOT NULL DEFAULT 0, `logID` INTEGER)",
|
||||
"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": "extraCommands",
|
||||
"columnName": "extraCommands",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true,
|
||||
"defaultValue": "''"
|
||||
},
|
||||
{
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"fieldPath": "logID",
|
||||
"columnName": "logID",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"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, `useAsExtraCommand` INTEGER NOT NULL DEFAULT 0, `useAsExtraCommandAudio` INTEGER NOT NULL DEFAULT 1, `useAsExtraCommandVideo` INTEGER NOT NULL DEFAULT 1)",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"fieldPath": "useAsExtraCommand",
|
||||
"columnName": "useAsExtraCommand",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "0"
|
||||
},
|
||||
{
|
||||
"fieldPath": "useAsExtraCommandAudio",
|
||||
"columnName": "useAsExtraCommandAudio",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "1"
|
||||
},
|
||||
{
|
||||
"fieldPath": "useAsExtraCommandVideo",
|
||||
"columnName": "useAsExtraCommandVideo",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "1"
|
||||
}
|
||||
],
|
||||
"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": []
|
||||
},
|
||||
{
|
||||
"tableName": "logs",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `format` TEXT NOT NULL, `downloadType` TEXT NOT NULL, `downloadTime` INTEGER 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
|
||||
},
|
||||
{
|
||||
"fieldPath": "format",
|
||||
"columnName": "format",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "downloadType",
|
||||
"columnName": "downloadType",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "downloadTime",
|
||||
"columnName": "downloadTime",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"autoGenerate": true,
|
||||
"columnNames": [
|
||||
"id"
|
||||
]
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "terminalDownloads",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `command` TEXT NOT NULL, `log` TEXT DEFAULT '')",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "command",
|
||||
"columnName": "command",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "log",
|
||||
"columnName": "log",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false,
|
||||
"defaultValue": "''"
|
||||
}
|
||||
],
|
||||
"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, 'd56ec0fdb461aabd551c64b826f0f8ea')"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -59,6 +59,7 @@ import kotlinx.coroutines.CoroutineScope
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.io.BufferedReader
|
||||
|
|
@ -146,14 +147,16 @@ class MainActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
val activeDownloadsBadge = (navigationView as NavigationBarView).getOrCreateBadge(R.id.historyFragment)
|
||||
downloadViewModel.activeDownloadsCount.observe(this){
|
||||
if (it == 0) {
|
||||
activeDownloadsBadge.isVisible = false
|
||||
activeDownloadsBadge.clearNumber()
|
||||
}
|
||||
else {
|
||||
activeDownloadsBadge.isVisible = true
|
||||
activeDownloadsBadge.number = it
|
||||
lifecycleScope.launch {
|
||||
downloadViewModel.activeDownloadsCount.collectLatest {
|
||||
if (it == 0) {
|
||||
activeDownloadsBadge.isVisible = false
|
||||
activeDownloadsBadge.clearNumber()
|
||||
}
|
||||
else {
|
||||
activeDownloadsBadge.isVisible = true
|
||||
activeDownloadsBadge.number = it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@ package com.deniscerri.ytdlnis.database
|
|||
|
||||
import android.content.Context
|
||||
import androidx.room.*
|
||||
import androidx.room.migration.AutoMigrationSpec
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import androidx.work.impl.Migration_11_12
|
||||
import androidx.work.impl.Migration_12_13
|
||||
import com.deniscerri.ytdlnis.database.dao.*
|
||||
import com.deniscerri.ytdlnis.database.models.*
|
||||
|
||||
|
|
@ -18,7 +23,7 @@ import com.deniscerri.ytdlnis.database.models.*
|
|||
LogItem::class,
|
||||
TerminalItem::class
|
||||
],
|
||||
version = 11,
|
||||
version = 12,
|
||||
autoMigrations = [
|
||||
AutoMigration (from = 1, to = 2),
|
||||
AutoMigration (from = 2, to = 3),
|
||||
|
|
@ -29,7 +34,8 @@ import com.deniscerri.ytdlnis.database.models.*
|
|||
AutoMigration (from = 7, to = 8),
|
||||
AutoMigration (from = 8, to = 9),
|
||||
AutoMigration (from = 9, to = 10),
|
||||
AutoMigration (from = 10, to = 11)
|
||||
AutoMigration (from = 10, to = 11),
|
||||
AutoMigration (from = 11, to = 12)
|
||||
]
|
||||
)
|
||||
abstract class DBManager : RoomDatabase(){
|
||||
|
|
@ -53,15 +59,18 @@ abstract class DBManager : RoomDatabase(){
|
|||
//if its not null return it, otherwise create db
|
||||
fun getInstance(context: Context) : DBManager {
|
||||
return instance ?: synchronized(this){
|
||||
|
||||
val dbInstance = Room.databaseBuilder(
|
||||
context.applicationContext,
|
||||
DBManager::class.java,
|
||||
"YTDLnisDatabase"
|
||||
)
|
||||
.build()
|
||||
.build()
|
||||
instance = dbInstance
|
||||
dbInstance
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -34,6 +34,12 @@ interface CommandTemplateDao {
|
|||
@Query("SELECT content FROM commandTemplates WHERE useAsExtraCommand is 1")
|
||||
fun getAllTemplatesAsExtraCommands() : List<String>
|
||||
|
||||
@Query("SELECT content FROM commandTemplates WHERE useAsExtraCommand is 1 AND useAsExtraCommandAudio = 1")
|
||||
fun getAllTemplatesAsExtraCommandsForAudio() : List<String>
|
||||
|
||||
@Query("SELECT content FROM commandTemplates WHERE useAsExtraCommand is 1 AND useAsExtraCommandVideo = 1")
|
||||
fun getAllTemplatesAsExtraCommandsForVideo() : List<String>
|
||||
|
||||
@Query("SELECT * FROM templateShortcuts ORDER BY id DESC")
|
||||
fun getAllShortcutsFlow() : Flow<List<TemplateShortcut>>
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ interface ResultDao {
|
|||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(item: ResultItem) : Long
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertMultiple(items: List<ResultItem?>) : List<Long>
|
||||
|
||||
@Update(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun update(item: ResultItem)
|
||||
|
||||
|
|
|
|||
|
|
@ -13,5 +13,9 @@ data class CommandTemplate(
|
|||
var title: String,
|
||||
var content: String,
|
||||
@ColumnInfo(defaultValue = "0")
|
||||
var useAsExtraCommand: Boolean
|
||||
var useAsExtraCommand: Boolean,
|
||||
@ColumnInfo(defaultValue = "1")
|
||||
var useAsExtraCommandAudio: Boolean,
|
||||
@ColumnInfo(defaultValue = "1")
|
||||
var useAsExtraCommandVideo: Boolean
|
||||
)
|
||||
|
|
@ -8,6 +8,7 @@ import com.deniscerri.ytdlnis.database.models.DownloadItem
|
|||
import com.deniscerri.ytdlnis.database.models.DownloadItemSimple
|
||||
import com.deniscerri.ytdlnis.util.FileUtil
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import java.io.File
|
||||
|
||||
|
||||
|
|
@ -16,7 +17,7 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
|
|||
config = PagingConfig(pageSize = 20, initialLoadSize = 20, prefetchDistance = 1),
|
||||
pagingSourceFactory = {downloadDao.getAllDownloads()}
|
||||
)
|
||||
val activeDownloads : Flow<List<DownloadItem>> = downloadDao.getActiveDownloads()
|
||||
val activeDownloads : Flow<List<DownloadItem>> = downloadDao.getActiveDownloads().distinctUntilChanged()
|
||||
val queuedDownloads : Pager<Int, DownloadItemSimple> = Pager(
|
||||
config = PagingConfig(pageSize = 20, initialLoadSize = 20, prefetchDistance = 1),
|
||||
pagingSourceFactory = {downloadDao.getQueuedDownloads()}
|
||||
|
|
|
|||
|
|
@ -25,9 +25,7 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co
|
|||
val infoUtil = InfoUtil(context)
|
||||
val items = infoUtil.getTrending()
|
||||
itemCount.value = items.size
|
||||
for (i in items){
|
||||
resultDao.insert(i!!)
|
||||
}
|
||||
resultDao.insertMultiple(items)
|
||||
}
|
||||
|
||||
suspend fun search(inputQuery: String, resetResults: Boolean) : ArrayList<ResultItem?>{
|
||||
|
|
@ -35,9 +33,7 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co
|
|||
if (resetResults) deleteAll()
|
||||
val res = infoUtil.search(inputQuery)
|
||||
itemCount.value = res.size
|
||||
res.forEach {
|
||||
resultDao.insert(it!!)
|
||||
}
|
||||
resultDao.insertMultiple(res)
|
||||
return res
|
||||
}
|
||||
|
||||
|
|
@ -50,9 +46,7 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co
|
|||
}else{
|
||||
v.forEach { it?.playlistTitle = "ytdlnis-Search" }
|
||||
}
|
||||
v.forEach {
|
||||
resultDao.insert(it!!)
|
||||
}
|
||||
resultDao.insertMultiple(v)
|
||||
return ArrayList(v)
|
||||
}
|
||||
|
||||
|
|
@ -72,9 +66,7 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co
|
|||
nextPageToken = tmpToken
|
||||
} while (true)
|
||||
itemCount.value = items.size
|
||||
items.forEach {
|
||||
resultDao.insert(it!!)
|
||||
}
|
||||
resultDao.insertMultiple(items.toList())
|
||||
return items
|
||||
}
|
||||
|
||||
|
|
@ -87,9 +79,7 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co
|
|||
}else{
|
||||
items.forEach { it!!.playlistTitle = "ytdlnis-Search" }
|
||||
}
|
||||
items.forEach {
|
||||
resultDao.insert(it!!)
|
||||
}
|
||||
resultDao.insertMultiple(items.toList())
|
||||
return items
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
|||
private val infoUtil : InfoUtil
|
||||
val allDownloads : Flow<PagingData<DownloadItem>>
|
||||
val queuedDownloads : Flow<PagingData<DownloadItemSimple>>
|
||||
val activeDownloads : LiveData<List<DownloadItem>>
|
||||
val activeDownloadsCount : LiveData<Int>
|
||||
val activeDownloads : Flow<List<DownloadItem>>
|
||||
val activeDownloadsCount : Flow<Int>
|
||||
val cancelledDownloads : Flow<PagingData<DownloadItemSimple>>
|
||||
val erroredDownloads : Flow<PagingData<DownloadItemSimple>>
|
||||
val savedDownloads : Flow<PagingData<DownloadItemSimple>>
|
||||
|
|
@ -78,7 +78,8 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
|||
private val formatIDPreference: List<String>
|
||||
private val audioFormatIDPreference: List<String>
|
||||
private val resources : Resources
|
||||
private var extraCommands: String = ""
|
||||
private var extraCommandsForAudio: String = ""
|
||||
private var extraCommandsForVideo: String = ""
|
||||
|
||||
private var audioContainer: String?
|
||||
private var videoContainer: String?
|
||||
|
|
@ -123,14 +124,15 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
|||
|
||||
allDownloads = repository.allDownloads.flow
|
||||
queuedDownloads = repository.queuedDownloads.flow
|
||||
activeDownloads = repository.activeDownloads.asLiveData()
|
||||
activeDownloadsCount = repository.activeDownloadsCount.asLiveData()
|
||||
activeDownloads = repository.activeDownloads
|
||||
activeDownloadsCount = repository.activeDownloadsCount
|
||||
savedDownloads = repository.savedDownloads.flow
|
||||
cancelledDownloads = repository.cancelledDownloads.flow
|
||||
erroredDownloads = repository.erroredDownloads.flow
|
||||
viewModelScope.launch(Dispatchers.IO){
|
||||
if (sharedPreferences.getBoolean("use_extra_commands", false)){
|
||||
extraCommands = commandTemplateDao.getAllTemplatesAsExtraCommands().joinToString(" ")
|
||||
extraCommandsForAudio = commandTemplateDao.getAllTemplatesAsExtraCommandsForAudio().joinToString(" ")
|
||||
extraCommandsForVideo = commandTemplateDao.getAllTemplatesAsExtraCommandsForVideo().joinToString(" ")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -283,6 +285,12 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
|||
audioFormatIDs = preferredAudioFormats
|
||||
)
|
||||
|
||||
val extraCommands = when(type){
|
||||
Type.audio -> extraCommandsForAudio
|
||||
Type.video -> extraCommandsForVideo
|
||||
else -> ""
|
||||
}
|
||||
|
||||
return DownloadItem(0,
|
||||
resultItem.url,
|
||||
resultItem.title,
|
||||
|
|
@ -404,6 +412,12 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
|||
|
||||
val sponsorblock = sharedPreferences.getStringSet("sponsorblock_filters", emptySet())
|
||||
|
||||
val extraCommands = when(historyItem.type){
|
||||
Type.audio -> extraCommandsForAudio
|
||||
Type.video -> extraCommandsForVideo
|
||||
else -> ""
|
||||
}
|
||||
|
||||
val audioPreferences = AudioPreferences(embedThumb, false, ArrayList(sponsorblock!!))
|
||||
val videoPreferences = VideoPreferences(embedSubs, addChapters, false, ArrayList(sponsorblock), saveSubs)
|
||||
val downloadPath = File(historyItem.downloadPath)
|
||||
|
|
@ -467,9 +481,9 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
|||
else -> {
|
||||
val lastUsedCommandTemplate = sharedPreferences.getString("lastCommandTemplateUsed", "")!!
|
||||
val c = if (lastUsedCommandTemplate.isBlank()){
|
||||
commandTemplateDao.getFirst() ?: CommandTemplate(0,"","", false)
|
||||
commandTemplateDao.getFirst() ?: CommandTemplate(0,"","", useAsExtraCommand = false, useAsExtraCommandAudio = false, useAsExtraCommandVideo = false)
|
||||
}else{
|
||||
commandTemplateDao.getTemplateByContent(lastUsedCommandTemplate) ?: CommandTemplate(0, "", lastUsedCommandTemplate, false)
|
||||
commandTemplateDao.getTemplateByContent(lastUsedCommandTemplate) ?: CommandTemplate(0, "", lastUsedCommandTemplate, useAsExtraCommand = false, useAsExtraCommandAudio = false, useAsExtraCommandVideo = false)
|
||||
}
|
||||
return generateCommandFormat(c)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,19 +4,29 @@ import android.app.Application
|
|||
import android.content.SharedPreferences
|
||||
import android.util.Log
|
||||
import android.util.Patterns
|
||||
import android.view.View
|
||||
import androidx.compose.material3.formatWithSkeleton
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.deniscerri.ytdlnis.App
|
||||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.database.DBManager
|
||||
import com.deniscerri.ytdlnis.database.models.Format
|
||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||
import com.deniscerri.ytdlnis.database.models.SearchHistoryItem
|
||||
import com.deniscerri.ytdlnis.database.repository.ResultRepository
|
||||
import com.deniscerri.ytdlnis.database.repository.SearchHistoryRepository
|
||||
import com.deniscerri.ytdlnis.receiver.ShareActivity
|
||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadAudioFragment
|
||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadVideoFragment
|
||||
import com.deniscerri.ytdlnis.util.InfoUtil
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -28,6 +38,7 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
|||
val repository : ResultRepository
|
||||
private val searchHistoryRepository : SearchHistoryRepository
|
||||
val items : LiveData<List<ResultItem>>
|
||||
private val infoUtil: InfoUtil
|
||||
data class ResultsUiState(
|
||||
var processing: Boolean,
|
||||
var errorMessage: Pair<Int, String>?,
|
||||
|
|
@ -51,6 +62,7 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
|||
searchHistoryRepository = SearchHistoryRepository(DBManager.getInstance(application).searchHistoryDao)
|
||||
items = repository.allResults.asLiveData()
|
||||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(application)
|
||||
infoUtil = InfoUtil(application)
|
||||
}
|
||||
|
||||
fun checkTrending() = viewModelScope.launch(Dispatchers.IO){
|
||||
|
|
@ -171,4 +183,62 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
|||
repository.delete(it)
|
||||
}
|
||||
}
|
||||
|
||||
val updatingData: MutableStateFlow<Boolean> = MutableStateFlow(false)
|
||||
var updateResultData: MutableStateFlow<List<ResultItem?>?> = MutableStateFlow(null)
|
||||
private var updateResultDataJob : Job? = null
|
||||
|
||||
val updatingFormats: MutableStateFlow<Boolean> = MutableStateFlow(false)
|
||||
var updateFormatsResultData: MutableStateFlow<MutableList<Format>?> = MutableStateFlow(null)
|
||||
private var updateFormatsResultDataJob: Job? = null
|
||||
|
||||
suspend fun updateItemData(res: ResultItem){
|
||||
if (updateResultDataJob == null || updateResultDataJob?.isCancelled == true || updateResultDataJob?.isCompleted == true){
|
||||
updateResultDataJob = viewModelScope.launch(Dispatchers.IO) {
|
||||
kotlin.runCatching {
|
||||
updatingData.emit(true)
|
||||
val result = parseQueries(listOf(res.url))
|
||||
updatingData.emit(false)
|
||||
updateResultData.emit(result)
|
||||
}.onFailure {
|
||||
updatingData.emit(false)
|
||||
updateResultData.emit(mutableListOf())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateResultDataJob?.start()
|
||||
}
|
||||
|
||||
suspend fun cancelUpdateItemData(){
|
||||
updatingData.emit(false)
|
||||
updateResultData.emit(null)
|
||||
updateResultDataJob?.cancel()
|
||||
}
|
||||
|
||||
suspend fun cancelUpdateFormatsItemData(){
|
||||
updatingFormats.emit(false)
|
||||
updateFormatsResultData.emit(null)
|
||||
updateFormatsResultDataJob?.cancel()
|
||||
}
|
||||
|
||||
suspend fun updateFormatItemData(result: ResultItem){
|
||||
updateFormatsResultDataJob = viewModelScope.launch(Dispatchers.IO) {
|
||||
kotlin.runCatching {
|
||||
updatingFormats.emit(true)
|
||||
val formats = infoUtil.getFormats(result.url)
|
||||
updatingFormats.emit(false)
|
||||
if (formats.isNotEmpty()){
|
||||
val res = getItemByURL(result.url)
|
||||
res.formats = formats.toMutableList()
|
||||
update(res)
|
||||
}
|
||||
updateFormatsResultData.emit(formats.toMutableList())
|
||||
}.onFailure {
|
||||
updatingFormats.emit(false)
|
||||
updateFormatsResultData.emit(mutableListOf())
|
||||
}
|
||||
}
|
||||
updateFormatsResultDataJob?.start()
|
||||
}
|
||||
}
|
||||
|
|
@ -33,18 +33,15 @@ import androidx.recyclerview.widget.GridLayoutManager
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.deniscerri.ytdlnis.MainActivity
|
||||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.ui.adapter.HomeAdapter
|
||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
|
||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadMultipleBottomSheetDialog
|
||||
import com.deniscerri.ytdlnis.ui.downloadcard.ResultCardDetailsDialog
|
||||
import com.deniscerri.ytdlnis.ui.adapter.HomeAdapter
|
||||
import com.deniscerri.ytdlnis.util.Extensions.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.InfoUtil
|
||||
import com.deniscerri.ytdlnis.util.ThemeUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.enableFastScroll
|
||||
import com.facebook.shimmer.ShimmerFrameLayout
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
|
|
@ -316,6 +313,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
|||
providersChipGroup!!.addView(tmp)
|
||||
}
|
||||
|
||||
val chipGroupDivider : View? = requireView().findViewById(R.id.chipGroupDivider)
|
||||
|
||||
searchView!!.addTransitionListener { _, _, newState ->
|
||||
if (newState == SearchView.TransitionState.SHOWN) {
|
||||
|
|
@ -328,13 +326,19 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
|||
}
|
||||
}
|
||||
|
||||
if (Patterns.WEB_URL.matcher(searchBar!!.text.toString()).matches() && searchBar!!.text.isNotBlank()){
|
||||
providersChipGroup.visibility = GONE
|
||||
chipGroupDivider?.visibility = GONE
|
||||
}else{
|
||||
providersChipGroup.visibility = VISIBLE
|
||||
chipGroupDivider?.visibility = VISIBLE
|
||||
}
|
||||
|
||||
try{
|
||||
val clipboard =
|
||||
requireContext().getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val regex =
|
||||
"(https?://(?:www\\.|(?!www))[a-zA-Z\\d][a-zA-Z\\d-]+[a-zA-Z\\d]\\.\\S{2,}|www\\.[a-zA-Z\\d][a-zA-Z\\d-]+[a-zA-Z\\d]\\.\\S{2,}|https?://(?:www\\.|(?!www))[a-zA-Z\\d]+\\.\\S{2,}|www\\.[a-zA-Z\\d]+\\.\\S{2,})".toRegex()
|
||||
val clip = clipboard.primaryClip!!.getItemAt(0).text
|
||||
if (regex.containsMatchIn(clip.toString())) {
|
||||
if (Patterns.WEB_URL.matcher(clip.toString()).matches()) {
|
||||
linkYouCopied!!.visibility = VISIBLE
|
||||
val textView = linkYouCopied!!.findViewById<TextView>(R.id.suggestion_text)
|
||||
textView.text = getString(R.string.link_you_copied)
|
||||
|
|
@ -381,6 +385,13 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
|||
lifecycleScope.launch {
|
||||
updateSearchViewItems(it, linkYouCopied)
|
||||
}
|
||||
if (Patterns.WEB_URL.matcher(it.toString()).matches()){
|
||||
providersChipGroup.visibility = GONE
|
||||
chipGroupDivider?.visibility = GONE
|
||||
}else{
|
||||
providersChipGroup.visibility = VISIBLE
|
||||
chipGroupDivider?.visibility = VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
searchView!!.editText.setOnTouchListener(OnTouchListener { _, event ->
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.deniscerri.ytdlnis.ui.adapter
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.app.Activity
|
||||
import android.content.SharedPreferences
|
||||
import android.graphics.Color
|
||||
|
|
@ -9,6 +10,7 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.preference.PreferenceManager
|
||||
|
|
@ -20,6 +22,7 @@ import com.deniscerri.ytdlnis.R
|
|||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||
import com.deniscerri.ytdlnis.util.Extensions.dp
|
||||
import com.deniscerri.ytdlnis.util.FileUtil
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
|
|
@ -27,6 +30,7 @@ import com.google.android.material.chip.Chip
|
|||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
import com.squareup.picasso.Picasso
|
||||
|
||||
|
||||
class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, ActiveDownloadAdapter.ViewHolder>(AsyncDifferConfig.Builder(
|
||||
DIFF_CALLBACK
|
||||
).build()) {
|
||||
|
|
@ -137,16 +141,37 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
|
|||
when(DownloadRepository.Status.valueOf(item.status)){
|
||||
DownloadRepository.Status.Active -> {
|
||||
progressBar.isIndeterminate = true
|
||||
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_pause_white)
|
||||
|
||||
val fromRadius: Int = dp(activity.resources, 30f)
|
||||
val toRadius: Int = dp(activity.resources, 15f)
|
||||
val animator = ValueAnimator.ofInt(fromRadius, toRadius)
|
||||
animator.setDuration(500)
|
||||
.addUpdateListener { animation ->
|
||||
val value = animation.animatedValue as Int
|
||||
pauseButton.cornerRadius = value
|
||||
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_pause_white)
|
||||
pauseButton.isEnabled = true
|
||||
pauseButton.tag = ActiveDownloadAction.Pause
|
||||
}
|
||||
animator.start()
|
||||
|
||||
cancelButton.visibility = View.GONE
|
||||
pauseButton.isEnabled = true
|
||||
pauseButton.tag = ActiveDownloadAction.Pause
|
||||
}
|
||||
DownloadRepository.Status.ActivePaused -> {
|
||||
progressBar.isIndeterminate = false
|
||||
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_play_arrow_white)
|
||||
pauseButton.tag = ActiveDownloadAction.Resume
|
||||
pauseButton.isEnabled = true
|
||||
|
||||
val fromRadius: Int = dp(activity.resources, 15f)
|
||||
val toRadius: Int = dp(activity.resources, 30f)
|
||||
val animator = ValueAnimator.ofInt(fromRadius, toRadius)
|
||||
animator.setDuration(500)
|
||||
.addUpdateListener { animation ->
|
||||
val value = animation.animatedValue as Int
|
||||
pauseButton.cornerRadius = value
|
||||
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_play_arrow_white)
|
||||
pauseButton.tag = ActiveDownloadAction.Resume
|
||||
pauseButton.isEnabled = true
|
||||
}
|
||||
animator.start()
|
||||
cancelButton.visibility = View.VISIBLE
|
||||
}
|
||||
DownloadRepository.Status.PausedReQueued -> {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.compose.ui.util.fastJoinToString
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
|
|
@ -51,11 +53,18 @@ class TemplatesAdapter(onItemClickListener: OnItemClickListener, activity: Activ
|
|||
val content = card.findViewById<TextView>(R.id.content)
|
||||
content.text = item?.content
|
||||
|
||||
val useInExtraCommands = card.findViewById<TextView>(R.id.useInExtraCommands)
|
||||
if (item!!.useAsExtraCommand) useInExtraCommands.visibility = View.VISIBLE
|
||||
else useInExtraCommands.visibility = View.GONE
|
||||
card.findViewById<TextView>(R.id.useInExtraCommands).apply {
|
||||
isVisible = item!!.useAsExtraCommand
|
||||
val extraAudio = if (item.useAsExtraCommandAudio) context.getString(R.string.audio) else null
|
||||
val extraVideo = if (item.useAsExtraCommandVideo) context.getString(R.string.video) else null
|
||||
val finalText = context.getString(R.string.extra_command) + " " + listOfNotNull(
|
||||
extraAudio,
|
||||
extraVideo
|
||||
).joinToString(" ", "[", "]", -1)
|
||||
text = finalText
|
||||
}
|
||||
|
||||
if (checkedItems.contains(item.id)) {
|
||||
if (checkedItems.contains(item!!.id)) {
|
||||
card.isChecked = true
|
||||
card.strokeWidth = 5
|
||||
} else {
|
||||
|
|
@ -132,7 +141,11 @@ class TemplatesAdapter(onItemClickListener: OnItemClickListener, activity: Activ
|
|||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: CommandTemplate, newItem: CommandTemplate): Boolean {
|
||||
return oldItem.title == newItem.title && oldItem.content == newItem.content && oldItem.useAsExtraCommand == newItem.useAsExtraCommand
|
||||
return oldItem.title == newItem.title &&
|
||||
oldItem.content == newItem.content &&
|
||||
oldItem.useAsExtraCommand == newItem.useAsExtraCommand &&
|
||||
oldItem.useAsExtraCommandAudio == newItem.useAsExtraCommandAudio &&
|
||||
oldItem.useAsExtraCommandVideo == newItem.useAsExtraCommandVideo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import com.deniscerri.ytdlnis.database.models.DownloadItem
|
|||
import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel
|
||||
import com.deniscerri.ytdlnis.util.InfoUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.enableTextHighlight
|
||||
import com.deniscerri.ytdlnis.util.Extensions.enableTextHighlight
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import com.deniscerri.ytdlnis.database.models.ChapterItem
|
|||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||
import com.deniscerri.ytdlnis.util.InfoUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.setTextAndRecalculateWidth
|
||||
import com.deniscerri.ytdlnis.util.Extensions.setTextAndRecalculateWidth
|
||||
import com.deniscerri.ytdlnis.util.VideoPlayerUtil
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
|
|||
infoUtil = InfoUtil(requireContext())
|
||||
genericAudioFormats = infoUtil.getGenericAudioFormats(requireContext().resources)
|
||||
preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
shownFields = preferences.getStringSet("modify_download_card", setOf())!!.toList().ifEmpty { requireContext().getStringArray(R.array.modify_download_card_values).toList() }
|
||||
shownFields = preferences.getStringSet("modify_download_card", requireContext().getStringArray(R.array.modify_download_card_values).toSet())!!.toList()
|
||||
return fragmentView
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import android.os.Build
|
|||
import android.os.Bundle
|
||||
import android.text.format.DateFormat
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.Log
|
||||
import android.util.Patterns
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
|
@ -20,8 +21,6 @@ import androidx.core.content.edit
|
|||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavDestination
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
|
@ -46,10 +45,10 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
|
@ -78,9 +77,6 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
|
|||
private lateinit var shimmerLoadingSubtitle : ShimmerFrameLayout
|
||||
private lateinit var subtitle : View
|
||||
|
||||
private var updateJob : Job? = null
|
||||
private var updateFormatsJob : Job? = null
|
||||
|
||||
|
||||
private lateinit var result: ResultItem
|
||||
private lateinit var type: Type
|
||||
|
|
@ -88,9 +84,9 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||
historyViewModel = ViewModelProvider(this)[HistoryViewModel::class.java]
|
||||
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
||||
downloadViewModel = ViewModelProvider(requireActivity())[DownloadViewModel::class.java]
|
||||
historyViewModel = ViewModelProvider(requireActivity())[HistoryViewModel::class.java]
|
||||
resultViewModel = ViewModelProvider(requireActivity())[ResultViewModel::class.java]
|
||||
commandTemplateDao = DBManager.getInstance(requireContext()).commandTemplateDao
|
||||
infoUtil = InfoUtil(requireContext())
|
||||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
|
|
@ -143,6 +139,16 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
|
|||
shimmerLoadingSubtitle = view.findViewById(R.id.shimmer_loading_subtitle)
|
||||
subtitle = view.findViewById(R.id.bottom_sheet_subtitle)
|
||||
|
||||
shimmerLoading.setOnClickListener {
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.IO){
|
||||
resultViewModel.cancelUpdateItemData()
|
||||
}
|
||||
(updateItem.parent as LinearLayout).visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
(viewPager2.getChildAt(0) as? RecyclerView)?.apply {
|
||||
isNestedScrollingEnabled = false
|
||||
overScrollMode = View.OVER_SCROLL_NEVER
|
||||
|
|
@ -259,7 +265,7 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
|
|||
|
||||
viewPager2.setPageTransformer(BackgroundToForegroundPageTransformer())
|
||||
|
||||
val shownFields = sharedPreferences.getStringSet("modify_download_card", setOf())!!.toList().ifEmpty { requireContext().getStringArray(R.array.modify_download_card_values).toList() }
|
||||
val shownFields = sharedPreferences.getStringSet("modify_download_card", requireContext().getStringArray(R.array.modify_download_card_values).toSet())!!.toList()
|
||||
|
||||
val scheduleBtn = view.findViewById<MaterialButton>(R.id.bottomsheet_schedule_button)
|
||||
scheduleBtn.visibility = if(shownFields.contains("schedule")){
|
||||
|
|
@ -272,8 +278,11 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
|
|||
|
||||
scheduleBtn.setOnClickListener{
|
||||
UiUtil.showDatePicker(fragmentManager) {
|
||||
updateJob?.cancel()
|
||||
updateFormatsJob?.cancel()
|
||||
lifecycleScope.launch {
|
||||
resultViewModel.cancelUpdateItemData()
|
||||
resultViewModel.cancelUpdateFormatsItemData()
|
||||
}
|
||||
|
||||
scheduleBtn.isEnabled = false
|
||||
download.isEnabled = false
|
||||
val item: DownloadItem = getDownloadItem()
|
||||
|
|
@ -287,8 +296,10 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
|
|||
}
|
||||
}
|
||||
download!!.setOnClickListener {
|
||||
updateJob?.cancel()
|
||||
updateFormatsJob?.cancel()
|
||||
lifecycleScope.launch {
|
||||
resultViewModel.cancelUpdateItemData()
|
||||
resultViewModel.cancelUpdateFormatsItemData()
|
||||
}
|
||||
scheduleBtn.isEnabled = false
|
||||
download.isEnabled = false
|
||||
val item: DownloadItem = getDownloadItem()
|
||||
|
|
@ -356,7 +367,7 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
|
|||
}else {
|
||||
val usingGenericFormatsOrEmpty = result.formats.isEmpty() || result.formats.any { it.format_note.contains("ytdlnisgeneric") }
|
||||
if (usingGenericFormatsOrEmpty && sharedPreferences.getBoolean("update_formats", false) && !sharedPreferences.getBoolean("quick_download", false)){
|
||||
initUpdateFormats(result.url)
|
||||
initUpdateFormats(result)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -392,7 +403,115 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
lifecycleScope.launch {
|
||||
resultViewModel.updatingData.collectLatest {
|
||||
if (it){
|
||||
title.visibility = View.GONE
|
||||
subtitle.visibility = View.GONE
|
||||
shimmerLoading.visibility = View.VISIBLE
|
||||
shimmerLoadingSubtitle.visibility = View.VISIBLE
|
||||
shimmerLoading.startShimmer()
|
||||
shimmerLoadingSubtitle.startShimmer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lifecycleScope.launch {
|
||||
resultViewModel.updatingFormats.collectLatest {
|
||||
if (it){
|
||||
runCatching {
|
||||
val f1 = fragmentManager.findFragmentByTag("f0") as DownloadAudioFragment
|
||||
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.visibility = View.VISIBLE
|
||||
}
|
||||
runCatching {
|
||||
val f1 = fragmentManager.findFragmentByTag("f1") as DownloadVideoFragment
|
||||
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lifecycleScope.launch {
|
||||
resultViewModel.updateResultData.collectLatest { result ->
|
||||
if (result == null) return@collectLatest
|
||||
lifecycleScope.launch(Dispatchers.Main) {
|
||||
if (result.isNotEmpty()){
|
||||
if (result.size == 1 && result[0] != null){
|
||||
fragmentAdapter.setResultItem(result[0]!!)
|
||||
runCatching {
|
||||
val f = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment
|
||||
f.updateUI(result[0])
|
||||
}
|
||||
|
||||
runCatching {
|
||||
val f1 = fragmentManager?.findFragmentByTag("f1") as DownloadVideoFragment
|
||||
f1.updateUI(result[0])
|
||||
}
|
||||
|
||||
title.visibility = View.VISIBLE
|
||||
subtitle.visibility = View.VISIBLE
|
||||
shimmerLoading.visibility = View.GONE
|
||||
shimmerLoadingSubtitle.visibility = View.GONE
|
||||
shimmerLoading.stopShimmer()
|
||||
shimmerLoadingSubtitle.stopShimmer()
|
||||
|
||||
val usingGenericFormatsOrEmpty = result[0]!!.formats.isEmpty() || result[0]!!.formats.any { it.format_note.contains("ytdlnisgeneric") }
|
||||
fragmentAdapter.setResultItem(result[0]!!)
|
||||
arguments?.putParcelable("result", result[0]!!)
|
||||
if (usingGenericFormatsOrEmpty && sharedPreferences.getBoolean("update_formats", false)){
|
||||
initUpdateFormats(result[0]!!)
|
||||
}
|
||||
}else{
|
||||
//open multi download card instead
|
||||
if (activity is ShareActivity){
|
||||
val preferredType = DownloadViewModel.Type.valueOf(sharedPreferences.getString("preferred_download_type", "video")!!)
|
||||
findNavController().navigate(R.id.action_downloadBottomSheetDialog_to_selectPlaylistItemsDialog, bundleOf(
|
||||
Pair("results", result),
|
||||
Pair("type", preferredType),
|
||||
))
|
||||
}else{
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
resultViewModel.updateResultData.emit(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lifecycleScope.launch {
|
||||
resultViewModel.updateFormatsResultData.collectLatest { formats ->
|
||||
if (formats == null) return@collectLatest
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.Main){
|
||||
runCatching {
|
||||
val f1 = fragmentManager.findFragmentByTag("f0") as DownloadAudioFragment
|
||||
val resultItem = downloadViewModel.createResultItemFromDownload(f1.downloadItem)
|
||||
resultItem.formats = formats
|
||||
fragmentAdapter.setResultItem(resultItem)
|
||||
f1.updateUI(resultItem)
|
||||
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.visibility = View.GONE
|
||||
}
|
||||
runCatching {
|
||||
val f1 = fragmentManager.findFragmentByTag("f1") as DownloadVideoFragment
|
||||
val resultItem = downloadViewModel.createResultItemFromDownload(f1.downloadItem)
|
||||
resultItem.formats = formats
|
||||
fragmentAdapter.setResultItem(resultItem)
|
||||
f1.updateUI(resultItem)
|
||||
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
if (formats.isNotEmpty()){
|
||||
result.formats = formats
|
||||
}
|
||||
resultViewModel.updateFormatsResultData.emit(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDownloadItem(selectedTabPosition: Int = tabLayout.selectedTabPosition) : DownloadItem{
|
||||
return when(selectedTabPosition){
|
||||
0 -> {
|
||||
|
|
@ -430,139 +549,22 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
|
|||
}
|
||||
|
||||
private fun initUpdateData() {
|
||||
updateJob = CoroutineScope(SupervisorJob()).launch(Dispatchers.IO){
|
||||
findNavController().saveState()
|
||||
kotlin.runCatching {
|
||||
withContext(Dispatchers.Main){
|
||||
title.visibility = View.GONE
|
||||
subtitle.visibility = View.GONE
|
||||
shimmerLoading.visibility = View.VISIBLE
|
||||
shimmerLoadingSubtitle.visibility = View.VISIBLE
|
||||
shimmerLoading.startShimmer()
|
||||
shimmerLoadingSubtitle.startShimmer()
|
||||
}
|
||||
|
||||
if (result.url.isBlank()){
|
||||
withContext(Dispatchers.Main){dismiss()}
|
||||
return@launch
|
||||
}
|
||||
|
||||
val result = resultViewModel.parseQueries(listOf(result.url))
|
||||
if (result.isEmpty()){
|
||||
return@launch
|
||||
}
|
||||
|
||||
if (result.size == 1 && result[0] != null){
|
||||
fragmentAdapter.setResultItem(result[0]!!)
|
||||
withContext(Dispatchers.Main){
|
||||
runCatching {
|
||||
val f = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment
|
||||
f.updateUI(result[0])
|
||||
}
|
||||
|
||||
runCatching {
|
||||
val f1 = fragmentManager?.findFragmentByTag("f1") as DownloadVideoFragment
|
||||
f1.updateUI(result[0])
|
||||
}
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main){
|
||||
title.visibility = View.VISIBLE
|
||||
subtitle.visibility = View.VISIBLE
|
||||
shimmerLoading.visibility = View.GONE
|
||||
shimmerLoadingSubtitle.visibility = View.GONE
|
||||
shimmerLoading.stopShimmer()
|
||||
shimmerLoadingSubtitle.stopShimmer()
|
||||
}
|
||||
|
||||
val usingGenericFormatsOrEmpty = result[0]!!.formats.isEmpty() || result[0]!!.formats.any { it.format_note.contains("ytdlnisgeneric") }
|
||||
|
||||
if (usingGenericFormatsOrEmpty && sharedPreferences.getBoolean("update_formats", false)){
|
||||
initUpdateFormats(result[0]!!.url)
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
}else{
|
||||
//open multi download card instead
|
||||
if (activity is ShareActivity){
|
||||
val preferredType = DownloadViewModel.Type.valueOf(sharedPreferences.getString("preferred_download_type", "video")!!)
|
||||
withContext(Dispatchers.Main){
|
||||
findNavController().navigate(R.id.action_downloadBottomSheetDialog_to_selectPlaylistItemsDialog, bundleOf(
|
||||
Pair("results", result),
|
||||
Pair("type", preferredType),
|
||||
))
|
||||
}
|
||||
}else{
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result.url.isBlank()) {
|
||||
dismiss()
|
||||
return
|
||||
}
|
||||
shimmerLoading.setOnClickListener {
|
||||
updateJob?.cancel()
|
||||
(updateItem.parent as LinearLayout).visibility = View.VISIBLE
|
||||
if (resultViewModel.updatingData.value) return
|
||||
|
||||
CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) {
|
||||
resultViewModel.updateItemData(result)
|
||||
}
|
||||
updateJob?.invokeOnCompletion {
|
||||
kotlin.runCatching {
|
||||
requireActivity().runOnUiThread {
|
||||
title.visibility = View.VISIBLE
|
||||
subtitle.visibility = View.VISIBLE
|
||||
shimmerLoading.visibility = View.GONE
|
||||
shimmerLoadingSubtitle.visibility = View.GONE
|
||||
shimmerLoading.stopShimmer()
|
||||
shimmerLoadingSubtitle.stopShimmer()
|
||||
}
|
||||
}
|
||||
}
|
||||
updateJob?.start()
|
||||
}
|
||||
|
||||
private fun initUpdateFormats(url: String){
|
||||
updateFormatsJob = CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) {
|
||||
withContext(Dispatchers.Main){
|
||||
runCatching {
|
||||
val f1 = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment
|
||||
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.visibility = View.VISIBLE
|
||||
}
|
||||
runCatching {
|
||||
val f1 = fragmentManager?.findFragmentByTag("f1") as DownloadVideoFragment
|
||||
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
val formats = runCatching {
|
||||
infoUtil.getFormats(url).toMutableList()
|
||||
}.getOrElse {
|
||||
mutableListOf()
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main){
|
||||
runCatching {
|
||||
val f1 = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment
|
||||
val resultItem = downloadViewModel.createResultItemFromDownload(f1.downloadItem)
|
||||
resultItem.formats = formats
|
||||
fragmentAdapter.setResultItem(resultItem)
|
||||
f1.updateUI(resultItem)
|
||||
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.visibility = View.GONE
|
||||
}
|
||||
runCatching {
|
||||
val f1 = fragmentManager?.findFragmentByTag("f1") as DownloadVideoFragment
|
||||
val resultItem = downloadViewModel.createResultItemFromDownload(f1.downloadItem)
|
||||
resultItem.formats = formats
|
||||
fragmentAdapter.setResultItem(resultItem)
|
||||
f1.updateUI(resultItem)
|
||||
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
if (formats.isNotEmpty()){
|
||||
result.formats = formats
|
||||
resultViewModel.update(result)
|
||||
}
|
||||
|
||||
private fun initUpdateFormats(res: ResultItem){
|
||||
if (resultViewModel.updatingFormats.value) return
|
||||
CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) {
|
||||
resultViewModel.updateFormatItemData(res)
|
||||
}
|
||||
updateFormatsJob?.start()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel
|
|||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||
import com.deniscerri.ytdlnis.util.FileUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.enableTextHighlight
|
||||
import com.deniscerri.ytdlnis.util.Extensions.enableTextHighlight
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.populateCommandCard
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.google.android.material.chip.Chip
|
||||
|
|
@ -87,7 +87,7 @@ class DownloadCommandFragment(private val resultItem: ResultItem? = null, privat
|
|||
preferences.edit().putString("lastCommandTemplateUsed", downloadItem.format.format_note).apply()
|
||||
|
||||
if (!Patterns.WEB_URL.matcher(downloadItem.url).matches()){
|
||||
downloadItem.format = downloadViewModel.generateCommandFormat(CommandTemplate(0,"txt", "-a \"${downloadItem.url}\"", false))
|
||||
downloadItem.format = downloadViewModel.generateCommandFormat(CommandTemplate(0,"txt", "-a \"${downloadItem.url}\"", useAsExtraCommand = false, useAsExtraCommandAudio = false, useAsExtraCommandVideo = false))
|
||||
downloadItem.url = ""
|
||||
}
|
||||
|
||||
|
|
@ -231,7 +231,7 @@ class DownloadCommandFragment(private val resultItem: ResultItem? = null, privat
|
|||
0,
|
||||
"",
|
||||
chosenCommandView.editText!!.text.toString(),
|
||||
false
|
||||
useAsExtraCommand = false, useAsExtraCommandAudio = false, useAsExtraCommandVideo = false
|
||||
)
|
||||
UiUtil.showCommandTemplateCreationOrUpdatingSheet(current, requireActivity(), viewLifecycleOwner, commandTemplateViewModel) {
|
||||
templates.add(it)
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ import com.deniscerri.ytdlnis.receiver.ShareActivity
|
|||
import com.deniscerri.ytdlnis.util.FileUtil
|
||||
import com.deniscerri.ytdlnis.util.InfoUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.Extensions.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.work.UpdatePlaylistFormatsWorker
|
||||
import com.google.android.material.bottomappbar.BottomAppBar
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
|
|||
infoUtil = InfoUtil(requireContext())
|
||||
genericVideoFormats = infoUtil.getGenericVideoFormats(requireContext().resources)
|
||||
preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
shownFields = preferences.getStringSet("modify_download_card", setOf())!!.toList().ifEmpty { requireContext().getStringArray(R.array.modify_download_card_values).toList() }
|
||||
shownFields = preferences.getStringSet("modify_download_card", requireContext().getStringArray(R.array.modify_download_card_values).toSet())!!.toList()
|
||||
return fragmentView
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ import com.google.android.material.snackbar.Snackbar
|
|||
import com.yausername.youtubedl_android.YoutubeDL
|
||||
import it.xabaras.android.recyclerview.swipedecorator.RecyclerViewSwipeDecorator
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -181,14 +182,17 @@ class ResultCardDetailsDialog : BottomSheetDialogFragment(), GenericDownloadAdap
|
|||
queuedRecycler.adapter = queuedAdapter
|
||||
queuedRecycler.layoutManager = GridLayoutManager(context, resources.getInteger(R.integer.grid_size))
|
||||
|
||||
downloadViewModel.activeDownloads.map { it.filter { d -> d.url == item.url } }.observe(viewLifecycleOwner) {
|
||||
activeAdapter.submitList(it)
|
||||
if (it.isEmpty()){
|
||||
running.visibility = View.GONE
|
||||
runningRecycler.visibility = View.GONE
|
||||
}else{
|
||||
running.visibility = View.VISIBLE
|
||||
runningRecycler.visibility = View.VISIBLE
|
||||
lifecycleScope.launch {
|
||||
downloadViewModel.activeDownloads.map { it.filter { d -> d.url == item.url } }.collectLatest {
|
||||
delay(500)
|
||||
activeAdapter.submitList(it)
|
||||
if (it.isEmpty()){
|
||||
running.visibility = View.GONE
|
||||
runningRecycler.visibility = View.GONE
|
||||
}else{
|
||||
running.visibility = View.VISIBLE
|
||||
runningRecycler.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -231,8 +235,10 @@ class ResultCardDetailsDialog : BottomSheetDialogFragment(), GenericDownloadAdap
|
|||
}
|
||||
}
|
||||
|
||||
downloadViewModel.activeDownloadsCount.observe(viewLifecycleOwner){
|
||||
activeCount = it
|
||||
lifecycleScope.launch {
|
||||
downloadViewModel.activeDownloadsCount.collectLatest {
|
||||
activeCount = it
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ import com.deniscerri.ytdlnis.database.models.ResultItem
|
|||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||
import com.deniscerri.ytdlnis.receiver.ShareActivity
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.setTextAndRecalculateWidth
|
||||
import com.deniscerri.ytdlnis.util.Extensions.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.Extensions.setTextAndRecalculateWidth
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import com.google.android.material.bottomappbar.BottomAppBar
|
||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
|
|
|
|||
|
|
@ -23,11 +23,13 @@ import com.deniscerri.ytdlnis.database.models.DownloadItem
|
|||
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.forceFastScrollMode
|
||||
import com.deniscerri.ytdlnis.util.Extensions.forceFastScrollMode
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
import com.yausername.youtubedl_android.YoutubeDL
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
@ -157,21 +159,30 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis
|
|||
}
|
||||
}
|
||||
|
||||
downloadViewModel.activeDownloads.observe(viewLifecycleOwner) {
|
||||
activeDownloads.submitList(it)
|
||||
|
||||
if (it.size > 1){
|
||||
pauseResume.visibility = View.VISIBLE
|
||||
if (it.all { l -> l.status == DownloadRepository.Status.ActivePaused.toString() }){
|
||||
pauseResume.text = requireContext().getString(R.string.resume)
|
||||
}else{
|
||||
pauseResume.text = requireContext().getString(R.string.pause)
|
||||
}
|
||||
}else{
|
||||
activeDownloads.notifyDataSetChanged()
|
||||
pauseResume.visibility = View.GONE
|
||||
lifecycleScope.launch {
|
||||
downloadViewModel.activeDownloadsCount.collectLatest {
|
||||
delay(200)
|
||||
noResults.visibility = if (it == 0) View.VISIBLE else View.GONE
|
||||
}
|
||||
noResults.visibility = if (it.isEmpty()) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
lifecycleScope.launch {
|
||||
downloadViewModel.activeDownloads.collectLatest {
|
||||
delay(100)
|
||||
activeDownloads.submitList(it)
|
||||
|
||||
if (it.size > 1){
|
||||
pauseResume.visibility = View.VISIBLE
|
||||
if (it.all { l -> l.status == DownloadRepository.Status.ActivePaused.toString() }){
|
||||
pauseResume.text = requireContext().getString(R.string.resume)
|
||||
}else{
|
||||
pauseResume.text = requireContext().getString(R.string.pause)
|
||||
}
|
||||
}else{
|
||||
pauseResume.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -212,7 +223,6 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis
|
|||
withContext(Dispatchers.IO){
|
||||
downloadViewModel.updateDownload(item)
|
||||
}
|
||||
activeDownloads.notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
ActiveDownloadAdapter.ActiveDownloadAction.Resume -> {
|
||||
|
|
@ -221,7 +231,6 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis
|
|||
withContext(Dispatchers.IO){
|
||||
downloadViewModel.updateDownload(item)
|
||||
}
|
||||
activeDownloads.notifyItemChanged(position)
|
||||
|
||||
runBlocking {
|
||||
downloadViewModel.queueDownloads(listOf(item))
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import androidx.preference.PreferenceManager
|
|||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
|
||||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.ui.adapter.GenericDownloadAdapter
|
||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||
|
|
@ -30,8 +31,8 @@ import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
|||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
|
||||
import com.deniscerri.ytdlnis.util.UiUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.forceFastScrollMode
|
||||
import com.deniscerri.ytdlnis.util.Extensions.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.Extensions.forceFastScrollMode
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
|
@ -80,7 +81,7 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
|
|||
cancelledRecyclerView.adapter = adapter
|
||||
cancelledRecyclerView.enableFastScroll()
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
if (preferences.getBoolean("swipe_gestures", true)){
|
||||
if (preferences.getStringSet("swipe_gesture", requireContext().getStringArray(R.array.swipe_gestures_values).toSet())!!.toList().contains("cancelled")){
|
||||
val itemTouchHelper = ItemTouchHelper(simpleCallback)
|
||||
itemTouchHelper.attachToRecyclerView(cancelledRecyclerView)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import androidx.preference.PreferenceManager
|
|||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
|
||||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.ui.adapter.GenericDownloadAdapter
|
||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||
|
|
@ -31,8 +32,8 @@ import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
|||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
|
||||
import com.deniscerri.ytdlnis.util.UiUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.forceFastScrollMode
|
||||
import com.deniscerri.ytdlnis.util.Extensions.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.Extensions.forceFastScrollMode
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
|
@ -80,7 +81,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
|||
erroredRecyclerView.adapter = adapter
|
||||
erroredRecyclerView.enableFastScroll()
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
if (preferences.getBoolean("swipe_gestures", true)){
|
||||
if (preferences.getStringSet("swipe_gesture", requireContext().getStringArray(R.array.swipe_gestures_values).toSet())!!.toList().contains("errored")){
|
||||
val itemTouchHelper = ItemTouchHelper(simpleCallback)
|
||||
itemTouchHelper.attachToRecyclerView(erroredRecyclerView)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import androidx.preference.PreferenceManager
|
|||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
|
||||
import com.deniscerri.ytdlnis.MainActivity
|
||||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.ui.adapter.HistoryAdapter
|
||||
|
|
@ -47,7 +48,7 @@ import com.deniscerri.ytdlnis.database.viewmodel.HistoryViewModel
|
|||
import com.deniscerri.ytdlnis.databinding.FragmentHistoryBinding
|
||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
|
||||
import com.deniscerri.ytdlnis.util.UiUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.Extensions.enableFastScroll
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
|
|
@ -122,7 +123,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
|||
recyclerView?.enableFastScroll()
|
||||
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
if (preferences.getBoolean("swipe_gestures", true)){
|
||||
if (preferences.getStringSet("swipe_gesture", requireContext().getStringArray(R.array.swipe_gestures_values).toSet())!!.toList().contains("history")){
|
||||
val itemTouchHelper = ItemTouchHelper(simpleCallback)
|
||||
itemTouchHelper.attachToRecyclerView(recyclerView)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import androidx.recyclerview.widget.GridLayoutManager
|
|||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.work.WorkManager
|
||||
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
|
||||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.ui.adapter.GenericDownloadAdapter
|
||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||
|
|
@ -35,8 +36,8 @@ import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
|
|||
import com.deniscerri.ytdlnis.util.FileUtil
|
||||
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.forceFastScrollMode
|
||||
import com.deniscerri.ytdlnis.util.Extensions.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.Extensions.forceFastScrollMode
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
|
@ -91,7 +92,7 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
|||
queuedRecyclerView.enableFastScroll()
|
||||
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
if (preferences.getBoolean("swipe_gestures", true)){
|
||||
if (preferences.getStringSet("swipe_gesture", requireContext().getStringArray(R.array.swipe_gestures_values).toSet())!!.toList().contains("queued")){
|
||||
val itemTouchHelper = ItemTouchHelper(simpleCallback)
|
||||
itemTouchHelper.attachToRecyclerView(queuedRecyclerView)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import androidx.preference.PreferenceManager
|
|||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
|
||||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.ui.adapter.GenericDownloadAdapter
|
||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||
|
|
@ -30,8 +31,8 @@ import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
|||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
|
||||
import com.deniscerri.ytdlnis.util.UiUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.forceFastScrollMode
|
||||
import com.deniscerri.ytdlnis.util.Extensions.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.Extensions.forceFastScrollMode
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
|
@ -79,7 +80,7 @@ class SavedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLis
|
|||
savedRecyclerView.enableFastScroll()
|
||||
savedRecyclerView.adapter = adapter
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
if (preferences.getBoolean("swipe_gestures", true)){
|
||||
if (preferences.getStringSet("swipe_gesture", requireContext().getStringArray(R.array.swipe_gestures_values).toSet())!!.toList().contains("saved")){
|
||||
val itemTouchHelper = ItemTouchHelper(simpleCallback)
|
||||
itemTouchHelper.attachToRecyclerView(savedRecyclerView)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import androidx.preference.PreferenceManager
|
|||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
|
||||
import com.deniscerri.ytdlnis.MainActivity
|
||||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.ui.adapter.TemplatesAdapter
|
||||
|
|
@ -94,7 +95,7 @@ class CommandTemplatesFragment : Fragment(), TemplatesAdapter.OnItemClickListene
|
|||
recyclerView.layoutManager = LinearLayoutManager(context)
|
||||
recyclerView.adapter = templatesAdapter
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
if (preferences.getBoolean("swipe_gestures", true)){
|
||||
if (preferences.getStringSet("swipe_gesture", requireContext().getStringArray(R.array.swipe_gestures_values).toSet())!!.toList().contains("templates")){
|
||||
val itemTouchHelper = ItemTouchHelper(simpleCallback)
|
||||
itemTouchHelper.attachToRecyclerView(recyclerView)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import androidx.preference.PreferenceManager
|
|||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
|
||||
import com.deniscerri.ytdlnis.MainActivity
|
||||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.ui.adapter.CookieAdapter
|
||||
|
|
@ -79,7 +80,7 @@ class CookiesFragment : Fragment(), CookieAdapter.OnItemClickListener {
|
|||
recyclerView.layoutManager = LinearLayoutManager(context)
|
||||
recyclerView.adapter = listAdapter
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
if (preferences.getBoolean("swipe_gestures", true)){
|
||||
if (preferences.getStringSet("swipe_gesture", requireContext().getStringArray(R.array.swipe_gestures_values).toSet())!!.toList().contains("cookies")){
|
||||
val itemTouchHelper = ItemTouchHelper(simpleCallback)
|
||||
itemTouchHelper.attachToRecyclerView(recyclerView)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import androidx.lifecycle.lifecycleScope
|
|||
import com.deniscerri.ytdlnis.MainActivity
|
||||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.LogViewModel
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.enableTextHighlight
|
||||
import com.deniscerri.ytdlnis.util.Extensions.enableTextHighlight
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import com.google.android.material.bottomappbar.BottomAppBar
|
||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ import com.deniscerri.ytdlnis.R
|
|||
import com.deniscerri.ytdlnis.ui.adapter.DownloadLogsAdapter
|
||||
import com.deniscerri.ytdlnis.database.models.LogItem
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.LogViewModel
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.forceFastScrollMode
|
||||
import com.deniscerri.ytdlnis.util.Extensions.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.Extensions.forceFastScrollMode
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
|
|
|
|||
|
|
@ -51,7 +51,10 @@ abstract class BaseSettingsFragment : PreferenceFragmentCompat() {
|
|||
}.toBooleanArray()
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(preference.title)
|
||||
.setMultiChoiceItems(preference.entries, selectedItems) { _, _, _ ->
|
||||
.setMultiChoiceItems(preference.entries, selectedItems) { _, which, isChecked ->
|
||||
selectedItems[which] = isChecked
|
||||
}
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
val newValues = preference.entryValues
|
||||
.filterIndexed { index, _ -> selectedItems[index] }
|
||||
.map { it.toString() }
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.PowerManager
|
||||
import android.provider.Settings
|
||||
|
|
@ -66,11 +67,9 @@ class GeneralSettingsFragment : BaseSettingsFragment() {
|
|||
language!!.entries = entries.toTypedArray()
|
||||
|
||||
if(language!!.value == null) language!!.value = Locale.getDefault().language
|
||||
language!!.summary = Locale(language!!.value).getDisplayLanguage(Locale(language!!.value))
|
||||
|
||||
language!!.onPreferenceChangeListener =
|
||||
Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
|
||||
language!!.summary = Locale(newValue.toString()).getDisplayLanguage(Locale(newValue.toString()))
|
||||
AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(newValue.toString()))
|
||||
true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import com.deniscerri.ytdlnis.R
|
|||
import com.deniscerri.ytdlnis.ui.adapter.TerminalDownloadsAdapter
|
||||
import com.deniscerri.ytdlnis.database.models.TerminalItem
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.TerminalViewModel
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.enableFastScroll
|
||||
import com.deniscerri.ytdlnis.util.Extensions.enableFastScroll
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ import com.deniscerri.ytdlnis.database.viewmodel.TerminalViewModel
|
|||
import com.deniscerri.ytdlnis.util.FileUtil
|
||||
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil
|
||||
import com.deniscerri.ytdlnis.util.UiUtil.enableTextHighlight
|
||||
import com.deniscerri.ytdlnis.util.Extensions.enableTextHighlight
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import com.google.android.material.bottomappbar.BottomAppBar
|
||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
|
|
|
|||
94
app/src/main/java/com/deniscerri/ytdlnis/util/Extensions.kt
Normal file
94
app/src/main/java/com/deniscerri/ytdlnis/util/Extensions.kt
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
package com.deniscerri.ytdlnis.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ShapeDrawable
|
||||
import android.graphics.drawable.shapes.OvalShape
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.neo.highlight.core.Highlight
|
||||
import com.neo.highlight.util.listener.HighlightTextWatcher
|
||||
import com.neo.highlight.util.scheme.ColorScheme
|
||||
import me.zhanghai.android.fastscroll.FastScrollerBuilder
|
||||
import java.util.regex.Pattern
|
||||
|
||||
|
||||
object Extensions {
|
||||
fun dp(resources: Resources, px: Float) : Int {
|
||||
val metrics: DisplayMetrics = resources.displayMetrics
|
||||
return (metrics.density * px).toInt()
|
||||
}
|
||||
|
||||
private var textHighLightSchemes = listOf(
|
||||
ColorScheme(Pattern.compile("([\"'])(?:\\\\1|.)*?\\1"), Color.parseColor("#FC8500")),
|
||||
ColorScheme(Pattern.compile("yt-dlp"), Color.parseColor("#77eb09")),
|
||||
ColorScheme(Pattern.compile("(https?://(?:www\\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|www\\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|https?://(?:www\\.|(?!www))[a-zA-Z0-9]+\\.[^\\s]{2,}|www\\.[a-zA-Z0-9]+\\.[^\\s]{2,})"), Color.parseColor("#b5942f")),
|
||||
ColorScheme(Pattern.compile("\\d+(\\.\\d)?%"), Color.parseColor("#43a564"))
|
||||
)
|
||||
|
||||
fun View.enableTextHighlight(){
|
||||
if (this is EditText || this is TextView){
|
||||
//init syntax highlighter
|
||||
val highlight = Highlight()
|
||||
val highlightWatcher = HighlightTextWatcher()
|
||||
|
||||
highlight.addScheme(
|
||||
*textHighLightSchemes.map { it }.toTypedArray()
|
||||
)
|
||||
highlightWatcher.addScheme(
|
||||
*textHighLightSchemes.map { it }.toTypedArray()
|
||||
)
|
||||
|
||||
highlight.setSpan(this as TextView)
|
||||
this.addTextChangedListener(highlightWatcher)
|
||||
}
|
||||
}
|
||||
|
||||
fun EditText.setTextAndRecalculateWidth(t : String){
|
||||
val scale = context.resources.displayMetrics.density
|
||||
this.setText(t)
|
||||
val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
|
||||
val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
|
||||
this.measure(widthMeasureSpec, heightMeasureSpec)
|
||||
val requiredWidth: Int = this.measuredWidth
|
||||
if (t.length < 5){
|
||||
this.layoutParams.width = (70 * scale + 0.5F).toInt()
|
||||
}else{
|
||||
this.layoutParams.width = requiredWidth
|
||||
}
|
||||
this.requestLayout()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
fun RecyclerView.forceFastScrollMode()
|
||||
{
|
||||
overScrollMode = View.OVER_SCROLL_ALWAYS
|
||||
scrollBarStyle = View.SCROLLBARS_INSIDE_INSET
|
||||
isVerticalScrollBarEnabled = true
|
||||
setOnTouchListener { view, event ->
|
||||
if (event.x >= this.width - 30) {
|
||||
view.parent.requestDisallowInterceptTouchEvent(true)
|
||||
when (event.action and MotionEvent.ACTION_MASK) {
|
||||
MotionEvent.ACTION_UP -> view.parent.requestDisallowInterceptTouchEvent(false)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun RecyclerView.enableFastScroll(){
|
||||
val drawable = ShapeDrawable(OvalShape())
|
||||
drawable.paint.color = context.getColor(android.R.color.transparent)
|
||||
|
||||
FastScrollerBuilder(this)
|
||||
.setTrackDrawable(drawable)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
|
@ -638,7 +638,7 @@ class InfoUtil(private val context: Context) {
|
|||
val website = jsonObject.getString(listOf("ie_key", "extractor_key", "extractor").first { jsonObject.has(it) })
|
||||
var playlistTitle: String? = ""
|
||||
if (jsonObject.has("playlist_title")) playlistTitle = jsonObject.getString("playlist_title")
|
||||
if(playlistTitle.equals(query)) playlistTitle = ""
|
||||
if(playlistTitle?.removeSurrounding("\"").equals(query)) playlistTitle = ""
|
||||
|
||||
if (playlistTitle?.isNotBlank() == true){
|
||||
playlistTitle += "[${jsonObject.getString("playlist_index")}]"
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import android.view.ViewGroup
|
|||
import android.view.Window
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.Button
|
||||
import android.widget.CheckBox
|
||||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
|
|
@ -100,14 +101,24 @@ object UiUtil {
|
|||
formatCard.findViewById<TextView>(R.id.container).text = container.uppercase()
|
||||
formatCard.findViewById<TextView>(R.id.format_note).text = formatNote.uppercase()
|
||||
|
||||
val audioFormatsTextView = formatCard.findViewById<TextView>(R.id.audio_formats)
|
||||
if (!audioFormats.isNullOrEmpty()) {
|
||||
audioFormatsTextView.text = "id: " + audioFormats.joinToString("+") { it.format_id }
|
||||
audioFormatsTextView.visibility = View.VISIBLE
|
||||
}else{
|
||||
audioFormatsTextView.visibility = View.GONE
|
||||
formatCard.findViewById<TextView>(R.id.audio_formats).apply {
|
||||
if (!audioFormats.isNullOrEmpty()){
|
||||
text = "id: " + audioFormats.joinToString("+") { it.format_id }
|
||||
visibility = View.VISIBLE
|
||||
}else{
|
||||
visibility = View.GONE
|
||||
}
|
||||
setOnClickListener {
|
||||
formatCard.callOnClick()
|
||||
}
|
||||
}
|
||||
|
||||
formatCard.findViewById<TextView>(R.id.format_id).apply {
|
||||
text = "id: ${chosenFormat.format_id}"
|
||||
setOnClickListener {
|
||||
formatCard.callOnClick()
|
||||
}
|
||||
}
|
||||
formatCard.findViewById<TextView>(R.id.format_id).text = "id: ${chosenFormat.format_id}"
|
||||
val codec =
|
||||
if (chosenFormat.encoding != "") {
|
||||
chosenFormat.encoding.uppercase()
|
||||
|
|
@ -116,15 +127,28 @@ object UiUtil {
|
|||
} else {
|
||||
chosenFormat.acodec.uppercase()
|
||||
}
|
||||
if (codec == "" || codec == "none"){
|
||||
formatCard.findViewById<TextView>(R.id.codec).visibility = View.GONE
|
||||
}else{
|
||||
formatCard.findViewById<TextView>(R.id.codec).visibility = View.VISIBLE
|
||||
formatCard.findViewById<TextView>(R.id.codec).text = codec
|
||||
|
||||
formatCard.findViewById<TextView>(R.id.codec).apply {
|
||||
if (codec == "" || codec == "none"){
|
||||
visibility = View.GONE
|
||||
}else{
|
||||
visibility = View.VISIBLE
|
||||
text = codec
|
||||
}
|
||||
setOnClickListener {
|
||||
formatCard.callOnClick()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var filesize = chosenFormat.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).apply {
|
||||
text = FileUtil.convertFileSize(filesize)
|
||||
setOnClickListener {
|
||||
formatCard.callOnClick()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -144,6 +168,8 @@ object UiUtil {
|
|||
val title : TextInputLayout = bottomSheet.findViewById(R.id.title)!!
|
||||
val content : TextInputLayout = bottomSheet.findViewById(R.id.content)!!
|
||||
val extraCommandsSwitch : MaterialSwitch = bottomSheet.findViewById(R.id.extraCommandsSwitch)!!
|
||||
val extraCommandsAudio : CheckBox = bottomSheet.findViewById(R.id.checkbox_audio)!!
|
||||
val extraCommandsVideo : CheckBox = bottomSheet.findViewById(R.id.checkbox_video)!!
|
||||
val shortcutsChipGroup : ChipGroup = bottomSheet.findViewById(R.id.shortcutsChipGroup)!!
|
||||
val editShortcuts : Button = bottomSheet.findViewById(R.id.edit_shortcuts)!!
|
||||
|
||||
|
|
@ -194,8 +220,34 @@ object UiUtil {
|
|||
|
||||
if (item != null){
|
||||
extraCommandsSwitch.isChecked = item.useAsExtraCommand
|
||||
if (item.useAsExtraCommand){
|
||||
extraCommandsAudio.isVisible = true
|
||||
extraCommandsAudio.isChecked = item.useAsExtraCommandAudio
|
||||
extraCommandsVideo.isVisible = true
|
||||
extraCommandsVideo.isChecked = item.useAsExtraCommandVideo
|
||||
}else{
|
||||
extraCommandsAudio.isVisible = false
|
||||
extraCommandsAudio.isChecked = false
|
||||
extraCommandsVideo.isVisible = false
|
||||
extraCommandsVideo.isChecked = false
|
||||
}
|
||||
}
|
||||
|
||||
extraCommandsSwitch.setOnCheckedChangeListener { compoundButton, b ->
|
||||
extraCommandsAudio.isVisible = extraCommandsSwitch.isChecked
|
||||
extraCommandsAudio.isChecked = true
|
||||
extraCommandsVideo.isVisible = extraCommandsSwitch.isChecked
|
||||
extraCommandsVideo.isChecked = true
|
||||
}
|
||||
|
||||
extraCommandsAudio.setOnCheckedChangeListener { compoundButton, b ->
|
||||
ok.isEnabled = extraCommandsAudio.isChecked || extraCommandsVideo.isChecked
|
||||
}
|
||||
|
||||
extraCommandsVideo.setOnCheckedChangeListener { compoundButton, b ->
|
||||
ok.isEnabled = extraCommandsAudio.isChecked || extraCommandsVideo.isChecked
|
||||
}
|
||||
|
||||
commandTemplateViewModel.shortcuts.observe(lifeCycle){
|
||||
shortcutsChipGroup.removeAllViews()
|
||||
it.forEach {shortcut ->
|
||||
|
|
@ -214,13 +266,15 @@ object UiUtil {
|
|||
|
||||
ok.setOnClickListener {
|
||||
if (item == null){
|
||||
val t = CommandTemplate(0, title.editText!!.text.toString(), content.editText!!.text.toString(), extraCommandsSwitch.isChecked)
|
||||
val t = CommandTemplate(0, title.editText!!.text.toString(), content.editText!!.text.toString(), extraCommandsSwitch.isChecked, extraCommandsAudio.isChecked, extraCommandsVideo.isChecked)
|
||||
commandTemplateViewModel.insert(t)
|
||||
newTemplate(t)
|
||||
}else{
|
||||
item.title = title.editText!!.text.toString()
|
||||
item.content = content.editText!!.text.toString()
|
||||
item.useAsExtraCommand = extraCommandsSwitch.isChecked
|
||||
item.useAsExtraCommandAudio = extraCommandsAudio.isChecked
|
||||
item.useAsExtraCommandVideo = extraCommandsVideo.isChecked
|
||||
Log.e("aa", item.toString())
|
||||
commandTemplateViewModel.update(item)
|
||||
newTemplate(item)
|
||||
|
|
@ -1311,72 +1365,6 @@ object UiUtil {
|
|||
|
||||
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
fun RecyclerView.forceFastScrollMode()
|
||||
{
|
||||
overScrollMode = View.OVER_SCROLL_ALWAYS
|
||||
scrollBarStyle = View.SCROLLBARS_INSIDE_INSET
|
||||
isVerticalScrollBarEnabled = true
|
||||
setOnTouchListener { view, event ->
|
||||
if (event.x >= this.width - 30) {
|
||||
view.parent.requestDisallowInterceptTouchEvent(true)
|
||||
when (event.action and MotionEvent.ACTION_MASK) {
|
||||
MotionEvent.ACTION_UP -> view.parent.requestDisallowInterceptTouchEvent(false)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun RecyclerView.enableFastScroll(){
|
||||
val drawable = ShapeDrawable(OvalShape())
|
||||
drawable.paint.color = context.getColor(android.R.color.transparent)
|
||||
|
||||
FastScrollerBuilder(this)
|
||||
.setTrackDrawable(drawable)
|
||||
.build()
|
||||
}
|
||||
|
||||
private var textHighLightSchemes = listOf(
|
||||
ColorScheme(Pattern.compile("([\"'])(?:\\\\1|.)*?\\1"), Color.parseColor("#FC8500")),
|
||||
ColorScheme(Pattern.compile("yt-dlp"), Color.parseColor("#77eb09")),
|
||||
ColorScheme(Pattern.compile("(https?://(?:www\\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|www\\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|https?://(?:www\\.|(?!www))[a-zA-Z0-9]+\\.[^\\s]{2,}|www\\.[a-zA-Z0-9]+\\.[^\\s]{2,})"), Color.parseColor("#b5942f")),
|
||||
ColorScheme(Pattern.compile("\\d+(\\.\\d)?%"), Color.parseColor("#43a564"))
|
||||
)
|
||||
|
||||
fun View.enableTextHighlight(){
|
||||
if (this is EditText || this is TextView){
|
||||
//init syntax highlighter
|
||||
val highlight = Highlight()
|
||||
val highlightWatcher = HighlightTextWatcher()
|
||||
|
||||
highlight.addScheme(
|
||||
*textHighLightSchemes.map { it }.toTypedArray()
|
||||
)
|
||||
highlightWatcher.addScheme(
|
||||
*textHighLightSchemes.map { it }.toTypedArray()
|
||||
)
|
||||
|
||||
highlight.setSpan(this as TextView)
|
||||
this.addTextChangedListener(highlightWatcher)
|
||||
}
|
||||
}
|
||||
|
||||
fun EditText.setTextAndRecalculateWidth(t : String){
|
||||
val scale = context.resources.displayMetrics.density
|
||||
this.setText(t)
|
||||
val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
|
||||
val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
|
||||
this.measure(widthMeasureSpec, heightMeasureSpec)
|
||||
val requiredWidth: Int = this.measuredWidth
|
||||
if (t.length < 5){
|
||||
this.layoutParams.width = (70 * scale + 0.5F).toInt()
|
||||
}else{
|
||||
this.layoutParams.width = requiredWidth
|
||||
}
|
||||
this.requestLayout()
|
||||
}
|
||||
|
||||
fun handleResultResponse(context: Activity, it: ResultViewModel.ResultsUiState, closed: () -> Unit){
|
||||
val title = context.getString(it.errorMessage!!.first)
|
||||
val message = it.errorMessage!!.second
|
||||
|
|
|
|||
5
app/src/main/res/drawable/baseline_share2_24.xml
Normal file
5
app/src/main/res/drawable/baseline_share2_24.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?android:colorAccent" android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
|
||||
</vector>
|
||||
|
|
@ -46,6 +46,7 @@
|
|||
</HorizontalScrollView>
|
||||
|
||||
<View
|
||||
android:id="@+id/chipGroupDivider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
style="@style/Divider.Vertical"/>
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
</HorizontalScrollView>
|
||||
|
||||
<View
|
||||
android:id="@+id/chipGroupDivider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
style="@style/Divider.Vertical"/>
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
</HorizontalScrollView>
|
||||
|
||||
<View
|
||||
android:id="@+id/chipGroupDivider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
style="@style/Divider.Vertical"/>
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
</HorizontalScrollView>
|
||||
|
||||
<View
|
||||
android:id="@+id/chipGroupDivider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
style="@style/Divider.Vertical"/>
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@
|
|||
android:dividerPadding="5dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toTopOf="@+id/output"
|
||||
app:layout_constraintEnd_toStartOf="@+id/active_download_pause"
|
||||
app:layout_constraintEnd_toStartOf="@+id/active_pause_cancel_btns"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/linearlayout2_horizontalscrollview">
|
||||
|
|
@ -151,37 +151,55 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/active_download_pause"
|
||||
style="?attr/materialIconButtonFilledStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:backgroundTint="?attr/colorSurface"
|
||||
app:cornerRadius="15dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
app:icon="@drawable/exomedia_ic_play_arrow_white"
|
||||
app:iconSize="30dp"
|
||||
app:iconTint="?android:textColorPrimary"
|
||||
app:layout_constraintBottom_toTopOf="@+id/output"
|
||||
app:layout_constraintEnd_toStartOf="@id/active_download_delete"
|
||||
app:layout_constraintTop_toBottomOf="@+id/linearlayout2_horizontalscrollview"
|
||||
app:layout_constraintVertical_bias="0.51" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/active_download_delete"
|
||||
style="?attr/materialIconButtonFilledStyle"
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/active_pause_cancel_btns"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="5dp"
|
||||
app:backgroundTint="?attr/colorSurface"
|
||||
app:cornerRadius="15dp"
|
||||
app:icon="@drawable/baseline_delete_24"
|
||||
app:iconSize="30dp"
|
||||
app:iconTint="?android:textColorPrimary"
|
||||
android:orientation="horizontal"
|
||||
android:animateLayoutChanges="true"
|
||||
app:layout_constraintBottom_toTopOf="@+id/output"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginEnd="5dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/linearlayout2_horizontalscrollview"
|
||||
app:layout_constraintVertical_bias="0.51" />
|
||||
app:layout_constraintVertical_bias="0.51"
|
||||
>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/active_download_pause"
|
||||
style="?attr/materialIconButtonFilledStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layoutAnimation="@anim/popup_enter"
|
||||
app:backgroundTint="?attr/colorSurface"
|
||||
app:cornerRadius="15dp"
|
||||
app:icon="@drawable/exomedia_ic_play_arrow_white"
|
||||
app:iconSize="30dp"
|
||||
app:iconTint="?android:textColorPrimary"
|
||||
app:layout_constraintBottom_toTopOf="@+id/output"
|
||||
app:layout_constraintEnd_toStartOf="@id/active_download_delete"
|
||||
app:layout_constraintTop_toBottomOf="@+id/linearlayout2_horizontalscrollview"
|
||||
app:layout_constraintVertical_bias="0.51" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/active_download_delete"
|
||||
style="?attr/materialIconButtonFilledStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:backgroundTint="?attr/colorSurface"
|
||||
app:cornerRadius="15dp"
|
||||
app:icon="@drawable/baseline_delete_24"
|
||||
app:iconSize="30dp"
|
||||
app:iconTint="?android:textColorPrimary"
|
||||
app:layout_constraintBottom_toTopOf="@+id/output"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/linearlayout2_horizontalscrollview"
|
||||
app:layout_constraintVertical_bias="0.51" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/output"
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@
|
|||
android:ellipsize="end"
|
||||
android:text="@string/extra_command"
|
||||
android:gravity="center"
|
||||
android:maxLength="17"
|
||||
android:maxLines="1"
|
||||
android:minWidth="30dp"
|
||||
android:paddingHorizontal="5dp"
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
|
|
@ -103,17 +103,51 @@
|
|||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/extraCommandsSwitch"
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:checked="false"
|
||||
android:layout_marginHorizontal="5dp"
|
||||
android:textSize="15sp"
|
||||
android:text="@string/extra_command"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
android:layout_height="wrap_content"
|
||||
app:cardCornerRadius="20dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/extraCommandsSwitch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:checked="false"
|
||||
android:text="@string/extra_command"
|
||||
android:textSize="15sp"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/checkbox_audio"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:checked="true"
|
||||
android:text="@string/audio" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/checkbox_video"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:text="@string/video" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<View
|
||||
style="@style/Divider.Horizontal"
|
||||
|
|
@ -171,5 +205,4 @@
|
|||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -89,6 +89,8 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:layout_marginStart="10dp"
|
||||
android:scrollbars="none">
|
||||
|
||||
|
|
@ -115,6 +117,7 @@
|
|||
android:textStyle="bold"
|
||||
app:cornerRadius="10dp"
|
||||
app:drawableStartCompat="@drawable/ic_music"
|
||||
android:textCursorDrawable="@string/audio_format"
|
||||
app:drawableTint="@color/white"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
</HorizontalScrollView>
|
||||
|
||||
<View
|
||||
android:id="@+id/chipGroupDivider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
style="@style/Divider.Vertical"/>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
android:id="@+id/search_command"
|
||||
android:title="@string/search"
|
||||
android:icon="@drawable/ic_search"
|
||||
app:showAsAction="collapseActionView|ifRoom"
|
||||
app:showAsAction="always"
|
||||
app:actionViewClass="androidx.appcompat.widget.SearchView"/>
|
||||
|
||||
<item
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@
|
|||
android:id="@+id/search_history"
|
||||
android:title="@string/search"
|
||||
android:icon="@drawable/ic_search"
|
||||
app:showAsAction="collapseActionView|ifRoom"
|
||||
app:showAsAction="collapseActionView|always"
|
||||
app:actionViewClass="androidx.appcompat.widget.SearchView"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/download_queue"
|
||||
android:title="@string/download_queue"
|
||||
android:icon="@drawable/baseline_downloading_24"
|
||||
app:showAsAction="collapseActionView|ifRoom"/>
|
||||
app:showAsAction="always"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/remove_history"
|
||||
|
|
|
|||
|
|
@ -1017,4 +1017,24 @@
|
|||
<item>ko</item>
|
||||
</string-array>
|
||||
|
||||
<array name="swipe_gestures">
|
||||
<item>@string/downloads</item>
|
||||
<item>@string/in_queue</item>
|
||||
<item>@string/cancelled</item>
|
||||
<item>@string/errored</item>
|
||||
<item>@string/saved</item>
|
||||
<item>@string/command_templates</item>
|
||||
<item>@string/cookies</item>
|
||||
</array>
|
||||
|
||||
<array name="swipe_gestures_values">
|
||||
<item>history</item>
|
||||
<item>queued</item>
|
||||
<item>cancelled</item>
|
||||
<item>errored</item>
|
||||
<item>saved</item>
|
||||
<item>templates</item>
|
||||
<item>cookies</item>
|
||||
</array>
|
||||
|
||||
</resources>
|
||||
|
|
@ -6,9 +6,11 @@
|
|||
<ListPreference
|
||||
android:entries="@array/language_values"
|
||||
android:entryValues="@array/language_values"
|
||||
android:defaultValue=""
|
||||
android:icon="@drawable/baseline_translate_24"
|
||||
app:key="app_language"
|
||||
app:summary="en"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
app:summary=""
|
||||
app:title="@string/language" />
|
||||
|
||||
<ListPreference
|
||||
|
|
@ -110,18 +112,19 @@
|
|||
app:summary="@string/search_suggestions_summary"
|
||||
app:title="@string/search_suggestions" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:widgetLayout="@layout/preferece_material_switch"
|
||||
app:defaultValue="true"
|
||||
<MultiSelectListPreference
|
||||
android:icon="@drawable/baseline_swipe_24"
|
||||
android:key="swipe_gestures"
|
||||
android:key="swipe_gesture"
|
||||
android:entries="@array/swipe_gestures"
|
||||
android:entryValues="@array/swipe_gestures_values"
|
||||
android:defaultValue="@array/swipe_gestures_values"
|
||||
app:summary="@string/swipe_gestures_summary"
|
||||
app:title="@string/swipe_gestures" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:widgetLayout="@layout/preferece_material_switch"
|
||||
app:defaultValue="false"
|
||||
android:icon="@drawable/baseline_share_24"
|
||||
android:icon="@drawable/baseline_share2_24"
|
||||
android:key="show_terminal"
|
||||
app:title="@string/show_terminal" />
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ buildscript {
|
|||
coroutineVer = '1.7.3'
|
||||
retrofitVer = "2.9.0"
|
||||
kodeinVer = "7.16.0"
|
||||
navVer = "2.7.4"
|
||||
navVer = "2.7.5"
|
||||
media3_version = "1.1.1"
|
||||
agp_version = '8.1.0'
|
||||
agp_version1 = '7.4.2'
|
||||
|
|
|
|||
Loading…
Reference in a new issue