From 759a078ce066a9402a1661f089e65cf5701dfaf0 Mon Sep 17 00:00:00 2001 From: ktprograms Date: Wed, 11 Aug 2021 16:26:13 +0800 Subject: [PATCH 01/16] Add uploader_url column to StreamEntity --- app/build.gradle | 1 + .../4.json | 713 ++++++++++++++++++ .../playlist/LocalPlaylistManagerTest.kt | 9 +- .../org/schabi/newpipe/NewPipeDatabase.java | 3 +- .../schabi/newpipe/database/AppDatabase.java | 4 +- .../schabi/newpipe/database/Migrations.java | 10 + .../database/playlist/PlaylistStreamEntry.kt | 1 + .../database/stream/model/StreamEntity.kt | 11 +- 8 files changed, 743 insertions(+), 9 deletions(-) create mode 100644 app/schemas/org.schabi.newpipe.database.AppDatabase/4.json diff --git a/app/build.gradle b/app/build.gradle index f88167b2e..f0bc394ad 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -214,6 +214,7 @@ dependencies { implementation 'androidx.recyclerview:recyclerview:1.1.0' implementation "androidx.room:room-runtime:${androidxRoomVersion}" implementation "androidx.room:room-rxjava3:${androidxRoomVersion}" + kapt "org.xerial:sqlite-jdbc:3.34.0" kapt "androidx.room:room-compiler:${androidxRoomVersion}" implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.webkit:webkit:1.4.0' diff --git a/app/schemas/org.schabi.newpipe.database.AppDatabase/4.json b/app/schemas/org.schabi.newpipe.database.AppDatabase/4.json new file mode 100644 index 000000000..f1851e587 --- /dev/null +++ b/app/schemas/org.schabi.newpipe.database.AppDatabase/4.json @@ -0,0 +1,713 @@ +{ + "formatVersion": 1, + "database": { + "version": 4, + "identityHash": "1dbb09d1ec0ce142bb07bc108ac58275", + "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 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}` (`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 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 NOT NULL, `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": "uploader_url", + "columnName": "uploader_url", + "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 + }, + { + "fieldPath": "isUploadDateApproximation", + "columnName": "is_upload_date_approximation", + "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 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": { + "columnNames": [ + "stream_id", + "access_date" + ], + "autoGenerate": false + }, + "indices": [ + { + "name": "index_stream_history_stream_id", + "unique": false, + "columnNames": [ + "stream_id" + ], + "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": { + "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 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": { + "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 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" + ], + "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": { + "columnNames": [ + "uid" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_remote_playlists_name", + "unique": false, + "columnNames": [ + "name" + ], + "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" + ], + "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": { + "columnNames": [ + "stream_id", + "subscription_id" + ], + "autoGenerate": false + }, + "indices": [ + { + "name": "index_feed_subscription_id", + "unique": false, + "columnNames": [ + "subscription_id" + ], + "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": { + "columnNames": [ + "uid" + ], + "autoGenerate": true + }, + "indices": [ + { + "name": "index_feed_group_sort_order", + "unique": false, + "columnNames": [ + "sort_order" + ], + "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": { + "columnNames": [ + "group_id", + "subscription_id" + ], + "autoGenerate": false + }, + "indices": [ + { + "name": "index_feed_group_subscription_join_subscription_id", + "unique": false, + "columnNames": [ + "subscription_id" + ], + "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": { + "columnNames": [ + "subscription_id" + ], + "autoGenerate": false + }, + "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, '1dbb09d1ec0ce142bb07bc108ac58275')" + ] + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt b/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt index 211312bc0..24563d1c1 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt +++ b/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt @@ -45,7 +45,8 @@ class LocalPlaylistManagerTest { fun createPlaylist() { val stream = StreamEntity( serviceId = 1, url = "https://newpipe.net/", title = "title", - streamType = StreamType.VIDEO_STREAM, duration = 1, uploader = "uploader" + streamType = StreamType.VIDEO_STREAM, duration = 1, uploader = "uploader", + uploaderUrl = "https://newpipe.net/" ) val result = manager.createPlaylist("name", listOf(stream)) @@ -69,12 +70,14 @@ class LocalPlaylistManagerTest { fun createPlaylist_nonExistentStreamsAreUpserted() { val stream = StreamEntity( serviceId = 1, url = "https://newpipe.net/", title = "title", - streamType = StreamType.VIDEO_STREAM, duration = 1, uploader = "uploader" + streamType = StreamType.VIDEO_STREAM, duration = 1, uploader = "uploader", + uploaderUrl = "https://newpipe.net/" ) database.streamDAO().insert(stream) val upserted = StreamEntity( serviceId = 1, url = "https://newpipe.net/2", title = "title2", - streamType = StreamType.VIDEO_STREAM, duration = 1, uploader = "uploader" + streamType = StreamType.VIDEO_STREAM, duration = 1, uploader = "uploader", + uploaderUrl = "https://newpipe.net/" ) val result = manager.createPlaylist("name", listOf(stream, upserted)) diff --git a/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java b/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java index 8f7732218..36bd6ee0d 100644 --- a/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java +++ b/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java @@ -11,6 +11,7 @@ import org.schabi.newpipe.database.AppDatabase; import static org.schabi.newpipe.database.AppDatabase.DATABASE_NAME; import static org.schabi.newpipe.database.Migrations.MIGRATION_1_2; import static org.schabi.newpipe.database.Migrations.MIGRATION_2_3; +import static org.schabi.newpipe.database.Migrations.MIGRATION_3_4; public final class NewPipeDatabase { private static volatile AppDatabase databaseInstance; @@ -22,7 +23,7 @@ public final class NewPipeDatabase { private static AppDatabase getDatabase(final Context context) { return Room .databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME) - .addMigrations(MIGRATION_1_2, MIGRATION_2_3) + .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4) .build(); } diff --git a/app/src/main/java/org/schabi/newpipe/database/AppDatabase.java b/app/src/main/java/org/schabi/newpipe/database/AppDatabase.java index 3b5bda155..cf52d9453 100644 --- a/app/src/main/java/org/schabi/newpipe/database/AppDatabase.java +++ b/app/src/main/java/org/schabi/newpipe/database/AppDatabase.java @@ -27,7 +27,7 @@ import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.database.subscription.SubscriptionDAO; import org.schabi.newpipe.database.subscription.SubscriptionEntity; -import static org.schabi.newpipe.database.Migrations.DB_VER_3; +import static org.schabi.newpipe.database.Migrations.DB_VER_4; @TypeConverters({Converters.class}) @Database( @@ -38,7 +38,7 @@ import static org.schabi.newpipe.database.Migrations.DB_VER_3; FeedEntity.class, FeedGroupEntity.class, FeedGroupSubscriptionEntity.class, FeedLastUpdatedEntity.class }, - version = DB_VER_3 + version = DB_VER_4 ) public abstract class AppDatabase extends RoomDatabase { public static final String DATABASE_NAME = "newpipe.db"; diff --git a/app/src/main/java/org/schabi/newpipe/database/Migrations.java b/app/src/main/java/org/schabi/newpipe/database/Migrations.java index f5195ba8d..724b5292c 100644 --- a/app/src/main/java/org/schabi/newpipe/database/Migrations.java +++ b/app/src/main/java/org/schabi/newpipe/database/Migrations.java @@ -12,6 +12,7 @@ public final class Migrations { public static final int DB_VER_1 = 1; public static final int DB_VER_2 = 2; public static final int DB_VER_3 = 3; + public static final int DB_VER_4 = 4; private static final String TAG = Migrations.class.getName(); public static final boolean DEBUG = MainActivity.DEBUG; @@ -160,5 +161,14 @@ public final class Migrations { } }; + public static final Migration MIGRATION_3_4 = new Migration(DB_VER_3, DB_VER_4) { + @Override + public void migrate(@NonNull final SupportSQLiteDatabase database) { + database.execSQL( + "ALTER TABLE streams ADD COLUMN uploader_url TEXT NOT NULL default ''" + ); + } + }; + private Migrations() { } } diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt index 81409ecf0..d2543ae6d 100644 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt @@ -27,6 +27,7 @@ data class PlaylistStreamEntry( val item = StreamInfoItem(streamEntity.serviceId, streamEntity.url, streamEntity.title, streamEntity.streamType) item.duration = streamEntity.duration item.uploaderName = streamEntity.uploader + item.uploaderUrl = streamEntity.uploaderUrl item.thumbnailUrl = streamEntity.thumbnailUrl return item diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt b/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt index 0f3e18e7b..4762c7940 100644 --- a/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt +++ b/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt @@ -12,6 +12,7 @@ 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.extractor.utils.Utils.EMPTY_STRING import org.schabi.newpipe.player.playqueue.PlayQueueItem import java.io.Serializable import java.time.OffsetDateTime @@ -45,6 +46,9 @@ data class StreamEntity( @ColumnInfo(name = STREAM_UPLOADER) var uploader: String, + @ColumnInfo(name = STREAM_UPLOADER_URL) + var uploaderUrl: String, + @ColumnInfo(name = STREAM_THUMBNAIL_URL) var thumbnailUrl: String? = null, @@ -64,7 +68,7 @@ data class StreamEntity( 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, + uploaderUrl = item.uploaderUrl, thumbnailUrl = item.thumbnailUrl, viewCount = item.viewCount, textualUploadDate = item.textualUploadDate, uploadDate = item.uploadDate?.offsetDateTime(), isUploadDateApproximation = item.uploadDate?.isApproximation ) @@ -73,7 +77,7 @@ data class StreamEntity( 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, + uploaderUrl = info.uploaderUrl, thumbnailUrl = info.thumbnailUrl, viewCount = info.viewCount, textualUploadDate = info.textualUploadDate, uploadDate = info.uploadDate?.offsetDateTime(), isUploadDateApproximation = info.uploadDate?.isApproximation ) @@ -82,7 +86,7 @@ data class StreamEntity( 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 + uploaderUrl = EMPTY_STRING, thumbnailUrl = item.thumbnailUrl ) fun toStreamInfoItem(): StreamInfoItem { @@ -109,6 +113,7 @@ data class StreamEntity( const val STREAM_TYPE = "stream_type" const val STREAM_DURATION = "duration" const val STREAM_UPLOADER = "uploader" + const val STREAM_UPLOADER_URL = "uploader_url" const val STREAM_THUMBNAIL_URL = "thumbnail_url" const val STREAM_VIEWS = "view_count" From c248741c0000873bb073ed69982f034221eb8e1d Mon Sep 17 00:00:00 2001 From: ktprograms Date: Fri, 13 Aug 2021 16:58:01 +0800 Subject: [PATCH 02/16] Add Show Channel Details to Subscription Feed & History --- .../org/schabi/newpipe/database/stream/StreamStatisticsEntry.kt | 1 + .../org/schabi/newpipe/database/stream/model/StreamEntity.kt | 1 + app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt | 1 + 3 files changed, 3 insertions(+) diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/StreamStatisticsEntry.kt b/app/src/main/java/org/schabi/newpipe/database/stream/StreamStatisticsEntry.kt index 9a622f643..dc0db59d8 100644 --- a/app/src/main/java/org/schabi/newpipe/database/stream/StreamStatisticsEntry.kt +++ b/app/src/main/java/org/schabi/newpipe/database/stream/StreamStatisticsEntry.kt @@ -29,6 +29,7 @@ class StreamStatisticsEntry( val item = StreamInfoItem(streamEntity.serviceId, streamEntity.url, streamEntity.title, streamEntity.streamType) item.duration = streamEntity.duration item.uploaderName = streamEntity.uploader + item.uploaderUrl = streamEntity.uploaderUrl item.thumbnailUrl = streamEntity.thumbnailUrl return item diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt b/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt index 4762c7940..8342cdedd 100644 --- a/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt +++ b/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt @@ -93,6 +93,7 @@ data class StreamEntity( val item = StreamInfoItem(serviceId, url, title, streamType) item.duration = duration item.uploaderName = uploader + item.uploaderUrl = uploaderUrl item.thumbnailUrl = thumbnailUrl if (viewCount != null) item.viewCount = viewCount as Long diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt index 125de0098..686cf0ac5 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt @@ -354,6 +354,7 @@ class FeedFragment : BaseStateFragment() { StreamDialogEntry.mark_as_watched ) } + entries.add(StreamDialogEntry.show_channel_details) StreamDialogEntry.setEnabledEntries(entries) InfoItemDialog(activity, item, StreamDialogEntry.getCommands(context)) { _, which -> From 76803bfcb1782b5859a2c8001f858e2859760b4a Mon Sep 17 00:00:00 2001 From: ktprograms Date: Fri, 13 Aug 2021 17:35:25 +0800 Subject: [PATCH 03/16] Save channelUrl to Database if it doesn't exist --- .../newpipe/database/stream/dao/StreamDAO.kt | 4 +++ .../history/StatisticsPlaylistFragment.java | 7 +--- .../local/playlist/LocalPlaylistFragment.java | 6 +--- .../newpipe/util/StreamDialogEntry.java | 32 +++++++++++++++---- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.kt b/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.kt index be8590382..7dc16e784 100644 --- a/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.kt +++ b/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.kt @@ -6,6 +6,7 @@ import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query import androidx.room.Transaction +import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Flowable import org.schabi.newpipe.database.BasicDAO import org.schabi.newpipe.database.stream.model.StreamEntity @@ -29,6 +30,9 @@ abstract class StreamDAO : BasicDAO { @Query("SELECT * FROM streams WHERE url = :url AND service_id = :serviceId") abstract fun getStream(serviceId: Long, url: String): Flowable> + @Query("UPDATE streams SET uploader_url = :uploaderUrl WHERE url = :url AND service_id = :serviceId") + abstract fun setUploaderUrl(serviceId: Long, url: String, uploaderUrl: String): Completable + @Insert(onConflict = OnConflictStrategy.IGNORE) internal abstract fun silentInsertInternal(stream: StreamEntity): Long diff --git a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java index 166b9c04e..6a7a300ca 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java @@ -53,8 +53,6 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.disposables.CompositeDisposable; import io.reactivex.rxjava3.disposables.Disposable; -import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; - public class StatisticsPlaylistFragment extends BaseLocalListFragment, Void> { private final CompositeDisposable disposables = new CompositeDisposable(); @@ -363,10 +361,7 @@ public class StatisticsPlaylistFragment if (KoreUtils.shouldShowPlayWithKodi(context, infoItem.getServiceId())) { entries.add(StreamDialogEntry.play_with_kodi); } - - if (!isNullOrEmpty(infoItem.getUploaderUrl())) { - entries.add(StreamDialogEntry.show_channel_details); - } + entries.add(StreamDialogEntry.show_channel_details); StreamDialogEntry.setEnabledEntries(entries); diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index 788a4d062..40a7b26e2 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -67,7 +67,6 @@ import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.subjects.PublishSubject; -import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; import static org.schabi.newpipe.ktx.ViewUtils.animate; import static org.schabi.newpipe.util.ThemeHelper.shouldUseGridLayout; @@ -778,10 +777,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment - // For some reason `getParentFragmentManager()` doesn't work, but this does. - NavigationHelper.openChannelFragment( - fragment.requireActivity().getSupportFragmentManager(), - item.getServiceId(), item.getUploaderUrl(), item.getUploaderName()) - ), + show_channel_details(R.string.show_channel_details, (fragment, item) -> { + if (isNullOrEmpty(item.getUploaderUrl())) { + final int serviceId = item.getServiceId(); + final String url = item.getUrl(); + // TODO: Some visual loading indicator + final String uploaderUrl = ExtractorHelper.getStreamInfo(serviceId, url, false) + .subscribeOn(Schedulers.io()) + .blockingGet() + .getUploaderUrl(); + NewPipeDatabase.getInstance(fragment.getContext()).streamDAO() + .setUploaderUrl(serviceId, url, uploaderUrl) + .subscribeOn(Schedulers.io()).subscribe(); + // For some reason `getParentFragmentManager()` doesn't work, but this does. + NavigationHelper.openChannelFragment( + fragment.requireActivity().getSupportFragmentManager(), + item.getServiceId(), uploaderUrl, item.getUploaderName()); + } else { + // For some reason `getParentFragmentManager()` doesn't work, but this does. + NavigationHelper.openChannelFragment( + fragment.requireActivity().getSupportFragmentManager(), + item.getServiceId(), item.getUploaderUrl(), item.getUploaderName()); + } + }), /** * Enqueues the stream automatically to the current PlayerType.
From d8888e3495da81321d5f5f302b2aea0b399634fa Mon Sep 17 00:00:00 2001 From: ktprograms Date: Sat, 14 Aug 2021 09:07:27 +0800 Subject: [PATCH 04/16] Catch error from ExtractorHelper.getStreamInfo, remove blockingGet --- .../newpipe/util/StreamDialogEntry.java | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java index 11b354b1f..06edd4d07 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java +++ b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java @@ -2,6 +2,7 @@ package org.schabi.newpipe.util; import android.content.Context; import android.net.Uri; +import android.widget.Toast; import androidx.fragment.app.Fragment; @@ -37,17 +38,23 @@ public enum StreamDialogEntry { final int serviceId = item.getServiceId(); final String url = item.getUrl(); // TODO: Some visual loading indicator - final String uploaderUrl = ExtractorHelper.getStreamInfo(serviceId, url, false) + ExtractorHelper.getStreamInfo(serviceId, url, false) .subscribeOn(Schedulers.io()) - .blockingGet() - .getUploaderUrl(); - NewPipeDatabase.getInstance(fragment.getContext()).streamDAO() - .setUploaderUrl(serviceId, url, uploaderUrl) - .subscribeOn(Schedulers.io()).subscribe(); - // For some reason `getParentFragmentManager()` doesn't work, but this does. - NavigationHelper.openChannelFragment( - fragment.requireActivity().getSupportFragmentManager(), - item.getServiceId(), uploaderUrl, item.getUploaderName()); + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(result -> { + NewPipeDatabase.getInstance(fragment.getContext()).streamDAO() + .setUploaderUrl(serviceId, url, result.getUploaderUrl()) + .subscribeOn(Schedulers.io()).subscribe(); + // For some reason `getParentFragmentManager()` doesn't work, but this does. + NavigationHelper.openChannelFragment( + fragment.requireActivity().getSupportFragmentManager(), + item.getServiceId(), result.getUploaderUrl(), + item.getUploaderName()); + }, throwable -> Toast.makeText( + fragment.getContext(), + "Error at Show Channel Details", + Toast.LENGTH_SHORT + ).show()); } else { // For some reason `getParentFragmentManager()` doesn't work, but this does. NavigationHelper.openChannelFragment( From 241054fd26a0a04433c3550420daa536e7b0093e Mon Sep 17 00:00:00 2001 From: ktprograms Date: Sat, 14 Aug 2021 15:38:57 +0800 Subject: [PATCH 05/16] Remove hardcoded string --- .../main/java/org/schabi/newpipe/util/StreamDialogEntry.java | 2 +- app/src/main/res/values/strings.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java index 06edd4d07..978677083 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java +++ b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java @@ -52,7 +52,7 @@ public enum StreamDialogEntry { item.getUploaderName()); }, throwable -> Toast.makeText( fragment.getContext(), - "Error at Show Channel Details", + R.string.error_show_channel_details, Toast.LENGTH_SHORT ).show()); } else { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1fda1f5cb..00910eed0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -755,4 +755,5 @@ Tablet mode On Off + Error at Show Channel Details \ No newline at end of file From bd0427c79f4474bc2c3194672d11d8223f7d4520 Mon Sep 17 00:00:00 2001 From: ktprograms Date: Sat, 14 Aug 2021 17:32:38 +0800 Subject: [PATCH 06/16] Refactor duplicated code into method --- .../newpipe/util/StreamDialogEntry.java | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java index 978677083..f3c15b8b0 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java +++ b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java @@ -45,21 +45,14 @@ public enum StreamDialogEntry { NewPipeDatabase.getInstance(fragment.getContext()).streamDAO() .setUploaderUrl(serviceId, url, result.getUploaderUrl()) .subscribeOn(Schedulers.io()).subscribe(); - // For some reason `getParentFragmentManager()` doesn't work, but this does. - NavigationHelper.openChannelFragment( - fragment.requireActivity().getSupportFragmentManager(), - item.getServiceId(), result.getUploaderUrl(), - item.getUploaderName()); + openChannelFragment(fragment, item, result.getUploaderUrl()); }, throwable -> Toast.makeText( fragment.getContext(), R.string.error_show_channel_details, Toast.LENGTH_SHORT ).show()); } else { - // For some reason `getParentFragmentManager()` doesn't work, but this does. - NavigationHelper.openChannelFragment( - fragment.requireActivity().getSupportFragmentManager(), - item.getServiceId(), item.getUploaderUrl(), item.getUploaderName()); + openChannelFragment(fragment, item, item.getUploaderUrl()); } }), @@ -206,4 +199,17 @@ public enum StreamDialogEntry { public interface StreamDialogEntryAction { void onClick(Fragment fragment, StreamInfoItem infoItem); } + + ///////////////////////////////////////////// + // private method to open channel fragment // + ///////////////////////////////////////////// + + private static void openChannelFragment(final Fragment fragment, + final StreamInfoItem item, + final String uploaderUrl) { + // For some reason `getParentFragmentManager()` doesn't work, but this does. + NavigationHelper.openChannelFragment( + fragment.requireActivity().getSupportFragmentManager(), + item.getServiceId(), uploaderUrl, item.getUploaderName()); + } } From 21bcadeecbfa90e2bc66e77d3eb17163ae42ad55 Mon Sep 17 00:00:00 2001 From: ktprograms Date: Sat, 14 Aug 2021 17:48:35 +0800 Subject: [PATCH 07/16] Make uploader_url column nullable --- .../org.schabi.newpipe.database.AppDatabase/4.json | 10 +++++----- .../java/org/schabi/newpipe/database/Migrations.java | 2 +- .../newpipe/database/playlist/PlaylistStreamEntry.kt | 2 +- .../newpipe/database/stream/model/StreamEntity.kt | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/schemas/org.schabi.newpipe.database.AppDatabase/4.json b/app/schemas/org.schabi.newpipe.database.AppDatabase/4.json index f1851e587..b555260d5 100644 --- a/app/schemas/org.schabi.newpipe.database.AppDatabase/4.json +++ b/app/schemas/org.schabi.newpipe.database.AppDatabase/4.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 4, - "identityHash": "1dbb09d1ec0ce142bb07bc108ac58275", + "identityHash": "d8070091972a7011bce18aed62f80b90", "entities": [ { "tableName": "subscriptions", @@ -119,7 +119,7 @@ }, { "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 NOT NULL, `thumbnail_url` TEXT, `view_count` INTEGER, `textual_upload_date` TEXT, `upload_date` INTEGER, `is_upload_date_approximation` INTEGER)", + "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", @@ -164,10 +164,10 @@ "notNull": true }, { - "fieldPath": "uploader_url", + "fieldPath": "uploaderUrl", "columnName": "uploader_url", "affinity": "TEXT", - "notNull": true + "notNull": false }, { "fieldPath": "thumbnailUrl", @@ -707,7 +707,7 @@ "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, '1dbb09d1ec0ce142bb07bc108ac58275')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd8070091972a7011bce18aed62f80b90')" ] } } \ No newline at end of file diff --git a/app/src/main/java/org/schabi/newpipe/database/Migrations.java b/app/src/main/java/org/schabi/newpipe/database/Migrations.java index 724b5292c..160793b7c 100644 --- a/app/src/main/java/org/schabi/newpipe/database/Migrations.java +++ b/app/src/main/java/org/schabi/newpipe/database/Migrations.java @@ -165,7 +165,7 @@ public final class Migrations { @Override public void migrate(@NonNull final SupportSQLiteDatabase database) { database.execSQL( - "ALTER TABLE streams ADD COLUMN uploader_url TEXT NOT NULL default ''" + "ALTER TABLE streams ADD COLUMN uploader_url TEXT" ); } }; diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt index d2543ae6d..2ecc39acc 100644 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt @@ -27,7 +27,7 @@ data class PlaylistStreamEntry( val item = StreamInfoItem(streamEntity.serviceId, streamEntity.url, streamEntity.title, streamEntity.streamType) item.duration = streamEntity.duration item.uploaderName = streamEntity.uploader - item.uploaderUrl = streamEntity.uploaderUrl + item.uploaderUrl = streamEntity.uploaderUrl ?: "" item.thumbnailUrl = streamEntity.thumbnailUrl return item diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt b/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt index 8342cdedd..5bf1ec7db 100644 --- a/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt +++ b/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt @@ -47,7 +47,7 @@ data class StreamEntity( var uploader: String, @ColumnInfo(name = STREAM_UPLOADER_URL) - var uploaderUrl: String, + var uploaderUrl: String? = null, @ColumnInfo(name = STREAM_THUMBNAIL_URL) var thumbnailUrl: String? = null, From 65f2730261ae1c0cc544223caee666c4060d4f71 Mon Sep 17 00:00:00 2001 From: ktprograms Date: Sat, 14 Aug 2021 20:54:23 +0800 Subject: [PATCH 08/16] Add comment about xerial sqlite workaround --- app/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index f0bc394ad..f8f7c25a4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -214,7 +214,10 @@ dependencies { implementation 'androidx.recyclerview:recyclerview:1.1.0' implementation "androidx.room:room-runtime:${androidxRoomVersion}" implementation "androidx.room:room-rxjava3:${androidxRoomVersion}" + + // Apple Sillicon Mac workaround (https://issuetracker.google.com/issues/174695268#comment9) kapt "org.xerial:sqlite-jdbc:3.34.0" + kapt "androidx.room:room-compiler:${androidxRoomVersion}" implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.webkit:webkit:1.4.0' From 85fbd2560d911d465812396d6bb293da425f6147 Mon Sep 17 00:00:00 2001 From: ktprograms Date: Sat, 14 Aug 2021 20:56:29 +0800 Subject: [PATCH 09/16] Fix typo in app/build.gradle --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index f8f7c25a4..ef254fbda 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -215,7 +215,7 @@ dependencies { implementation "androidx.room:room-runtime:${androidxRoomVersion}" implementation "androidx.room:room-rxjava3:${androidxRoomVersion}" - // Apple Sillicon Mac workaround (https://issuetracker.google.com/issues/174695268#comment9) + // Apple Silicon Mac workaround (https://issuetracker.google.com/issues/174695268#comment9) kapt "org.xerial:sqlite-jdbc:3.34.0" kapt "androidx.room:room-compiler:${androidxRoomVersion}" From 6f1958d398f4a3a45d7f896bb03275fbaf497530 Mon Sep 17 00:00:00 2001 From: ktprograms Date: Sat, 14 Aug 2021 20:59:38 +0800 Subject: [PATCH 10/16] Remove setting uploaderUrl to empty string if null --- .../org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt index 2ecc39acc..d2543ae6d 100644 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt @@ -27,7 +27,7 @@ data class PlaylistStreamEntry( val item = StreamInfoItem(streamEntity.serviceId, streamEntity.url, streamEntity.title, streamEntity.streamType) item.duration = streamEntity.duration item.uploaderName = streamEntity.uploader - item.uploaderUrl = streamEntity.uploaderUrl ?: "" + item.uploaderUrl = streamEntity.uploaderUrl item.thumbnailUrl = streamEntity.thumbnailUrl return item From 712985ced11da560bb1fed80bf401be070f0c8f4 Mon Sep 17 00:00:00 2001 From: ktprograms Date: Mon, 16 Aug 2021 08:08:50 +0800 Subject: [PATCH 11/16] Save uploader url when adding from PlayQueueItem --- .../newpipe/database/stream/model/StreamEntity.kt | 3 +-- .../newpipe/player/playqueue/PlayQueueItem.java | 14 +++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt b/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt index 5bf1ec7db..c56f91949 100644 --- a/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt +++ b/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.kt @@ -12,7 +12,6 @@ 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.extractor.utils.Utils.EMPTY_STRING import org.schabi.newpipe.player.playqueue.PlayQueueItem import java.io.Serializable import java.time.OffsetDateTime @@ -86,7 +85,7 @@ data class StreamEntity( constructor(item: PlayQueueItem) : this( serviceId = item.serviceId, url = item.url, title = item.title, streamType = item.streamType, duration = item.duration, uploader = item.uploader, - uploaderUrl = EMPTY_STRING, thumbnailUrl = item.thumbnailUrl + uploaderUrl = item.uploaderUrl, thumbnailUrl = item.thumbnailUrl ) fun toStreamInfoItem(): StreamInfoItem { diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItem.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItem.java index 182a91e59..f7dfc562e 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItem.java +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItem.java @@ -27,6 +27,7 @@ public class PlayQueueItem implements Serializable { private final String thumbnailUrl; @NonNull private final String uploader; + private final String uploaderUrl; @NonNull private final StreamType streamType; @@ -37,7 +38,8 @@ public class PlayQueueItem implements Serializable { PlayQueueItem(@NonNull final StreamInfo info) { this(info.getName(), info.getUrl(), info.getServiceId(), info.getDuration(), - info.getThumbnailUrl(), info.getUploaderName(), info.getStreamType()); + info.getThumbnailUrl(), info.getUploaderName(), + info.getUploaderUrl(), info.getStreamType()); if (info.getStartPosition() > 0) { setRecoveryPosition(info.getStartPosition() * 1000); @@ -46,19 +48,21 @@ public class PlayQueueItem implements Serializable { PlayQueueItem(@NonNull final StreamInfoItem item) { this(item.getName(), item.getUrl(), item.getServiceId(), item.getDuration(), - item.getThumbnailUrl(), item.getUploaderName(), item.getStreamType()); + item.getThumbnailUrl(), item.getUploaderName(), + item.getUploaderUrl(), item.getStreamType()); } private PlayQueueItem(@Nullable final String name, @Nullable final String url, final int serviceId, final long duration, @Nullable final String thumbnailUrl, @Nullable final String uploader, - @NonNull final StreamType streamType) { + final String uploaderUrl, @NonNull final StreamType streamType) { this.title = name != null ? name : EMPTY_STRING; this.url = url != null ? url : EMPTY_STRING; this.serviceId = serviceId; this.duration = duration; this.thumbnailUrl = thumbnailUrl != null ? thumbnailUrl : EMPTY_STRING; this.uploader = uploader != null ? uploader : EMPTY_STRING; + this.uploaderUrl = uploaderUrl; this.streamType = streamType; this.recoveryPosition = RECOVERY_UNSET; @@ -92,6 +96,10 @@ public class PlayQueueItem implements Serializable { return uploader; } + public String getUploaderUrl() { + return uploaderUrl; + } + @NonNull public StreamType getStreamType() { return streamType; From 02aa6fcab07d31566ed6f9d0d18ed9ba19366113 Mon Sep 17 00:00:00 2001 From: ktprograms Date: Mon, 16 Aug 2021 21:12:54 +0800 Subject: [PATCH 12/16] Remove v2 to v3 migration test, add v3 to v4 test --- .../newpipe/database/AppDatabaseTest.kt | 74 +++---------------- 1 file changed, 9 insertions(+), 65 deletions(-) diff --git a/app/src/androidTest/java/org/schabi/newpipe/database/AppDatabaseTest.kt b/app/src/androidTest/java/org/schabi/newpipe/database/AppDatabaseTest.kt index 239c46f7a..051831f03 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/database/AppDatabaseTest.kt +++ b/app/src/androidTest/java/org/schabi/newpipe/database/AppDatabaseTest.kt @@ -24,10 +24,6 @@ class AppDatabaseTest { private val DEFAULT_TYPE = StreamType.VIDEO_STREAM private const val DEFAULT_DURATION = 480L 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_URL = "https://www.youtube.com/watch?v=ncQU6iBn5Fc" } @get:Rule @@ -37,10 +33,10 @@ class AppDatabaseTest { ) @Test - fun migrateDatabaseFrom2to3() { - val databaseInV2 = testHelper.createDatabase(AppDatabase.DATABASE_NAME, Migrations.DB_VER_2) + fun migrateDatabaseFrom3to4() { + val databaseInV3 = testHelper.createDatabase(AppDatabase.DATABASE_NAME, Migrations.DB_VER_3) - databaseInV2.run { + databaseInV3.run { insert( "streams", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply { @@ -51,75 +47,23 @@ class AppDatabaseTest { put("stream_type", DEFAULT_TYPE.name) put("duration", DEFAULT_DURATION) put("uploader", DEFAULT_UPLOADER_NAME) - put("thumbnail_url", DEFAULT_THUMBNAIL) - } - ) - insert( - "streams", SQLiteDatabase.CONFLICT_FAIL, - ContentValues().apply { - // put("uid", null) - put("service_id", DEFAULT_SECOND_SERVICE_ID) - put("url", DEFAULT_SECOND_URL) - // put("title", null) - // put("stream_type", null) - // put("duration", null) - // put("uploader", null) - // put("thumbnail_url", null) - } - ) - insert( - "streams", SQLiteDatabase.CONFLICT_FAIL, - ContentValues().apply { - // put("uid", null) - put("service_id", DEFAULT_SERVICE_ID) - // put("url", null) - // put("title", null) - // put("stream_type", null) - // put("duration", null) - // put("uploader", null) - // put("thumbnail_url", null) } ) close() } testHelper.runMigrationsAndValidate( - AppDatabase.DATABASE_NAME, Migrations.DB_VER_3, - true, Migrations.MIGRATION_2_3 + AppDatabase.DATABASE_NAME, Migrations.DB_VER_4, + true, Migrations.MIGRATION_3_4 ) - val migratedDatabaseV3 = getMigratedDatabase() - val listFromDB = migratedDatabaseV3.streamDAO().all.blockingFirst() + val migratedDatabaseV4 = getMigratedDatabase() + val listFromDB = migratedDatabaseV4.streamDAO().all.blockingFirst() - // Only expect 2, the one with the null url will be ignored - assertEquals(2, listFromDB.size) + assertEquals(1, listFromDB.size) val streamFromMigratedDatabase = listFromDB[0] - assertEquals(DEFAULT_SERVICE_ID, streamFromMigratedDatabase.serviceId) - assertEquals(DEFAULT_URL, streamFromMigratedDatabase.url) - assertEquals(DEFAULT_TITLE, streamFromMigratedDatabase.title) - assertEquals(DEFAULT_TYPE, streamFromMigratedDatabase.streamType) - assertEquals(DEFAULT_DURATION, streamFromMigratedDatabase.duration) - assertEquals(DEFAULT_UPLOADER_NAME, streamFromMigratedDatabase.uploader) - assertEquals(DEFAULT_THUMBNAIL, streamFromMigratedDatabase.thumbnailUrl) - assertNull(streamFromMigratedDatabase.viewCount) - assertNull(streamFromMigratedDatabase.textualUploadDate) - assertNull(streamFromMigratedDatabase.uploadDate) - assertNull(streamFromMigratedDatabase.isUploadDateApproximation) - - val secondStreamFromMigratedDatabase = listFromDB[1] - assertEquals(DEFAULT_SECOND_SERVICE_ID, secondStreamFromMigratedDatabase.serviceId) - assertEquals(DEFAULT_SECOND_URL, secondStreamFromMigratedDatabase.url) - assertEquals("", secondStreamFromMigratedDatabase.title) - // Should fallback to VIDEO_STREAM - assertEquals(StreamType.VIDEO_STREAM, secondStreamFromMigratedDatabase.streamType) - assertEquals(0, secondStreamFromMigratedDatabase.duration) - assertEquals("", secondStreamFromMigratedDatabase.uploader) - assertEquals("", secondStreamFromMigratedDatabase.thumbnailUrl) - assertNull(secondStreamFromMigratedDatabase.viewCount) - assertNull(secondStreamFromMigratedDatabase.textualUploadDate) - assertNull(secondStreamFromMigratedDatabase.uploadDate) - assertNull(secondStreamFromMigratedDatabase.isUploadDateApproximation) + assertNull(streamFromMigratedDatabase.uploaderUrl) } private fun getMigratedDatabase(): AppDatabase { From 967bdf8f08ef22c53789403835b9a5e2bb7ccf55 Mon Sep 17 00:00:00 2001 From: ktprograms Date: Tue, 17 Aug 2021 08:57:03 +0800 Subject: [PATCH 13/16] Remove migration test, add manual testing reminder to Migrations.java --- .../newpipe/database/AppDatabaseTest.kt | 78 ------------------- .../schabi/newpipe/database/Migrations.java | 9 +++ 2 files changed, 9 insertions(+), 78 deletions(-) delete mode 100644 app/src/androidTest/java/org/schabi/newpipe/database/AppDatabaseTest.kt diff --git a/app/src/androidTest/java/org/schabi/newpipe/database/AppDatabaseTest.kt b/app/src/androidTest/java/org/schabi/newpipe/database/AppDatabaseTest.kt deleted file mode 100644 index 051831f03..000000000 --- a/app/src/androidTest/java/org/schabi/newpipe/database/AppDatabaseTest.kt +++ /dev/null @@ -1,78 +0,0 @@ -package org.schabi.newpipe.database - -import android.content.ContentValues -import android.database.sqlite.SQLiteDatabase -import androidx.room.Room -import androidx.room.testing.MigrationTestHelper -import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory -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.assertNull -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.schabi.newpipe.extractor.stream.StreamType - -@RunWith(AndroidJUnit4::class) -class AppDatabaseTest { - companion object { - private const val DEFAULT_SERVICE_ID = 0 - private const val DEFAULT_URL = "https://www.youtube.com/watch?v=cDphUib5iG4" - private const val DEFAULT_TITLE = "Test Title" - private val DEFAULT_TYPE = StreamType.VIDEO_STREAM - private const val DEFAULT_DURATION = 480L - private const val DEFAULT_UPLOADER_NAME = "Uploader Test" - } - - @get:Rule - val testHelper = MigrationTestHelper( - InstrumentationRegistry.getInstrumentation(), - AppDatabase::class.java.canonicalName, FrameworkSQLiteOpenHelperFactory() - ) - - @Test - fun migrateDatabaseFrom3to4() { - val databaseInV3 = testHelper.createDatabase(AppDatabase.DATABASE_NAME, Migrations.DB_VER_3) - - databaseInV3.run { - insert( - "streams", SQLiteDatabase.CONFLICT_FAIL, - ContentValues().apply { - // put("uid", null) - put("service_id", DEFAULT_SERVICE_ID) - put("url", DEFAULT_URL) - put("title", DEFAULT_TITLE) - put("stream_type", DEFAULT_TYPE.name) - put("duration", DEFAULT_DURATION) - put("uploader", DEFAULT_UPLOADER_NAME) - } - ) - close() - } - - testHelper.runMigrationsAndValidate( - AppDatabase.DATABASE_NAME, Migrations.DB_VER_4, - true, Migrations.MIGRATION_3_4 - ) - - val migratedDatabaseV4 = getMigratedDatabase() - val listFromDB = migratedDatabaseV4.streamDAO().all.blockingFirst() - - assertEquals(1, listFromDB.size) - - val streamFromMigratedDatabase = listFromDB[0] - assertNull(streamFromMigratedDatabase.uploaderUrl) - } - - private fun getMigratedDatabase(): AppDatabase { - val database: AppDatabase = Room.databaseBuilder( - ApplicationProvider.getApplicationContext(), - AppDatabase::class.java, AppDatabase.DATABASE_NAME - ) - .build() - testHelper.closeWhenFinished(database) - return database - } -} diff --git a/app/src/main/java/org/schabi/newpipe/database/Migrations.java b/app/src/main/java/org/schabi/newpipe/database/Migrations.java index 160793b7c..fdd38a824 100644 --- a/app/src/main/java/org/schabi/newpipe/database/Migrations.java +++ b/app/src/main/java/org/schabi/newpipe/database/Migrations.java @@ -9,6 +9,15 @@ import androidx.sqlite.db.SupportSQLiteDatabase; import org.schabi.newpipe.MainActivity; public final class Migrations { + + ///////////////////////////////////////////////////////////////////////////// + // Test new migrations manually by importing a database from daily usage // + // and checking if the migration works (Use the Database Inspector // + // https://developer.android.com/studio/inspect/database). // + // If you add a migration point it out in the pull request, so that // + // others remember to test it themselves. // + ///////////////////////////////////////////////////////////////////////////// + public static final int DB_VER_1 = 1; public static final int DB_VER_2 = 2; public static final int DB_VER_3 = 3; From a209e87c69f4e92fb6e6fa07436510f4aa2e5c1f Mon Sep 17 00:00:00 2001 From: ktprograms Date: Sat, 21 Aug 2021 09:30:40 +0800 Subject: [PATCH 14/16] Add Loading Channel Details Toast --- .../main/java/org/schabi/newpipe/util/StreamDialogEntry.java | 5 +++-- app/src/main/res/values/strings.xml | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java index f3c15b8b0..8f6c92d39 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java +++ b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java @@ -37,7 +37,8 @@ public enum StreamDialogEntry { if (isNullOrEmpty(item.getUploaderUrl())) { final int serviceId = item.getServiceId(); final String url = item.getUrl(); - // TODO: Some visual loading indicator + Toast.makeText(fragment.getContext(), R.string.loading_channel_details, + Toast.LENGTH_SHORT).show(); ExtractorHelper.getStreamInfo(serviceId, url, false) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -46,7 +47,7 @@ public enum StreamDialogEntry { .setUploaderUrl(serviceId, url, result.getUploaderUrl()) .subscribeOn(Schedulers.io()).subscribe(); openChannelFragment(fragment, item, result.getUploaderUrl()); - }, throwable -> Toast.makeText( + }, throwable -> Toast.makeText( // TODO: Open the Error Activity fragment.getContext(), R.string.error_show_channel_details, Toast.LENGTH_SHORT diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 00910eed0..f8ed5ee62 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -755,5 +755,7 @@ Tablet mode On Off + Error at Show Channel Details + Loading Channel Details… \ No newline at end of file From 2928df0cc91897967ec2e1b00e7091f6b49f312e Mon Sep 17 00:00:00 2001 From: ktprograms Date: Tue, 24 Aug 2021 21:17:08 +0800 Subject: [PATCH 15/16] Fix checkstyle ParenPad error --- .../main/java/org/schabi/newpipe/util/StreamDialogEntry.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java index 8f6c92d39..6245d6f14 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java +++ b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java @@ -47,7 +47,8 @@ public enum StreamDialogEntry { .setUploaderUrl(serviceId, url, result.getUploaderUrl()) .subscribeOn(Schedulers.io()).subscribe(); openChannelFragment(fragment, item, result.getUploaderUrl()); - }, throwable -> Toast.makeText( // TODO: Open the Error Activity + }, throwable -> Toast.makeText( + // TODO: Open the Error Activity fragment.getContext(), R.string.error_show_channel_details, Toast.LENGTH_SHORT From 7e27e73532e3253a18a323421accccd4c662bd17 Mon Sep 17 00:00:00 2001 From: ktprograms Date: Tue, 24 Aug 2021 22:07:30 +0800 Subject: [PATCH 16/16] Remove xerial sqlite dependency --- app/build.gradle | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index ef254fbda..f88167b2e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -214,10 +214,6 @@ dependencies { implementation 'androidx.recyclerview:recyclerview:1.1.0' implementation "androidx.room:room-runtime:${androidxRoomVersion}" implementation "androidx.room:room-rxjava3:${androidxRoomVersion}" - - // Apple Silicon Mac workaround (https://issuetracker.google.com/issues/174695268#comment9) - kapt "org.xerial:sqlite-jdbc:3.34.0" - kapt "androidx.room:room-compiler:${androidxRoomVersion}" implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.webkit:webkit:1.4.0'