history revamp paginated wip
This commit is contained in:
parent
0c00ab350d
commit
8ae2a4d8a3
24 changed files with 2249 additions and 322 deletions
753
app/schemas/com.deniscerri.ytdl.database.DBManager/20.json
Normal file
753
app/schemas/com.deniscerri.ytdl.database.DBManager/20.json
Normal file
|
|
@ -0,0 +1,753 @@
|
||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 20,
|
||||||
|
"identityHash": "3be2d00eeed0d077b84c352d10f6628f",
|
||||||
|
"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, `playlistURL` TEXT DEFAULT '', `playlistIndex` INTEGER, `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": "playlistURL",
|
||||||
|
"columnName": "playlistURL",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false,
|
||||||
|
"defaultValue": "''"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistIndex",
|
||||||
|
"columnName": "playlistIndex",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"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, `filesize` INTEGER NOT NULL DEFAULT 0, `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": "filesize",
|
||||||
|
"columnName": "filesize",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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, `playlistURL` TEXT DEFAULT '', `playlistIndex` INTEGER, `incognito` INTEGER NOT NULL DEFAULT 0)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "title",
|
||||||
|
"columnName": "title",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "author",
|
||||||
|
"columnName": "author",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumb",
|
||||||
|
"columnName": "thumb",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "duration",
|
||||||
|
"columnName": "duration",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "format",
|
||||||
|
"columnName": "format",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "container",
|
||||||
|
"columnName": "container",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "'Default'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadSections",
|
||||||
|
"columnName": "downloadSections",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "''"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "allFormats",
|
||||||
|
"columnName": "allFormats",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadPath",
|
||||||
|
"columnName": "downloadPath",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "website",
|
||||||
|
"columnName": "website",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadSize",
|
||||||
|
"columnName": "downloadSize",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistTitle",
|
||||||
|
"columnName": "playlistTitle",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "audioPreferences",
|
||||||
|
"columnName": "audioPreferences",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "videoPreferences",
|
||||||
|
"columnName": "videoPreferences",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "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
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistURL",
|
||||||
|
"columnName": "playlistURL",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false,
|
||||||
|
"defaultValue": "''"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistIndex",
|
||||||
|
"columnName": "playlistIndex",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "incognito",
|
||||||
|
"columnName": "incognito",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "commandTemplates",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `useAsExtraCommand` INTEGER NOT NULL DEFAULT 0, `useAsExtraCommandAudio` INTEGER NOT NULL DEFAULT 1, `useAsExtraCommandVideo` INTEGER NOT NULL DEFAULT 1, `useAsExtraCommandDataFetching` INTEGER NOT NULL DEFAULT 0)",
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "useAsExtraCommandDataFetching",
|
||||||
|
"columnName": "useAsExtraCommandDataFetching",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "sources",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `downloadItemTemplate` TEXT NOT NULL, `everyNr` INTEGER NOT NULL, `everyCategory` TEXT NOT NULL, `everyTime` INTEGER NOT NULL, `weeklyConfig` TEXT, `monthlyConfig` TEXT, `status` TEXT NOT NULL, `startsTime` INTEGER NOT NULL, `endsDate` INTEGER NOT NULL DEFAULT 0, `endsAfterCount` INTEGER NOT NULL DEFAULT 0, `runCount` INTEGER NOT NULL DEFAULT 0, `getOnlyNewUploads` INTEGER NOT NULL DEFAULT 0, `retryMissingDownloads` INTEGER NOT NULL, `ignoredLinks` TEXT NOT NULL DEFAULT '[]', `alreadyProcessedLinks` TEXT NOT NULL, `syncWithSource` INTEGER NOT NULL DEFAULT 0)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadItemTemplate",
|
||||||
|
"columnName": "downloadItemTemplate",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "everyNr",
|
||||||
|
"columnName": "everyNr",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "everyCategory",
|
||||||
|
"columnName": "everyCategory",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "everyTime",
|
||||||
|
"columnName": "everyTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "weeklyConfig",
|
||||||
|
"columnName": "weeklyConfig",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "monthlyConfig",
|
||||||
|
"columnName": "monthlyConfig",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "status",
|
||||||
|
"columnName": "status",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "startsTime",
|
||||||
|
"columnName": "startsTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "endsDate",
|
||||||
|
"columnName": "endsDate",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "endsAfterCount",
|
||||||
|
"columnName": "endsAfterCount",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "runCount",
|
||||||
|
"columnName": "runCount",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "getOnlyNewUploads",
|
||||||
|
"columnName": "getOnlyNewUploads",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "retryMissingDownloads",
|
||||||
|
"columnName": "retryMissingDownloads",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "ignoredLinks",
|
||||||
|
"columnName": "ignoredLinks",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "'[]'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "alreadyProcessedLinks",
|
||||||
|
"columnName": "alreadyProcessedLinks",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "syncWithSource",
|
||||||
|
"columnName": "syncWithSource",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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, '3be2d00eeed0d077b84c352d10f6628f')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
753
app/schemas/com.deniscerri.ytdl.database.DBManager/21.json
Normal file
753
app/schemas/com.deniscerri.ytdl.database.DBManager/21.json
Normal file
|
|
@ -0,0 +1,753 @@
|
||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 21,
|
||||||
|
"identityHash": "3be2d00eeed0d077b84c352d10f6628f",
|
||||||
|
"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, `playlistURL` TEXT DEFAULT '', `playlistIndex` INTEGER, `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": "playlistURL",
|
||||||
|
"columnName": "playlistURL",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false,
|
||||||
|
"defaultValue": "''"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistIndex",
|
||||||
|
"columnName": "playlistIndex",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"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, `filesize` INTEGER NOT NULL DEFAULT 0, `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": "filesize",
|
||||||
|
"columnName": "filesize",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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, `playlistURL` TEXT DEFAULT '', `playlistIndex` INTEGER, `incognito` INTEGER NOT NULL DEFAULT 0)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "title",
|
||||||
|
"columnName": "title",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "author",
|
||||||
|
"columnName": "author",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumb",
|
||||||
|
"columnName": "thumb",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "duration",
|
||||||
|
"columnName": "duration",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "format",
|
||||||
|
"columnName": "format",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "container",
|
||||||
|
"columnName": "container",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "'Default'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadSections",
|
||||||
|
"columnName": "downloadSections",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "''"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "allFormats",
|
||||||
|
"columnName": "allFormats",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadPath",
|
||||||
|
"columnName": "downloadPath",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "website",
|
||||||
|
"columnName": "website",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadSize",
|
||||||
|
"columnName": "downloadSize",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistTitle",
|
||||||
|
"columnName": "playlistTitle",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "audioPreferences",
|
||||||
|
"columnName": "audioPreferences",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "videoPreferences",
|
||||||
|
"columnName": "videoPreferences",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "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
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistURL",
|
||||||
|
"columnName": "playlistURL",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false,
|
||||||
|
"defaultValue": "''"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistIndex",
|
||||||
|
"columnName": "playlistIndex",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "incognito",
|
||||||
|
"columnName": "incognito",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "commandTemplates",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL, `useAsExtraCommand` INTEGER NOT NULL DEFAULT 0, `useAsExtraCommandAudio` INTEGER NOT NULL DEFAULT 1, `useAsExtraCommandVideo` INTEGER NOT NULL DEFAULT 1, `useAsExtraCommandDataFetching` INTEGER NOT NULL DEFAULT 0)",
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "useAsExtraCommandDataFetching",
|
||||||
|
"columnName": "useAsExtraCommandDataFetching",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "sources",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `downloadItemTemplate` TEXT NOT NULL, `everyNr` INTEGER NOT NULL, `everyCategory` TEXT NOT NULL, `everyTime` INTEGER NOT NULL, `weeklyConfig` TEXT, `monthlyConfig` TEXT, `status` TEXT NOT NULL, `startsTime` INTEGER NOT NULL, `endsDate` INTEGER NOT NULL DEFAULT 0, `endsAfterCount` INTEGER NOT NULL DEFAULT 0, `runCount` INTEGER NOT NULL DEFAULT 0, `getOnlyNewUploads` INTEGER NOT NULL DEFAULT 0, `retryMissingDownloads` INTEGER NOT NULL, `ignoredLinks` TEXT NOT NULL DEFAULT '[]', `alreadyProcessedLinks` TEXT NOT NULL, `syncWithSource` INTEGER NOT NULL DEFAULT 0)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "downloadItemTemplate",
|
||||||
|
"columnName": "downloadItemTemplate",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "everyNr",
|
||||||
|
"columnName": "everyNr",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "everyCategory",
|
||||||
|
"columnName": "everyCategory",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "everyTime",
|
||||||
|
"columnName": "everyTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "weeklyConfig",
|
||||||
|
"columnName": "weeklyConfig",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "monthlyConfig",
|
||||||
|
"columnName": "monthlyConfig",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "status",
|
||||||
|
"columnName": "status",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "startsTime",
|
||||||
|
"columnName": "startsTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "endsDate",
|
||||||
|
"columnName": "endsDate",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "endsAfterCount",
|
||||||
|
"columnName": "endsAfterCount",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "runCount",
|
||||||
|
"columnName": "runCount",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "getOnlyNewUploads",
|
||||||
|
"columnName": "getOnlyNewUploads",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "retryMissingDownloads",
|
||||||
|
"columnName": "retryMissingDownloads",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "ignoredLinks",
|
||||||
|
"columnName": "ignoredLinks",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "'[]'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "alreadyProcessedLinks",
|
||||||
|
"columnName": "alreadyProcessedLinks",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "syncWithSource",
|
||||||
|
"columnName": "syncWithSource",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true,
|
||||||
|
"defaultValue": "0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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, '3be2d00eeed0d077b84c352d10f6628f')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -52,8 +52,6 @@ import com.deniscerri.ytdl.ui.downloads.DownloadQueueMainFragment
|
||||||
import com.deniscerri.ytdl.ui.downloads.HistoryFragment
|
import com.deniscerri.ytdl.ui.downloads.HistoryFragment
|
||||||
import com.deniscerri.ytdl.ui.more.settings.SettingsActivity
|
import com.deniscerri.ytdl.ui.more.settings.SettingsActivity
|
||||||
import com.deniscerri.ytdl.util.CrashListener
|
import com.deniscerri.ytdl.util.CrashListener
|
||||||
import com.deniscerri.ytdl.util.Extensions.extractURL
|
|
||||||
import com.deniscerri.ytdl.util.FileUtil
|
|
||||||
import com.deniscerri.ytdl.util.NavbarUtil
|
import com.deniscerri.ytdl.util.NavbarUtil
|
||||||
import com.deniscerri.ytdl.util.NavbarUtil.applyNavBarStyle
|
import com.deniscerri.ytdl.util.NavbarUtil.applyNavBarStyle
|
||||||
import com.deniscerri.ytdl.util.ThemeUtil
|
import com.deniscerri.ytdl.util.ThemeUtil
|
||||||
|
|
@ -440,7 +438,7 @@ class MainActivity : BaseActivity() {
|
||||||
textBuilder.append(c.toChar())
|
textBuilder.append(c.toChar())
|
||||||
}
|
}
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putString("url", textBuilder.toString().extractURL())
|
bundle.putString("url", textBuilder.toString())
|
||||||
navController.popBackStack(R.id.homeFragment, true)
|
navController.popBackStack(R.id.homeFragment, true)
|
||||||
navController.navigate(
|
navController.navigate(
|
||||||
R.id.homeFragment,
|
R.id.homeFragment,
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ import com.deniscerri.ytdl.database.models.TerminalItem
|
||||||
TerminalItem::class,
|
TerminalItem::class,
|
||||||
ObserveSourcesItem::class
|
ObserveSourcesItem::class
|
||||||
],
|
],
|
||||||
version = 19,
|
version = 21,
|
||||||
autoMigrations = [
|
autoMigrations = [
|
||||||
AutoMigration (from = 1, to = 2),
|
AutoMigration (from = 1, to = 2),
|
||||||
AutoMigration (from = 2, to = 3),
|
AutoMigration (from = 2, to = 3),
|
||||||
|
|
@ -61,6 +61,8 @@ import com.deniscerri.ytdl.database.models.TerminalItem
|
||||||
AutoMigration (from = 16, to = 17),
|
AutoMigration (from = 16, to = 17),
|
||||||
AutoMigration (from = 17, to = 18),
|
AutoMigration (from = 17, to = 18),
|
||||||
AutoMigration (from = 18, to = 19),
|
AutoMigration (from = 18, to = 19),
|
||||||
|
AutoMigration (from = 19, to = 20),
|
||||||
|
//AutoMigration (from = 20, to = 21) MANUALLY HANDLED
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
abstract class DBManager : RoomDatabase(){
|
abstract class DBManager : RoomDatabase(){
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import androidx.room.DeleteTable
|
||||||
import androidx.room.migration.AutoMigrationSpec
|
import androidx.room.migration.AutoMigrationSpec
|
||||||
import androidx.room.migration.Migration
|
import androidx.room.migration.Migration
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
|
import com.deniscerri.ytdl.database.models.Format
|
||||||
|
import com.google.gson.Gson
|
||||||
|
|
||||||
|
|
||||||
object Migrations {
|
object Migrations {
|
||||||
|
|
@ -28,6 +30,19 @@ object Migrations {
|
||||||
// Migration(17, 18 ){ database ->
|
// Migration(17, 18 ){ database ->
|
||||||
// database.execSQL("ALTER TABLE `sources` ADD COLUMN `syncWithSource` INTEGER NOT NULL DEFAULT 0")
|
// database.execSQL("ALTER TABLE `sources` ADD COLUMN `syncWithSource` INTEGER NOT NULL DEFAULT 0")
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
//add filesizes to history
|
||||||
|
Migration(20, 21) { database ->
|
||||||
|
val cursor = database.query("SELECT * FROM history")
|
||||||
|
while(cursor.moveToNext()) {
|
||||||
|
kotlin.runCatching {
|
||||||
|
val id = cursor.getLong(cursor.getColumnIndex("id"))
|
||||||
|
val format = cursor.getString(cursor.getColumnIndex("format"))
|
||||||
|
val parsed = Gson().fromJson(format, Format::class.java)
|
||||||
|
database.execSQL("UPDATE history SET filesize = ${parsed.filesize} WHERE id = $id")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@DeleteTable.Entries(
|
@DeleteTable.Entries(
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
package com.deniscerri.ytdl.database.dao
|
package com.deniscerri.ytdl.database.dao
|
||||||
|
|
||||||
|
import androidx.paging.PagingSource
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
import androidx.room.OnConflictStrategy
|
import androidx.room.OnConflictStrategy
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import androidx.room.Update
|
import androidx.room.Update
|
||||||
|
import com.deniscerri.ytdl.database.models.DownloadItem
|
||||||
import com.deniscerri.ytdl.database.models.HistoryItem
|
import com.deniscerri.ytdl.database.models.HistoryItem
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
|
@ -30,9 +32,44 @@ interface HistoryDao {
|
||||||
fun getHistorySortedByAuthor(query : String, type : String, site : String, sort : String) : List<HistoryItem>
|
fun getHistorySortedByAuthor(query : String, type : String, site : String, sort : String) : List<HistoryItem>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Query("SELECT * FROM history WHERE (title LIKE '%'||:query||'%' OR author LIKE '%'||:query||'%') AND type LIKE '%'||:type||'%' AND website LIKE '%'||:site||'%' ORDER BY " +
|
||||||
|
"CASE WHEN :sort = 'ASC' THEN id END ASC," +
|
||||||
|
"CASE WHEN :sort = 'DESC' THEN id END DESC," +
|
||||||
|
"CASE WHEN :sort = '' THEN id END DESC ")
|
||||||
|
fun getHistorySortedByIDPaginated(query : String, type : String, site : String, sort : String) : PagingSource<Int, HistoryItem>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM history WHERE (title LIKE '%'||:query||'%' OR author LIKE '%'||:query||'%') AND type LIKE '%'||:type||'%' AND website LIKE '%'||:site||'%' ORDER BY " +
|
||||||
|
"CASE WHEN :sort = 'ASC' THEN title END ASC," +
|
||||||
|
"CASE WHEN :sort = 'DESC' THEN title END DESC," +
|
||||||
|
"CASE WHEN :sort = '' THEN title END DESC ")
|
||||||
|
fun getHistorySortedByTitlePaginated(query : String, type : String, site : String, sort : String) : PagingSource<Int, HistoryItem>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM history WHERE (title LIKE '%'||:query||'%' OR author LIKE '%'||:query||'%') AND type LIKE '%'||:type||'%' AND website LIKE '%'||:site||'%' ORDER BY " +
|
||||||
|
"CASE WHEN :sort = 'ASC' THEN author END ASC," +
|
||||||
|
"CASE WHEN :sort = 'DESC' THEN author END DESC," +
|
||||||
|
"CASE WHEN :sort = '' THEN author END DESC ")
|
||||||
|
fun getHistorySortedByAuthorPaginated(query : String, type : String, site : String, sort : String) : PagingSource<Int, HistoryItem>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM history WHERE (title LIKE '%'||:query||'%' OR author LIKE '%'||:query||'%') AND type LIKE '%'||:type||'%' AND website LIKE '%'||:site||'%' ORDER BY " +
|
||||||
|
"CASE WHEN :sort = 'ASC' THEN filesize END ASC," +
|
||||||
|
"CASE WHEN :sort = 'DESC' THEN filesize END DESC," +
|
||||||
|
"CASE WHEN :sort = '' THEN filesize END DESC ")
|
||||||
|
fun getHistorySortedByFilesizePaginated(query : String, type : String, site : String, sort : String) : PagingSource<Int, HistoryItem>
|
||||||
|
|
||||||
|
|
||||||
@Query("SELECT * FROM history")
|
@Query("SELECT * FROM history")
|
||||||
fun getAllHistory() : Flow<List<HistoryItem>>
|
fun getAllHistory() : Flow<List<HistoryItem>>
|
||||||
|
|
||||||
|
@Query("SELECT DISTINCT website FROM history")
|
||||||
|
fun getWebsites() : Flow<List<String>>
|
||||||
|
|
||||||
|
@Query("SELECT COUNT(*) FROM history")
|
||||||
|
fun getCount() : Flow<Int>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM history")
|
||||||
|
fun getAllHistoryPaginated() : PagingSource<Int, HistoryItem>
|
||||||
|
|
||||||
@Query("SELECT * FROM history")
|
@Query("SELECT * FROM history")
|
||||||
fun getAllHistoryList() : List<HistoryItem>
|
fun getAllHistoryList() : List<HistoryItem>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,5 +17,7 @@ data class CommandTemplate(
|
||||||
@ColumnInfo(defaultValue = "1")
|
@ColumnInfo(defaultValue = "1")
|
||||||
var useAsExtraCommandAudio: Boolean,
|
var useAsExtraCommandAudio: Boolean,
|
||||||
@ColumnInfo(defaultValue = "1")
|
@ColumnInfo(defaultValue = "1")
|
||||||
var useAsExtraCommandVideo: Boolean
|
var useAsExtraCommandVideo: Boolean,
|
||||||
|
@ColumnInfo(defaultValue = "0")
|
||||||
|
var useAsExtraCommandDataFetching: Boolean
|
||||||
)
|
)
|
||||||
|
|
@ -20,6 +20,8 @@ data class HistoryItem(
|
||||||
val website: String,
|
val website: String,
|
||||||
val format: Format,
|
val format: Format,
|
||||||
@ColumnInfo(defaultValue = "0")
|
@ColumnInfo(defaultValue = "0")
|
||||||
|
val filesize: Long = 0,
|
||||||
|
@ColumnInfo(defaultValue = "0")
|
||||||
val downloadId: Long,
|
val downloadId: Long,
|
||||||
@ColumnInfo(defaultValue = "")
|
@ColumnInfo(defaultValue = "")
|
||||||
val command: String = ""
|
val command: String = ""
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
package com.deniscerri.ytdl.database.repository
|
package com.deniscerri.ytdl.database.repository
|
||||||
|
|
||||||
|
import androidx.paging.Pager
|
||||||
|
import androidx.paging.PagingConfig
|
||||||
|
import androidx.paging.PagingData
|
||||||
|
import androidx.paging.PagingSource
|
||||||
|
import androidx.paging.filter
|
||||||
import com.deniscerri.ytdl.database.DBManager.SORTING
|
import com.deniscerri.ytdl.database.DBManager.SORTING
|
||||||
import com.deniscerri.ytdl.database.dao.HistoryDao
|
import com.deniscerri.ytdl.database.dao.HistoryDao
|
||||||
import com.deniscerri.ytdl.database.models.HistoryItem
|
import com.deniscerri.ytdl.database.models.HistoryItem
|
||||||
|
|
@ -7,9 +12,12 @@ import com.deniscerri.ytdl.database.viewmodel.HistoryViewModel
|
||||||
import com.deniscerri.ytdl.util.FileUtil
|
import com.deniscerri.ytdl.util.FileUtil
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
class HistoryRepository(private val historyDao: HistoryDao) {
|
class HistoryRepository(private val historyDao: HistoryDao) {
|
||||||
val items : Flow<List<HistoryItem>> = historyDao.getAllHistory()
|
val items : Flow<List<HistoryItem>> = historyDao.getAllHistory()
|
||||||
|
val websites : Flow<List<String>> = historyDao.getWebsites()
|
||||||
|
val count : Flow<Int> = historyDao.getCount()
|
||||||
|
|
||||||
enum class HistorySortType {
|
enum class HistorySortType {
|
||||||
DATE, TITLE, AUTHOR, FILESIZE
|
DATE, TITLE, AUTHOR, FILESIZE
|
||||||
|
|
@ -27,6 +35,7 @@ class HistoryRepository(private val historyDao: HistoryDao) {
|
||||||
return historyDao.getAllHistoryByURL(url)
|
return historyDao.getAllHistoryByURL(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun getFiltered(query : String, type : String, site : String, sortType: HistorySortType, sort: SORTING, statusFilter: HistoryViewModel.HistoryStatus) : List<HistoryItem> {
|
fun getFiltered(query : String, type : String, site : String, sortType: HistorySortType, sort: SORTING, statusFilter: HistoryViewModel.HistoryStatus) : List<HistoryItem> {
|
||||||
var filtered = when(sortType){
|
var filtered = when(sortType){
|
||||||
HistorySortType.DATE -> historyDao.getHistorySortedByID(query, type, site, sort.toString())
|
HistorySortType.DATE -> historyDao.getHistorySortedByID(query, type, site, sort.toString())
|
||||||
|
|
@ -54,6 +63,20 @@ class HistoryRepository(private val historyDao: HistoryDao) {
|
||||||
return filtered
|
return filtered
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getPaginatedSource(query : String, type : String, site : String, sortType: HistorySortType, sort: SORTING) : PagingSource<Int, HistoryItem> {
|
||||||
|
val source = when(sortType){
|
||||||
|
HistorySortType.DATE -> historyDao.getHistorySortedByIDPaginated(query, type, site, sort.toString())
|
||||||
|
HistorySortType.TITLE -> historyDao.getHistorySortedByTitlePaginated(query, type, site, sort.toString())
|
||||||
|
HistorySortType.AUTHOR -> historyDao.getHistorySortedByAuthorPaginated(query, type, site, sort.toString())
|
||||||
|
HistorySortType.FILESIZE -> {
|
||||||
|
historyDao.getHistorySortedByFilesizePaginated(query, type, site, sort.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return source
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
suspend fun insert(item: HistoryItem){
|
suspend fun insert(item: HistoryItem){
|
||||||
historyDao.insert(item)
|
historyDao.insert(item)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -550,7 +550,7 @@ class DownloadViewModel(private val application: Application) : AndroidViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
return generateCommandFormat(
|
return generateCommandFormat(
|
||||||
c ?: CommandTemplate(0, "", preferredTemplateContent, useAsExtraCommand = false, useAsExtraCommandAudio = false, useAsExtraCommandVideo = false)
|
c ?: CommandTemplate(0, "", preferredTemplateContent, useAsExtraCommand = false, useAsExtraCommandAudio = false, useAsExtraCommandVideo = false, useAsExtraCommandDataFetching = false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,68 +6,109 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MediatorLiveData
|
import androidx.lifecycle.MediatorLiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.asLiveData
|
import androidx.lifecycle.asLiveData
|
||||||
|
import androidx.lifecycle.switchMap
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.paging.Pager
|
||||||
|
import androidx.paging.PagingConfig
|
||||||
|
import androidx.paging.PagingData
|
||||||
|
import androidx.paging.cachedIn
|
||||||
|
import androidx.paging.filter
|
||||||
import com.deniscerri.ytdl.database.DBManager
|
import com.deniscerri.ytdl.database.DBManager
|
||||||
import com.deniscerri.ytdl.database.DBManager.SORTING
|
import com.deniscerri.ytdl.database.DBManager.SORTING
|
||||||
import com.deniscerri.ytdl.database.models.HistoryItem
|
import com.deniscerri.ytdl.database.models.HistoryItem
|
||||||
import com.deniscerri.ytdl.database.repository.DownloadRepository
|
|
||||||
import com.deniscerri.ytdl.database.repository.HistoryRepository
|
import com.deniscerri.ytdl.database.repository.HistoryRepository
|
||||||
import com.deniscerri.ytdl.database.repository.HistoryRepository.HistorySortType
|
import com.deniscerri.ytdl.database.repository.HistoryRepository.HistorySortType
|
||||||
import com.deniscerri.ytdl.util.Extensions
|
import com.deniscerri.ytdl.util.Extensions
|
||||||
|
import com.deniscerri.ytdl.util.FileUtil
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.buffer
|
||||||
|
import kotlinx.coroutines.flow.cache
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
|
import kotlinx.coroutines.flow.flattenMerge
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.merge
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
class HistoryViewModel(application: Application) : AndroidViewModel(application) {
|
class HistoryViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
private val repository : HistoryRepository
|
private val repository : HistoryRepository
|
||||||
val sortOrder = MutableLiveData(SORTING.DESC)
|
val sortOrder = MutableStateFlow(SORTING.DESC)
|
||||||
val sortType = MutableLiveData(HistorySortType.DATE)
|
val sortType = MutableStateFlow(HistorySortType.DATE)
|
||||||
val websiteFilter = MutableLiveData("")
|
val websiteFilter = MutableStateFlow("")
|
||||||
val statusFilter = MutableLiveData(HistoryStatus.ALL)
|
val statusFilter = MutableStateFlow(HistoryStatus.ALL)
|
||||||
private val queryFilter = MutableLiveData("")
|
private val queryFilter = MutableStateFlow("")
|
||||||
private val typeFilter = MutableLiveData("")
|
private val typeFilter = MutableStateFlow("")
|
||||||
|
|
||||||
enum class HistoryStatus {
|
enum class HistoryStatus {
|
||||||
UNSET, DELETED, NOT_DELETED, ALL
|
UNSET, DELETED, NOT_DELETED, ALL
|
||||||
}
|
}
|
||||||
|
|
||||||
val allItems : LiveData<List<HistoryItem>>
|
|
||||||
private var _items = MediatorLiveData<List<HistoryItem>>()
|
private var _items = MediatorLiveData<List<HistoryItem>>()
|
||||||
|
|
||||||
|
var paginatedItems : Flow<PagingData<HistoryItem>>
|
||||||
|
var websites : Flow<List<String>>
|
||||||
|
var totalCount : Flow<Int>
|
||||||
|
|
||||||
|
data class HistoryFilters(
|
||||||
|
var type: String = "",
|
||||||
|
var sortType: HistorySortType = HistorySortType.DATE,
|
||||||
|
var sortOrder: SORTING = SORTING.DESC,
|
||||||
|
var query: String = "",
|
||||||
|
var status: HistoryStatus = HistoryStatus.ALL,
|
||||||
|
var website: String = ""
|
||||||
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val dao = DBManager.getInstance(application).historyDao
|
val dao = DBManager.getInstance(application).historyDao
|
||||||
repository = HistoryRepository(dao)
|
repository = HistoryRepository(dao)
|
||||||
allItems = repository.items.asLiveData()
|
websites = repository.websites
|
||||||
_items.addSource(allItems){
|
totalCount = repository.count
|
||||||
filter(queryFilter.value!!, typeFilter.value!!, websiteFilter.value!!, sortType.value!!, sortOrder.value!!, statusFilter.value!!)
|
|
||||||
}
|
|
||||||
_items.addSource(typeFilter){
|
|
||||||
filter(queryFilter.value!!, typeFilter.value!!, websiteFilter.value!!, sortType.value!!, sortOrder.value!!, statusFilter.value!!)
|
|
||||||
}
|
|
||||||
_items.addSource(sortType){
|
|
||||||
filter(queryFilter.value!!, typeFilter.value!!, websiteFilter.value!!, sortType.value!!, sortOrder.value!!, statusFilter.value!!)
|
|
||||||
}
|
|
||||||
_items.addSource(websiteFilter){
|
|
||||||
filter(queryFilter.value!!, typeFilter.value!!, websiteFilter.value!!, sortType.value!!, sortOrder.value!!, statusFilter.value!!)
|
|
||||||
}
|
|
||||||
_items.addSource(queryFilter){
|
|
||||||
filter(queryFilter.value!!, typeFilter.value!!, websiteFilter.value!!, sortType.value!!, sortOrder.value!!, statusFilter.value!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
_items.addSource(statusFilter){
|
val filters = listOf(dao.getAllHistory(), sortOrder, sortType, websiteFilter, statusFilter, queryFilter, typeFilter)
|
||||||
filter(queryFilter.value!!, typeFilter.value!!, websiteFilter.value!!, sortType.value!!, sortOrder.value!!, statusFilter.value!!)
|
paginatedItems = combine(filters) { f ->
|
||||||
}
|
val sortOrder = f[1] as SORTING
|
||||||
|
val sortType = f[2] as HistorySortType
|
||||||
|
val website = f[3] as String
|
||||||
|
val status = f[4] as HistoryStatus
|
||||||
|
val query = f[5] as String
|
||||||
|
val type = f[6] as String
|
||||||
|
|
||||||
}
|
var pager = Pager(
|
||||||
|
config = PagingConfig(pageSize = 20, initialLoadSize = 20, prefetchDistance = 1),
|
||||||
|
pagingSourceFactory = {
|
||||||
|
repository.getPaginatedSource(query, type, website, sortType, sortOrder)
|
||||||
|
}
|
||||||
|
).flow
|
||||||
|
|
||||||
fun getFilteredList() : LiveData<List<HistoryItem>>{
|
when(status) {
|
||||||
return _items
|
HistoryStatus.DELETED -> {
|
||||||
|
pager = pager.map {
|
||||||
|
it.filter { it2 ->
|
||||||
|
it2.downloadPath.any { it3 ->
|
||||||
|
!FileUtil.exists(it3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HistoryStatus.NOT_DELETED -> {
|
||||||
|
pager = pager.map {
|
||||||
|
it.filter { it2 ->
|
||||||
|
it2.downloadPath.any { it3 ->
|
||||||
|
FileUtil.exists(it3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pager
|
||||||
|
}.flatMapLatest { it }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSorting(sort: HistorySortType){
|
fun setSorting(sort: HistorySortType){
|
||||||
|
|
@ -98,7 +139,8 @@ class HistoryViewModel(application: Application) : AndroidViewModel(application)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun filter(query : String, format : String, site : String, sortType: HistorySortType, sort: SORTING, statusFilter: HistoryStatus) = viewModelScope.launch(Dispatchers.IO){
|
private fun filter(query : String, format : String, site : String, sortType: HistorySortType, sort: SORTING, statusFilter: HistoryStatus) = viewModelScope.launch(Dispatchers.IO){
|
||||||
_items.postValue(repository.getFiltered(query, format, site, sortType, sort, statusFilter))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAll() : List<HistoryItem> {
|
fun getAll() : List<HistoryItem> {
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,6 @@ import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
|
||||||
import com.deniscerri.ytdl.ui.BaseActivity
|
import com.deniscerri.ytdl.ui.BaseActivity
|
||||||
import com.deniscerri.ytdl.util.Extensions.extractURL
|
import com.deniscerri.ytdl.util.Extensions.extractURL
|
||||||
import com.deniscerri.ytdl.util.ThemeUtil
|
import com.deniscerri.ytdl.util.ThemeUtil
|
||||||
import com.deniscerri.ytdl.util.UiUtil
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
|
@ -50,7 +48,6 @@ import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
import kotlin.system.exitProcess
|
|
||||||
|
|
||||||
|
|
||||||
class ShareActivity : BaseActivity() {
|
class ShareActivity : BaseActivity() {
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ import com.deniscerri.ytdl.ui.adapter.SearchSuggestionsAdapter
|
||||||
import com.deniscerri.ytdl.ui.downloads.HistoryFragment
|
import com.deniscerri.ytdl.ui.downloads.HistoryFragment
|
||||||
import com.deniscerri.ytdl.ui.downloads.HistoryFragment.Companion
|
import com.deniscerri.ytdl.ui.downloads.HistoryFragment.Companion
|
||||||
import com.deniscerri.ytdl.util.Extensions.enableFastScroll
|
import com.deniscerri.ytdl.util.Extensions.enableFastScroll
|
||||||
|
import com.deniscerri.ytdl.util.Extensions.isURL
|
||||||
import com.deniscerri.ytdl.util.NotificationUtil
|
import com.deniscerri.ytdl.util.NotificationUtil
|
||||||
import com.deniscerri.ytdl.util.ThemeUtil
|
import com.deniscerri.ytdl.util.ThemeUtil
|
||||||
import com.deniscerri.ytdl.util.UiUtil
|
import com.deniscerri.ytdl.util.UiUtil
|
||||||
|
|
@ -231,7 +232,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, SearchSuggesti
|
||||||
val url = requireArguments().getString("url")
|
val url = requireArguments().getString("url")
|
||||||
if (inputQueries == null) inputQueries = mutableListOf()
|
if (inputQueries == null) inputQueries = mutableListOf()
|
||||||
searchBar?.setText(url)
|
searchBar?.setText(url)
|
||||||
val argList = url!!.split("\n").toMutableList()
|
val argList = url!!.split("\n").filter { it.isURL() }.toMutableList()
|
||||||
argList.removeAll(listOf("", null))
|
argList.removeAll(listOf("", null))
|
||||||
inputQueries!!.addAll(argList)
|
inputQueries!!.addAll(argList)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,243 @@
|
||||||
|
package com.deniscerri.ytdl.ui.adapter
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.graphics.ColorMatrix
|
||||||
|
import android.graphics.ColorMatrixColorFilter
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.paging.PagingDataAdapter
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.deniscerri.ytdl.R
|
||||||
|
import com.deniscerri.ytdl.database.models.HistoryItem
|
||||||
|
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
|
||||||
|
import com.deniscerri.ytdl.util.Extensions.loadThumbnail
|
||||||
|
import com.deniscerri.ytdl.util.Extensions.popup
|
||||||
|
import com.google.android.material.card.MaterialCardView
|
||||||
|
import com.google.android.material.color.MaterialColors
|
||||||
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
import java.io.File
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
class HistoryPaginatedAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : PagingDataAdapter<HistoryItem, HistoryPaginatedAdapter.ViewHolder>(
|
||||||
|
DIFF_CALLBACK
|
||||||
|
) {
|
||||||
|
val checkedItems: MutableSet<Long>
|
||||||
|
var inverted: Boolean
|
||||||
|
private val onItemClickListener: OnItemClickListener
|
||||||
|
private val activity: Activity
|
||||||
|
private val sharedPreferences: SharedPreferences
|
||||||
|
|
||||||
|
init {
|
||||||
|
checkedItems = mutableSetOf()
|
||||||
|
this.inverted = false
|
||||||
|
this.onItemClickListener = onItemClickListener
|
||||||
|
this.activity = activity
|
||||||
|
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
val cardView: MaterialCardView
|
||||||
|
|
||||||
|
init {
|
||||||
|
cardView = itemView.findViewById(R.id.downloads_card_view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HistoryPaginatedAdapter.ViewHolder {
|
||||||
|
return if (viewType == 0){
|
||||||
|
val cardView = LayoutInflater.from(parent.context)
|
||||||
|
.inflate(R.layout.history_card, parent, false)
|
||||||
|
ViewHolder(cardView, onItemClickListener)
|
||||||
|
}else{
|
||||||
|
val cardView = LayoutInflater.from(parent.context)
|
||||||
|
.inflate(R.layout.history_card_multiple, parent, false)
|
||||||
|
ViewHolder(cardView, onItemClickListener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemViewType(position: Int): Int {
|
||||||
|
getItem(position)?.apply {
|
||||||
|
return if(this.downloadPath.size == 1){
|
||||||
|
0
|
||||||
|
}else{
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
val item = getItem(position) ?: return
|
||||||
|
val card = holder.cardView
|
||||||
|
card.tag = item.id.toString()
|
||||||
|
card.popup()
|
||||||
|
|
||||||
|
|
||||||
|
val uiHandler = Handler(Looper.getMainLooper())
|
||||||
|
val thumbnail = card.findViewById<ImageView>(R.id.downloads_image_view)
|
||||||
|
|
||||||
|
// THUMBNAIL ----------------------------------
|
||||||
|
val hideThumb = sharedPreferences.getStringSet("hide_thumbnails", emptySet())!!.contains("downloads")
|
||||||
|
uiHandler.post { thumbnail.loadThumbnail(hideThumb, item!!.thumb) }
|
||||||
|
|
||||||
|
// TITLE ----------------------------------
|
||||||
|
val itemTitle = card.findViewById<TextView>(R.id.downloads_title)
|
||||||
|
var title = item!!.title.ifEmpty { item.url }
|
||||||
|
if (title.length > 100) {
|
||||||
|
title = title.substring(0, 40) + "..."
|
||||||
|
}
|
||||||
|
itemTitle.text = title
|
||||||
|
|
||||||
|
// Bottom Info ----------------------------------
|
||||||
|
val author = card.findViewById<TextView>(R.id.downloads_info_bottom)
|
||||||
|
author.text = item.author
|
||||||
|
|
||||||
|
val length = card.findViewById<TextView>(R.id.length)
|
||||||
|
length.text = if(item.downloadPath.size == 1) item.duration else ""
|
||||||
|
|
||||||
|
|
||||||
|
// TIME DOWNLOADED ----------------------------------
|
||||||
|
val datetime = card.findViewById<TextView>(R.id.downloads_info_time)
|
||||||
|
datetime.text = SimpleDateFormat(android.text.format.DateFormat.getBestDateTimePattern(Locale.getDefault(), "ddMMMyyyy - HHmm"), Locale.getDefault()).format(item.time * 1000L)
|
||||||
|
|
||||||
|
// BUTTON ----------------------------------
|
||||||
|
val btn = card.findViewById<FloatingActionButton>(R.id.downloads_download_button_type)
|
||||||
|
var filesPresent = true
|
||||||
|
|
||||||
|
//IS IN THE FILE SYSTEM?
|
||||||
|
if (item.downloadPath.all { !File(it).exists() && it.isNotBlank()}) {
|
||||||
|
filesPresent = false
|
||||||
|
thumbnail.colorFilter = ColorMatrixColorFilter(object : ColorMatrix() {
|
||||||
|
init {
|
||||||
|
setSaturation(0f)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
thumbnail.alpha = 0.7f
|
||||||
|
btn.backgroundTintList = MaterialColors.getColorStateList(activity, R.attr.colorSurface, ContextCompat.getColorStateList(activity, android.R.color.transparent)!!)
|
||||||
|
}else{
|
||||||
|
thumbnail.alpha = 1f
|
||||||
|
thumbnail.colorFilter = null
|
||||||
|
btn.backgroundTintList = MaterialColors.getColorStateList(activity, R.attr.colorPrimaryContainer, ContextCompat.getColorStateList(activity, android.R.color.transparent)!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.type == DownloadViewModel.Type.audio) {
|
||||||
|
if (filesPresent) btn.setImageResource(R.drawable.ic_music_downloaded) else {
|
||||||
|
btn.setImageResource(R.drawable.ic_music)
|
||||||
|
}
|
||||||
|
} else if (item.type == DownloadViewModel.Type.video) {
|
||||||
|
if (filesPresent) btn.setImageResource(R.drawable.ic_video_downloaded) else btn.setImageResource(R.drawable.ic_video)
|
||||||
|
}else{
|
||||||
|
if (filesPresent) btn.setImageResource(R.drawable.ic_terminal) else btn.setImageResource(R.drawable.baseline_code_off_24)
|
||||||
|
}
|
||||||
|
if (btn.hasOnClickListeners()) btn.setOnClickListener(null)
|
||||||
|
btn.isClickable = filesPresent
|
||||||
|
|
||||||
|
if (checkedItems.contains(item.id)) {
|
||||||
|
card.isChecked = true
|
||||||
|
card.strokeWidth = 5
|
||||||
|
} else {
|
||||||
|
card.isChecked = false
|
||||||
|
card.strokeWidth = 0
|
||||||
|
}
|
||||||
|
val finalFilePresent = filesPresent
|
||||||
|
card.setOnLongClickListener {
|
||||||
|
checkCard(card, item.id)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
card.setOnClickListener {
|
||||||
|
if (checkedItems.size > 0) {
|
||||||
|
checkCard(card, item.id)
|
||||||
|
} else {
|
||||||
|
onItemClickListener.onCardClick(item.id, finalFilePresent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btn.setOnClickListener {
|
||||||
|
onItemClickListener.onButtonClick(item.id, finalFilePresent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
fun clearCheckedItems() {
|
||||||
|
inverted = false
|
||||||
|
checkedItems.clear()
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
fun checkAll() {
|
||||||
|
checkedItems.clear()
|
||||||
|
inverted = true
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
fun checkMultipleItems(list: List<Long>){
|
||||||
|
checkedItems.clear()
|
||||||
|
inverted = false
|
||||||
|
checkedItems.addAll(list)
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
fun invertSelected() {
|
||||||
|
inverted = !inverted
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSelectedObjectsCount(totalSize: Int) : Int{
|
||||||
|
return if (inverted){
|
||||||
|
totalSize - checkedItems.size
|
||||||
|
}else{
|
||||||
|
checkedItems.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkCard(card: MaterialCardView, itemID: Long) {
|
||||||
|
if (card.isChecked) {
|
||||||
|
card.strokeWidth = 0
|
||||||
|
if (inverted) checkedItems.add(itemID)
|
||||||
|
else checkedItems.remove(itemID)
|
||||||
|
} else {
|
||||||
|
card.strokeWidth = 5
|
||||||
|
if (inverted) checkedItems.remove(itemID)
|
||||||
|
else checkedItems.add(itemID)
|
||||||
|
}
|
||||||
|
card.isChecked = !card.isChecked
|
||||||
|
onItemClickListener.onCardSelect(itemID, card.isChecked)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnItemClickListener {
|
||||||
|
fun onCardClick(itemID: Long, isPresent: Boolean)
|
||||||
|
fun onButtonClick(itemID: Long, isPresent: Boolean)
|
||||||
|
fun onCardSelect(itemID: Long, isChecked: Boolean)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val DIFF_CALLBACK: DiffUtil.ItemCallback<HistoryItem> = object : DiffUtil.ItemCallback<HistoryItem>() {
|
||||||
|
override fun areItemsTheSame(oldItem: HistoryItem, newItem: HistoryItem): Boolean {
|
||||||
|
val ranged = arrayListOf(oldItem.id, newItem.id)
|
||||||
|
return ranged[0] == ranged[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: HistoryItem, newItem: HistoryItem): Boolean {
|
||||||
|
return oldItem.time == newItem.time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -93,7 +93,7 @@ class DownloadCommandFragment(private val resultItem: ResultItem? = null, privat
|
||||||
preferences.edit().putString("lastCommandTemplateUsed", downloadItem.format.format_note).apply()
|
preferences.edit().putString("lastCommandTemplateUsed", downloadItem.format.format_note).apply()
|
||||||
|
|
||||||
if (!Patterns.WEB_URL.matcher(downloadItem.url).matches() && downloadItem.url.endsWith(".txt")){
|
if (!Patterns.WEB_URL.matcher(downloadItem.url).matches() && downloadItem.url.endsWith(".txt")){
|
||||||
downloadItem.format = downloadViewModel.generateCommandFormat(CommandTemplate(0,"txt", "-a \"${downloadItem.url}\"", useAsExtraCommand = false, useAsExtraCommandAudio = false, useAsExtraCommandVideo = false))
|
downloadItem.format = downloadViewModel.generateCommandFormat(CommandTemplate(0,"txt", "-a \"${downloadItem.url}\"", useAsExtraCommand = false, useAsExtraCommandAudio = false, useAsExtraCommandVideo = false, useAsExtraCommandDataFetching = false))
|
||||||
downloadItem.url = ""
|
downloadItem.url = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -249,7 +249,7 @@ class DownloadCommandFragment(private val resultItem: ResultItem? = null, privat
|
||||||
0,
|
0,
|
||||||
"",
|
"",
|
||||||
chosenCommandView.editText!!.text.toString(),
|
chosenCommandView.editText!!.text.toString(),
|
||||||
useAsExtraCommand = false, useAsExtraCommandAudio = false, useAsExtraCommandVideo = false
|
useAsExtraCommand = false, useAsExtraCommandAudio = false, useAsExtraCommandVideo = false, useAsExtraCommandDataFetching = false
|
||||||
)
|
)
|
||||||
UiUtil.showCommandTemplateCreationOrUpdatingSheet(
|
UiUtil.showCommandTemplateCreationOrUpdatingSheet(
|
||||||
current, requireActivity(), viewLifecycleOwner, commandTemplateViewModel,
|
current, requireActivity(), viewLifecycleOwner, commandTemplateViewModel,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package com.deniscerri.ytdl.ui.downloads
|
package com.deniscerri.ytdl.ui.downloads
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
|
|
@ -16,8 +15,6 @@ import android.view.LayoutInflater
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.GONE
|
|
||||||
import android.view.View.VISIBLE
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.Window
|
import android.view.Window
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
|
@ -45,13 +42,12 @@ import com.deniscerri.ytdl.MainActivity
|
||||||
import com.deniscerri.ytdl.R
|
import com.deniscerri.ytdl.R
|
||||||
import com.deniscerri.ytdl.database.DBManager.SORTING
|
import com.deniscerri.ytdl.database.DBManager.SORTING
|
||||||
import com.deniscerri.ytdl.database.models.HistoryItem
|
import com.deniscerri.ytdl.database.models.HistoryItem
|
||||||
|
import com.deniscerri.ytdl.database.repository.DownloadRepository
|
||||||
import com.deniscerri.ytdl.database.repository.HistoryRepository
|
import com.deniscerri.ytdl.database.repository.HistoryRepository
|
||||||
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
|
||||||
import com.deniscerri.ytdl.database.viewmodel.HistoryViewModel
|
import com.deniscerri.ytdl.database.viewmodel.HistoryViewModel
|
||||||
import com.deniscerri.ytdl.ui.adapter.HistoryAdapter
|
import com.deniscerri.ytdl.ui.adapter.HistoryPaginatedAdapter
|
||||||
import com.deniscerri.ytdl.ui.downloadcard.FormatSelectionBottomSheetDialog.FormatCategory
|
|
||||||
import com.deniscerri.ytdl.util.Extensions.enableFastScroll
|
import com.deniscerri.ytdl.util.Extensions.enableFastScroll
|
||||||
import com.deniscerri.ytdl.util.Extensions.isYoutubeURL
|
|
||||||
import com.deniscerri.ytdl.util.FileUtil
|
import com.deniscerri.ytdl.util.FileUtil
|
||||||
import com.deniscerri.ytdl.util.NavbarUtil
|
import com.deniscerri.ytdl.util.NavbarUtil
|
||||||
import com.deniscerri.ytdl.util.UiUtil
|
import com.deniscerri.ytdl.util.UiUtil
|
||||||
|
|
@ -73,26 +69,23 @@ import kotlinx.coroutines.withContext
|
||||||
/**
|
/**
|
||||||
* A fragment representing a list of Items.
|
* A fragment representing a list of Items.
|
||||||
*/
|
*/
|
||||||
class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
class HistoryFragment : Fragment(), HistoryPaginatedAdapter.OnItemClickListener{
|
||||||
private lateinit var historyViewModel : HistoryViewModel
|
private lateinit var historyViewModel : HistoryViewModel
|
||||||
private lateinit var downloadViewModel : DownloadViewModel
|
private lateinit var downloadViewModel : DownloadViewModel
|
||||||
|
|
||||||
private var fragmentView: View? = null
|
private lateinit var fragmentView: View
|
||||||
private var activity: Activity? = null
|
|
||||||
private var mainActivity: MainActivity? = null
|
private var mainActivity: MainActivity? = null
|
||||||
private var fragmentContext: Context? = null
|
private var fragmentContext: Context? = null
|
||||||
private var layoutinflater: LayoutInflater? = null
|
private lateinit var layoutinflater: LayoutInflater
|
||||||
private var topAppBar: MaterialToolbar? = null
|
private lateinit var topAppBar: MaterialToolbar
|
||||||
private lateinit var recyclerView: RecyclerView
|
private lateinit var recyclerView: RecyclerView
|
||||||
private var historyAdapter: HistoryAdapter? = null
|
private lateinit var historyAdapter: HistoryPaginatedAdapter
|
||||||
private var sortSheet: BottomSheetDialog? = null
|
private lateinit var sortSheet: BottomSheetDialog
|
||||||
private var uiHandler: Handler? = null
|
private lateinit var uiHandler: Handler
|
||||||
private var noResults: RelativeLayout? = null
|
private lateinit var noResults: RelativeLayout
|
||||||
private var selectionChips: LinearLayout? = null
|
private lateinit var selectionChips: LinearLayout
|
||||||
private var historyList: List<HistoryItem?>? = null
|
|
||||||
private var allhistoryList: List<HistoryItem?>? = null
|
|
||||||
private var websiteList: MutableList<String> = mutableListOf()
|
private var websiteList: MutableList<String> = mutableListOf()
|
||||||
private lateinit var selectedObjects: ArrayList<HistoryItem>
|
private var totalCount = 0
|
||||||
private var actionMode : ActionMode? = null
|
private var actionMode : ActionMode? = null
|
||||||
|
|
||||||
private lateinit var sortChip: Chip
|
private lateinit var sortChip: Chip
|
||||||
|
|
@ -100,9 +93,8 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View {
|
||||||
fragmentView = inflater.inflate(R.layout.fragment_history, container, false)
|
fragmentView = inflater.inflate(R.layout.fragment_history, container, false)
|
||||||
activity = getActivity()
|
|
||||||
mainActivity = activity as MainActivity?
|
mainActivity = activity as MainActivity?
|
||||||
return fragmentView
|
return fragmentView
|
||||||
}
|
}
|
||||||
|
|
@ -118,24 +110,15 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
selectionChips = view.findViewById(R.id.history_selection_chips)
|
selectionChips = view.findViewById(R.id.history_selection_chips)
|
||||||
uiHandler = Handler(Looper.getMainLooper())
|
uiHandler = Handler(Looper.getMainLooper())
|
||||||
sortChip = view.findViewById(R.id.sortChip)
|
sortChip = view.findViewById(R.id.sortChip)
|
||||||
selectedObjects = arrayListOf()
|
|
||||||
|
|
||||||
val isInNavBar = NavbarUtil.getNavBarItems(requireActivity()).any { n -> n.itemId == R.id.historyFragment && n.isVisible }
|
val isInNavBar = NavbarUtil.getNavBarItems(requireActivity()).any { n -> n.itemId == R.id.historyFragment && n.isVisible }
|
||||||
if (isInNavBar) {
|
if (isInNavBar) {
|
||||||
topAppBar?.navigationIcon = null
|
topAppBar.navigationIcon = null
|
||||||
}else{
|
}else{
|
||||||
mainActivity?.hideBottomNavigation()
|
mainActivity?.hideBottomNavigation()
|
||||||
}
|
}
|
||||||
topAppBar?.setNavigationOnClickListener { mainActivity?.onBackPressedDispatcher?.onBackPressed() }
|
topAppBar.setNavigationOnClickListener { mainActivity?.onBackPressedDispatcher?.onBackPressed() }
|
||||||
|
historyAdapter = HistoryPaginatedAdapter(this, requireActivity())
|
||||||
|
|
||||||
historyList = mutableListOf()
|
|
||||||
|
|
||||||
historyAdapter =
|
|
||||||
HistoryAdapter(
|
|
||||||
this,
|
|
||||||
requireActivity()
|
|
||||||
)
|
|
||||||
recyclerView = view.findViewById(R.id.recyclerviewhistorys)
|
recyclerView = view.findViewById(R.id.recyclerviewhistorys)
|
||||||
recyclerView.enableFastScroll()
|
recyclerView.enableFastScroll()
|
||||||
|
|
||||||
|
|
@ -146,37 +129,44 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
}
|
}
|
||||||
|
|
||||||
recyclerView.layoutManager = GridLayoutManager(context, resources.getInteger(R.integer.grid_size))
|
recyclerView.layoutManager = GridLayoutManager(context, resources.getInteger(R.integer.grid_size))
|
||||||
noResults?.visibility = GONE
|
noResults.isVisible = false
|
||||||
|
|
||||||
|
|
||||||
historyViewModel = ViewModelProvider(this)[HistoryViewModel::class.java]
|
historyViewModel = ViewModelProvider(this)[HistoryViewModel::class.java]
|
||||||
historyViewModel.allItems.observe(viewLifecycleOwner) {
|
recyclerView.adapter = historyAdapter
|
||||||
allhistoryList = it
|
lifecycleScope.launch {
|
||||||
if(it.isEmpty()){
|
historyViewModel.paginatedItems.collectLatest {
|
||||||
noResults!!.visibility = VISIBLE
|
withContext(Dispatchers.IO){
|
||||||
selectionChips!!.visibility = GONE
|
historyAdapter.submitData(it)
|
||||||
topAppBar!!.menu.children.firstOrNull { m -> m.itemId == R.id.filters }?.isVisible = false
|
}
|
||||||
}else{
|
}
|
||||||
noResults!!.visibility = GONE
|
}
|
||||||
selectionChips!!.visibility = VISIBLE
|
lifecycleScope.launch {
|
||||||
topAppBar!!.menu.children.firstOrNull { m -> m.itemId == R.id.filters }?.isVisible = true
|
historyViewModel.websites.collectLatest {
|
||||||
updateWebsiteChips(it)
|
if(it.isEmpty()) {
|
||||||
|
noResults.isVisible = true
|
||||||
|
selectionChips.isVisible = false
|
||||||
|
topAppBar.menu.children.firstOrNull { m -> m.itemId == R.id.filters }?.isVisible = false
|
||||||
|
}else{
|
||||||
|
noResults.isVisible = false
|
||||||
|
selectionChips.isVisible = true
|
||||||
|
topAppBar.menu.children.firstOrNull { m -> m.itemId == R.id.filters }?.isVisible = true
|
||||||
|
|
||||||
|
websiteList = mutableListOf()
|
||||||
|
for (item in it){
|
||||||
|
if (item == "null" || item.isEmpty()) continue
|
||||||
|
if (!websiteList.any { it.contentEquals(item, true) }) websiteList.add(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
historyViewModel.getFilteredList().observe(viewLifecycleOwner) {
|
lifecycleScope.launch {
|
||||||
historyAdapter!!.submitList(it)
|
historyViewModel.totalCount.collectLatest {
|
||||||
historyList = it
|
totalCount = it
|
||||||
|
|
||||||
if (recyclerView.adapter == null){
|
|
||||||
recyclerView.adapter = historyAdapter
|
|
||||||
}else{
|
|
||||||
scrollToTop()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
historyViewModel.sortOrder.observe(viewLifecycleOwner){
|
lifecycleScope.launch {
|
||||||
if (it != null){
|
historyViewModel.sortOrder.collectLatest {
|
||||||
when(it){
|
when(it){
|
||||||
SORTING.ASC -> sortChip.chipIcon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_down)
|
SORTING.ASC -> sortChip.chipIcon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_down)
|
||||||
SORTING.DESC -> sortChip.chipIcon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_up)
|
SORTING.DESC -> sortChip.chipIcon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_up)
|
||||||
|
|
@ -184,20 +174,18 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
historyViewModel.sortType.observe(viewLifecycleOwner){
|
lifecycleScope.launch {
|
||||||
if(it != null){
|
historyViewModel.sortType.collectLatest {
|
||||||
when(it){
|
when(it){
|
||||||
HistoryRepository.HistorySortType.AUTHOR -> sortChip.text = getString(R.string.author)
|
HistoryRepository.HistorySortType.AUTHOR -> sortChip.text = getString(R.string.author)
|
||||||
HistoryRepository.HistorySortType.DATE -> sortChip.text = getString(R.string.date_added)
|
HistoryRepository.HistorySortType.DATE -> sortChip.text = getString(R.string.date_added)
|
||||||
HistoryRepository.HistorySortType.TITLE -> sortChip.text = getString(R.string.title)
|
HistoryRepository.HistorySortType.TITLE -> sortChip.text = getString(R.string.title)
|
||||||
HistoryRepository.HistorySortType.FILESIZE -> sortChip.text = getString(R.string.file_size)
|
HistoryRepository.HistorySortType.FILESIZE -> sortChip.text = getString(R.string.file_size)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
|
|
||||||
|
|
||||||
lifecycleScope.launch{
|
lifecycleScope.launch{
|
||||||
downloadViewModel.alreadyExistsUiState.collectLatest { res ->
|
downloadViewModel.alreadyExistsUiState.collectLatest { res ->
|
||||||
if (res.isNotEmpty()){
|
if (res.isNotEmpty()){
|
||||||
|
|
@ -212,7 +200,6 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
initMenu()
|
initMenu()
|
||||||
initChips()
|
initChips()
|
||||||
}
|
}
|
||||||
|
|
@ -220,7 +207,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
fun scrollToTop() {
|
fun scrollToTop() {
|
||||||
recyclerView.scrollToPosition(0)
|
recyclerView.scrollToPosition(0)
|
||||||
Handler(Looper.getMainLooper()).post {
|
Handler(Looper.getMainLooper()).post {
|
||||||
(topAppBar!!.parent as AppBarLayout).setExpanded(
|
(topAppBar.parent as AppBarLayout).setExpanded(
|
||||||
true,
|
true,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
|
@ -238,14 +225,14 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
topAppBar!!.menu.findItem(R.id.search_history)
|
topAppBar.menu.findItem(R.id.search_history)
|
||||||
.setOnActionExpandListener(onActionExpandListener)
|
.setOnActionExpandListener(onActionExpandListener)
|
||||||
val searchView = topAppBar!!.menu.findItem(R.id.search_history).actionView as SearchView?
|
val searchView = topAppBar.menu.findItem(R.id.search_history).actionView as SearchView?
|
||||||
searchView!!.inputType = InputType.TYPE_CLASS_TEXT
|
searchView!!.inputType = InputType.TYPE_CLASS_TEXT
|
||||||
searchView.queryHint = getString(R.string.search_history_hint)
|
searchView.queryHint = getString(R.string.search_history_hint)
|
||||||
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||||
override fun onQueryTextSubmit(query: String): Boolean {
|
override fun onQueryTextSubmit(query: String): Boolean {
|
||||||
topAppBar!!.menu.findItem(R.id.search_history).collapseActionView()
|
topAppBar.menu.findItem(R.id.search_history).collapseActionView()
|
||||||
historyViewModel.setQueryFilter(query)
|
historyViewModel.setQueryFilter(query)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -255,13 +242,13 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
topAppBar!!.setOnClickListener { scrollToTop() }
|
topAppBar.setOnClickListener { scrollToTop() }
|
||||||
val showingDownloadQueue = NavbarUtil.getNavBarItems(requireContext()).any { n -> n.itemId == R.id.downloadQueueMainFragment && n.isVisible }
|
val showingDownloadQueue = NavbarUtil.getNavBarItems(requireContext()).any { n -> n.itemId == R.id.downloadQueueMainFragment && n.isVisible }
|
||||||
topAppBar!!.menu.findItem(R.id.download_queue).isVisible = !showingDownloadQueue
|
topAppBar.menu.findItem(R.id.download_queue).isVisible = !showingDownloadQueue
|
||||||
topAppBar!!.setOnMenuItemClickListener { m: MenuItem ->
|
topAppBar.setOnMenuItemClickListener { m: MenuItem ->
|
||||||
when (m.itemId) {
|
when (m.itemId) {
|
||||||
R.id.remove_history -> {
|
R.id.remove_history -> {
|
||||||
if(allhistoryList!!.isEmpty()){
|
if(websiteList.isEmpty()){
|
||||||
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
|
||||||
}else{
|
}else{
|
||||||
val deleteFile = booleanArrayOf(false)
|
val deleteFile = booleanArrayOf(false)
|
||||||
|
|
@ -282,7 +269,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
findNavController().navigate(R.id.downloadQueueMainFragment)
|
findNavController().navigate(R.id.downloadQueueMainFragment)
|
||||||
}
|
}
|
||||||
R.id.remove_deleted_history -> {
|
R.id.remove_deleted_history -> {
|
||||||
if(allhistoryList!!.isEmpty()){
|
if(websiteList.isEmpty()){
|
||||||
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
|
||||||
}else{
|
}else{
|
||||||
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
|
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
|
||||||
|
|
@ -296,7 +283,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
R.id.remove_duplicates -> {
|
R.id.remove_duplicates -> {
|
||||||
if(allhistoryList!!.isEmpty()){
|
if(websiteList.isEmpty()){
|
||||||
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
|
||||||
}else{
|
}else{
|
||||||
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
|
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
|
||||||
|
|
@ -384,7 +371,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
|
|
||||||
for (i in websiteList.indices) {
|
for (i in websiteList.indices) {
|
||||||
val w = websiteList[i]
|
val w = websiteList[i]
|
||||||
val tmp = layoutinflater!!.inflate(R.layout.filter_chip, websiteGroup, false) as Chip
|
val tmp = layoutinflater.inflate(R.layout.filter_chip, websiteGroup, false) as Chip
|
||||||
tmp.text = w
|
tmp.text = w
|
||||||
tmp.id = i
|
tmp.id = i
|
||||||
tmp.setOnClickListener {
|
tmp.setOnClickListener {
|
||||||
|
|
@ -427,16 +414,16 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
|
|
||||||
|
|
||||||
private fun initChips() {
|
private fun initChips() {
|
||||||
val sortChip = fragmentView!!.findViewById<Chip>(R.id.sortChip)
|
val sortChip = fragmentView.findViewById<Chip>(R.id.sortChip)
|
||||||
sortChip.setOnClickListener {
|
sortChip.setOnClickListener {
|
||||||
sortSheet = BottomSheetDialog(requireContext())
|
sortSheet = BottomSheetDialog(requireContext())
|
||||||
sortSheet!!.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
sortSheet.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||||
sortSheet!!.setContentView(R.layout.history_sort_sheet)
|
sortSheet.setContentView(R.layout.history_sort_sheet)
|
||||||
|
|
||||||
val date = sortSheet!!.findViewById<TextView>(R.id.date)
|
val date = sortSheet.findViewById<TextView>(R.id.date)
|
||||||
val title = sortSheet!!.findViewById<TextView>(R.id.title)
|
val title = sortSheet.findViewById<TextView>(R.id.title)
|
||||||
val author = sortSheet!!.findViewById<TextView>(R.id.author)
|
val author = sortSheet.findViewById<TextView>(R.id.author)
|
||||||
val filesize = sortSheet!!.findViewById<TextView>(R.id.filesize)
|
val filesize = sortSheet.findViewById<TextView>(R.id.filesize)
|
||||||
|
|
||||||
val sortOptions = listOf(date!!, title!!, author!!, filesize!!)
|
val sortOptions = listOf(date!!, title!!, author!!, filesize!!)
|
||||||
sortOptions.forEach { it.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.empty,0,0,0) }
|
sortOptions.forEach { it.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.empty,0,0,0) }
|
||||||
|
|
@ -469,12 +456,12 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
}
|
}
|
||||||
val displayMetrics = DisplayMetrics()
|
val displayMetrics = DisplayMetrics()
|
||||||
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
||||||
sortSheet!!.behavior.peekHeight = displayMetrics.heightPixels
|
sortSheet.behavior.peekHeight = displayMetrics.heightPixels
|
||||||
sortSheet!!.show()
|
sortSheet.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
//format
|
//format
|
||||||
val audio = fragmentView!!.findViewById<Chip>(R.id.audio_chip)
|
val audio = fragmentView.findViewById<Chip>(R.id.audio_chip)
|
||||||
audio.setOnClickListener {
|
audio.setOnClickListener {
|
||||||
if (audio.isChecked) {
|
if (audio.isChecked) {
|
||||||
historyViewModel.setTypeFilter(DownloadViewModel.Type.audio.toString())
|
historyViewModel.setTypeFilter(DownloadViewModel.Type.audio.toString())
|
||||||
|
|
@ -484,7 +471,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
audio.isChecked = false
|
audio.isChecked = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val video = fragmentView!!.findViewById<Chip>(R.id.video_chip)
|
val video = fragmentView.findViewById<Chip>(R.id.video_chip)
|
||||||
video.setOnClickListener {
|
video.setOnClickListener {
|
||||||
if (video.isChecked) {
|
if (video.isChecked) {
|
||||||
historyViewModel.setTypeFilter(DownloadViewModel.Type.video.toString())
|
historyViewModel.setTypeFilter(DownloadViewModel.Type.video.toString())
|
||||||
|
|
@ -494,7 +481,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
video.isChecked = false
|
video.isChecked = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val command = fragmentView!!.findViewById<Chip>(R.id.command_chip)
|
val command = fragmentView.findViewById<Chip>(R.id.command_chip)
|
||||||
command.setOnClickListener {
|
command.setOnClickListener {
|
||||||
if (command.isChecked) {
|
if (command.isChecked) {
|
||||||
historyViewModel.setTypeFilter(DownloadViewModel.Type.command.toString())
|
historyViewModel.setTypeFilter(DownloadViewModel.Type.command.toString())
|
||||||
|
|
@ -508,71 +495,68 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateWebsiteChips(list : List<HistoryItem>) {
|
|
||||||
websiteList = mutableListOf()
|
|
||||||
for (item in list){
|
|
||||||
if (item.website == "null" || item.website.isEmpty()) continue
|
|
||||||
if (!websiteList.any { it.contentEquals(item.website, true) }) websiteList.add(item.website)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCardClick(itemID: Long, isPresent: Boolean) {
|
override fun onCardClick(itemID: Long, isPresent: Boolean) {
|
||||||
val item = findItem(itemID)
|
lifecycleScope.launch {
|
||||||
UiUtil.showHistoryItemDetailsCard(item, requireActivity(), isPresent,
|
val item = withContext(Dispatchers.IO){
|
||||||
removeItem = { it, deleteFile ->
|
historyViewModel.getByID(itemID)
|
||||||
historyViewModel.delete(it, deleteFile)
|
|
||||||
},
|
|
||||||
redownloadItem = {
|
|
||||||
val downloadItem = downloadViewModel.createDownloadItemFromHistory(it)
|
|
||||||
runBlocking{
|
|
||||||
downloadViewModel.queueDownloads(listOf(downloadItem))
|
|
||||||
}
|
|
||||||
historyViewModel.delete(it, false)
|
|
||||||
},
|
|
||||||
redownloadShowDownloadCard = {
|
|
||||||
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
|
|
||||||
Pair("result", downloadViewModel.createResultItemFromHistory(it)),
|
|
||||||
Pair("type", it.type),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
UiUtil.showHistoryItemDetailsCard(item, requireActivity(), isPresent,
|
||||||
|
removeItem = { it, deleteFile ->
|
||||||
|
historyViewModel.delete(it, deleteFile)
|
||||||
|
},
|
||||||
|
redownloadItem = {
|
||||||
|
val downloadItem = downloadViewModel.createDownloadItemFromHistory(it)
|
||||||
|
runBlocking{
|
||||||
|
downloadViewModel.queueDownloads(listOf(downloadItem))
|
||||||
|
}
|
||||||
|
historyViewModel.delete(it, false)
|
||||||
|
},
|
||||||
|
redownloadShowDownloadCard = {
|
||||||
|
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
|
||||||
|
Pair("result", downloadViewModel.createResultItemFromHistory(it)),
|
||||||
|
Pair("type", it.type),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCardSelect(itemID: Long, isChecked: Boolean) {
|
override fun onCardSelect(itemID: Long, isChecked: Boolean) {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val item = findItem(itemID)
|
val item = withContext(Dispatchers.IO) {
|
||||||
if (actionMode == null) actionMode = (getActivity() as AppCompatActivity?)!!.startSupportActionMode(contextualActionBar)
|
historyViewModel.getByID(itemID)
|
||||||
actionMode?.apply {
|
}
|
||||||
if (isChecked) selectedObjects.add(item!!)
|
|
||||||
else selectedObjects.remove(item!!)
|
|
||||||
|
|
||||||
if (selectedObjects.size == 0){
|
if (actionMode == null) actionMode = (activity as AppCompatActivity?)!!.startSupportActionMode(contextualActionBar)
|
||||||
|
val selectedObjects = historyAdapter.getSelectedObjectsCount(totalCount)
|
||||||
|
actionMode?.apply {
|
||||||
|
if (selectedObjects == 0){
|
||||||
this.finish()
|
this.finish()
|
||||||
}else{
|
}else{
|
||||||
actionMode?.title = "${selectedObjects.size} ${getString(R.string.selected)}"
|
actionMode?.title = "$selectedObjects ${getString(R.string.selected)}"
|
||||||
this.menu.findItem(R.id.select_between).isVisible = false
|
this.menu.findItem(R.id.select_between).isVisible = false
|
||||||
if(selectedObjects.size == 2){
|
if(selectedObjects == 2){
|
||||||
val selectedIDs = selectedObjects.sortedBy { it.id }
|
//TODO
|
||||||
val resultsInMiddle = withContext(Dispatchers.IO){
|
// val selectedIDs = contextualActionBar.getSelectedIDs().sortedBy { it }
|
||||||
historyViewModel.getRecordsBetweenTwoItems(selectedIDs.first().id, selectedIDs.last().id)
|
// val resultsInMiddle = withContext(Dispatchers.IO){
|
||||||
}.toMutableList()
|
// historyViewModel.getRecordsBetweenTwoItems(selectedIDs.first().id, selectedIDs.last().id)
|
||||||
this.menu.findItem(R.id.select_between).isVisible = resultsInMiddle.isNotEmpty()
|
// }.toMutableList()
|
||||||
|
// this.menu.findItem(R.id.select_between).isVisible = resultsInMiddle.isNotEmpty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findItem(id : Long): HistoryItem? {
|
|
||||||
return historyList?.find { it?.id == id }
|
|
||||||
}
|
|
||||||
|
|
||||||
private val contextualActionBar = object : ActionMode.Callback {
|
private val contextualActionBar = object : ActionMode.Callback {
|
||||||
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
|
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
|
||||||
mode!!.menuInflater.inflate(R.menu.history_menu_context, menu)
|
mode!!.menuInflater.inflate(R.menu.history_menu_context, menu)
|
||||||
mode.title = "${selectedObjects.size} ${getString(R.string.selected)}"
|
mode.title = "${historyAdapter.getSelectedObjectsCount(totalCount)} ${getString(R.string.selected)}"
|
||||||
(activity as MainActivity).disableBottomNavigation()
|
(activity as MainActivity).disableBottomNavigation()
|
||||||
topAppBar!!.menu.forEach { it.isEnabled = false }
|
topAppBar.menu.forEach { it.isEnabled = false }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -589,62 +573,66 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return when (item!!.itemId) {
|
return when (item!!.itemId) {
|
||||||
R.id.select_between -> {
|
R.id.select_between -> {
|
||||||
lifecycleScope.launch {
|
//TODO
|
||||||
val selectedIDs = selectedObjects.sortedBy { it.id }
|
// lifecycleScope.launch {
|
||||||
val resultsInMiddle = withContext(Dispatchers.IO){
|
// val selectedIDs = selectedObjects.sortedBy { it.id }
|
||||||
historyViewModel.getRecordsBetweenTwoItems(selectedIDs.first().id, selectedIDs.last().id)
|
// val resultsInMiddle = withContext(Dispatchers.IO){
|
||||||
}.toMutableList()
|
// historyViewModel.getRecordsBetweenTwoItems(selectedIDs.first().id, selectedIDs.last().id)
|
||||||
if (resultsInMiddle.isNotEmpty()){
|
// }.toMutableList()
|
||||||
selectedObjects.addAll(resultsInMiddle)
|
// if (resultsInMiddle.isNotEmpty()){
|
||||||
historyAdapter?.checkMultipleItems(selectedObjects.map { it.id })
|
// selectedObjects.addAll(resultsInMiddle)
|
||||||
actionMode?.title = "${selectedObjects.count()} ${getString(R.string.selected)}"
|
// historyAdapter.checkMultipleItems(selectedObjects.map { it.id })
|
||||||
}
|
// actionMode?.title = "${selectedObjects.count()} ${getString(R.string.selected)}"
|
||||||
mode?.menu?.findItem(R.id.select_between)?.isVisible = false
|
// }
|
||||||
}
|
// mode?.menu?.findItem(R.id.select_between)?.isVisible = false
|
||||||
|
// }
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
R.id.delete_results -> {
|
R.id.delete_results -> {
|
||||||
val deleteFile = booleanArrayOf(false)
|
//TODO
|
||||||
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
|
// val deleteFile = booleanArrayOf(false)
|
||||||
deleteDialog.setTitle(getString(R.string.you_are_going_to_delete_multiple_items))
|
// val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
|
||||||
deleteDialog.setMultiChoiceItems(
|
// deleteDialog.setTitle(getString(R.string.you_are_going_to_delete_multiple_items))
|
||||||
arrayOf(getString(R.string.delete_files_too)),
|
// deleteDialog.setMultiChoiceItems(
|
||||||
booleanArrayOf(false)
|
// arrayOf(getString(R.string.delete_files_too)),
|
||||||
) { _: DialogInterface?, _: Int, b: Boolean -> deleteFile[0] = b }
|
// booleanArrayOf(false)
|
||||||
deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
|
// ) { _: DialogInterface?, _: Int, b: Boolean -> deleteFile[0] = b }
|
||||||
deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
|
// deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
|
||||||
for (obj in selectedObjects){
|
// deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
|
||||||
historyViewModel.delete(obj, deleteFile[0])
|
// for (obj in selectedObjects){
|
||||||
}
|
// historyViewModel.delete(obj, deleteFile[0])
|
||||||
clearCheckedItems()
|
// }
|
||||||
actionMode?.finish()
|
// clearCheckedItems()
|
||||||
}
|
// actionMode?.finish()
|
||||||
deleteDialog.show()
|
// }
|
||||||
|
// deleteDialog.show()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
R.id.share -> {
|
R.id.share -> {
|
||||||
FileUtil.shareFileIntent(requireContext(), selectedObjects.map { it.downloadPath }.flatten())
|
//TODO
|
||||||
clearCheckedItems()
|
// FileUtil.shareFileIntent(requireContext(), selectedObjects.map { it.downloadPath }.flatten())
|
||||||
actionMode?.finish()
|
// clearCheckedItems()
|
||||||
|
// actionMode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
R.id.select_all -> {
|
R.id.select_all -> {
|
||||||
historyAdapter?.checkAll(historyList)
|
//TODO
|
||||||
selectedObjects.clear()
|
// historyAdapter.checkAll()
|
||||||
historyList?.forEach { selectedObjects.add(it!!) }
|
// historyList?.forEach { selectedObjects.add(it!!) }
|
||||||
mode?.title = "(${selectedObjects.size}) ${resources.getString(R.string.all_items_selected)}"
|
// mode?.title = "(${selectedObjects.size}) ${resources.getString(R.string.all_items_selected)}"
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
R.id.invert_selected -> {
|
R.id.invert_selected -> {
|
||||||
historyAdapter?.invertSelected(historyList)
|
//TODO
|
||||||
val invertedList = arrayListOf<HistoryItem>()
|
// historyAdapter.invertSelected()
|
||||||
historyList?.forEach {
|
// val invertedList = arrayListOf<HistoryItem>()
|
||||||
if (!selectedObjects.contains(it)!!) invertedList.add(it!!)
|
// historyList?.forEach {
|
||||||
}
|
// if (!selectedObjects.contains(it)!!) invertedList.add(it!!)
|
||||||
selectedObjects.clear()
|
// }
|
||||||
selectedObjects.addAll(invertedList)
|
// selectedObjects.clear()
|
||||||
actionMode!!.title = "${selectedObjects.size} ${getString(R.string.selected)}"
|
// selectedObjects.addAll(invertedList)
|
||||||
if (invertedList.isEmpty()) actionMode?.finish()
|
// actionMode!!.title = "${selectedObjects.size} ${getString(R.string.selected)}"
|
||||||
|
// if (invertedList.isEmpty()) actionMode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
else -> false
|
else -> false
|
||||||
|
|
@ -654,15 +642,23 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
override fun onDestroyActionMode(mode: ActionMode?) {
|
||||||
actionMode = null
|
actionMode = null
|
||||||
(activity as MainActivity).enableBottomNavigation()
|
(activity as MainActivity).enableBottomNavigation()
|
||||||
clearCheckedItems()
|
historyAdapter.clearCheckedItems()
|
||||||
topAppBar!!.menu.forEach { it.isEnabled = true }
|
topAppBar.menu.forEach { it.isEnabled = true }
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getSelectedIDs() : List<Long>{
|
||||||
|
//TODO
|
||||||
|
// return if (historyAdapter.inverted || historyAdapter.checkedItems.isEmpty()) {
|
||||||
|
// withContext(Dispatchers.IO){
|
||||||
|
// historyViewModel.getItemIDsNotPresentIn(historyAdapter.checkedItems.toList())
|
||||||
|
// }
|
||||||
|
// }else{
|
||||||
|
// historyAdapter.checkedItems.toList()
|
||||||
|
// }
|
||||||
|
return listOf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun clearCheckedItems(){
|
|
||||||
historyAdapter?.clearCheckeditems()
|
|
||||||
selectedObjects.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
private var simpleCallback: ItemTouchHelper.SimpleCallback =
|
private var simpleCallback: ItemTouchHelper.SimpleCallback =
|
||||||
object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
|
object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
|
||||||
|
|
@ -672,34 +668,44 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||||
|
val itemID = viewHolder.itemView.tag.toString().toLong()
|
||||||
val position = viewHolder.bindingAdapterPosition
|
val position = viewHolder.bindingAdapterPosition
|
||||||
when (direction) {
|
when (direction) {
|
||||||
ItemTouchHelper.LEFT -> {
|
ItemTouchHelper.LEFT -> {
|
||||||
val deletedItem = historyList!![position]
|
lifecycleScope.launch {
|
||||||
historyAdapter!!.notifyItemChanged(position)
|
val deletedItem = withContext(Dispatchers.IO) {
|
||||||
UiUtil.showRemoveHistoryItemDialog(deletedItem!!, requireActivity(),
|
historyViewModel.getByID(itemID)
|
||||||
delete = { item, deleteFile ->
|
}
|
||||||
lifecycleScope.launch {
|
historyAdapter.notifyItemChanged(position)
|
||||||
withContext(Dispatchers.IO){
|
UiUtil.showRemoveHistoryItemDialog(deletedItem, requireActivity(),
|
||||||
historyViewModel.delete(item, deleteFile)
|
delete = { item, deleteFile ->
|
||||||
}
|
lifecycleScope.launch {
|
||||||
|
withContext(Dispatchers.IO){
|
||||||
|
historyViewModel.delete(item, deleteFile)
|
||||||
|
}
|
||||||
|
|
||||||
if (!deleteFile){
|
if (!deleteFile){
|
||||||
Snackbar.make(recyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title, Snackbar.LENGTH_INDEFINITE)
|
Snackbar.make(recyclerView, getString(R.string.you_are_going_to_delete) + ": " + deletedItem.title, Snackbar.LENGTH_INDEFINITE)
|
||||||
.setAction(getString(R.string.undo)) {
|
.setAction(getString(R.string.undo)) {
|
||||||
historyViewModel.insert(deletedItem)
|
historyViewModel.insert(deletedItem)
|
||||||
}.show()
|
}.show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ItemTouchHelper.RIGHT -> {
|
ItemTouchHelper.RIGHT -> {
|
||||||
val item = historyList!![position]!!
|
lifecycleScope.launch {
|
||||||
historyAdapter!!.notifyItemChanged(position)
|
val item = withContext(Dispatchers.IO) {
|
||||||
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
|
historyViewModel.getByID(itemID)
|
||||||
Pair("result", downloadViewModel.createResultItemFromHistory(item)),
|
}
|
||||||
Pair("type", item.type)
|
historyAdapter.notifyItemChanged(position)
|
||||||
))
|
findNavController().navigate(R.id.downloadBottomSheetDialog, bundleOf(
|
||||||
|
Pair("result", downloadViewModel.createResultItemFromHistory(item)),
|
||||||
|
Pair("type", item.type)
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -737,7 +743,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
super.onChildDraw(
|
super.onChildDraw(
|
||||||
c,
|
c,
|
||||||
recyclerView,
|
recyclerView,
|
||||||
viewHolder!!,
|
viewHolder,
|
||||||
dX,
|
dX,
|
||||||
dY,
|
dY,
|
||||||
actionState,
|
actionState,
|
||||||
|
|
@ -748,7 +754,13 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
||||||
|
|
||||||
override fun onButtonClick(itemID: Long, isPresent: Boolean) {
|
override fun onButtonClick(itemID: Long, isPresent: Boolean) {
|
||||||
if (isPresent){
|
if (isPresent){
|
||||||
FileUtil.shareFileIntent(requireContext(), historyList!!.first { it!!.id == itemID }!!.downloadPath)
|
lifecycleScope.launch {
|
||||||
|
val item = withContext(Dispatchers.IO){
|
||||||
|
historyViewModel.getByID(itemID)
|
||||||
|
}
|
||||||
|
FileUtil.shareFileIntent(requireContext(), item.downloadPath)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,12 @@ class UpdateSettingsFragment : BaseSettingsFragment() {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ytdlVersion!!.setOnPreferenceClickListener {
|
||||||
|
initYTDLUpdate(editor)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
updateYTDL!!.onPreferenceClickListener =
|
updateYTDL!!.onPreferenceClickListener =
|
||||||
Preference.OnPreferenceClickListener {
|
Preference.OnPreferenceClickListener {
|
||||||
initYTDLUpdate(editor)
|
initYTDLUpdate(editor)
|
||||||
|
|
|
||||||
|
|
@ -46,9 +46,6 @@ import com.deniscerri.ytdl.database.models.Format
|
||||||
import com.deniscerri.ytdl.database.models.observeSources.ObserveSourcesItem
|
import com.deniscerri.ytdl.database.models.observeSources.ObserveSourcesItem
|
||||||
import com.deniscerri.ytdl.database.repository.DownloadRepository
|
import com.deniscerri.ytdl.database.repository.DownloadRepository
|
||||||
import com.deniscerri.ytdl.database.repository.ObserveSourcesRepository.EveryCategory
|
import com.deniscerri.ytdl.database.repository.ObserveSourcesRepository.EveryCategory
|
||||||
import com.deniscerri.ytdl.util.Extensions.isYoutubeChannelURL
|
|
||||||
import com.deniscerri.ytdl.util.Extensions.isYoutubeURL
|
|
||||||
import com.deniscerri.ytdl.util.Extensions.toTimePeriodsArray
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
|
|
@ -59,6 +56,7 @@ import com.neo.highlight.util.listener.HighlightTextWatcher
|
||||||
import com.neo.highlight.util.scheme.ColorScheme
|
import com.neo.highlight.util.scheme.ColorScheme
|
||||||
import com.squareup.picasso.Picasso
|
import com.squareup.picasso.Picasso
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.FlowCollector
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
|
@ -526,11 +524,43 @@ object Extensions {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.extractURL() : String {
|
fun String.extractURL() : String {
|
||||||
val res = Pattern.compile("(http|ftp|https)://([\\w_-]+(?:\\.[\\w_-]+)+)([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])").matcher(this)
|
val res =
|
||||||
return if (res.find()){
|
Pattern.compile("(http|ftp|https)://([\\w_-]+(?:\\.[\\w_-]+)+)([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])")
|
||||||
|
.matcher(this)
|
||||||
|
return if (res.find()) {
|
||||||
res.group()
|
res.group()
|
||||||
}else{
|
} else {
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun String.isURL(): Boolean {
|
||||||
|
return Pattern.compile("(http|ftp|https)://([\\w_-]+(?:\\.[\\w_-]+)+)([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])").matcher(this).find()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, T3, T4, T5, T6, T7, R> combine(
|
||||||
|
flow: Flow<T1>,
|
||||||
|
flow2: Flow<T2>,
|
||||||
|
flow3: Flow<T3>,
|
||||||
|
flow4: Flow<T4>,
|
||||||
|
flow5: Flow<T5>,
|
||||||
|
flow6: Flow<T6>,
|
||||||
|
flow7: Flow<T7>,
|
||||||
|
transform: suspend (T1, T2, T3, T4, T5, T6, T7) -> R
|
||||||
|
): Flow<R> = combine(
|
||||||
|
flow,
|
||||||
|
combine(flow2, flow3, ::Pair),
|
||||||
|
combine(flow4, flow5, ::Pair),
|
||||||
|
combine(flow6, flow7, ::Pair),
|
||||||
|
) { t1, t2, t3, t4, ->
|
||||||
|
transform(
|
||||||
|
t1,
|
||||||
|
t2.first,
|
||||||
|
t2.second,
|
||||||
|
t3.first,
|
||||||
|
t3.second,
|
||||||
|
t4.first,
|
||||||
|
t4.second
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -191,6 +191,7 @@ object UiUtil {
|
||||||
val extraCommandsSwitch : MaterialSwitch = bottomSheet.findViewById(R.id.extraCommandsSwitch)!!
|
val extraCommandsSwitch : MaterialSwitch = bottomSheet.findViewById(R.id.extraCommandsSwitch)!!
|
||||||
val extraCommandsAudio : CheckBox = bottomSheet.findViewById(R.id.checkbox_audio)!!
|
val extraCommandsAudio : CheckBox = bottomSheet.findViewById(R.id.checkbox_audio)!!
|
||||||
val extraCommandsVideo : CheckBox = bottomSheet.findViewById(R.id.checkbox_video)!!
|
val extraCommandsVideo : CheckBox = bottomSheet.findViewById(R.id.checkbox_video)!!
|
||||||
|
val extraCommandsDataFetchingSwitch : MaterialSwitch = bottomSheet.findViewById(R.id.extraCommandDataFetching)!!
|
||||||
val shortcutsChipGroup : ChipGroup = bottomSheet.findViewById(R.id.shortcutsChipGroup)!!
|
val shortcutsChipGroup : ChipGroup = bottomSheet.findViewById(R.id.shortcutsChipGroup)!!
|
||||||
val editShortcuts : Button = bottomSheet.findViewById(R.id.edit_shortcuts)!!
|
val editShortcuts : Button = bottomSheet.findViewById(R.id.edit_shortcuts)!!
|
||||||
|
|
||||||
|
|
@ -252,6 +253,7 @@ object UiUtil {
|
||||||
|
|
||||||
if (item != null){
|
if (item != null){
|
||||||
preferredCommandSwitch.isChecked = item.content == sharedPreferences.getString("preferred_command_template", "")
|
preferredCommandSwitch.isChecked = item.content == sharedPreferences.getString("preferred_command_template", "")
|
||||||
|
extraCommandsDataFetchingSwitch.isChecked = item.useAsExtraCommandDataFetching
|
||||||
|
|
||||||
extraCommandsSwitch.isChecked = item.useAsExtraCommand
|
extraCommandsSwitch.isChecked = item.useAsExtraCommand
|
||||||
if (item.useAsExtraCommand){
|
if (item.useAsExtraCommand){
|
||||||
|
|
@ -307,7 +309,7 @@ object UiUtil {
|
||||||
|
|
||||||
|
|
||||||
if (item == null){
|
if (item == null){
|
||||||
val t = CommandTemplate(0, title.editText!!.text.toString(), content.editText!!.text.toString(), extraCommandsSwitch.isChecked, extraCommandsAudio.isChecked, extraCommandsVideo.isChecked)
|
val t = CommandTemplate(0, title.editText!!.text.toString(), content.editText!!.text.toString(), extraCommandsSwitch.isChecked, extraCommandsAudio.isChecked, extraCommandsVideo.isChecked, extraCommandsDataFetchingSwitch.isChecked)
|
||||||
commandTemplateViewModel.insert(t)
|
commandTemplateViewModel.insert(t)
|
||||||
newTemplate(t)
|
newTemplate(t)
|
||||||
}else{
|
}else{
|
||||||
|
|
@ -316,6 +318,7 @@ object UiUtil {
|
||||||
item.useAsExtraCommand = extraCommandsSwitch.isChecked
|
item.useAsExtraCommand = extraCommandsSwitch.isChecked
|
||||||
item.useAsExtraCommandAudio = extraCommandsAudio.isChecked
|
item.useAsExtraCommandAudio = extraCommandsAudio.isChecked
|
||||||
item.useAsExtraCommandVideo = extraCommandsVideo.isChecked
|
item.useAsExtraCommandVideo = extraCommandsVideo.isChecked
|
||||||
|
item.useAsExtraCommandDataFetching = extraCommandsDataFetchingSwitch.isChecked
|
||||||
commandTemplateViewModel.update(item)
|
commandTemplateViewModel.update(item)
|
||||||
newTemplate(item)
|
newTemplate(item)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -113,8 +113,8 @@ class DownloadWorker(
|
||||||
setForegroundAsync(ForegroundInfo(notificationID, workNotif))
|
setForegroundAsync(ForegroundInfo(notificationID, workNotif))
|
||||||
}
|
}
|
||||||
|
|
||||||
queuedItems.collectLatest { items ->
|
queuedItems.collect { items ->
|
||||||
if (this@DownloadWorker.isStopped) return@collectLatest
|
if (this@DownloadWorker.isStopped) return@collect
|
||||||
|
|
||||||
runningYTDLInstances.clear()
|
runningYTDLInstances.clear()
|
||||||
val activeDownloads = dao.getActiveDownloadsList()
|
val activeDownloads = dao.getActiveDownloadsList()
|
||||||
|
|
@ -126,19 +126,19 @@ class DownloadWorker(
|
||||||
val useScheduler = sharedPreferences.getBoolean("use_scheduler", false)
|
val useScheduler = sharedPreferences.getBoolean("use_scheduler", false)
|
||||||
if (items.isEmpty() && running.isEmpty()) {
|
if (items.isEmpty() && running.isEmpty()) {
|
||||||
WorkManager.getInstance(context).cancelWorkById(this@DownloadWorker.id)
|
WorkManager.getInstance(context).cancelWorkById(this@DownloadWorker.id)
|
||||||
return@collectLatest
|
return@collect
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useScheduler){
|
if (useScheduler){
|
||||||
if (items.none{it.downloadStartTime > 0L} && running.isEmpty() && !alarmScheduler.isDuringTheScheduledTime()) {
|
if (items.none{it.downloadStartTime > 0L} && running.isEmpty() && !alarmScheduler.isDuringTheScheduledTime()) {
|
||||||
WorkManager.getInstance(context).cancelWorkById(this@DownloadWorker.id)
|
WorkManager.getInstance(context).cancelWorkById(this@DownloadWorker.id)
|
||||||
return@collectLatest
|
return@collect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priorityItemIDs.isEmpty() && !continueAfterPriorityIds) {
|
if (priorityItemIDs.isEmpty() && !continueAfterPriorityIds) {
|
||||||
WorkManager.getInstance(context).cancelWorkById(this@DownloadWorker.id)
|
WorkManager.getInstance(context).cancelWorkById(this@DownloadWorker.id)
|
||||||
return@collectLatest
|
return@collect
|
||||||
}
|
}
|
||||||
|
|
||||||
val concurrentDownloads = sharedPreferences.getInt("concurrent_downloads", 1) - running.size
|
val concurrentDownloads = sharedPreferences.getInt("concurrent_downloads", 1) - running.size
|
||||||
|
|
@ -312,6 +312,7 @@ class DownloadWorker(
|
||||||
finalPaths,
|
finalPaths,
|
||||||
downloadItem.website,
|
downloadItem.website,
|
||||||
downloadItem.format,
|
downloadItem.format,
|
||||||
|
downloadItem.format.filesize,
|
||||||
downloadItem.id,
|
downloadItem.id,
|
||||||
commandString)
|
commandString)
|
||||||
historyDao.insert(historyItem)
|
historyDao.insert(historyItem)
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,20 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style="@style/Divider.Horizontal"
|
||||||
|
android:layout_marginVertical="10dp" />
|
||||||
|
|
||||||
|
<com.google.android.material.materialswitch.MaterialSwitch
|
||||||
|
android:id="@+id/extraCommandDataFetching"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginHorizontal="10dp"
|
||||||
|
android:checked="false"
|
||||||
|
android:text="@string/data_fetching_extra_command"
|
||||||
|
android:textSize="15sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
style="@style/Divider.Horizontal"
|
style="@style/Divider.Horizontal"
|
||||||
android:layout_marginVertical="10dp" />
|
android:layout_marginVertical="10dp" />
|
||||||
|
|
|
||||||
|
|
@ -434,6 +434,6 @@
|
||||||
<string name="socket_timeout">Socket Timeout</string>
|
<string name="socket_timeout">Socket Timeout</string>
|
||||||
<string name="socket_timeout_description">Time to wait before giving up, in seconds</string>
|
<string name="socket_timeout_description">Time to wait before giving up, in seconds</string>
|
||||||
<string name="advanced">Advanced</string>
|
<string name="advanced">Advanced</string>
|
||||||
<string name="data_fetching_extra_commands">Data Fetching Extra Commands</string>
|
<string name="data_fetching_extra_command">Data Fetching Extra Command</string>
|
||||||
<string name="thumbnail">Thumbnail</string>
|
<string name="thumbnail">Thumbnail</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -2,32 +2,27 @@
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<EditTextPreference
|
<PreferenceCategory android:title="YouTube">
|
||||||
android:defaultValue="default,mediaconnect"
|
<EditTextPreference
|
||||||
android:icon="@drawable/ic_code"
|
android:defaultValue="default,mediaconnect"
|
||||||
android:key="youtube_player_client"
|
android:icon="@drawable/ic_code"
|
||||||
app:useSimpleSummaryProvider="true"
|
android:key="youtube_player_client"
|
||||||
android:title="Player Client" />
|
app:useSimpleSummaryProvider="true"
|
||||||
|
android:title="Player Client" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:defaultValue=""
|
android:defaultValue=""
|
||||||
android:icon="@drawable/ic_code"
|
android:icon="@drawable/ic_code"
|
||||||
android:key="youtube_po_token"
|
android:key="youtube_po_token"
|
||||||
app:useSimpleSummaryProvider="true"
|
app:useSimpleSummaryProvider="true"
|
||||||
android:title="PO Token" />
|
android:title="PO Token" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:defaultValue=""
|
android:defaultValue=""
|
||||||
android:icon="@drawable/ic_code"
|
android:icon="@drawable/ic_code"
|
||||||
android:key="youtube_other_extractor_args"
|
android:key="youtube_other_extractor_args"
|
||||||
app:useSimpleSummaryProvider="true"
|
app:useSimpleSummaryProvider="true"
|
||||||
android:title="@string/other_youtube_extractor_args" />
|
android:title="@string/other_youtube_extractor_args" />
|
||||||
|
</PreferenceCategory>
|
||||||
<EditTextPreference
|
|
||||||
android:defaultValue=""
|
|
||||||
android:icon="@drawable/ic_terminal"
|
|
||||||
android:key="data_fetching_extra_commands"
|
|
||||||
app:useSimpleSummaryProvider="true"
|
|
||||||
android:title="@string/data_fetching_extra_commands" />
|
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
app:icon="@drawable/ic_info"
|
||||||
|
app:key="version"
|
||||||
|
app:title="@string/version"/>
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/source">
|
<PreferenceCategory android:title="@string/source">
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
|
|
@ -35,6 +40,36 @@
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/app">
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:widgetLayout="@layout/preferece_material_switch"
|
||||||
|
app:defaultValue="true"
|
||||||
|
android:icon="@drawable/ic_update_app"
|
||||||
|
android:key="update_app"
|
||||||
|
app:summary="@string/update_app_summary"
|
||||||
|
app:title="@string/update_app" />
|
||||||
|
|
||||||
|
<EditTextPreference
|
||||||
|
app:isPreferenceVisible="false"
|
||||||
|
app:key="skip_updates"
|
||||||
|
app:defaultValue="" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:widgetLayout="@layout/preferece_material_switch"
|
||||||
|
app:defaultValue="false"
|
||||||
|
android:icon="@drawable/ic_experiment"
|
||||||
|
android:key="update_beta"
|
||||||
|
app:summary="@string/update_app_beta_summary"
|
||||||
|
app:title="@string/update_app_beta" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
app:icon="@drawable/ic_chapters"
|
||||||
|
app:key="changelog"
|
||||||
|
app:title="@string/changelog" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/format">
|
<PreferenceCategory android:title="@string/format">
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="filesize"
|
android:defaultValue="filesize"
|
||||||
|
|
@ -63,41 +98,4 @@
|
||||||
app:title="@string/update_formats" />
|
app:title="@string/update_formats" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/app">
|
|
||||||
|
|
||||||
<SwitchPreferenceCompat
|
|
||||||
android:widgetLayout="@layout/preferece_material_switch"
|
|
||||||
app:defaultValue="true"
|
|
||||||
android:icon="@drawable/ic_update_app"
|
|
||||||
android:key="update_app"
|
|
||||||
app:summary="@string/update_app_summary"
|
|
||||||
app:title="@string/update_app" />
|
|
||||||
|
|
||||||
<EditTextPreference
|
|
||||||
app:isPreferenceVisible="false"
|
|
||||||
app:key="skip_updates"
|
|
||||||
app:defaultValue="" />
|
|
||||||
|
|
||||||
<SwitchPreferenceCompat
|
|
||||||
android:widgetLayout="@layout/preferece_material_switch"
|
|
||||||
app:defaultValue="false"
|
|
||||||
android:icon="@drawable/ic_experiment"
|
|
||||||
android:key="update_beta"
|
|
||||||
app:summary="@string/update_app_beta_summary"
|
|
||||||
app:title="@string/update_app_beta" />
|
|
||||||
|
|
||||||
<Preference
|
|
||||||
app:icon="@drawable/ic_chapters"
|
|
||||||
app:key="changelog"
|
|
||||||
app:title="@string/changelog" />
|
|
||||||
|
|
||||||
|
|
||||||
<Preference
|
|
||||||
app:icon="@drawable/ic_info"
|
|
||||||
app:key="version"
|
|
||||||
app:title="@string/version"/>
|
|
||||||
|
|
||||||
|
|
||||||
</PreferenceCategory>
|
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
Loading…
Reference in a new issue