mirror of
https://github.com/TeamNewPipe/NewPipe.git
synced 2024-11-21 18:42:35 +01:00
Setup initial database for feed implementation
- Update the database diagram - Add new migration for the new tables and fields - Enable schema exports
This commit is contained in:
parent
0e2f062148
commit
e8ab5aacc7
@ -35,6 +35,12 @@ android {
|
|||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|
||||||
|
javaCompileOptions {
|
||||||
|
annotationProcessorOptions {
|
||||||
|
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
479
app/schemas/org.schabi.newpipe.database.AppDatabase/2.json
Normal file
479
app/schemas/org.schabi.newpipe.database.AppDatabase/2.json
Normal file
@ -0,0 +1,479 @@
|
|||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 2,
|
||||||
|
"identityHash": "b7856223e2595ddf20a3ce6243ce9527",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "subscriptions",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `service_id` INTEGER NOT NULL, `url` TEXT, `name` TEXT, `avatar_url` TEXT, `subscriber_count` INTEGER, `description` TEXT)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "uid",
|
||||||
|
"columnName": "uid",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "serviceId",
|
||||||
|
"columnName": "service_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "avatarUrl",
|
||||||
|
"columnName": "avatar_url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "subscriberCount",
|
||||||
|
"columnName": "subscriber_count",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "description",
|
||||||
|
"columnName": "description",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"uid"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_subscriptions_service_id_url",
|
||||||
|
"unique": true,
|
||||||
|
"columnNames": [
|
||||||
|
"service_id",
|
||||||
|
"url"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE UNIQUE INDEX `index_subscriptions_service_id_url` ON `${TABLE_NAME}` (`service_id`, `url`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "search_history",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `creation_date` INTEGER, `service_id` INTEGER NOT NULL, `search` TEXT)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "creationDate",
|
||||||
|
"columnName": "creation_date",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "serviceId",
|
||||||
|
"columnName": "service_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "search",
|
||||||
|
"columnName": "search",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_search_history_search",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"search"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE INDEX `index_search_history_search` ON `${TABLE_NAME}` (`search`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "streams",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `service_id` INTEGER NOT NULL, `url` TEXT, `title` TEXT, `stream_type` TEXT, `duration` INTEGER, `uploader` TEXT, `thumbnail_url` TEXT)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "uid",
|
||||||
|
"columnName": "uid",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "serviceId",
|
||||||
|
"columnName": "service_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "title",
|
||||||
|
"columnName": "title",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "streamType",
|
||||||
|
"columnName": "stream_type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "duration",
|
||||||
|
"columnName": "duration",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploader",
|
||||||
|
"columnName": "uploader",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumbnailUrl",
|
||||||
|
"columnName": "thumbnail_url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"uid"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_streams_service_id_url",
|
||||||
|
"unique": true,
|
||||||
|
"columnNames": [
|
||||||
|
"service_id",
|
||||||
|
"url"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE UNIQUE INDEX `index_streams_service_id_url` ON `${TABLE_NAME}` (`service_id`, `url`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "stream_history",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`stream_id` INTEGER NOT NULL, `access_date` INTEGER NOT NULL, `repeat_count` INTEGER NOT NULL, PRIMARY KEY(`stream_id`, `access_date`), FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "streamUid",
|
||||||
|
"columnName": "stream_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "accessDate",
|
||||||
|
"columnName": "access_date",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "repeatCount",
|
||||||
|
"columnName": "repeat_count",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"stream_id",
|
||||||
|
"access_date"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_stream_history_stream_id",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"stream_id"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE INDEX `index_stream_history_stream_id` ON `${TABLE_NAME}` (`stream_id`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "streams",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"stream_id"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"uid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "stream_state",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`stream_id` INTEGER NOT NULL, `progress_time` INTEGER NOT NULL, PRIMARY KEY(`stream_id`), FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "streamUid",
|
||||||
|
"columnName": "stream_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "progressTime",
|
||||||
|
"columnName": "progress_time",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"stream_id"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "streams",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"stream_id"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"uid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "playlists",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `thumbnail_url` TEXT)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "uid",
|
||||||
|
"columnName": "uid",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumbnailUrl",
|
||||||
|
"columnName": "thumbnail_url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"uid"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_playlists_name",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE INDEX `index_playlists_name` ON `${TABLE_NAME}` (`name`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "playlist_stream_join",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`playlist_id` INTEGER NOT NULL, `stream_id` INTEGER NOT NULL, `join_index` INTEGER NOT NULL, PRIMARY KEY(`playlist_id`, `join_index`), FOREIGN KEY(`playlist_id`) REFERENCES `playlists`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistUid",
|
||||||
|
"columnName": "playlist_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "streamUid",
|
||||||
|
"columnName": "stream_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "index",
|
||||||
|
"columnName": "join_index",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"playlist_id",
|
||||||
|
"join_index"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_playlist_stream_join_playlist_id_join_index",
|
||||||
|
"unique": true,
|
||||||
|
"columnNames": [
|
||||||
|
"playlist_id",
|
||||||
|
"join_index"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE UNIQUE INDEX `index_playlist_stream_join_playlist_id_join_index` ON `${TABLE_NAME}` (`playlist_id`, `join_index`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_playlist_stream_join_stream_id",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"stream_id"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE INDEX `index_playlist_stream_join_stream_id` ON `${TABLE_NAME}` (`stream_id`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "playlists",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"playlist_id"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"uid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"table": "streams",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"stream_id"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"uid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "remote_playlists",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `service_id` INTEGER NOT NULL, `name` TEXT, `url` TEXT, `thumbnail_url` TEXT, `uploader` TEXT, `stream_count` INTEGER)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "uid",
|
||||||
|
"columnName": "uid",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "serviceId",
|
||||||
|
"columnName": "service_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumbnailUrl",
|
||||||
|
"columnName": "thumbnail_url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploader",
|
||||||
|
"columnName": "uploader",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "streamCount",
|
||||||
|
"columnName": "stream_count",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"uid"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_remote_playlists_name",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE INDEX `index_remote_playlists_name` ON `${TABLE_NAME}` (`name`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_remote_playlists_service_id_url",
|
||||||
|
"unique": true,
|
||||||
|
"columnNames": [
|
||||||
|
"service_id",
|
||||||
|
"url"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE UNIQUE INDEX `index_remote_playlists_service_id_url` ON `${TABLE_NAME}` (`service_id`, `url`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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, \"b7856223e2595ddf20a3ce6243ce9527\")"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
647
app/schemas/org.schabi.newpipe.database.AppDatabase/3.json
Normal file
647
app/schemas/org.schabi.newpipe.database.AppDatabase/3.json
Normal file
@ -0,0 +1,647 @@
|
|||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 3,
|
||||||
|
"identityHash": "ecffbb2ea251aeb38a8f508acf2aa404",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "subscriptions",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `service_id` INTEGER NOT NULL, `url` TEXT, `name` TEXT, `avatar_url` TEXT, `subscriber_count` INTEGER, `description` TEXT)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "uid",
|
||||||
|
"columnName": "uid",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "serviceId",
|
||||||
|
"columnName": "service_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "avatarUrl",
|
||||||
|
"columnName": "avatar_url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "subscriberCount",
|
||||||
|
"columnName": "subscriber_count",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "description",
|
||||||
|
"columnName": "description",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"uid"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_subscriptions_service_id_url",
|
||||||
|
"unique": true,
|
||||||
|
"columnNames": [
|
||||||
|
"service_id",
|
||||||
|
"url"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE UNIQUE INDEX `index_subscriptions_service_id_url` ON `${TABLE_NAME}` (`service_id`, `url`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "search_history",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `creation_date` INTEGER, `service_id` INTEGER NOT NULL, `search` TEXT)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "creationDate",
|
||||||
|
"columnName": "creation_date",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "serviceId",
|
||||||
|
"columnName": "service_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "search",
|
||||||
|
"columnName": "search",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_search_history_search",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"search"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE INDEX `index_search_history_search` ON `${TABLE_NAME}` (`search`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "streams",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `service_id` INTEGER NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `stream_type` TEXT NOT NULL, `duration` INTEGER NOT NULL, `uploader` TEXT NOT NULL, `thumbnail_url` TEXT, `view_count` INTEGER, `textual_upload_date` TEXT, `upload_date` INTEGER)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "uid",
|
||||||
|
"columnName": "uid",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "serviceId",
|
||||||
|
"columnName": "service_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "title",
|
||||||
|
"columnName": "title",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "streamType",
|
||||||
|
"columnName": "stream_type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "duration",
|
||||||
|
"columnName": "duration",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploader",
|
||||||
|
"columnName": "uploader",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumbnailUrl",
|
||||||
|
"columnName": "thumbnail_url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "viewCount",
|
||||||
|
"columnName": "view_count",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "textualUploadDate",
|
||||||
|
"columnName": "textual_upload_date",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploadDate",
|
||||||
|
"columnName": "upload_date",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"uid"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_streams_service_id_url",
|
||||||
|
"unique": true,
|
||||||
|
"columnNames": [
|
||||||
|
"service_id",
|
||||||
|
"url"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE UNIQUE INDEX `index_streams_service_id_url` ON `${TABLE_NAME}` (`service_id`, `url`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "stream_history",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`stream_id` INTEGER NOT NULL, `access_date` INTEGER NOT NULL, `repeat_count` INTEGER NOT NULL, PRIMARY KEY(`stream_id`, `access_date`), FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "streamUid",
|
||||||
|
"columnName": "stream_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "accessDate",
|
||||||
|
"columnName": "access_date",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "repeatCount",
|
||||||
|
"columnName": "repeat_count",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"stream_id",
|
||||||
|
"access_date"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_stream_history_stream_id",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"stream_id"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE INDEX `index_stream_history_stream_id` ON `${TABLE_NAME}` (`stream_id`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "streams",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"stream_id"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"uid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "stream_state",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`stream_id` INTEGER NOT NULL, `progress_time` INTEGER NOT NULL, PRIMARY KEY(`stream_id`), FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "streamUid",
|
||||||
|
"columnName": "stream_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "progressTime",
|
||||||
|
"columnName": "progress_time",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"stream_id"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "streams",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"stream_id"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"uid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "playlists",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `thumbnail_url` TEXT)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "uid",
|
||||||
|
"columnName": "uid",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumbnailUrl",
|
||||||
|
"columnName": "thumbnail_url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"uid"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_playlists_name",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE INDEX `index_playlists_name` ON `${TABLE_NAME}` (`name`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "playlist_stream_join",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`playlist_id` INTEGER NOT NULL, `stream_id` INTEGER NOT NULL, `join_index` INTEGER NOT NULL, PRIMARY KEY(`playlist_id`, `join_index`), FOREIGN KEY(`playlist_id`) REFERENCES `playlists`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistUid",
|
||||||
|
"columnName": "playlist_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "streamUid",
|
||||||
|
"columnName": "stream_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "index",
|
||||||
|
"columnName": "join_index",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"playlist_id",
|
||||||
|
"join_index"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_playlist_stream_join_playlist_id_join_index",
|
||||||
|
"unique": true,
|
||||||
|
"columnNames": [
|
||||||
|
"playlist_id",
|
||||||
|
"join_index"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE UNIQUE INDEX `index_playlist_stream_join_playlist_id_join_index` ON `${TABLE_NAME}` (`playlist_id`, `join_index`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_playlist_stream_join_stream_id",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"stream_id"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE INDEX `index_playlist_stream_join_stream_id` ON `${TABLE_NAME}` (`stream_id`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "playlists",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"playlist_id"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"uid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"table": "streams",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"stream_id"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"uid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "remote_playlists",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `service_id` INTEGER NOT NULL, `name` TEXT, `url` TEXT, `thumbnail_url` TEXT, `uploader` TEXT, `stream_count` INTEGER)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "uid",
|
||||||
|
"columnName": "uid",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "serviceId",
|
||||||
|
"columnName": "service_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "url",
|
||||||
|
"columnName": "url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumbnailUrl",
|
||||||
|
"columnName": "thumbnail_url",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploader",
|
||||||
|
"columnName": "uploader",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "streamCount",
|
||||||
|
"columnName": "stream_count",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"uid"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_remote_playlists_name",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE INDEX `index_remote_playlists_name` ON `${TABLE_NAME}` (`name`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_remote_playlists_service_id_url",
|
||||||
|
"unique": true,
|
||||||
|
"columnNames": [
|
||||||
|
"service_id",
|
||||||
|
"url"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE UNIQUE INDEX `index_remote_playlists_service_id_url` ON `${TABLE_NAME}` (`service_id`, `url`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "feed",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`stream_id` INTEGER NOT NULL, `subscription_id` INTEGER NOT NULL, PRIMARY KEY(`stream_id`, `subscription_id`), FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY(`subscription_id`) REFERENCES `subscriptions`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "streamId",
|
||||||
|
"columnName": "stream_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "subscriptionId",
|
||||||
|
"columnName": "subscription_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"stream_id",
|
||||||
|
"subscription_id"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_feed_subscription_id",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"subscription_id"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE INDEX `index_feed_subscription_id` ON `${TABLE_NAME}` (`subscription_id`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "streams",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"stream_id"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"uid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"table": "subscriptions",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"subscription_id"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"uid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "feed_group",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `icon_id` INTEGER NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "uid",
|
||||||
|
"columnName": "uid",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "iconId",
|
||||||
|
"columnName": "icon_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"uid"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "feed_group_subscription_join",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`group_id` INTEGER NOT NULL, `subscription_id` INTEGER NOT NULL, PRIMARY KEY(`group_id`, `subscription_id`), FOREIGN KEY(`group_id`) REFERENCES `feed_group`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY(`subscription_id`) REFERENCES `subscriptions`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "feedGroupId",
|
||||||
|
"columnName": "group_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "subscriptionId",
|
||||||
|
"columnName": "subscription_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"group_id",
|
||||||
|
"subscription_id"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_feed_group_subscription_join_subscription_id",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"subscription_id"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE INDEX `index_feed_group_subscription_join_subscription_id` ON `${TABLE_NAME}` (`subscription_id`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "feed_group",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"group_id"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"uid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"table": "subscriptions",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "CASCADE",
|
||||||
|
"columns": [
|
||||||
|
"subscription_id"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"uid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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, \"ecffbb2ea251aeb38a8f508acf2aa404\")"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,8 @@ import androidx.room.Room;
|
|||||||
import org.schabi.newpipe.database.AppDatabase;
|
import org.schabi.newpipe.database.AppDatabase;
|
||||||
|
|
||||||
import static org.schabi.newpipe.database.AppDatabase.DATABASE_NAME;
|
import static org.schabi.newpipe.database.AppDatabase.DATABASE_NAME;
|
||||||
import static org.schabi.newpipe.database.Migrations.MIGRATION_11_12;
|
import static org.schabi.newpipe.database.Migrations.MIGRATION_1_2;
|
||||||
|
import static org.schabi.newpipe.database.Migrations.MIGRATION_2_3;
|
||||||
|
|
||||||
public final class NewPipeDatabase {
|
public final class NewPipeDatabase {
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ public final class NewPipeDatabase {
|
|||||||
private static AppDatabase getDatabase(Context context) {
|
private static AppDatabase getDatabase(Context context) {
|
||||||
return Room
|
return Room
|
||||||
.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME)
|
.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME)
|
||||||
.addMigrations(MIGRATION_11_12)
|
.addMigrations(MIGRATION_1_2, MIGRATION_2_3)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,11 @@ import androidx.room.Database;
|
|||||||
import androidx.room.RoomDatabase;
|
import androidx.room.RoomDatabase;
|
||||||
import androidx.room.TypeConverters;
|
import androidx.room.TypeConverters;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.database.feed.dao.FeedDAO;
|
||||||
|
import org.schabi.newpipe.database.feed.dao.FeedGroupDAO;
|
||||||
|
import org.schabi.newpipe.database.feed.model.FeedEntity;
|
||||||
|
import org.schabi.newpipe.database.feed.model.FeedGroupEntity;
|
||||||
|
import org.schabi.newpipe.database.feed.model.FeedGroupSubscriptionEntity;
|
||||||
import org.schabi.newpipe.database.history.dao.SearchHistoryDAO;
|
import org.schabi.newpipe.database.history.dao.SearchHistoryDAO;
|
||||||
import org.schabi.newpipe.database.history.dao.StreamHistoryDAO;
|
import org.schabi.newpipe.database.history.dao.StreamHistoryDAO;
|
||||||
import org.schabi.newpipe.database.history.model.SearchHistoryEntry;
|
import org.schabi.newpipe.database.history.model.SearchHistoryEntry;
|
||||||
@ -21,35 +26,32 @@ import org.schabi.newpipe.database.stream.model.StreamStateEntity;
|
|||||||
import org.schabi.newpipe.database.subscription.SubscriptionDAO;
|
import org.schabi.newpipe.database.subscription.SubscriptionDAO;
|
||||||
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
|
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
|
||||||
|
|
||||||
import static org.schabi.newpipe.database.Migrations.DB_VER_12_0;
|
import static org.schabi.newpipe.database.Migrations.DB_VER_3;
|
||||||
|
|
||||||
@TypeConverters({Converters.class})
|
@TypeConverters({Converters.class})
|
||||||
@Database(
|
@Database(
|
||||||
entities = {
|
entities = {
|
||||||
SubscriptionEntity.class, SearchHistoryEntry.class,
|
SubscriptionEntity.class, SearchHistoryEntry.class,
|
||||||
StreamEntity.class, StreamHistoryEntity.class, StreamStateEntity.class,
|
StreamEntity.class, StreamHistoryEntity.class, StreamStateEntity.class,
|
||||||
PlaylistEntity.class, PlaylistStreamEntity.class, PlaylistRemoteEntity.class
|
PlaylistEntity.class, PlaylistStreamEntity.class, PlaylistRemoteEntity.class,
|
||||||
|
FeedEntity.class, FeedGroupEntity.class, FeedGroupSubscriptionEntity.class
|
||||||
},
|
},
|
||||||
version = DB_VER_12_0,
|
version = DB_VER_3
|
||||||
exportSchema = false
|
|
||||||
)
|
)
|
||||||
public abstract class AppDatabase extends RoomDatabase {
|
public abstract class AppDatabase extends RoomDatabase {
|
||||||
|
|
||||||
public static final String DATABASE_NAME = "newpipe.db";
|
public static final String DATABASE_NAME = "newpipe.db";
|
||||||
|
|
||||||
public abstract SubscriptionDAO subscriptionDAO();
|
|
||||||
|
|
||||||
public abstract SearchHistoryDAO searchHistoryDAO();
|
public abstract SearchHistoryDAO searchHistoryDAO();
|
||||||
|
|
||||||
public abstract StreamDAO streamDAO();
|
public abstract StreamDAO streamDAO();
|
||||||
|
|
||||||
public abstract StreamHistoryDAO streamHistoryDAO();
|
public abstract StreamHistoryDAO streamHistoryDAO();
|
||||||
|
|
||||||
public abstract StreamStateDAO streamStateDAO();
|
public abstract StreamStateDAO streamStateDAO();
|
||||||
|
|
||||||
public abstract PlaylistDAO playlistDAO();
|
public abstract PlaylistDAO playlistDAO();
|
||||||
|
|
||||||
public abstract PlaylistStreamDAO playlistStreamDAO();
|
public abstract PlaylistStreamDAO playlistStreamDAO();
|
||||||
|
|
||||||
public abstract PlaylistRemoteDAO playlistRemoteDAO();
|
public abstract PlaylistRemoteDAO playlistRemoteDAO();
|
||||||
|
|
||||||
|
public abstract FeedDAO feedDAO();
|
||||||
|
public abstract FeedGroupDAO feedGroupDAO();
|
||||||
|
public abstract SubscriptionDAO subscriptionDAO();
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,14 @@ import android.util.Log;
|
|||||||
import org.schabi.newpipe.BuildConfig;
|
import org.schabi.newpipe.BuildConfig;
|
||||||
|
|
||||||
public class Migrations {
|
public class Migrations {
|
||||||
|
public static final int DB_VER_1 = 1;
|
||||||
public static final int DB_VER_11_0 = 1;
|
public static final int DB_VER_2 = 2;
|
||||||
public static final int DB_VER_12_0 = 2;
|
public static final int DB_VER_3 = 3;
|
||||||
|
|
||||||
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
||||||
private static final String TAG = Migrations.class.getName();
|
private static final String TAG = Migrations.class.getName();
|
||||||
|
|
||||||
public static final Migration MIGRATION_11_12 = new Migration(DB_VER_11_0, DB_VER_12_0) {
|
public static final Migration MIGRATION_1_2 = new Migration(DB_VER_1, DB_VER_2) {
|
||||||
@Override
|
@Override
|
||||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||||
if(DEBUG) {
|
if(DEBUG) {
|
||||||
@ -71,4 +71,29 @@ public class Migrations {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static final Migration MIGRATION_2_3 = new Migration(DB_VER_2, DB_VER_3) {
|
||||||
|
@Override
|
||||||
|
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||||
|
// Add NOT NULLs and new fields
|
||||||
|
database.execSQL("CREATE TABLE IF NOT EXISTS streams_new " +
|
||||||
|
"(uid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, service_id INTEGER NOT NULL, url TEXT NOT NULL, title TEXT NOT NULL, stream_type TEXT NOT NULL," +
|
||||||
|
" duration INTEGER NOT NULL, uploader TEXT NOT NULL, thumbnail_url TEXT, view_count INTEGER, textual_upload_date TEXT, upload_date INTEGER)");
|
||||||
|
|
||||||
|
database.execSQL("INSERT INTO streams_new (uid, service_id, url, title, stream_type, duration, uploader, thumbnail_url, view_count, textual_upload_date, upload_date)"+
|
||||||
|
" SELECT uid, service_id, url, title, stream_type, duration, uploader, thumbnail_url, NULL, NULL, NULL FROM streams");
|
||||||
|
|
||||||
|
database.execSQL("DROP TABLE streams");
|
||||||
|
database.execSQL("ALTER TABLE streams_new RENAME TO streams");
|
||||||
|
database.execSQL("CREATE UNIQUE INDEX index_streams_service_id_url ON streams (service_id, url)");
|
||||||
|
|
||||||
|
// Tables for feed feature
|
||||||
|
database.execSQL("CREATE TABLE IF NOT EXISTS feed (stream_id INTEGER NOT NULL, subscription_id INTEGER NOT NULL, PRIMARY KEY(stream_id, subscription_id), FOREIGN KEY(stream_id) REFERENCES streams(uid) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY(subscription_id) REFERENCES subscriptions(uid) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)");
|
||||||
|
database.execSQL("CREATE INDEX index_feed_subscription_id ON feed (subscription_id)");
|
||||||
|
database.execSQL("CREATE TABLE IF NOT EXISTS feed_group (uid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name TEXT NOT NULL, icon_id INTEGER NOT NULL)");
|
||||||
|
database.execSQL("CREATE TABLE IF NOT EXISTS feed_group_subscription_join (group_id INTEGER NOT NULL, subscription_id INTEGER NOT NULL, PRIMARY KEY(group_id, subscription_id), FOREIGN KEY(group_id) REFERENCES feed_group(uid) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY(subscription_id) REFERENCES subscriptions(uid) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)");
|
||||||
|
database.execSQL("CREATE INDEX index_feed_group_subscription_join_subscription_id ON feed_group_subscription_join (subscription_id)");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
package org.schabi.newpipe.database.feed.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.Query
|
||||||
|
import io.reactivex.Flowable
|
||||||
|
import org.schabi.newpipe.database.feed.model.FeedEntity
|
||||||
|
import org.schabi.newpipe.database.stream.model.StreamEntity
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
abstract class FeedDAO {
|
||||||
|
@Query("DELETE FROM feed")
|
||||||
|
abstract fun deleteAll(): Int
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT s.* FROM streams s
|
||||||
|
|
||||||
|
INNER JOIN feed f
|
||||||
|
ON s.uid = f.stream_id
|
||||||
|
|
||||||
|
ORDER BY s.upload_date IS NULL DESC, s.upload_date DESC
|
||||||
|
""")
|
||||||
|
abstract fun getAllStreams(): Flowable<List<StreamEntity>>
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT s.* FROM streams s
|
||||||
|
|
||||||
|
INNER JOIN feed f
|
||||||
|
ON s.uid = f.stream_id
|
||||||
|
|
||||||
|
INNER JOIN feed_group_subscription_join fgs
|
||||||
|
ON fgs.subscription_id = f.subscription_id
|
||||||
|
|
||||||
|
INNER JOIN feed_group fg
|
||||||
|
ON fg.uid = fgs.group_id
|
||||||
|
|
||||||
|
WHERE fgs.group_id = :groupId
|
||||||
|
""")
|
||||||
|
abstract fun getAllStreamsFromGroup(groupId: Long): Flowable<List<StreamEntity>>
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.FAIL)
|
||||||
|
abstract fun insert(feedEntity: FeedEntity)
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.FAIL)
|
||||||
|
abstract fun insertAll(entities: List<FeedEntity>): List<Long>
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package org.schabi.newpipe.database.feed.dao
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import io.reactivex.Flowable
|
||||||
|
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
abstract class FeedGroupDAO {
|
||||||
|
@Query("DELETE FROM feed_group")
|
||||||
|
abstract fun deleteAll(): Int
|
||||||
|
|
||||||
|
@Query("SELECT * FROM feed_group")
|
||||||
|
abstract fun getAll(): Flowable<List<FeedGroupEntity>>
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.ABORT)
|
||||||
|
abstract fun insert(feedEntity: FeedGroupEntity)
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package org.schabi.newpipe.database.feed.model
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.ForeignKey
|
||||||
|
import androidx.room.Index
|
||||||
|
import org.schabi.newpipe.database.feed.model.FeedEntity.Companion.FEED_TABLE
|
||||||
|
import org.schabi.newpipe.database.feed.model.FeedEntity.Companion.STREAM_ID
|
||||||
|
import org.schabi.newpipe.database.feed.model.FeedEntity.Companion.SUBSCRIPTION_ID
|
||||||
|
import org.schabi.newpipe.database.stream.model.StreamEntity
|
||||||
|
import org.schabi.newpipe.database.subscription.SubscriptionEntity
|
||||||
|
|
||||||
|
@Entity(tableName = FEED_TABLE,
|
||||||
|
primaryKeys = [STREAM_ID, SUBSCRIPTION_ID],
|
||||||
|
indices = [Index(SUBSCRIPTION_ID)],
|
||||||
|
foreignKeys = [
|
||||||
|
ForeignKey(
|
||||||
|
entity = StreamEntity::class,
|
||||||
|
parentColumns = [StreamEntity.STREAM_ID],
|
||||||
|
childColumns = [STREAM_ID],
|
||||||
|
onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE, deferred = true),
|
||||||
|
ForeignKey(
|
||||||
|
entity = SubscriptionEntity::class,
|
||||||
|
parentColumns = [SubscriptionEntity.SUBSCRIPTION_UID],
|
||||||
|
childColumns = [SUBSCRIPTION_ID],
|
||||||
|
onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE, deferred = true)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
data class FeedEntity(
|
||||||
|
@ColumnInfo(name = STREAM_ID)
|
||||||
|
var streamId: Long,
|
||||||
|
|
||||||
|
@ColumnInfo(name = SUBSCRIPTION_ID)
|
||||||
|
var subscriptionId: Long
|
||||||
|
) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val FEED_TABLE = "feed"
|
||||||
|
|
||||||
|
const val STREAM_ID = "stream_id"
|
||||||
|
const val SUBSCRIPTION_ID = "subscription_id"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package org.schabi.newpipe.database.feed.model
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import org.schabi.newpipe.database.feed.model.FeedGroupEntity.Companion.FEED_GROUP_TABLE
|
||||||
|
|
||||||
|
@Entity(tableName = FEED_GROUP_TABLE)
|
||||||
|
data class FeedGroupEntity(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
@ColumnInfo(name = ID)
|
||||||
|
val uid: Long,
|
||||||
|
|
||||||
|
@ColumnInfo(name = NAME)
|
||||||
|
var name: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = ICON)
|
||||||
|
var iconId: Int
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
const val FEED_GROUP_TABLE = "feed_group"
|
||||||
|
|
||||||
|
const val ID = "uid"
|
||||||
|
const val NAME = "name"
|
||||||
|
const val ICON = "icon_id"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package org.schabi.newpipe.database.feed.model
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.ForeignKey
|
||||||
|
import androidx.room.ForeignKey.CASCADE
|
||||||
|
import androidx.room.Index
|
||||||
|
import org.schabi.newpipe.database.feed.model.FeedGroupSubscriptionEntity.Companion.FEED_GROUP_SUBSCRIPTION_TABLE
|
||||||
|
import org.schabi.newpipe.database.feed.model.FeedGroupSubscriptionEntity.Companion.GROUP_ID
|
||||||
|
import org.schabi.newpipe.database.feed.model.FeedGroupSubscriptionEntity.Companion.SUBSCRIPTION_ID
|
||||||
|
import org.schabi.newpipe.database.subscription.SubscriptionEntity
|
||||||
|
|
||||||
|
@Entity(
|
||||||
|
tableName = FEED_GROUP_SUBSCRIPTION_TABLE,
|
||||||
|
primaryKeys = [GROUP_ID, SUBSCRIPTION_ID],
|
||||||
|
indices = [Index(SUBSCRIPTION_ID)],
|
||||||
|
foreignKeys = [
|
||||||
|
ForeignKey(
|
||||||
|
entity = FeedGroupEntity::class,
|
||||||
|
parentColumns = [FeedGroupEntity.ID],
|
||||||
|
childColumns = [GROUP_ID],
|
||||||
|
onDelete = CASCADE, onUpdate = CASCADE, deferred = true),
|
||||||
|
|
||||||
|
ForeignKey(
|
||||||
|
entity = SubscriptionEntity::class,
|
||||||
|
parentColumns = [SubscriptionEntity.SUBSCRIPTION_UID],
|
||||||
|
childColumns = [SUBSCRIPTION_ID],
|
||||||
|
onDelete = CASCADE, onUpdate = CASCADE, deferred = true)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
data class FeedGroupSubscriptionEntity(
|
||||||
|
@ColumnInfo(name = GROUP_ID)
|
||||||
|
var feedGroupId: Long,
|
||||||
|
|
||||||
|
@ColumnInfo(name = SUBSCRIPTION_ID)
|
||||||
|
var subscriptionId: Long
|
||||||
|
) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val FEED_GROUP_SUBSCRIPTION_TABLE = "feed_group_subscription_join"
|
||||||
|
|
||||||
|
const val GROUP_ID = "group_id"
|
||||||
|
const val SUBSCRIPTION_ID = "subscription_id"
|
||||||
|
}
|
||||||
|
}
|
@ -1,59 +0,0 @@
|
|||||||
package org.schabi.newpipe.database.history.model;
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.database.stream.model.StreamEntity;
|
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
public class StreamHistoryEntry {
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_ID)
|
|
||||||
final public long uid;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_SERVICE_ID)
|
|
||||||
final public int serviceId;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_URL)
|
|
||||||
final public String url;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_TITLE)
|
|
||||||
final public String title;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_TYPE)
|
|
||||||
final public StreamType streamType;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_DURATION)
|
|
||||||
final public long duration;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_UPLOADER)
|
|
||||||
final public String uploader;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_THUMBNAIL_URL)
|
|
||||||
final public String thumbnailUrl;
|
|
||||||
@ColumnInfo(name = StreamHistoryEntity.JOIN_STREAM_ID)
|
|
||||||
final public long streamId;
|
|
||||||
@ColumnInfo(name = StreamHistoryEntity.STREAM_ACCESS_DATE)
|
|
||||||
final public Date accessDate;
|
|
||||||
@ColumnInfo(name = StreamHistoryEntity.STREAM_REPEAT_COUNT)
|
|
||||||
final public long repeatCount;
|
|
||||||
|
|
||||||
public StreamHistoryEntry(long uid, int serviceId, String url, String title,
|
|
||||||
StreamType streamType, long duration, String uploader,
|
|
||||||
String thumbnailUrl, long streamId, Date accessDate,
|
|
||||||
long repeatCount) {
|
|
||||||
this.uid = uid;
|
|
||||||
this.serviceId = serviceId;
|
|
||||||
this.url = url;
|
|
||||||
this.title = title;
|
|
||||||
this.streamType = streamType;
|
|
||||||
this.duration = duration;
|
|
||||||
this.uploader = uploader;
|
|
||||||
this.thumbnailUrl = thumbnailUrl;
|
|
||||||
this.streamId = streamId;
|
|
||||||
this.accessDate = accessDate;
|
|
||||||
this.repeatCount = repeatCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StreamHistoryEntity toStreamHistoryEntity() {
|
|
||||||
return new StreamHistoryEntity(streamId, accessDate, repeatCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasEqualValues(StreamHistoryEntry other) {
|
|
||||||
return this.uid == other.uid && streamId == other.streamId &&
|
|
||||||
accessDate.compareTo(other.accessDate) == 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,30 @@
|
|||||||
|
package org.schabi.newpipe.database.history.model
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Embedded
|
||||||
|
import org.schabi.newpipe.database.stream.model.StreamEntity
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
data class StreamHistoryEntry(
|
||||||
|
@Embedded
|
||||||
|
val streamEntity: StreamEntity,
|
||||||
|
|
||||||
|
@ColumnInfo(name = StreamHistoryEntity.JOIN_STREAM_ID)
|
||||||
|
val streamId: Long,
|
||||||
|
|
||||||
|
@ColumnInfo(name = StreamHistoryEntity.STREAM_ACCESS_DATE)
|
||||||
|
val accessDate: Date,
|
||||||
|
|
||||||
|
@ColumnInfo(name = StreamHistoryEntity.STREAM_REPEAT_COUNT)
|
||||||
|
val repeatCount: Long
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun toStreamHistoryEntity(): StreamHistoryEntity {
|
||||||
|
return StreamHistoryEntity(streamId, accessDate, repeatCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasEqualValues(other: StreamHistoryEntry): Boolean {
|
||||||
|
return this.streamEntity.uid == other.streamEntity.uid && streamId == other.streamId &&
|
||||||
|
accessDate.compareTo(other.accessDate) == 0
|
||||||
|
}
|
||||||
|
}
|
@ -1,60 +0,0 @@
|
|||||||
package org.schabi.newpipe.database.playlist;
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.database.LocalItem;
|
|
||||||
import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity;
|
|
||||||
import org.schabi.newpipe.database.stream.model.StreamEntity;
|
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
|
||||||
|
|
||||||
public class PlaylistStreamEntry implements LocalItem {
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_ID)
|
|
||||||
final public long uid;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_SERVICE_ID)
|
|
||||||
final public int serviceId;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_URL)
|
|
||||||
final public String url;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_TITLE)
|
|
||||||
final public String title;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_TYPE)
|
|
||||||
final public StreamType streamType;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_DURATION)
|
|
||||||
final public long duration;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_UPLOADER)
|
|
||||||
final public String uploader;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_THUMBNAIL_URL)
|
|
||||||
final public String thumbnailUrl;
|
|
||||||
@ColumnInfo(name = PlaylistStreamEntity.JOIN_STREAM_ID)
|
|
||||||
final public long streamId;
|
|
||||||
@ColumnInfo(name = PlaylistStreamEntity.JOIN_INDEX)
|
|
||||||
final public int joinIndex;
|
|
||||||
|
|
||||||
public PlaylistStreamEntry(long uid, int serviceId, String url, String title,
|
|
||||||
StreamType streamType, long duration, String uploader,
|
|
||||||
String thumbnailUrl, long streamId, int joinIndex) {
|
|
||||||
this.uid = uid;
|
|
||||||
this.serviceId = serviceId;
|
|
||||||
this.url = url;
|
|
||||||
this.title = title;
|
|
||||||
this.streamType = streamType;
|
|
||||||
this.duration = duration;
|
|
||||||
this.uploader = uploader;
|
|
||||||
this.thumbnailUrl = thumbnailUrl;
|
|
||||||
this.streamId = streamId;
|
|
||||||
this.joinIndex = joinIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StreamInfoItem toStreamInfoItem() throws IllegalArgumentException {
|
|
||||||
StreamInfoItem item = new StreamInfoItem(serviceId, url, title, streamType);
|
|
||||||
item.setThumbnailUrl(thumbnailUrl);
|
|
||||||
item.setUploaderName(uploader);
|
|
||||||
item.setDuration(duration);
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LocalItemType getLocalItemType() {
|
|
||||||
return LocalItemType.PLAYLIST_STREAM_ITEM;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,34 @@
|
|||||||
|
package org.schabi.newpipe.database.playlist
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Embedded
|
||||||
|
import org.schabi.newpipe.database.LocalItem
|
||||||
|
import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity
|
||||||
|
import org.schabi.newpipe.database.stream.model.StreamEntity
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem
|
||||||
|
|
||||||
|
class PlaylistStreamEntry(
|
||||||
|
@Embedded
|
||||||
|
val streamEntity: StreamEntity,
|
||||||
|
|
||||||
|
@ColumnInfo(name = PlaylistStreamEntity.JOIN_STREAM_ID)
|
||||||
|
val streamId: Long,
|
||||||
|
|
||||||
|
@ColumnInfo(name = PlaylistStreamEntity.JOIN_INDEX)
|
||||||
|
val joinIndex: Int
|
||||||
|
) : LocalItem {
|
||||||
|
|
||||||
|
@Throws(IllegalArgumentException::class)
|
||||||
|
fun toStreamInfoItem(): StreamInfoItem {
|
||||||
|
val item = StreamInfoItem(streamEntity.serviceId, streamEntity.url, streamEntity.title, streamEntity.streamType)
|
||||||
|
item.duration = streamEntity.duration
|
||||||
|
item.uploaderName = streamEntity.uploader
|
||||||
|
item.thumbnailUrl = streamEntity.thumbnailUrl
|
||||||
|
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLocalItemType(): LocalItem.LocalItemType {
|
||||||
|
return LocalItem.LocalItemType.PLAYLIST_STREAM_ITEM
|
||||||
|
}
|
||||||
|
}
|
@ -1,69 +0,0 @@
|
|||||||
package org.schabi.newpipe.database.stream;
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.database.LocalItem;
|
|
||||||
import org.schabi.newpipe.database.history.model.StreamHistoryEntity;
|
|
||||||
import org.schabi.newpipe.database.stream.model.StreamEntity;
|
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
public class StreamStatisticsEntry implements LocalItem {
|
|
||||||
final public static String STREAM_LATEST_DATE = "latestAccess";
|
|
||||||
final public static String STREAM_WATCH_COUNT = "watchCount";
|
|
||||||
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_ID)
|
|
||||||
final public long uid;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_SERVICE_ID)
|
|
||||||
final public int serviceId;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_URL)
|
|
||||||
final public String url;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_TITLE)
|
|
||||||
final public String title;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_TYPE)
|
|
||||||
final public StreamType streamType;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_DURATION)
|
|
||||||
final public long duration;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_UPLOADER)
|
|
||||||
final public String uploader;
|
|
||||||
@ColumnInfo(name = StreamEntity.STREAM_THUMBNAIL_URL)
|
|
||||||
final public String thumbnailUrl;
|
|
||||||
@ColumnInfo(name = StreamHistoryEntity.JOIN_STREAM_ID)
|
|
||||||
final public long streamId;
|
|
||||||
@ColumnInfo(name = StreamStatisticsEntry.STREAM_LATEST_DATE)
|
|
||||||
final public Date latestAccessDate;
|
|
||||||
@ColumnInfo(name = StreamStatisticsEntry.STREAM_WATCH_COUNT)
|
|
||||||
final public long watchCount;
|
|
||||||
|
|
||||||
public StreamStatisticsEntry(long uid, int serviceId, String url, String title,
|
|
||||||
StreamType streamType, long duration, String uploader,
|
|
||||||
String thumbnailUrl, long streamId, Date latestAccessDate,
|
|
||||||
long watchCount) {
|
|
||||||
this.uid = uid;
|
|
||||||
this.serviceId = serviceId;
|
|
||||||
this.url = url;
|
|
||||||
this.title = title;
|
|
||||||
this.streamType = streamType;
|
|
||||||
this.duration = duration;
|
|
||||||
this.uploader = uploader;
|
|
||||||
this.thumbnailUrl = thumbnailUrl;
|
|
||||||
this.streamId = streamId;
|
|
||||||
this.latestAccessDate = latestAccessDate;
|
|
||||||
this.watchCount = watchCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StreamInfoItem toStreamInfoItem() {
|
|
||||||
StreamInfoItem item = new StreamInfoItem(serviceId, url, title, streamType);
|
|
||||||
item.setDuration(duration);
|
|
||||||
item.setUploaderName(uploader);
|
|
||||||
item.setThumbnailUrl(thumbnailUrl);
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LocalItemType getLocalItemType() {
|
|
||||||
return LocalItemType.STATISTIC_STREAM_ITEM;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,42 @@
|
|||||||
|
package org.schabi.newpipe.database.stream
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Embedded
|
||||||
|
import org.schabi.newpipe.database.LocalItem
|
||||||
|
import org.schabi.newpipe.database.history.model.StreamHistoryEntity
|
||||||
|
import org.schabi.newpipe.database.stream.model.StreamEntity
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class StreamStatisticsEntry(
|
||||||
|
@Embedded
|
||||||
|
val streamEntity: StreamEntity,
|
||||||
|
|
||||||
|
@ColumnInfo(name = StreamHistoryEntity.JOIN_STREAM_ID)
|
||||||
|
val streamId: Long,
|
||||||
|
|
||||||
|
@ColumnInfo(name = STREAM_LATEST_DATE)
|
||||||
|
val latestAccessDate: Date,
|
||||||
|
|
||||||
|
@ColumnInfo(name = STREAM_WATCH_COUNT)
|
||||||
|
val watchCount: Long
|
||||||
|
) : LocalItem {
|
||||||
|
|
||||||
|
fun toStreamInfoItem(): StreamInfoItem {
|
||||||
|
val item = StreamInfoItem(streamEntity.serviceId, streamEntity.url, streamEntity.title, streamEntity.streamType)
|
||||||
|
item.duration = streamEntity.duration
|
||||||
|
item.uploaderName = streamEntity.uploader
|
||||||
|
item.thumbnailUrl = streamEntity.thumbnailUrl
|
||||||
|
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLocalItemType(): LocalItem.LocalItemType {
|
||||||
|
return LocalItem.LocalItemType.STATISTIC_STREAM_ITEM
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val STREAM_LATEST_DATE = "latestAccess"
|
||||||
|
const val STREAM_WATCH_COUNT = "watchCount"
|
||||||
|
}
|
||||||
|
}
|
@ -1,98 +0,0 @@
|
|||||||
package org.schabi.newpipe.database.stream.dao;
|
|
||||||
|
|
||||||
import androidx.room.Dao;
|
|
||||||
import androidx.room.Insert;
|
|
||||||
import androidx.room.OnConflictStrategy;
|
|
||||||
import androidx.room.Query;
|
|
||||||
import androidx.room.Transaction;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.database.BasicDAO;
|
|
||||||
import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity;
|
|
||||||
import org.schabi.newpipe.database.stream.model.StreamEntity;
|
|
||||||
import org.schabi.newpipe.database.history.model.StreamHistoryEntity;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import io.reactivex.Flowable;
|
|
||||||
|
|
||||||
import static org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.PLAYLIST_STREAM_JOIN_TABLE;
|
|
||||||
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_ID;
|
|
||||||
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_SERVICE_ID;
|
|
||||||
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_TABLE;
|
|
||||||
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_URL;
|
|
||||||
import static org.schabi.newpipe.database.history.model.StreamHistoryEntity.STREAM_HISTORY_TABLE;
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
public abstract class StreamDAO implements BasicDAO<StreamEntity> {
|
|
||||||
@Override
|
|
||||||
@Query("SELECT * FROM " + STREAM_TABLE)
|
|
||||||
public abstract Flowable<List<StreamEntity>> getAll();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Query("DELETE FROM " + STREAM_TABLE)
|
|
||||||
public abstract int deleteAll();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Query("SELECT * FROM " + STREAM_TABLE + " WHERE " + STREAM_SERVICE_ID + " = :serviceId")
|
|
||||||
public abstract Flowable<List<StreamEntity>> listByService(int serviceId);
|
|
||||||
|
|
||||||
@Query("SELECT * FROM " + STREAM_TABLE + " WHERE " +
|
|
||||||
STREAM_URL + " = :url AND " +
|
|
||||||
STREAM_SERVICE_ID + " = :serviceId")
|
|
||||||
public abstract Flowable<List<StreamEntity>> getStream(long serviceId, String url);
|
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
|
||||||
abstract void silentInsertAllInternal(final List<StreamEntity> streams);
|
|
||||||
|
|
||||||
@Query("SELECT " + STREAM_ID + " FROM " + STREAM_TABLE + " WHERE " +
|
|
||||||
STREAM_URL + " = :url AND " +
|
|
||||||
STREAM_SERVICE_ID + " = :serviceId")
|
|
||||||
abstract Long getStreamIdInternal(long serviceId, String url);
|
|
||||||
|
|
||||||
@Transaction
|
|
||||||
public long upsert(StreamEntity stream) {
|
|
||||||
final Long streamIdCandidate = getStreamIdInternal(stream.getServiceId(), stream.getUrl());
|
|
||||||
|
|
||||||
if (streamIdCandidate == null) {
|
|
||||||
return insert(stream);
|
|
||||||
} else {
|
|
||||||
stream.setUid(streamIdCandidate);
|
|
||||||
update(stream);
|
|
||||||
return streamIdCandidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transaction
|
|
||||||
public List<Long> upsertAll(List<StreamEntity> streams) {
|
|
||||||
silentInsertAllInternal(streams);
|
|
||||||
|
|
||||||
final List<Long> streamIds = new ArrayList<>(streams.size());
|
|
||||||
for (StreamEntity stream : streams) {
|
|
||||||
final Long streamId = getStreamIdInternal(stream.getServiceId(), stream.getUrl());
|
|
||||||
if (streamId == null) {
|
|
||||||
throw new IllegalStateException("StreamID cannot be null just after insertion.");
|
|
||||||
}
|
|
||||||
|
|
||||||
streamIds.add(streamId);
|
|
||||||
stream.setUid(streamId);
|
|
||||||
}
|
|
||||||
|
|
||||||
update(streams);
|
|
||||||
return streamIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Query("DELETE FROM " + STREAM_TABLE + " WHERE " + STREAM_ID +
|
|
||||||
" NOT IN " +
|
|
||||||
"(SELECT DISTINCT " + STREAM_ID + " FROM " + STREAM_TABLE +
|
|
||||||
|
|
||||||
" LEFT JOIN " + STREAM_HISTORY_TABLE +
|
|
||||||
" ON " + STREAM_ID + " = " +
|
|
||||||
StreamHistoryEntity.STREAM_HISTORY_TABLE + "." + StreamHistoryEntity.JOIN_STREAM_ID +
|
|
||||||
|
|
||||||
" LEFT JOIN " + PLAYLIST_STREAM_JOIN_TABLE +
|
|
||||||
" ON " + STREAM_ID + " = " +
|
|
||||||
PlaylistStreamEntity.PLAYLIST_STREAM_JOIN_TABLE + "." + PlaylistStreamEntity.JOIN_STREAM_ID +
|
|
||||||
")")
|
|
||||||
public abstract int deleteOrphans();
|
|
||||||
}
|
|
@ -0,0 +1,116 @@
|
|||||||
|
package org.schabi.newpipe.database.stream.dao
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import io.reactivex.Flowable
|
||||||
|
import org.schabi.newpipe.database.BasicDAO
|
||||||
|
import org.schabi.newpipe.database.stream.model.StreamEntity
|
||||||
|
import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_ID
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamType
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamType.*
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
abstract class StreamDAO : BasicDAO<StreamEntity> {
|
||||||
|
@Query("SELECT * FROM streams")
|
||||||
|
abstract override fun getAll(): Flowable<List<StreamEntity>>
|
||||||
|
|
||||||
|
@Query("DELETE FROM streams")
|
||||||
|
abstract override fun deleteAll(): Int
|
||||||
|
|
||||||
|
@Query("SELECT * FROM streams WHERE service_id = :serviceId")
|
||||||
|
abstract override fun listByService(serviceId: Int): Flowable<List<StreamEntity>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM streams WHERE url = :url AND service_id = :serviceId")
|
||||||
|
abstract fun getStream(serviceId: Long, url: String): Flowable<List<StreamEntity>>
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||||
|
internal abstract fun silentInsertInternal(stream: StreamEntity): Long
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||||
|
internal abstract fun silentInsertAllInternal(streams: List<StreamEntity>): List<Long>
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT uid, stream_type, textual_upload_date, upload_date FROM streams
|
||||||
|
WHERE url = :url AND service_id = :serviceId
|
||||||
|
""")
|
||||||
|
internal abstract fun getMinimalStreamForCompare(serviceId: Int, url: String): StreamCompareFeed?
|
||||||
|
|
||||||
|
@Transaction
|
||||||
|
open fun upsert(newerStream: StreamEntity): Long {
|
||||||
|
val uid = silentInsertInternal(newerStream)
|
||||||
|
|
||||||
|
if (uid != -1L) {
|
||||||
|
newerStream.uid = uid
|
||||||
|
return uid
|
||||||
|
}
|
||||||
|
|
||||||
|
compareAndUpdateStream(newerStream)
|
||||||
|
|
||||||
|
update(newerStream)
|
||||||
|
return newerStream.uid
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transaction
|
||||||
|
open fun upsertAll(streams: List<StreamEntity>): List<Long> {
|
||||||
|
val insertUidList = silentInsertAllInternal(streams)
|
||||||
|
|
||||||
|
val streamIds = ArrayList<Long>(streams.size)
|
||||||
|
for ((index, uid) in insertUidList.withIndex()) {
|
||||||
|
val newerStream = streams[index]
|
||||||
|
if (uid != -1L) {
|
||||||
|
streamIds.add(uid)
|
||||||
|
newerStream.uid = uid
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
compareAndUpdateStream(newerStream)
|
||||||
|
streamIds.add(newerStream.uid)
|
||||||
|
}
|
||||||
|
|
||||||
|
update(streams)
|
||||||
|
return streamIds
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun compareAndUpdateStream(newerStream: StreamEntity) {
|
||||||
|
val existentMinimalStream = getMinimalStreamForCompare(newerStream.serviceId, newerStream.url)
|
||||||
|
?: throw IllegalStateException("Stream cannot be null just after insertion.")
|
||||||
|
newerStream.uid = existentMinimalStream.uid
|
||||||
|
|
||||||
|
val isNewerStreamLive = newerStream.streamType == AUDIO_LIVE_STREAM || newerStream.streamType == LIVE_STREAM
|
||||||
|
if (!isNewerStreamLive) {
|
||||||
|
if (existentMinimalStream.uploadDate != null) newerStream.uploadDate = existentMinimalStream.uploadDate
|
||||||
|
if (existentMinimalStream.textualUploadDate != null) newerStream.textualUploadDate = existentMinimalStream.textualUploadDate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
DELETE FROM streams WHERE
|
||||||
|
|
||||||
|
NOT EXISTS (SELECT 1 FROM stream_history sh
|
||||||
|
WHERE sh.stream_id = streams.uid)
|
||||||
|
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM playlist_stream_join ps
|
||||||
|
WHERE ps.stream_id = streams.uid)
|
||||||
|
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM feed f
|
||||||
|
WHERE f.stream_id = streams.uid)
|
||||||
|
""")
|
||||||
|
abstract fun deleteOrphans(): Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimal entry class used when comparing/updating an existent stream.
|
||||||
|
*/
|
||||||
|
internal data class StreamCompareFeed(
|
||||||
|
@ColumnInfo(name = STREAM_ID)
|
||||||
|
var uid: Long = 0,
|
||||||
|
|
||||||
|
@field:ColumnInfo(name = StreamEntity.STREAM_TYPE)
|
||||||
|
var streamType: StreamType,
|
||||||
|
|
||||||
|
@field:ColumnInfo(name = StreamEntity.STREAM_TEXTUAL_UPLOAD_DATE)
|
||||||
|
var textualUploadDate: String? = null,
|
||||||
|
|
||||||
|
@field:ColumnInfo(name = StreamEntity.STREAM_UPLOAD_DATE)
|
||||||
|
var uploadDate: Date? = null)
|
||||||
|
}
|
@ -1,153 +0,0 @@
|
|||||||
package org.schabi.newpipe.database.stream.model;
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo;
|
|
||||||
import androidx.room.Entity;
|
|
||||||
import androidx.room.Ignore;
|
|
||||||
import androidx.room.Index;
|
|
||||||
import androidx.room.PrimaryKey;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
|
||||||
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
|
|
||||||
import org.schabi.newpipe.util.Constants;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_SERVICE_ID;
|
|
||||||
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_TABLE;
|
|
||||||
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_URL;
|
|
||||||
|
|
||||||
@Entity(tableName = STREAM_TABLE,
|
|
||||||
indices = {@Index(value = {STREAM_SERVICE_ID, STREAM_URL}, unique = true)})
|
|
||||||
public class StreamEntity implements Serializable {
|
|
||||||
|
|
||||||
final public static String STREAM_TABLE = "streams";
|
|
||||||
final public static String STREAM_ID = "uid";
|
|
||||||
final public static String STREAM_SERVICE_ID = "service_id";
|
|
||||||
final public static String STREAM_URL = "url";
|
|
||||||
final public static String STREAM_TITLE = "title";
|
|
||||||
final public static String STREAM_TYPE = "stream_type";
|
|
||||||
final public static String STREAM_DURATION = "duration";
|
|
||||||
final public static String STREAM_UPLOADER = "uploader";
|
|
||||||
final public static String STREAM_THUMBNAIL_URL = "thumbnail_url";
|
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
|
||||||
@ColumnInfo(name = STREAM_ID)
|
|
||||||
private long uid = 0;
|
|
||||||
|
|
||||||
@ColumnInfo(name = STREAM_SERVICE_ID)
|
|
||||||
private int serviceId = Constants.NO_SERVICE_ID;
|
|
||||||
|
|
||||||
@ColumnInfo(name = STREAM_URL)
|
|
||||||
private String url;
|
|
||||||
|
|
||||||
@ColumnInfo(name = STREAM_TITLE)
|
|
||||||
private String title;
|
|
||||||
|
|
||||||
@ColumnInfo(name = STREAM_TYPE)
|
|
||||||
private StreamType streamType;
|
|
||||||
|
|
||||||
@ColumnInfo(name = STREAM_DURATION)
|
|
||||||
private Long duration;
|
|
||||||
|
|
||||||
@ColumnInfo(name = STREAM_UPLOADER)
|
|
||||||
private String uploader;
|
|
||||||
|
|
||||||
@ColumnInfo(name = STREAM_THUMBNAIL_URL)
|
|
||||||
private String thumbnailUrl;
|
|
||||||
|
|
||||||
public StreamEntity(final int serviceId, final String title, final String url,
|
|
||||||
final StreamType streamType, final String thumbnailUrl, final String uploader,
|
|
||||||
final long duration) {
|
|
||||||
this.serviceId = serviceId;
|
|
||||||
this.title = title;
|
|
||||||
this.url = url;
|
|
||||||
this.streamType = streamType;
|
|
||||||
this.thumbnailUrl = thumbnailUrl;
|
|
||||||
this.uploader = uploader;
|
|
||||||
this.duration = duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
public StreamEntity(final StreamInfoItem item) {
|
|
||||||
this(item.getServiceId(), item.getName(), item.getUrl(), item.getStreamType(), item.getThumbnailUrl(),
|
|
||||||
item.getUploaderName(), item.getDuration());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
public StreamEntity(final StreamInfo info) {
|
|
||||||
this(info.getServiceId(), info.getName(), info.getUrl(), info.getStreamType(), info.getThumbnailUrl(),
|
|
||||||
info.getUploaderName(), info.getDuration());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
public StreamEntity(final PlayQueueItem item) {
|
|
||||||
this(item.getServiceId(), item.getTitle(), item.getUrl(), item.getStreamType(),
|
|
||||||
item.getThumbnailUrl(), item.getUploader(), item.getDuration());
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getUid() {
|
|
||||||
return uid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUid(long uid) {
|
|
||||||
this.uid = uid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getServiceId() {
|
|
||||||
return serviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setServiceId(int serviceId) {
|
|
||||||
this.serviceId = serviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUrl() {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUrl(String url) {
|
|
||||||
this.url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StreamType getStreamType() {
|
|
||||||
return streamType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStreamType(StreamType type) {
|
|
||||||
this.streamType = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getDuration() {
|
|
||||||
return duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDuration(Long duration) {
|
|
||||||
this.duration = duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUploader() {
|
|
||||||
return uploader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUploader(String uploader) {
|
|
||||||
this.uploader = uploader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getThumbnailUrl() {
|
|
||||||
return thumbnailUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setThumbnailUrl(String thumbnailUrl) {
|
|
||||||
this.thumbnailUrl = thumbnailUrl;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,107 @@
|
|||||||
|
package org.schabi.newpipe.database.stream.model
|
||||||
|
|
||||||
|
import androidx.room.*
|
||||||
|
import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_SERVICE_ID
|
||||||
|
import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_TABLE
|
||||||
|
import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_URL
|
||||||
|
import org.schabi.newpipe.extractor.localization.DateWrapper
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamInfo
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamType
|
||||||
|
import org.schabi.newpipe.player.playqueue.PlayQueueItem
|
||||||
|
import java.io.Serializable
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@Entity(tableName = STREAM_TABLE,
|
||||||
|
indices = [
|
||||||
|
Index(value = [STREAM_SERVICE_ID, STREAM_URL], unique = true)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
data class StreamEntity(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
@ColumnInfo(name = STREAM_ID)
|
||||||
|
var uid: Long = 0,
|
||||||
|
|
||||||
|
@ColumnInfo(name = STREAM_SERVICE_ID)
|
||||||
|
var serviceId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = STREAM_URL)
|
||||||
|
var url: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = STREAM_TITLE)
|
||||||
|
var title: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = STREAM_TYPE)
|
||||||
|
var streamType: StreamType,
|
||||||
|
|
||||||
|
@ColumnInfo(name = STREAM_DURATION)
|
||||||
|
var duration: Long,
|
||||||
|
|
||||||
|
@ColumnInfo(name = STREAM_UPLOADER)
|
||||||
|
var uploader: String,
|
||||||
|
|
||||||
|
@ColumnInfo(name = STREAM_THUMBNAIL_URL)
|
||||||
|
var thumbnailUrl: String? = null,
|
||||||
|
|
||||||
|
@ColumnInfo(name = STREAM_VIEWS)
|
||||||
|
var viewCount: Long? = null,
|
||||||
|
|
||||||
|
@ColumnInfo(name = STREAM_TEXTUAL_UPLOAD_DATE)
|
||||||
|
var textualUploadDate: String? = null,
|
||||||
|
|
||||||
|
@ColumnInfo(name = STREAM_UPLOAD_DATE)
|
||||||
|
var uploadDate: Date? = null
|
||||||
|
) : Serializable {
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
constructor(item: StreamInfoItem) : this(
|
||||||
|
serviceId = item.serviceId, url = item.url, title = item.name,
|
||||||
|
streamType = item.streamType, duration = item.duration, uploader = item.uploaderName,
|
||||||
|
thumbnailUrl = item.thumbnailUrl, viewCount = item.viewCount,
|
||||||
|
textualUploadDate = item.textualUploadDate, uploadDate = item.uploadDate?.date()?.time
|
||||||
|
)
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
constructor(info: StreamInfo) : this(
|
||||||
|
serviceId = info.serviceId, url = info.url, title = info.name,
|
||||||
|
streamType = info.streamType, duration = info.duration, uploader = info.uploaderName,
|
||||||
|
thumbnailUrl = info.thumbnailUrl, viewCount = info.viewCount,
|
||||||
|
textualUploadDate = info.textualUploadDate, uploadDate = info.uploadDate?.date()?.time
|
||||||
|
)
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
constructor(item: PlayQueueItem) : this(
|
||||||
|
serviceId = item.serviceId, url = item.url, title = item.title,
|
||||||
|
streamType = item.streamType, duration = item.duration, uploader = item.uploader,
|
||||||
|
thumbnailUrl = item.thumbnailUrl
|
||||||
|
)
|
||||||
|
|
||||||
|
fun toStreamInfoItem(): StreamInfoItem {
|
||||||
|
val item = StreamInfoItem(serviceId, url, title, streamType)
|
||||||
|
item.duration = duration
|
||||||
|
item.uploaderName = uploader
|
||||||
|
item.thumbnailUrl = thumbnailUrl
|
||||||
|
|
||||||
|
if (viewCount != null) item.viewCount = viewCount as Long
|
||||||
|
item.textualUploadDate = textualUploadDate
|
||||||
|
item.uploadDate = uploadDate?.let { DateWrapper(Calendar.getInstance().apply { time = it }) }
|
||||||
|
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val STREAM_TABLE = "streams"
|
||||||
|
const val STREAM_ID = "uid"
|
||||||
|
const val STREAM_SERVICE_ID = "service_id"
|
||||||
|
const val STREAM_URL = "url"
|
||||||
|
const val STREAM_TITLE = "title"
|
||||||
|
const val STREAM_TYPE = "stream_type"
|
||||||
|
const val STREAM_DURATION = "duration"
|
||||||
|
const val STREAM_UPLOADER = "uploader"
|
||||||
|
const val STREAM_THUMBNAIL_URL = "thumbnail_url"
|
||||||
|
|
||||||
|
const val STREAM_VIEWS = "view_count"
|
||||||
|
const val STREAM_TEXTUAL_UPLOAD_DATE = "textual_upload_date"
|
||||||
|
const val STREAM_UPLOAD_DATE = "upload_date"
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,9 @@ public abstract class SubscriptionDAO implements BasicDAO<SubscriptionEntity> {
|
|||||||
@Query("SELECT * FROM " + SUBSCRIPTION_TABLE)
|
@Query("SELECT * FROM " + SUBSCRIPTION_TABLE)
|
||||||
public abstract Flowable<List<SubscriptionEntity>> getAll();
|
public abstract Flowable<List<SubscriptionEntity>> getAll();
|
||||||
|
|
||||||
|
@Query("SELECT COUNT(*) FROM subscriptions")
|
||||||
|
public abstract Flowable<Long> rowCount();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Query("DELETE FROM " + SUBSCRIPTION_TABLE)
|
@Query("DELETE FROM " + SUBSCRIPTION_TABLE)
|
||||||
public abstract int deleteAll();
|
public abstract int deleteAll();
|
||||||
|
@ -19,7 +19,7 @@ import static org.schabi.newpipe.database.subscription.SubscriptionEntity.SUBSCR
|
|||||||
indices = {@Index(value = {SUBSCRIPTION_SERVICE_ID, SUBSCRIPTION_URL}, unique = true)})
|
indices = {@Index(value = {SUBSCRIPTION_SERVICE_ID, SUBSCRIPTION_URL}, unique = true)})
|
||||||
public class SubscriptionEntity {
|
public class SubscriptionEntity {
|
||||||
|
|
||||||
final static String SUBSCRIPTION_UID = "uid";
|
public final static String SUBSCRIPTION_UID = "uid";
|
||||||
final static String SUBSCRIPTION_TABLE = "subscriptions";
|
final static String SUBSCRIPTION_TABLE = "subscriptions";
|
||||||
final static String SUBSCRIPTION_SERVICE_ID = "service_id";
|
final static String SUBSCRIPTION_SERVICE_ID = "service_id";
|
||||||
final static String SUBSCRIPTION_URL = "url";
|
final static String SUBSCRIPTION_URL = "url";
|
||||||
|
@ -269,11 +269,11 @@ public class HistoryRecordManager {
|
|||||||
for (LocalItem item : items) {
|
for (LocalItem item : items) {
|
||||||
long streamId;
|
long streamId;
|
||||||
if (item instanceof StreamStatisticsEntry) {
|
if (item instanceof StreamStatisticsEntry) {
|
||||||
streamId = ((StreamStatisticsEntry) item).streamId;
|
streamId = ((StreamStatisticsEntry) item).getStreamId();
|
||||||
} else if (item instanceof PlaylistStreamEntity) {
|
} else if (item instanceof PlaylistStreamEntity) {
|
||||||
streamId = ((PlaylistStreamEntity) item).getStreamUid();
|
streamId = ((PlaylistStreamEntity) item).getStreamUid();
|
||||||
} else if (item instanceof PlaylistStreamEntry) {
|
} else if (item instanceof PlaylistStreamEntry) {
|
||||||
streamId = ((PlaylistStreamEntry) item).streamId;
|
streamId = ((PlaylistStreamEntry) item).getStreamId();
|
||||||
} else {
|
} else {
|
||||||
result.add(null);
|
result.add(null);
|
||||||
continue;
|
continue;
|
||||||
|
@ -76,11 +76,11 @@ public class StatisticsPlaylistFragment
|
|||||||
switch (sortMode) {
|
switch (sortMode) {
|
||||||
case LAST_PLAYED:
|
case LAST_PLAYED:
|
||||||
Collections.sort(results, (left, right) ->
|
Collections.sort(results, (left, right) ->
|
||||||
right.latestAccessDate.compareTo(left.latestAccessDate));
|
right.getLatestAccessDate().compareTo(left.getLatestAccessDate()));
|
||||||
return results;
|
return results;
|
||||||
case MOST_PLAYED:
|
case MOST_PLAYED:
|
||||||
Collections.sort(results, (left, right) ->
|
Collections.sort(results, (left, right) ->
|
||||||
Long.compare(right.watchCount, left.watchCount));
|
Long.compare(right.getWatchCount(), left.getWatchCount()));
|
||||||
return results;
|
return results;
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
@ -153,9 +153,9 @@ public class StatisticsPlaylistFragment
|
|||||||
if (selectedItem instanceof StreamStatisticsEntry) {
|
if (selectedItem instanceof StreamStatisticsEntry) {
|
||||||
final StreamStatisticsEntry item = (StreamStatisticsEntry) selectedItem;
|
final StreamStatisticsEntry item = (StreamStatisticsEntry) selectedItem;
|
||||||
NavigationHelper.openVideoDetailFragment(getFM(),
|
NavigationHelper.openVideoDetailFragment(getFM(),
|
||||||
item.serviceId,
|
item.getStreamEntity().getServiceId(),
|
||||||
item.url,
|
item.getStreamEntity().getUrl(),
|
||||||
item.title);
|
item.getStreamEntity().getTitle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,7 +402,7 @@ public class StatisticsPlaylistFragment
|
|||||||
.get(index);
|
.get(index);
|
||||||
if(infoItem instanceof StreamStatisticsEntry) {
|
if(infoItem instanceof StreamStatisticsEntry) {
|
||||||
final StreamStatisticsEntry entry = (StreamStatisticsEntry) infoItem;
|
final StreamStatisticsEntry entry = (StreamStatisticsEntry) infoItem;
|
||||||
final Disposable onDelete = recordManager.deleteStreamHistory(entry.streamId)
|
final Disposable onDelete = recordManager.deleteStreamHistory(entry.getStreamId())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(
|
.subscribe(
|
||||||
howManyDeleted -> {
|
howManyDeleted -> {
|
||||||
|
@ -52,12 +52,12 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
|
|||||||
if (!(localItem instanceof PlaylistStreamEntry)) return;
|
if (!(localItem instanceof PlaylistStreamEntry)) return;
|
||||||
final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem;
|
final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem;
|
||||||
|
|
||||||
itemVideoTitleView.setText(item.title);
|
itemVideoTitleView.setText(item.getStreamEntity().getTitle());
|
||||||
itemAdditionalDetailsView.setText(Localization.concatenateStrings(item.uploader,
|
itemAdditionalDetailsView.setText(Localization.concatenateStrings(item.getStreamEntity().getUploader(),
|
||||||
NewPipe.getNameOfService(item.serviceId)));
|
NewPipe.getNameOfService(item.getStreamEntity().getServiceId())));
|
||||||
|
|
||||||
if (item.duration > 0) {
|
if (item.getStreamEntity().getDuration() > 0) {
|
||||||
itemDurationView.setText(Localization.getDurationString(item.duration));
|
itemDurationView.setText(Localization.getDurationString(item.getStreamEntity().getDuration()));
|
||||||
itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(),
|
itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(),
|
||||||
R.color.duration_background_color));
|
R.color.duration_background_color));
|
||||||
itemDurationView.setVisibility(View.VISIBLE);
|
itemDurationView.setVisibility(View.VISIBLE);
|
||||||
@ -65,7 +65,7 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
|
|||||||
StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0);
|
StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0);
|
||||||
if (state != null) {
|
if (state != null) {
|
||||||
itemProgressView.setVisibility(View.VISIBLE);
|
itemProgressView.setVisibility(View.VISIBLE);
|
||||||
itemProgressView.setMax((int) item.duration);
|
itemProgressView.setMax((int) item.getStreamEntity().getDuration());
|
||||||
itemProgressView.setProgress((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime()));
|
itemProgressView.setProgress((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime()));
|
||||||
} else {
|
} else {
|
||||||
itemProgressView.setVisibility(View.GONE);
|
itemProgressView.setVisibility(View.GONE);
|
||||||
@ -75,7 +75,7 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default thumbnail is shown on error, while loading and if the url is empty
|
// Default thumbnail is shown on error, while loading and if the url is empty
|
||||||
itemBuilder.displayImage(item.thumbnailUrl, itemThumbnailView,
|
itemBuilder.displayImage(item.getStreamEntity().getThumbnailUrl(), itemThumbnailView,
|
||||||
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS);
|
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS);
|
||||||
|
|
||||||
itemView.setOnClickListener(view -> {
|
itemView.setOnClickListener(view -> {
|
||||||
@ -102,8 +102,8 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
|
|||||||
final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem;
|
final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem;
|
||||||
|
|
||||||
StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0);
|
StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0);
|
||||||
if (state != null && item.duration > 0) {
|
if (state != null && item.getStreamEntity().getDuration() > 0) {
|
||||||
itemProgressView.setMax((int) item.duration);
|
itemProgressView.setMax((int) item.getStreamEntity().getDuration());
|
||||||
if (itemProgressView.getVisibility() == View.VISIBLE) {
|
if (itemProgressView.getVisibility() == View.VISIBLE) {
|
||||||
itemProgressView.setProgressAnimated((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime()));
|
itemProgressView.setProgressAnimated((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime()));
|
||||||
} else {
|
} else {
|
||||||
|
@ -71,9 +71,9 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
|
|||||||
private String getStreamInfoDetailLine(final StreamStatisticsEntry entry,
|
private String getStreamInfoDetailLine(final StreamStatisticsEntry entry,
|
||||||
final DateFormat dateFormat) {
|
final DateFormat dateFormat) {
|
||||||
final String watchCount = Localization.shortViewCount(itemBuilder.getContext(),
|
final String watchCount = Localization.shortViewCount(itemBuilder.getContext(),
|
||||||
entry.watchCount);
|
entry.getWatchCount());
|
||||||
final String uploadDate = dateFormat.format(entry.latestAccessDate);
|
final String uploadDate = dateFormat.format(entry.getLatestAccessDate());
|
||||||
final String serviceName = NewPipe.getNameOfService(entry.serviceId);
|
final String serviceName = NewPipe.getNameOfService(entry.getStreamEntity().getServiceId());
|
||||||
return Localization.concatenateStrings(watchCount, uploadDate, serviceName);
|
return Localization.concatenateStrings(watchCount, uploadDate, serviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,11 +82,11 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
|
|||||||
if (!(localItem instanceof StreamStatisticsEntry)) return;
|
if (!(localItem instanceof StreamStatisticsEntry)) return;
|
||||||
final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem;
|
final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem;
|
||||||
|
|
||||||
itemVideoTitleView.setText(item.title);
|
itemVideoTitleView.setText(item.getStreamEntity().getTitle());
|
||||||
itemUploaderView.setText(item.uploader);
|
itemUploaderView.setText(item.getStreamEntity().getUploader());
|
||||||
|
|
||||||
if (item.duration > 0) {
|
if (item.getStreamEntity().getDuration() > 0) {
|
||||||
itemDurationView.setText(Localization.getDurationString(item.duration));
|
itemDurationView.setText(Localization.getDurationString(item.getStreamEntity().getDuration()));
|
||||||
itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(),
|
itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(),
|
||||||
R.color.duration_background_color));
|
R.color.duration_background_color));
|
||||||
itemDurationView.setVisibility(View.VISIBLE);
|
itemDurationView.setVisibility(View.VISIBLE);
|
||||||
@ -94,7 +94,7 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
|
|||||||
StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0);
|
StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0);
|
||||||
if (state != null) {
|
if (state != null) {
|
||||||
itemProgressView.setVisibility(View.VISIBLE);
|
itemProgressView.setVisibility(View.VISIBLE);
|
||||||
itemProgressView.setMax((int) item.duration);
|
itemProgressView.setMax((int) item.getStreamEntity().getDuration());
|
||||||
itemProgressView.setProgress((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime()));
|
itemProgressView.setProgress((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime()));
|
||||||
} else {
|
} else {
|
||||||
itemProgressView.setVisibility(View.GONE);
|
itemProgressView.setVisibility(View.GONE);
|
||||||
@ -109,7 +109,7 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default thumbnail is shown on error, while loading and if the url is empty
|
// Default thumbnail is shown on error, while loading and if the url is empty
|
||||||
itemBuilder.displayImage(item.thumbnailUrl, itemThumbnailView,
|
itemBuilder.displayImage(item.getStreamEntity().getThumbnailUrl(), itemThumbnailView,
|
||||||
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS);
|
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS);
|
||||||
|
|
||||||
itemView.setOnClickListener(view -> {
|
itemView.setOnClickListener(view -> {
|
||||||
@ -133,8 +133,8 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
|
|||||||
final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem;
|
final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem;
|
||||||
|
|
||||||
StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0);
|
StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0);
|
||||||
if (state != null && item.duration > 0) {
|
if (state != null && item.getStreamEntity().getDuration() > 0) {
|
||||||
itemProgressView.setMax((int) item.duration);
|
itemProgressView.setMax((int) item.getStreamEntity().getDuration());
|
||||||
if (itemProgressView.getVisibility() == View.VISIBLE) {
|
if (itemProgressView.getVisibility() == View.VISIBLE) {
|
||||||
itemProgressView.setProgressAnimated((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime()));
|
itemProgressView.setProgressAnimated((int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime()));
|
||||||
} else {
|
} else {
|
||||||
|
@ -168,7 +168,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||||||
if (selectedItem instanceof PlaylistStreamEntry) {
|
if (selectedItem instanceof PlaylistStreamEntry) {
|
||||||
final PlaylistStreamEntry item = (PlaylistStreamEntry) selectedItem;
|
final PlaylistStreamEntry item = (PlaylistStreamEntry) selectedItem;
|
||||||
NavigationHelper.openVideoDetailFragment(getFragmentManager(),
|
NavigationHelper.openVideoDetailFragment(getFragmentManager(),
|
||||||
item.serviceId, item.url, item.title);
|
item.getStreamEntity().getServiceId(), item.getStreamEntity().getUrl(), item.getStreamEntity().getTitle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,7 +422,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||||||
String newThumbnailUrl;
|
String newThumbnailUrl;
|
||||||
|
|
||||||
if (!itemListAdapter.getItemsList().isEmpty()) {
|
if (!itemListAdapter.getItemsList().isEmpty()) {
|
||||||
newThumbnailUrl = ((PlaylistStreamEntry) itemListAdapter.getItemsList().get(0)).thumbnailUrl;
|
newThumbnailUrl = ((PlaylistStreamEntry) itemListAdapter.getItemsList().get(0)).getStreamEntity().getThumbnailUrl();
|
||||||
} else {
|
} else {
|
||||||
newThumbnailUrl = "drawable://" + R.drawable.dummy_thumbnail_playlist;
|
newThumbnailUrl = "drawable://" + R.drawable.dummy_thumbnail_playlist;
|
||||||
}
|
}
|
||||||
@ -434,7 +434,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||||||
if (itemListAdapter == null) return;
|
if (itemListAdapter == null) return;
|
||||||
|
|
||||||
itemListAdapter.removeItem(item);
|
itemListAdapter.removeItem(item);
|
||||||
if (playlistManager.getPlaylistThumbnail(playlistId).equals(item.thumbnailUrl))
|
if (playlistManager.getPlaylistThumbnail(playlistId).equals(item.getStreamEntity().getThumbnailUrl()))
|
||||||
updateThumbnailUrl();
|
updateThumbnailUrl();
|
||||||
|
|
||||||
setVideoCount(itemListAdapter.getItemsList().size());
|
setVideoCount(itemListAdapter.getItemsList().size());
|
||||||
@ -472,7 +472,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||||||
List<Long> streamIds = new ArrayList<>(items.size());
|
List<Long> streamIds = new ArrayList<>(items.size());
|
||||||
for (final LocalItem item : items) {
|
for (final LocalItem item : items) {
|
||||||
if (item instanceof PlaylistStreamEntry) {
|
if (item instanceof PlaylistStreamEntry) {
|
||||||
streamIds.add(((PlaylistStreamEntry) item).streamId);
|
streamIds.add(((PlaylistStreamEntry) item).getStreamId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,7 +579,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||||||
StreamDialogEntry.start_here_on_background.setCustomAction(
|
StreamDialogEntry.start_here_on_background.setCustomAction(
|
||||||
(fragment, infoItemDuplicate) -> NavigationHelper.playOnBackgroundPlayer(context, getPlayQueueStartingAt(item), true));
|
(fragment, infoItemDuplicate) -> NavigationHelper.playOnBackgroundPlayer(context, getPlayQueueStartingAt(item), true));
|
||||||
StreamDialogEntry.set_as_playlist_thumbnail.setCustomAction(
|
StreamDialogEntry.set_as_playlist_thumbnail.setCustomAction(
|
||||||
(fragment, infoItemDuplicate) -> changeThumbnailUrl(item.thumbnailUrl));
|
(fragment, infoItemDuplicate) -> changeThumbnailUrl(item.getStreamEntity().getThumbnailUrl()));
|
||||||
StreamDialogEntry.delete.setCustomAction(
|
StreamDialogEntry.delete.setCustomAction(
|
||||||
(fragment, infoItemDuplicate) -> deleteItem(item));
|
(fragment, infoItemDuplicate) -> deleteItem(item));
|
||||||
|
|
||||||
|
BIN
assets/db.dia
BIN
assets/db.dia
Binary file not shown.
Loading…
Reference in New Issue
Block a user