mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 15:23:00 +00:00 
			
		
		
		
	Trim search string and remove duplicate records from the database
Co-authored-by: Yingwei Zheng <dtcxzyw@qq.com>
This commit is contained in:
		
							
								
								
									
										737
									
								
								app/schemas/org.schabi.newpipe.database.AppDatabase/8.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										737
									
								
								app/schemas/org.schabi.newpipe.database.AppDatabase/8.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,737 @@ | ||||
| { | ||||
|   "formatVersion": 1, | ||||
|   "database": { | ||||
|     "version": 8, | ||||
|     "identityHash": "012fc8e7ad3333f1597347f34e76a513", | ||||
|     "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, `notification_mode` INTEGER NOT NULL)", | ||||
|         "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 | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "notificationMode", | ||||
|             "columnName": "notification_mode", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           } | ||||
|         ], | ||||
|         "primaryKey": { | ||||
|           "autoGenerate": true, | ||||
|           "columnNames": [ | ||||
|             "uid" | ||||
|           ] | ||||
|         }, | ||||
|         "indices": [ | ||||
|           { | ||||
|             "name": "index_subscriptions_service_id_url", | ||||
|             "unique": true, | ||||
|             "columnNames": [ | ||||
|               "service_id", | ||||
|               "url" | ||||
|             ], | ||||
|             "orders": [], | ||||
|             "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_subscriptions_service_id_url` ON `${TABLE_NAME}` (`service_id`, `url`)" | ||||
|           } | ||||
|         ], | ||||
|         "foreignKeys": [] | ||||
|       }, | ||||
|       { | ||||
|         "tableName": "search_history", | ||||
|         "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`creation_date` INTEGER, `service_id` INTEGER NOT NULL, `search` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", | ||||
|         "fields": [ | ||||
|           { | ||||
|             "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 | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "id", | ||||
|             "columnName": "id", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           } | ||||
|         ], | ||||
|         "primaryKey": { | ||||
|           "autoGenerate": true, | ||||
|           "columnNames": [ | ||||
|             "id" | ||||
|           ] | ||||
|         }, | ||||
|         "indices": [ | ||||
|           { | ||||
|             "name": "index_search_history_search", | ||||
|             "unique": false, | ||||
|             "columnNames": [ | ||||
|               "search" | ||||
|             ], | ||||
|             "orders": [], | ||||
|             "createSql": "CREATE INDEX IF NOT EXISTS `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, `uploader_url` TEXT, `thumbnail_url` TEXT, `view_count` INTEGER, `textual_upload_date` TEXT, `upload_date` INTEGER, `is_upload_date_approximation` 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": "uploaderUrl", | ||||
|             "columnName": "uploader_url", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "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 | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "isUploadDateApproximation", | ||||
|             "columnName": "is_upload_date_approximation", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           } | ||||
|         ], | ||||
|         "primaryKey": { | ||||
|           "autoGenerate": true, | ||||
|           "columnNames": [ | ||||
|             "uid" | ||||
|           ] | ||||
|         }, | ||||
|         "indices": [ | ||||
|           { | ||||
|             "name": "index_streams_service_id_url", | ||||
|             "unique": true, | ||||
|             "columnNames": [ | ||||
|               "service_id", | ||||
|               "url" | ||||
|             ], | ||||
|             "orders": [], | ||||
|             "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `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": { | ||||
|           "autoGenerate": false, | ||||
|           "columnNames": [ | ||||
|             "stream_id", | ||||
|             "access_date" | ||||
|           ] | ||||
|         }, | ||||
|         "indices": [ | ||||
|           { | ||||
|             "name": "index_stream_history_stream_id", | ||||
|             "unique": false, | ||||
|             "columnNames": [ | ||||
|               "stream_id" | ||||
|             ], | ||||
|             "orders": [], | ||||
|             "createSql": "CREATE INDEX IF NOT EXISTS `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": "progressMillis", | ||||
|             "columnName": "progress_time", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           } | ||||
|         ], | ||||
|         "primaryKey": { | ||||
|           "autoGenerate": false, | ||||
|           "columnNames": [ | ||||
|             "stream_id" | ||||
|           ] | ||||
|         }, | ||||
|         "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, `is_thumbnail_permanent` INTEGER NOT NULL, `thumbnail_stream_id` INTEGER NOT NULL)", | ||||
|         "fields": [ | ||||
|           { | ||||
|             "fieldPath": "uid", | ||||
|             "columnName": "uid", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "name", | ||||
|             "columnName": "name", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": false | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "isThumbnailPermanent", | ||||
|             "columnName": "is_thumbnail_permanent", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "thumbnailStreamId", | ||||
|             "columnName": "thumbnail_stream_id", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           } | ||||
|         ], | ||||
|         "primaryKey": { | ||||
|           "autoGenerate": true, | ||||
|           "columnNames": [ | ||||
|             "uid" | ||||
|           ] | ||||
|         }, | ||||
|         "indices": [ | ||||
|           { | ||||
|             "name": "index_playlists_name", | ||||
|             "unique": false, | ||||
|             "columnNames": [ | ||||
|               "name" | ||||
|             ], | ||||
|             "orders": [], | ||||
|             "createSql": "CREATE INDEX IF NOT EXISTS `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": { | ||||
|           "autoGenerate": false, | ||||
|           "columnNames": [ | ||||
|             "playlist_id", | ||||
|             "join_index" | ||||
|           ] | ||||
|         }, | ||||
|         "indices": [ | ||||
|           { | ||||
|             "name": "index_playlist_stream_join_playlist_id_join_index", | ||||
|             "unique": true, | ||||
|             "columnNames": [ | ||||
|               "playlist_id", | ||||
|               "join_index" | ||||
|             ], | ||||
|             "orders": [], | ||||
|             "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `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" | ||||
|             ], | ||||
|             "orders": [], | ||||
|             "createSql": "CREATE INDEX IF NOT EXISTS `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": { | ||||
|           "autoGenerate": true, | ||||
|           "columnNames": [ | ||||
|             "uid" | ||||
|           ] | ||||
|         }, | ||||
|         "indices": [ | ||||
|           { | ||||
|             "name": "index_remote_playlists_name", | ||||
|             "unique": false, | ||||
|             "columnNames": [ | ||||
|               "name" | ||||
|             ], | ||||
|             "orders": [], | ||||
|             "createSql": "CREATE INDEX IF NOT EXISTS `index_remote_playlists_name` ON `${TABLE_NAME}` (`name`)" | ||||
|           }, | ||||
|           { | ||||
|             "name": "index_remote_playlists_service_id_url", | ||||
|             "unique": true, | ||||
|             "columnNames": [ | ||||
|               "service_id", | ||||
|               "url" | ||||
|             ], | ||||
|             "orders": [], | ||||
|             "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `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": { | ||||
|           "autoGenerate": false, | ||||
|           "columnNames": [ | ||||
|             "stream_id", | ||||
|             "subscription_id" | ||||
|           ] | ||||
|         }, | ||||
|         "indices": [ | ||||
|           { | ||||
|             "name": "index_feed_subscription_id", | ||||
|             "unique": false, | ||||
|             "columnNames": [ | ||||
|               "subscription_id" | ||||
|             ], | ||||
|             "orders": [], | ||||
|             "createSql": "CREATE INDEX IF NOT EXISTS `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, `sort_order` INTEGER NOT NULL)", | ||||
|         "fields": [ | ||||
|           { | ||||
|             "fieldPath": "uid", | ||||
|             "columnName": "uid", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "name", | ||||
|             "columnName": "name", | ||||
|             "affinity": "TEXT", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "icon", | ||||
|             "columnName": "icon_id", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "sortOrder", | ||||
|             "columnName": "sort_order", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           } | ||||
|         ], | ||||
|         "primaryKey": { | ||||
|           "autoGenerate": true, | ||||
|           "columnNames": [ | ||||
|             "uid" | ||||
|           ] | ||||
|         }, | ||||
|         "indices": [ | ||||
|           { | ||||
|             "name": "index_feed_group_sort_order", | ||||
|             "unique": false, | ||||
|             "columnNames": [ | ||||
|               "sort_order" | ||||
|             ], | ||||
|             "orders": [], | ||||
|             "createSql": "CREATE INDEX IF NOT EXISTS `index_feed_group_sort_order` ON `${TABLE_NAME}` (`sort_order`)" | ||||
|           } | ||||
|         ], | ||||
|         "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": { | ||||
|           "autoGenerate": false, | ||||
|           "columnNames": [ | ||||
|             "group_id", | ||||
|             "subscription_id" | ||||
|           ] | ||||
|         }, | ||||
|         "indices": [ | ||||
|           { | ||||
|             "name": "index_feed_group_subscription_join_subscription_id", | ||||
|             "unique": false, | ||||
|             "columnNames": [ | ||||
|               "subscription_id" | ||||
|             ], | ||||
|             "orders": [], | ||||
|             "createSql": "CREATE INDEX IF NOT EXISTS `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" | ||||
|             ] | ||||
|           } | ||||
|         ] | ||||
|       }, | ||||
|       { | ||||
|         "tableName": "feed_last_updated", | ||||
|         "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`subscription_id` INTEGER NOT NULL, `last_updated` INTEGER, PRIMARY KEY(`subscription_id`), FOREIGN KEY(`subscription_id`) REFERENCES `subscriptions`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", | ||||
|         "fields": [ | ||||
|           { | ||||
|             "fieldPath": "subscriptionId", | ||||
|             "columnName": "subscription_id", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": true | ||||
|           }, | ||||
|           { | ||||
|             "fieldPath": "lastUpdated", | ||||
|             "columnName": "last_updated", | ||||
|             "affinity": "INTEGER", | ||||
|             "notNull": false | ||||
|           } | ||||
|         ], | ||||
|         "primaryKey": { | ||||
|           "autoGenerate": false, | ||||
|           "columnNames": [ | ||||
|             "subscription_id" | ||||
|           ] | ||||
|         }, | ||||
|         "indices": [], | ||||
|         "foreignKeys": [ | ||||
|           { | ||||
|             "table": "subscriptions", | ||||
|             "onDelete": "CASCADE", | ||||
|             "onUpdate": "CASCADE", | ||||
|             "columns": [ | ||||
|               "subscription_id" | ||||
|             ], | ||||
|             "referencedColumns": [ | ||||
|               "uid" | ||||
|             ] | ||||
|           } | ||||
|         ] | ||||
|       } | ||||
|     ], | ||||
|     "views": [], | ||||
|     "setupQueries": [ | ||||
|       "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", | ||||
|       "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '012fc8e7ad3333f1597347f34e76a513')" | ||||
|     ] | ||||
|   } | ||||
| } | ||||
| @@ -8,6 +8,7 @@ import androidx.test.core.app.ApplicationProvider | ||||
| import androidx.test.ext.junit.runners.AndroidJUnit4 | ||||
| import androidx.test.platform.app.InstrumentationRegistry | ||||
| import org.junit.Assert.assertEquals | ||||
| import org.junit.Assert.assertNotEquals | ||||
| import org.junit.Assert.assertNull | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| @@ -25,8 +26,11 @@ class DatabaseMigrationTest { | ||||
|         private const val DEFAULT_UPLOADER_NAME = "Uploader Test" | ||||
|         private const val DEFAULT_THUMBNAIL = "https://example.com/example.jpg" | ||||
|  | ||||
|         private const val DEFAULT_SECOND_SERVICE_ID = 0 | ||||
|         private const val DEFAULT_SECOND_SERVICE_ID = 1 | ||||
|         private const val DEFAULT_SECOND_URL = "https://www.youtube.com/watch?v=ncQU6iBn5Fc" | ||||
|  | ||||
|         private const val DEFAULT_SEARCH1 = " abc " | ||||
|         private const val DEFAULT_SEARCH2 = " abc" | ||||
|     } | ||||
|  | ||||
|     @get:Rule | ||||
| @@ -106,6 +110,11 @@ class DatabaseMigrationTest { | ||||
|             Migrations.MIGRATION_6_7 | ||||
|         ) | ||||
|  | ||||
|         testHelper.runMigrationsAndValidate( | ||||
|             AppDatabase.DATABASE_NAME, Migrations.DB_VER_6, | ||||
|             true, Migrations.MIGRATION_5_6 | ||||
|         ) | ||||
|  | ||||
|         val migratedDatabaseV3 = getMigratedDatabase() | ||||
|         val listFromDB = migratedDatabaseV3.streamDAO().all.blockingFirst() | ||||
|  | ||||
| @@ -140,6 +149,56 @@ class DatabaseMigrationTest { | ||||
|         assertNull(secondStreamFromMigratedDatabase.isUploadDateApproximation) | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     fun migrateDatabaseFrom5to6() { | ||||
|         val databaseInV5 = testHelper.createDatabase(AppDatabase.DATABASE_NAME, Migrations.DB_VER_5) | ||||
|  | ||||
|         databaseInV5.run { | ||||
|             insert( | ||||
|                 "search_history", SQLiteDatabase.CONFLICT_FAIL, | ||||
|                 ContentValues().apply { | ||||
|                     put("service_id", DEFAULT_SERVICE_ID) | ||||
|                     put("search", DEFAULT_SEARCH1) | ||||
|                 } | ||||
|             ) | ||||
|             insert( | ||||
|                 "search_history", SQLiteDatabase.CONFLICT_FAIL, | ||||
|                 ContentValues().apply { | ||||
|                     put("service_id", DEFAULT_SERVICE_ID) | ||||
|                     put("search", DEFAULT_SEARCH2) | ||||
|                 } | ||||
|             ) | ||||
|             insert( | ||||
|                 "search_history", SQLiteDatabase.CONFLICT_FAIL, | ||||
|                 ContentValues().apply { | ||||
|                     put("service_id", DEFAULT_SECOND_SERVICE_ID) | ||||
|                     put("search", DEFAULT_SEARCH1) | ||||
|                 } | ||||
|             ) | ||||
|             insert( | ||||
|                 "search_history", SQLiteDatabase.CONFLICT_FAIL, | ||||
|                 ContentValues().apply { | ||||
|                     put("service_id", DEFAULT_SECOND_SERVICE_ID) | ||||
|                     put("search", DEFAULT_SEARCH2) | ||||
|                 } | ||||
|             ) | ||||
|             close() | ||||
|         } | ||||
|  | ||||
|         testHelper.runMigrationsAndValidate( | ||||
|             AppDatabase.DATABASE_NAME, Migrations.DB_VER_6, | ||||
|             true, Migrations.MIGRATION_5_6 | ||||
|         ) | ||||
|  | ||||
|         val migratedDatabaseV6 = getMigratedDatabase() | ||||
|         val listFromDB = migratedDatabaseV6.searchHistoryDAO().all.blockingFirst() | ||||
|  | ||||
|         assertEquals(2, listFromDB.size) | ||||
|         assertEquals("abc", listFromDB[0].search) | ||||
|         assertEquals("abc", listFromDB[1].search) | ||||
|         assertNotEquals(listFromDB[0].serviceId, listFromDB[1].serviceId) | ||||
|     } | ||||
|  | ||||
|     private fun getMigratedDatabase(): AppDatabase { | ||||
|         val database: AppDatabase = Room.databaseBuilder( | ||||
|             ApplicationProvider.getApplicationContext(), | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import static org.schabi.newpipe.database.Migrations.MIGRATION_3_4; | ||||
| import static org.schabi.newpipe.database.Migrations.MIGRATION_4_5; | ||||
| import static org.schabi.newpipe.database.Migrations.MIGRATION_5_6; | ||||
| import static org.schabi.newpipe.database.Migrations.MIGRATION_6_7; | ||||
| import static org.schabi.newpipe.database.Migrations.MIGRATION_7_8; | ||||
|  | ||||
| import android.content.Context; | ||||
| import android.database.Cursor; | ||||
| @@ -27,7 +28,7 @@ public final class NewPipeDatabase { | ||||
|         return Room | ||||
|                 .databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME) | ||||
|                 .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5, | ||||
|                         MIGRATION_5_6, MIGRATION_6_7) | ||||
|                         MIGRATION_5_6, MIGRATION_6_7, MIGRATION_7_8) | ||||
|                 .build(); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| package org.schabi.newpipe.database; | ||||
|  | ||||
| import static org.schabi.newpipe.database.Migrations.DB_VER_7; | ||||
| import static org.schabi.newpipe.database.Migrations.DB_VER_8; | ||||
|  | ||||
| import androidx.room.Database; | ||||
| import androidx.room.RoomDatabase; | ||||
| @@ -38,7 +38,7 @@ import org.schabi.newpipe.database.subscription.SubscriptionEntity; | ||||
|                 FeedEntity.class, FeedGroupEntity.class, FeedGroupSubscriptionEntity.class, | ||||
|                 FeedLastUpdatedEntity.class | ||||
|         }, | ||||
|         version = DB_VER_7 | ||||
|         version = DB_VER_8 | ||||
| ) | ||||
| public abstract class AppDatabase extends RoomDatabase { | ||||
|     public static final String DATABASE_NAME = "newpipe.db"; | ||||
|   | ||||
| @@ -25,6 +25,7 @@ public final class Migrations { | ||||
|     public static final int DB_VER_5 = 5; | ||||
|     public static final int DB_VER_6 = 6; | ||||
|     public static final int DB_VER_7 = 7; | ||||
|     public static final int DB_VER_8 = 8; | ||||
|  | ||||
|     private static final String TAG = Migrations.class.getName(); | ||||
|     public static final boolean DEBUG = MainActivity.DEBUG; | ||||
| @@ -235,6 +236,15 @@ public final class Migrations { | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     public static final Migration MIGRATION_7_8 = new Migration(DB_VER_7, DB_VER_8) { | ||||
|         @Override | ||||
|         public void migrate(@NonNull final SupportSQLiteDatabase database) { | ||||
|             database.execSQL("DELETE FROM search_history WHERE id NOT IN (SELECT id FROM " | ||||
|                     + "(SELECT id FROM search_history GROUP BY trim(search), service_id) tmp)"); | ||||
|             database.execSQL("UPDATE search_history SET search = trim(search)"); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     private Migrations() { | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -384,6 +384,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|  | ||||
|     @Override | ||||
|     public void onSaveInstanceState(@NonNull final Bundle bundle) { | ||||
|         searchEditText.setText(searchEditText.getText().toString().trim()); | ||||
|         searchString = searchEditText != null | ||||
|                 ? searchEditText.getText().toString() | ||||
|                 : searchString; | ||||
| @@ -396,8 +397,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|  | ||||
|     @Override | ||||
|     public void reloadContent() { | ||||
|         if (!TextUtils.isEmpty(searchString) | ||||
|                 || (searchEditText != null && !TextUtils.isEmpty(searchEditText.getText()))) { | ||||
|         if (!TextUtils.isEmpty(searchString) || (searchEditText != null | ||||
|                 && TextUtils.getTrimmedLength(searchEditText.getText()) > 0)) { | ||||
|             search(!TextUtils.isEmpty(searchString) | ||||
|                     ? searchString | ||||
|                     : searchEditText.getText().toString(), this.contentFilter, ""); | ||||
| @@ -494,7 +495,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|         } | ||||
|         searchEditText.setText(searchString); | ||||
|  | ||||
|         if (TextUtils.isEmpty(searchString) || TextUtils.isEmpty(searchEditText.getText())) { | ||||
|         if (TextUtils.isEmpty(searchString) | ||||
|                 || TextUtils.getTrimmedLength(searchEditText.getText()) == 0) { | ||||
|             searchToolbarContainer.setTranslationX(100); | ||||
|             searchToolbarContainer.setAlpha(0.0f); | ||||
|             searchToolbarContainer.setVisibility(View.VISIBLE); | ||||
| @@ -518,7 +520,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|             if (DEBUG) { | ||||
|                 Log.d(TAG, "onClick() called with: v = [" + v + "]"); | ||||
|             } | ||||
|             if (TextUtils.isEmpty(searchEditText.getText())) { | ||||
|             if (TextUtils.getTrimmedLength(searchEditText.getText()) == 0) { | ||||
|                 NavigationHelper.gotoMainFragment(getFM()); | ||||
|                 return; | ||||
|             } | ||||
| @@ -580,9 +582,12 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|             searchEditText.removeTextChangedListener(textWatcher); | ||||
|         } | ||||
|         textWatcher = new TextWatcher() { | ||||
|             private boolean isPastedText = false; | ||||
|  | ||||
|             @Override | ||||
|             public void beforeTextChanged(final CharSequence s, final int start, | ||||
|                                           final int count, final int after) { | ||||
|                 isPastedText = TextUtils.isEmpty(s) && after > 1; | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
| @@ -597,8 +602,13 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|                     s.removeSpan(span); | ||||
|                 } | ||||
|  | ||||
|                 final String newText = searchEditText.getText().toString(); | ||||
|                 final String newText = searchEditText.getText().toString().trim(); | ||||
|                 suggestionPublisher.onNext(newText); | ||||
|  | ||||
|                 if (isPastedText) { | ||||
|                     // trim pasted text | ||||
|                     searchEditText.setText(newText); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|         searchEditText.addTextChangedListener(textWatcher); | ||||
| @@ -613,6 +623,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|                     } else if (event != null | ||||
|                             && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER | ||||
|                             || event.getAction() == EditorInfo.IME_ACTION_SEARCH)) { | ||||
|                         searchEditText.setText(searchEditText.getText().toString().trim()); | ||||
|                         search(searchEditText.getText().toString(), new String[0], ""); | ||||
|                         return true; | ||||
|                     } | ||||
| @@ -717,9 +728,9 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|                 .getRelatedSearches(query, similarQueryLimit, 25) | ||||
|                 .toObservable() | ||||
|                 .map(searchHistoryEntries -> | ||||
|                     searchHistoryEntries.stream() | ||||
|                             .map(entry -> new SuggestionItem(true, entry)) | ||||
|                             .collect(Collectors.toList())); | ||||
|                         searchHistoryEntries.stream() | ||||
|                                 .map(entry -> new SuggestionItem(true, entry)) | ||||
|                                 .collect(Collectors.toList())); | ||||
|     } | ||||
|  | ||||
|     private Observable<List<SuggestionItem>> getRemoteSuggestionsObservable(final String query) { | ||||
| @@ -786,12 +797,12 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|                             } else if (listNotification.isOnError() | ||||
|                                     && listNotification.getError() != null | ||||
|                                     && !ExceptionUtils.isInterruptedCaused( | ||||
|                                             listNotification.getError())) { | ||||
|                                     listNotification.getError())) { | ||||
|                                 showSnackBarError(new ErrorInfo(listNotification.getError(), | ||||
|                                         UserAction.GET_SUGGESTIONS, searchString, serviceId)); | ||||
|                             } | ||||
|                         }, throwable -> showSnackBarError(new ErrorInfo( | ||||
|                             throwable, UserAction.GET_SUGGESTIONS, searchString, serviceId))); | ||||
|                                 throwable, UserAction.GET_SUGGESTIONS, searchString, serviceId))); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -804,6 +815,11 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|                         final String theSortFilter) { | ||||
|         if (DEBUG) { | ||||
|             Log.d(TAG, "search() called with: query = [" + theSearchString + "]"); | ||||
|             final String trimmedSearchString = theSearchString.trim(); | ||||
|             if (!trimmedSearchString.equals(theSearchString)) { | ||||
|                 Log.d(TAG, "The precondition is not satisfied. " | ||||
|                         + "\"theSearchString\" is not allowed to have leading or trailing spaces"); | ||||
|             } | ||||
|         } | ||||
|         if (theSearchString.isEmpty()) { | ||||
|             return; | ||||
| @@ -839,7 +855,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|         disposables.add(historyRecordManager.onSearched(serviceId, theSearchString) | ||||
|                 .observeOn(AndroidSchedulers.mainThread()) | ||||
|                 .subscribe( | ||||
|                         ignored -> { }, | ||||
|                         ignored -> { | ||||
|                         }, | ||||
|                         throwable -> showSnackBarError(new ErrorInfo(throwable, UserAction.SEARCHED, | ||||
|                                 theSearchString, serviceId)) | ||||
|                 )); | ||||
| @@ -973,6 +990,9 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I | ||||
|         } | ||||
|  | ||||
|         searchSuggestion = result.getSearchSuggestion(); | ||||
|         if (searchSuggestion != null) { | ||||
|             searchSuggestion = searchSuggestion.trim(); | ||||
|         } | ||||
|         isCorrectedSearch = result.isCorrectedSearch(); | ||||
|  | ||||
|         // List<MetaInfo> cannot be bundled without creating some containers | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 TobiGr
					TobiGr