From 90f0809029a257f62c442eede1735e2386e8aed1 Mon Sep 17 00:00:00 2001
From: TobiGr
Date: Wed, 16 Aug 2023 21:24:55 +0200
Subject: [PATCH 001/162] Trim search string and remove duplicate records from
the database
Co-authored-by: Yingwei Zheng
---
.../8.json | 737 ++++++++++++++++++
.../newpipe/database/DatabaseMigrationTest.kt | 61 +-
.../org/schabi/newpipe/NewPipeDatabase.java | 3 +-
.../schabi/newpipe/database/AppDatabase.java | 4 +-
.../schabi/newpipe/database/Migrations.java | 10 +
.../fragments/list/search/SearchFragment.java | 42 +-
6 files changed, 842 insertions(+), 15 deletions(-)
create mode 100644 app/schemas/org.schabi.newpipe.database.AppDatabase/8.json
diff --git a/app/schemas/org.schabi.newpipe.database.AppDatabase/8.json b/app/schemas/org.schabi.newpipe.database.AppDatabase/8.json
new file mode 100644
index 000000000..d4a89567b
--- /dev/null
+++ b/app/schemas/org.schabi.newpipe.database.AppDatabase/8.json
@@ -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')"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt b/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt
index 88e737205..cd048ac44 100644
--- a/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt
+++ b/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt
@@ -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(),
diff --git a/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java b/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java
index 856fbff8b..c4f9feba7 100644
--- a/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java
+++ b/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java
@@ -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();
}
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 03e39cd43..d03823e66 100644
--- a/app/src/main/java/org/schabi/newpipe/database/AppDatabase.java
+++ b/app/src/main/java/org/schabi/newpipe/database/AppDatabase.java
@@ -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";
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 1886b87c2..65c5626a5 100644
--- a/app/src/main/java/org/schabi/newpipe/database/Migrations.java
+++ b/app/src/main/java/org/schabi/newpipe/database/Migrations.java
@@ -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() {
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
index 26a283229..87c48b69c 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
@@ -384,6 +384,7 @@ public class SearchFragment extends BaseListFragment 0)) {
search(!TextUtils.isEmpty(searchString)
? searchString
: searchEditText.getText().toString(), this.contentFilter, "");
@@ -494,7 +495,8 @@ public class SearchFragment extends BaseListFragment 1;
}
@Override
@@ -597,8 +602,13 @@ public class SearchFragment extends BaseListFragment
- searchHistoryEntries.stream()
- .map(entry -> new SuggestionItem(true, entry))
- .collect(Collectors.toList()));
+ searchHistoryEntries.stream()
+ .map(entry -> new SuggestionItem(true, entry))
+ .collect(Collectors.toList()));
}
private Observable> getRemoteSuggestionsObservable(final String query) {
@@ -786,12 +797,12 @@ public class SearchFragment extends BaseListFragment 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 { },
+ ignored -> {
+ },
throwable -> showSnackBarError(new ErrorInfo(throwable, UserAction.SEARCHED,
theSearchString, serviceId))
));
@@ -973,6 +990,9 @@ public class SearchFragment extends BaseListFragment cannot be bundled without creating some containers
From 4af5b5f6f21c28b718224690a6239d13f019f032 Mon Sep 17 00:00:00 2001
From: TobiGr
Date: Wed, 16 Aug 2023 22:01:58 +0200
Subject: [PATCH 002/162] Fix database migration and string trimming
Co-authored-by: Yingwei Zheng
---
.../newpipe/database/DatabaseMigrationTest.kt | 23 +++++++++++--------
.../schabi/newpipe/database/Migrations.java | 4 ++--
.../fragments/list/search/SearchFragment.java | 17 ++++----------
3 files changed, 21 insertions(+), 23 deletions(-)
diff --git a/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt b/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt
index cd048ac44..c0c608a58 100644
--- a/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt
+++ b/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt
@@ -111,8 +111,10 @@ class DatabaseMigrationTest {
)
testHelper.runMigrationsAndValidate(
- AppDatabase.DATABASE_NAME, Migrations.DB_VER_6,
- true, Migrations.MIGRATION_5_6
+ AppDatabase.DATABASE_NAME,
+ Migrations.DB_VER_8,
+ true,
+ Migrations.MIGRATION_7_8
)
val migratedDatabaseV3 = getMigratedDatabase()
@@ -150,10 +152,13 @@ class DatabaseMigrationTest {
}
@Test
- fun migrateDatabaseFrom5to6() {
- val databaseInV5 = testHelper.createDatabase(AppDatabase.DATABASE_NAME, Migrations.DB_VER_5)
+ fun migrateDatabaseFrom7to8() {
+ val databaseInV7 = testHelper.createDatabase(AppDatabase.DATABASE_NAME, Migrations.DB_VER_7)
- databaseInV5.run {
+ val defaultSearch1 = " abc "
+ val defaultSearch2 = " abc"
+
+ databaseInV7.run {
insert(
"search_history", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
@@ -186,12 +191,12 @@ class DatabaseMigrationTest {
}
testHelper.runMigrationsAndValidate(
- AppDatabase.DATABASE_NAME, Migrations.DB_VER_6,
- true, Migrations.MIGRATION_5_6
+ AppDatabase.DATABASE_NAME, Migrations.DB_VER_8,
+ true, Migrations.MIGRATION_7_8
)
- val migratedDatabaseV6 = getMigratedDatabase()
- val listFromDB = migratedDatabaseV6.searchHistoryDAO().all.blockingFirst()
+ val migratedDatabaseV8 = getMigratedDatabase()
+ val listFromDB = migratedDatabaseV8.searchHistoryDAO().all.blockingFirst()
assertEquals(2, listFromDB.size)
assertEquals("abc", listFromDB[0].search)
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 65c5626a5..4b1a34dd6 100644
--- a/app/src/main/java/org/schabi/newpipe/database/Migrations.java
+++ b/app/src/main/java/org/schabi/newpipe/database/Migrations.java
@@ -239,8 +239,8 @@ 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("DELETE FROM search_history WHERE id NOT IN (SELECT id FROM (SELECT "
+ + "MIN(id) as id FROM search_history GROUP BY trim(search), service_id ) tmp)");
database.execSQL("UPDATE search_history SET search = trim(search)");
}
};
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
index 87c48b69c..df4a47bc5 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
@@ -1,6 +1,7 @@
package org.schabi.newpipe.fragments.list.search;
import static androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags;
+import static org.schabi.newpipe.extractor.utils.Utils.isBlank;
import static org.schabi.newpipe.ktx.ViewUtils.animate;
import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView;
import static java.util.Arrays.asList;
@@ -398,7 +399,7 @@ public class SearchFragment extends BaseListFragment 0)) {
+ && !isBlank(searchEditText.getText().toString()))) {
search(!TextUtils.isEmpty(searchString)
? searchString
: searchEditText.getText().toString(), this.contentFilter, "");
@@ -496,7 +497,7 @@ public class SearchFragment extends BaseListFragment 1;
}
@Override
@@ -604,11 +602,6 @@ public class SearchFragment extends BaseListFragment
Date: Wed, 4 May 2022 20:20:19 +0800
Subject: [PATCH 003/162] Refactor database migration test and string trimming
---
.../newpipe/database/DatabaseMigrationTest.kt | 11 +++----
.../fragments/list/search/SearchFragment.java | 29 ++++++++++++-------
2 files changed, 22 insertions(+), 18 deletions(-)
diff --git a/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt b/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt
index c0c608a58..19053ba97 100644
--- a/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt
+++ b/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt
@@ -28,9 +28,6 @@ class DatabaseMigrationTest {
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
@@ -163,28 +160,28 @@ class DatabaseMigrationTest {
"search_history", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
put("service_id", DEFAULT_SERVICE_ID)
- put("search", DEFAULT_SEARCH1)
+ put("search", defaultSearch1)
}
)
insert(
"search_history", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
put("service_id", DEFAULT_SERVICE_ID)
- put("search", DEFAULT_SEARCH2)
+ put("search", defaultSearch2)
}
)
insert(
"search_history", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
put("service_id", DEFAULT_SECOND_SERVICE_ID)
- put("search", DEFAULT_SEARCH1)
+ put("search", defaultSearch1)
}
)
insert(
"search_history", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
put("service_id", DEFAULT_SECOND_SERVICE_ID)
- put("search", DEFAULT_SEARCH2)
+ put("search", defaultSearch2)
}
)
close()
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
index df4a47bc5..07d41c160 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
@@ -385,9 +385,8 @@ public class SearchFragment extends BaseListFragment suggestionPublisher
- .onNext(searchEditText.getText().toString()),
+ .onNext(getSearchEditString()),
throwable -> showSnackBarError(new ErrorInfo(throwable,
UserAction.DELETE_FROM_HISTORY,
"Deleting item failed")));
@@ -942,6 +941,14 @@ public class SearchFragment extends BaseListFragment suggestionPublisher
- .onNext(searchEditText.getText().toString()),
+ .onNext(getSearchEditString()),
throwable -> showSnackBarError(new ErrorInfo(throwable,
UserAction.DELETE_FROM_HISTORY, "Deleting item failed")));
disposables.add(onDelete);
From ef40ac7bb37a1e10214e48bd1b9ee82f88d69fd3 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng
Date: Thu, 5 May 2022 14:15:19 +0800
Subject: [PATCH 004/162] Fix a typo
---
.../schabi/newpipe/fragments/list/search/SearchFragment.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
index 07d41c160..ebdde2f95 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
@@ -945,7 +945,7 @@ public class SearchFragment extends BaseListFragment
Date: Wed, 16 Aug 2023 22:18:53 +0200
Subject: [PATCH 005/162] Apply review
---
.../newpipe/database/DatabaseMigrationTest.kt | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt b/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt
index 19053ba97..65f41d8fa 100644
--- a/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt
+++ b/app/src/androidTest/java/org/schabi/newpipe/database/DatabaseMigrationTest.kt
@@ -13,6 +13,7 @@ import org.junit.Assert.assertNull
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
+import org.schabi.newpipe.extractor.ServiceList
import org.schabi.newpipe.extractor.stream.StreamType
@RunWith(AndroidJUnit4::class)
@@ -26,7 +27,7 @@ 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 = 1
+ private const val DEFAULT_SECOND_SERVICE_ID = 0
private const val DEFAULT_SECOND_URL = "https://www.youtube.com/watch?v=ncQU6iBn5Fc"
}
@@ -155,32 +156,37 @@ class DatabaseMigrationTest {
val defaultSearch1 = " abc "
val defaultSearch2 = " abc"
+ val serviceId = DEFAULT_SERVICE_ID // YouTube
+ // Use id different to YouTube because two searches with the same query
+ // but different service are considered not equal.
+ val otherServiceId = ServiceList.SoundCloud.serviceId
+
databaseInV7.run {
insert(
"search_history", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
- put("service_id", DEFAULT_SERVICE_ID)
+ put("service_id", serviceId)
put("search", defaultSearch1)
}
)
insert(
"search_history", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
- put("service_id", DEFAULT_SERVICE_ID)
+ put("service_id", serviceId)
put("search", defaultSearch2)
}
)
insert(
"search_history", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
- put("service_id", DEFAULT_SECOND_SERVICE_ID)
+ put("service_id", otherServiceId)
put("search", defaultSearch1)
}
)
insert(
"search_history", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
- put("service_id", DEFAULT_SECOND_SERVICE_ID)
+ put("service_id", otherServiceId)
put("search", defaultSearch2)
}
)
From 9118ecd68fa8793df4db46958e4d63015d5e1c61 Mon Sep 17 00:00:00 2001
From: TobiGr
Date: Thu, 17 Aug 2023 16:51:31 +0200
Subject: [PATCH 006/162] Remove unnecessary debug warning and use JDoc instead
---
.../fragments/list/search/SearchFragment.java | 43 +++++++++++--------
1 file changed, 24 insertions(+), 19 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
index ebdde2f95..558f8df44 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
@@ -802,40 +802,42 @@ public class SearchFragment extends BaseListFragment NavigationHelper.getIntentByLink(activity,
- streamingService, theSearchString))
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(intent -> {
- getFM().popBackStackImmediate();
- activity.startActivity(intent);
- }, throwable -> showTextError(getString(R.string.unsupported_url))));
- return;
- }
+ showLoading();
+ disposables.add(Observable
+ .fromCallable(() -> NavigationHelper.getIntentByLink(activity,
+ streamingService, theSearchString))
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(intent -> {
+ getFM().popBackStackImmediate();
+ activity.startActivity(intent);
+ }, throwable -> showTextError(getString(R.string.unsupported_url))));
+ return;
} catch (final Exception ignored) {
// Exception occurred, it's not a url
}
+ // prepare search
lastSearchedString = this.searchString;
this.searchString = theSearchString;
infoListAdapter.clearStreamItemList();
@@ -844,6 +846,7 @@ public class SearchFragment extends BaseListFragment showSnackBarError(new ErrorInfo(throwable, UserAction.SEARCHED,
theSearchString, serviceId))
));
+
+ // load search results
suggestionPublisher.onNext(theSearchString);
startLoading(false);
}
From d1a82a85cdc28d9226a3b4e6d7dcfceac479e6b6 Mon Sep 17 00:00:00 2001
From: Edward
Date: Wed, 29 Mar 2023 01:04:26 +0800
Subject: [PATCH 007/162] Include a high-resolution option in the default
resolution settings.
---
.../settings/VideoAudioSettingsFragment.java | 65 ++++++++++++++++++-
.../org/schabi/newpipe/util/ListHelper.java | 25 +++++++
app/src/main/res/values/settings_keys.xml | 15 +++++
app/src/main/res/values/strings.xml | 4 ++
4 files changed, 108 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java
index aae9cfca5..b498bcf30 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java
@@ -13,6 +13,7 @@ import androidx.preference.ListPreference;
import com.google.android.material.snackbar.Snackbar;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.PermissionHelper;
import java.util.LinkedList;
@@ -26,7 +27,7 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment {
addPreferencesFromResourceRegistry();
updateSeekOptions();
-
+ updateResolutionOptions();
listener = (sharedPreferences, key) -> {
// on M and above, if user chooses to minimise to popup player on exit
@@ -48,10 +49,72 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment {
}
} else if (getString(R.string.use_inexact_seek_key).equals(key)) {
updateSeekOptions();
+ } else if (getString(R.string.show_higher_resolutions_key).equals(key)) {
+ updateResolutionOptions();
}
};
}
+ /**
+ * Update default resolution, default popup resolution & mobile data resolution options.
+ * show high resolution when "Show higher resolution" option enabled.
+ */
+ private void updateResolutionOptions() {
+ final ListPreference defaultResolution = findPreference(
+ getString(R.string.default_resolution_key));
+ final ListPreference defaultPopupResolution = findPreference(
+ getString(R.string.default_popup_resolution_key));
+ final ListPreference mobileDataResolution = findPreference(
+ getString(R.string.limit_mobile_data_usage_key));
+ final Resources resources = getResources();
+ final boolean showHigherResolutions = getPreferenceManager().getSharedPreferences()
+ .getBoolean(resources.getString(R.string.show_higher_resolutions_key), false);
+ final List resolutionListDescriptions = ListHelper.getSortedResolutionList(
+ resources,
+ R.array.resolution_list_description,
+ R.array.high_resolution_list_descriptions,
+ showHigherResolutions);
+ final List resolutionListValues = ListHelper.getSortedResolutionList(
+ resources,
+ R.array.resolution_list_values,
+ R.array.high_resolution_list_values,
+ showHigherResolutions);
+ final List limitDataUsageResolutionValues = ListHelper.getSortedResolutionList(
+ resources,
+ R.array.limit_data_usage_values_list,
+ R.array.high_resolution_limit_data_usage_values_list,
+ showHigherResolutions);
+ final List limitDataUsageResolutionDescriptions = ListHelper
+ .getSortedResolutionList(resources,
+ R.array.limit_data_usage_description_list,
+ R.array.high_resolution_list_descriptions,
+ showHigherResolutions);
+ defaultResolution.setEntries(resolutionListDescriptions.toArray(new String[0]));
+ defaultResolution.setEntryValues(resolutionListValues.toArray(new String[0]));
+ defaultPopupResolution.setEntries(resolutionListDescriptions.toArray(new String[0]));
+ defaultPopupResolution.setEntryValues(resolutionListValues.toArray(new String[0]));
+ mobileDataResolution.setEntries(
+ limitDataUsageResolutionDescriptions.toArray(new String[0]));
+ mobileDataResolution.setEntryValues(limitDataUsageResolutionValues.toArray(new String[0]));
+ if (!showHigherResolutions) {
+ if (ListHelper.isHighResolutionSelected(defaultResolution.getValue(),
+ R.array.high_resolution_list_values,
+ resources)) {
+ defaultResolution.setValueIndex(0);
+ }
+ if (ListHelper.isHighResolutionSelected(defaultPopupResolution.getValue(),
+ R.array.high_resolution_list_values,
+ resources)) {
+ defaultPopupResolution.setValueIndex(0);
+ }
+ if (ListHelper.isHighResolutionSelected(mobileDataResolution.getValue(),
+ R.array.high_resolution_limit_data_usage_values_list,
+ resources)) {
+ mobileDataResolution.setValueIndex(0);
+ }
+ }
+ }
+
/**
* Update fast-forward/-rewind seek duration options
* according to language and inexact seek setting.
diff --git a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java
index f45f3786d..ead98211e 100644
--- a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java
+++ b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java
@@ -4,6 +4,7 @@ import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import android.content.Context;
import android.content.SharedPreferences;
+import android.content.res.Resources;
import android.net.ConnectivityManager;
import androidx.annotation.NonNull;
@@ -239,6 +240,30 @@ public final class ListHelper {
videoOnlyStreams, ascendingOrder, preferVideoOnlyStreams);
}
+ public static List getSortedResolutionList(
+ final Resources resources,
+ final int defaultResolutionKey,
+ final int additionalResolutionKey,
+ final boolean showHigherResolutions) {
+ final List defaultResolution = new ArrayList(Arrays.asList(
+ resources.getStringArray(defaultResolutionKey)));
+ if (!showHigherResolutions) {
+ return defaultResolution;
+ }
+ final List additionalResolutions = Arrays.asList(
+ resources.getStringArray(additionalResolutionKey));
+ defaultResolution.addAll(1, additionalResolutions);
+ return defaultResolution;
+ }
+
+ public static boolean isHighResolutionSelected(final String selectedResolution,
+ final int additionalResolutionKey,
+ final Resources resources) {
+ return Arrays.asList(resources.getStringArray(
+ additionalResolutionKey))
+ .contains(selectedResolution);
+ }
+
/**
* Filter the list of audio streams and return a list with the preferred stream for
* each audio track. Streams are sorted with the preferred language in the first position.
diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml
index 56fc19eed..0ec60dbdf 100644
--- a/app/src/main/res/values/settings_keys.xml
+++ b/app/src/main/res/values/settings_keys.xml
@@ -124,6 +124,16 @@
480pbest_resolution
+
+ 2160p
+ 1440p
+
+
+
+ 2160p
+ 1440p
+
+
@string/best_resolution_key1080p60
@@ -1301,6 +1311,11 @@
144p
+
+ 2160p
+ 1440p
+
+
list_view_mode@string/list_view_mode_auto_key
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5cf214c0d..984f52233 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -543,6 +543,10 @@
240p144p
+
+ 2160p
+ 1440p
+ New streams notificationsNotify about new streams from subscriptions
From 19640d5e7cbd57ce7a30cda8bcf267c13f521d4d Mon Sep 17 00:00:00 2001
From: TobiGr
Date: Mon, 18 Sep 2023 01:43:14 +0200
Subject: [PATCH 008/162] Add documentation to increase maintainablilty
Rename a variable
---
.../settings/VideoAudioSettingsFragment.java | 26 ++++++++++++++-----
.../org/schabi/newpipe/util/ListHelper.java | 19 +++++++++++---
2 files changed, 34 insertions(+), 11 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java
index b498bcf30..a1f563724 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/VideoAudioSettingsFragment.java
@@ -57,18 +57,17 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment {
/**
* Update default resolution, default popup resolution & mobile data resolution options.
- * show high resolution when "Show higher resolution" option enabled.
+ *
+ * Show high resolutions when "Show higher resolution" option is enabled.
+ * Set default resolution to "best resolution" when "Show higher resolution" option
+ * is disabled.
*/
private void updateResolutionOptions() {
- final ListPreference defaultResolution = findPreference(
- getString(R.string.default_resolution_key));
- final ListPreference defaultPopupResolution = findPreference(
- getString(R.string.default_popup_resolution_key));
- final ListPreference mobileDataResolution = findPreference(
- getString(R.string.limit_mobile_data_usage_key));
final Resources resources = getResources();
final boolean showHigherResolutions = getPreferenceManager().getSharedPreferences()
.getBoolean(resources.getString(R.string.show_higher_resolutions_key), false);
+
+ // get sorted resolution lists
final List resolutionListDescriptions = ListHelper.getSortedResolutionList(
resources,
R.array.resolution_list_description,
@@ -89,6 +88,16 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment {
R.array.limit_data_usage_description_list,
R.array.high_resolution_list_descriptions,
showHigherResolutions);
+
+ // get resolution preferences
+ final ListPreference defaultResolution = findPreference(
+ getString(R.string.default_resolution_key));
+ final ListPreference defaultPopupResolution = findPreference(
+ getString(R.string.default_popup_resolution_key));
+ final ListPreference mobileDataResolution = findPreference(
+ getString(R.string.limit_mobile_data_usage_key));
+
+ // update resolution preferences with new resolutions, entries & values for each
defaultResolution.setEntries(resolutionListDescriptions.toArray(new String[0]));
defaultResolution.setEntryValues(resolutionListValues.toArray(new String[0]));
defaultPopupResolution.setEntries(resolutionListDescriptions.toArray(new String[0]));
@@ -96,6 +105,9 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment {
mobileDataResolution.setEntries(
limitDataUsageResolutionDescriptions.toArray(new String[0]));
mobileDataResolution.setEntryValues(limitDataUsageResolutionValues.toArray(new String[0]));
+
+ // if "Show higher resolution" option is disabled,
+ // set default resolution to "best resolution"
if (!showHigherResolutions) {
if (ListHelper.isHighResolutionSelected(defaultResolution.getValue(),
R.array.high_resolution_list_values,
diff --git a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java
index ead98211e..5918ece25 100644
--- a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java
+++ b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java
@@ -240,20 +240,31 @@ public final class ListHelper {
videoOnlyStreams, ascendingOrder, preferVideoOnlyStreams);
}
+ /**
+ * Get a sorted list containing a set of default resolution info
+ * and additional resolution info if showHigherResolutions is true.
+ *
+ * @param resources the resources to get the resolutions from
+ * @param defaultResolutionKey the settings key of the default resolution
+ * @param additionalResolutionKey the settings key of the additional resolutions
+ * @param showHigherResolutions if higher resolutions should be included in the sorted list
+ * @return a sorted list containing the default and maybe additional resolutions
+ */
public static List getSortedResolutionList(
final Resources resources,
final int defaultResolutionKey,
final int additionalResolutionKey,
final boolean showHigherResolutions) {
- final List defaultResolution = new ArrayList(Arrays.asList(
+ final List resolutions = new ArrayList<>(Arrays.asList(
resources.getStringArray(defaultResolutionKey)));
if (!showHigherResolutions) {
- return defaultResolution;
+ return resolutions;
}
final List additionalResolutions = Arrays.asList(
resources.getStringArray(additionalResolutionKey));
- defaultResolution.addAll(1, additionalResolutions);
- return defaultResolution;
+ // keep "best resolution" at the top
+ resolutions.addAll(1, additionalResolutions);
+ return resolutions;
}
public static boolean isHighResolutionSelected(final String selectedResolution,
From af2375948de932dde1ac3e186ab40c60f86d531f Mon Sep 17 00:00:00 2001
From: Stypox
Date: Mon, 1 May 2023 23:11:48 +0200
Subject: [PATCH 009/162] Support obtaining multiple images from the extractor
---
app/build.gradle | 2 +-
.../org/schabi/newpipe/QueueItemMenuUtil.java | 2 +-
.../database/playlist/PlaylistStreamEntry.kt | 3 +-
.../playlist/model/PlaylistRemoteEntity.java | 7 +-
.../database/stream/StreamStatisticsEntry.kt | 3 +-
.../database/stream/model/StreamEntity.kt | 10 ++-
.../subscription/SubscriptionEntity.java | 7 +-
.../fragments/detail/DescriptionFragment.java | 3 +-
.../fragments/detail/VideoDetailFragment.java | 25 +++---
.../list/channel/ChannelAboutFragment.java | 5 +-
.../list/channel/ChannelFragment.java | 13 ++-
.../list/playlist/PlaylistFragment.java | 5 +-
.../dialog/StreamDialogDefaultEntry.java | 2 +-
.../holder/ChannelMiniInfoItemHolder.java | 2 +-
.../holder/CommentsMiniInfoItemHolder.java | 2 +-
.../holder/PlaylistMiniInfoItemHolder.java | 2 +-
.../holder/StreamMiniInfoItemHolder.java | 2 +-
.../subscription/SubscriptionFragment.kt | 3 +-
.../local/subscription/SubscriptionManager.kt | 10 ++-
.../local/subscription/item/ChannelItem.kt | 2 +-
.../org/schabi/newpipe/player/Player.java | 13 +--
.../player/mediaitem/ExceptionTag.java | 3 +-
.../player/mediaitem/StreamInfoTag.java | 3 +-
.../mediasession/PlayQueueNavigator.java | 4 +-
.../player/playqueue/PlayQueueItem.java | 16 ++--
.../playqueue/PlayQueueItemBuilder.java | 2 +-
.../newpipe/player/ui/MainPlayerUi.java | 2 +-
.../newpipe/player/ui/VideoPlayerUi.java | 2 +-
.../schabi/newpipe/util/PicassoHelper.java | 87 ++++++++++++++++---
.../external_communication/ShareUtils.java | 25 ++++++
30 files changed, 190 insertions(+), 77 deletions(-)
diff --git a/app/build.gradle b/app/build.gradle
index 831b758b9..aa7ac8720 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -197,7 +197,7 @@ dependencies {
// name and the commit hash with the commit hash of the (pushed) commit you want to test
// This works thanks to JitPack: https://jitpack.io/
implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751'
- implementation 'com.github.TeamNewPipe:NewPipeExtractor:95a3cc0a173bba28c179f9f9503b1010ec6bff21'
+ implementation 'com.github.TeamNewPipe:NewPipeExtractor:3be76a6406d59f1fd8eedf5fab6552e6c2a3da76'
implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0'
/** Checkstyle **/
diff --git a/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java b/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java
index 3255489b0..e6177f6a3 100644
--- a/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java
+++ b/app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java
@@ -75,7 +75,7 @@ public final class QueueItemMenuUtil {
return true;
case R.id.menu_item_share:
shareText(context, item.getTitle(), item.getUrl(),
- item.getThumbnailUrl());
+ item.getThumbnails());
return true;
case R.id.menu_item_download:
fetchStreamInfoAndSaveToDatabase(context, item.getServiceId(), item.getUrl(),
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..3b6bc9593 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
@@ -7,6 +7,7 @@ import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity
import org.schabi.newpipe.database.stream.model.StreamEntity
import org.schabi.newpipe.database.stream.model.StreamStateEntity
import org.schabi.newpipe.extractor.stream.StreamInfoItem
+import org.schabi.newpipe.util.PicassoHelper
data class PlaylistStreamEntry(
@Embedded
@@ -28,7 +29,7 @@ data class PlaylistStreamEntry(
item.duration = streamEntity.duration
item.uploaderName = streamEntity.uploader
item.uploaderUrl = streamEntity.uploaderUrl
- item.thumbnailUrl = streamEntity.thumbnailUrl
+ item.thumbnails = PicassoHelper.urlToImageList(streamEntity.thumbnailUrl)
return item
}
diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java
index 2e9a15d7d..640b6d1fa 100644
--- a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java
+++ b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java
@@ -11,6 +11,7 @@ import androidx.room.PrimaryKey;
import org.schabi.newpipe.database.playlist.PlaylistLocalItem;
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
import org.schabi.newpipe.util.Constants;
+import org.schabi.newpipe.util.PicassoHelper;
import static org.schabi.newpipe.database.LocalItem.LocalItemType.PLAYLIST_REMOTE_ITEM;
import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_NAME;
@@ -69,8 +70,7 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem {
@Ignore
public PlaylistRemoteEntity(final PlaylistInfo info) {
this(info.getServiceId(), info.getName(), info.getUrl(),
- info.getThumbnailUrl() == null
- ? info.getUploaderAvatarUrl() : info.getThumbnailUrl(),
+ PicassoHelper.choosePreferredImage(info.getThumbnails()),
info.getUploaderName(), info.getStreamCount());
}
@@ -84,7 +84,8 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem {
&& getStreamCount() == info.getStreamCount()
&& TextUtils.equals(getName(), info.getName())
&& TextUtils.equals(getUrl(), info.getUrl())
- && TextUtils.equals(getThumbnailUrl(), info.getThumbnailUrl())
+ && TextUtils.equals(getThumbnailUrl(),
+ PicassoHelper.choosePreferredImage(info.getThumbnails()))
&& TextUtils.equals(getUploader(), info.getUploaderName());
}
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 dc0db59d8..a268f8bbf 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
@@ -7,6 +7,7 @@ import org.schabi.newpipe.database.history.model.StreamHistoryEntity
import org.schabi.newpipe.database.stream.model.StreamEntity
import org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_PROGRESS_MILLIS
import org.schabi.newpipe.extractor.stream.StreamInfoItem
+import org.schabi.newpipe.util.PicassoHelper
import java.time.OffsetDateTime
class StreamStatisticsEntry(
@@ -30,7 +31,7 @@ class StreamStatisticsEntry(
item.duration = streamEntity.duration
item.uploaderName = streamEntity.uploader
item.uploaderUrl = streamEntity.uploaderUrl
- item.thumbnailUrl = streamEntity.thumbnailUrl
+ item.thumbnails = PicassoHelper.urlToImageList(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 c56f91949..8b7639bbd 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
@@ -13,6 +13,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfo
import org.schabi.newpipe.extractor.stream.StreamInfoItem
import org.schabi.newpipe.extractor.stream.StreamType
import org.schabi.newpipe.player.playqueue.PlayQueueItem
+import org.schabi.newpipe.util.PicassoHelper
import java.io.Serializable
import java.time.OffsetDateTime
@@ -67,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,
- uploaderUrl = item.uploaderUrl, thumbnailUrl = item.thumbnailUrl, viewCount = item.viewCount,
+ uploaderUrl = item.uploaderUrl, thumbnailUrl = PicassoHelper.choosePreferredImage(item.thumbnails), viewCount = item.viewCount,
textualUploadDate = item.textualUploadDate, uploadDate = item.uploadDate?.offsetDateTime(),
isUploadDateApproximation = item.uploadDate?.isApproximation
)
@@ -76,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,
- uploaderUrl = info.uploaderUrl, thumbnailUrl = info.thumbnailUrl, viewCount = info.viewCount,
+ uploaderUrl = info.uploaderUrl, thumbnailUrl = PicassoHelper.choosePreferredImage(info.thumbnails), viewCount = info.viewCount,
textualUploadDate = info.textualUploadDate, uploadDate = info.uploadDate?.offsetDateTime(),
isUploadDateApproximation = info.uploadDate?.isApproximation
)
@@ -85,7 +86,8 @@ 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 = item.uploaderUrl, thumbnailUrl = item.thumbnailUrl
+ uploaderUrl = item.uploaderUrl,
+ thumbnailUrl = PicassoHelper.choosePreferredImage(item.thumbnails)
)
fun toStreamInfoItem(): StreamInfoItem {
@@ -93,7 +95,7 @@ data class StreamEntity(
item.duration = duration
item.uploaderName = uploader
item.uploaderUrl = uploaderUrl
- item.thumbnailUrl = thumbnailUrl
+ item.thumbnails = PicassoHelper.urlToImageList(thumbnailUrl)
if (viewCount != null) item.viewCount = viewCount as Long
item.textualUploadDate = textualUploadDate
diff --git a/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java b/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java
index 0e4bda490..a455cf258 100644
--- a/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java
+++ b/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java
@@ -10,6 +10,7 @@ import androidx.room.PrimaryKey;
import org.schabi.newpipe.extractor.channel.ChannelInfo;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.util.Constants;
+import org.schabi.newpipe.util.PicassoHelper;
import static org.schabi.newpipe.database.subscription.SubscriptionEntity.SUBSCRIPTION_SERVICE_ID;
import static org.schabi.newpipe.database.subscription.SubscriptionEntity.SUBSCRIPTION_TABLE;
@@ -57,8 +58,8 @@ public class SubscriptionEntity {
final SubscriptionEntity result = new SubscriptionEntity();
result.setServiceId(info.getServiceId());
result.setUrl(info.getUrl());
- result.setData(info.getName(), info.getAvatarUrl(), info.getDescription(),
- info.getSubscriberCount());
+ result.setData(info.getName(), PicassoHelper.choosePreferredImage(info.getAvatars()),
+ info.getDescription(), info.getSubscriberCount());
return result;
}
@@ -138,7 +139,7 @@ public class SubscriptionEntity {
@Ignore
public ChannelInfoItem toChannelInfoItem() {
final ChannelInfoItem item = new ChannelInfoItem(getServiceId(), getUrl(), getName());
- item.setThumbnailUrl(getAvatarUrl());
+ item.setThumbnails(PicassoHelper.urlToImageList(getAvatarUrl()));
item.setSubscriberCount(getSubscriberCount());
item.setDescription(getDescription());
return item;
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java
index 92219883b..e7f257665 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java
@@ -17,6 +17,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.util.Localization;
import java.util.List;
+import org.schabi.newpipe.util.PicassoHelper;
import icepick.State;
@@ -113,7 +114,7 @@ public class DescriptionFragment extends BaseDescriptionFragment {
addMetadataItem(inflater, layout, true, R.string.metadata_host,
streamInfo.getHost());
addMetadataItem(inflater, layout, true, R.string.metadata_thumbnail_url,
- streamInfo.getThumbnailUrl());
+ PicassoHelper.choosePreferredImage(streamInfo.getThumbnails()));
}
private void addPrivacyMetadataItem(final LayoutInflater inflater, final LinearLayout layout) {
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
index 686e102f1..2e6f493a3 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
@@ -71,6 +71,7 @@ import org.schabi.newpipe.error.ErrorInfo;
import org.schabi.newpipe.error.ErrorUtil;
import org.schabi.newpipe.error.ReCaptchaActivity;
import org.schabi.newpipe.error.UserAction;
+import org.schabi.newpipe.extractor.Image;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException;
@@ -483,7 +484,7 @@ public final class VideoDetailFragment
});
binding.detailControlsShare.setOnClickListener(makeOnClickListener(info ->
ShareUtils.shareText(requireContext(), info.getName(), info.getUrl(),
- info.getThumbnailUrl())));
+ info.getThumbnails())));
binding.detailControlsOpenInBrowser.setOnClickListener(makeOnClickListener(info ->
ShareUtils.openUrlInBrowser(requireContext(), info.getUrl())));
binding.detailControlsPlayWithKodi.setOnClickListener(makeOnClickListener(info ->
@@ -723,7 +724,7 @@ public final class VideoDetailFragment
final boolean isPlayerStopped = !isPlayerAvailable() || player.isStopped();
if (playQueueItem != null && isPlayerStopped) {
updateOverlayData(playQueueItem.getTitle(),
- playQueueItem.getUploader(), playQueueItem.getThumbnailUrl());
+ playQueueItem.getUploader(), playQueueItem.getThumbnails());
}
}
@@ -1536,13 +1537,13 @@ public final class VideoDetailFragment
binding.detailSecondaryControlPanel.setVisibility(View.GONE);
checkUpdateProgressInfo(info);
- PicassoHelper.loadDetailsThumbnail(info.getThumbnailUrl()).tag(PICASSO_VIDEO_DETAILS_TAG)
+ PicassoHelper.loadDetailsThumbnail(info.getThumbnails()).tag(PICASSO_VIDEO_DETAILS_TAG)
.into(binding.detailThumbnailImageView);
showMetaInfoInTextView(info.getMetaInfo(), binding.detailMetaInfoTextView,
binding.detailMetaInfoSeparator, disposables);
if (!isPlayerAvailable() || player.isStopped()) {
- updateOverlayData(info.getName(), info.getUploaderName(), info.getThumbnailUrl());
+ updateOverlayData(info.getName(), info.getUploaderName(), info.getThumbnails());
}
if (!info.getErrors().isEmpty()) {
@@ -1587,7 +1588,7 @@ public final class VideoDetailFragment
binding.detailUploaderTextView.setVisibility(View.GONE);
}
- PicassoHelper.loadAvatar(info.getUploaderAvatarUrl()).tag(PICASSO_VIDEO_DETAILS_TAG)
+ PicassoHelper.loadAvatar(info.getUploaderAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG)
.into(binding.detailSubChannelThumbnailView);
binding.detailSubChannelThumbnailView.setVisibility(View.VISIBLE);
binding.detailUploaderThumbnailView.setVisibility(View.GONE);
@@ -1619,10 +1620,10 @@ public final class VideoDetailFragment
binding.detailUploaderTextView.setVisibility(View.GONE);
}
- PicassoHelper.loadAvatar(info.getSubChannelAvatarUrl()).tag(PICASSO_VIDEO_DETAILS_TAG)
+ PicassoHelper.loadAvatar(info.getSubChannelAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG)
.into(binding.detailSubChannelThumbnailView);
binding.detailSubChannelThumbnailView.setVisibility(View.VISIBLE);
- PicassoHelper.loadAvatar(info.getUploaderAvatarUrl()).tag(PICASSO_VIDEO_DETAILS_TAG)
+ PicassoHelper.loadAvatar(info.getUploaderAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG)
.into(binding.detailUploaderThumbnailView);
binding.detailUploaderThumbnailView.setVisibility(View.VISIBLE);
}
@@ -1797,7 +1798,7 @@ public final class VideoDetailFragment
return;
}
- updateOverlayData(info.getName(), info.getUploaderName(), info.getThumbnailUrl());
+ updateOverlayData(info.getName(), info.getUploaderName(), info.getThumbnails());
if (currentInfo != null && info.getUrl().equals(currentInfo.getUrl())) {
return;
}
@@ -1826,7 +1827,7 @@ public final class VideoDetailFragment
if (currentInfo != null) {
updateOverlayData(currentInfo.getName(),
currentInfo.getUploaderName(),
- currentInfo.getThumbnailUrl());
+ currentInfo.getThumbnails());
}
updateOverlayPlayQueueButtonVisibility();
}
@@ -2191,7 +2192,7 @@ public final class VideoDetailFragment
playerHolder.stopService();
setInitialData(0, null, "", null);
currentInfo = null;
- updateOverlayData(null, null, null);
+ updateOverlayData(null, null, List.of());
}
/*//////////////////////////////////////////////////////////////////////////
@@ -2373,11 +2374,11 @@ public final class VideoDetailFragment
private void updateOverlayData(@Nullable final String overlayTitle,
@Nullable final String uploader,
- @Nullable final String thumbnailUrl) {
+ @NonNull final List thumbnails) {
binding.overlayTitleTextView.setText(isEmpty(overlayTitle) ? "" : overlayTitle);
binding.overlayChannelTextView.setText(isEmpty(uploader) ? "" : uploader);
binding.overlayThumbnail.setImageDrawable(null);
- PicassoHelper.loadDetailsThumbnail(thumbnailUrl).tag(PICASSO_VIDEO_DETAILS_TAG)
+ PicassoHelper.loadDetailsThumbnail(thumbnails).tag(PICASSO_VIDEO_DETAILS_TAG)
.into(binding.overlayThumbnail);
}
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java
index 543fd80f3..eebd12d20 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java
@@ -17,6 +17,7 @@ import org.schabi.newpipe.extractor.stream.Description;
import org.schabi.newpipe.fragments.detail.BaseDescriptionFragment;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.Localization;
+import org.schabi.newpipe.util.PicassoHelper;
import java.util.List;
@@ -100,8 +101,8 @@ public class ChannelAboutFragment extends BaseDescriptionFragment {
}
addMetadataItem(inflater, layout, true, R.string.metadata_avatar_url,
- channelInfo.getAvatarUrl());
+ PicassoHelper.choosePreferredImage(channelInfo.getAvatars()));
addMetadataItem(inflater, layout, true, R.string.metadata_banner_url,
- channelInfo.getBannerUrl());
+ PicassoHelper.choosePreferredImage(channelInfo.getBanners()));
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
index c1345180b..6b2c71337 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
@@ -1,6 +1,5 @@
package org.schabi.newpipe.fragments.list.channel;
-import static org.schabi.newpipe.extractor.utils.Utils.isBlank;
import static org.schabi.newpipe.ktx.TextViewUtils.animateTextColor;
import static org.schabi.newpipe.ktx.ViewUtils.animate;
import static org.schabi.newpipe.ktx.ViewUtils.animateBackgroundColor;
@@ -234,7 +233,7 @@ public class ChannelFragment extends BaseStateFragment
case R.id.menu_item_share:
if (currentInfo != null) {
ShareUtils.shareText(requireContext(), name, currentInfo.getOriginalUrl(),
- currentInfo.getAvatarUrl());
+ currentInfo.getAvatars());
}
break;
default:
@@ -355,7 +354,7 @@ public class ChannelFragment extends BaseStateFragment
channel.setServiceId(info.getServiceId());
channel.setUrl(info.getUrl());
channel.setData(info.getName(),
- info.getAvatarUrl(),
+ PicassoHelper.choosePreferredImage(info.getAvatars()),
info.getDescription(),
info.getSubscriberCount());
channelSubscription = null;
@@ -579,17 +578,17 @@ public class ChannelFragment extends BaseStateFragment
currentInfo = result;
setInitialData(result.getServiceId(), result.getOriginalUrl(), result.getName());
- if (PicassoHelper.getShouldLoadImages() && !isBlank(result.getBannerUrl())) {
- PicassoHelper.loadBanner(result.getBannerUrl()).tag(PICASSO_CHANNEL_TAG)
+ if (PicassoHelper.getShouldLoadImages() && !result.getBanners().isEmpty()) {
+ PicassoHelper.loadBanner(result.getBanners()).tag(PICASSO_CHANNEL_TAG)
.into(binding.channelBannerImage);
} else {
// do not waste space for the banner, if the user disabled images or there is not one
binding.channelBannerImage.setImageDrawable(null);
}
- PicassoHelper.loadAvatar(result.getAvatarUrl()).tag(PICASSO_CHANNEL_TAG)
+ PicassoHelper.loadAvatar(result.getAvatars()).tag(PICASSO_CHANNEL_TAG)
.into(binding.channelAvatarView);
- PicassoHelper.loadAvatar(result.getParentChannelAvatarUrl()).tag(PICASSO_CHANNEL_TAG)
+ PicassoHelper.loadAvatar(result.getParentChannelAvatars()).tag(PICASSO_CHANNEL_TAG)
.into(binding.subChannelAvatarView);
binding.channelTitleView.setText(result.getName());
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java
index 2b7cf9446..9b3f693e1 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java
@@ -234,7 +234,7 @@ public class PlaylistFragment extends BaseListInfoFragment
ShareUtils.shareText(fragment.requireContext(), item.getName(), item.getUrl(),
- item.getThumbnailUrl())),
+ item.getThumbnails())),
/**
* Opens a {@link DownloadDialog} after fetching some stream info.
diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java
index 3b375d6eb..d971a6a6d 100644
--- a/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java
+++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java
@@ -56,7 +56,7 @@ public class ChannelMiniInfoItemHolder extends InfoItemHolder {
itemAdditionalDetailView.setText(getDetailLine(item));
}
- PicassoHelper.loadAvatar(item.getThumbnailUrl()).into(itemThumbnailView);
+ PicassoHelper.loadAvatar(item.getThumbnails()).into(itemThumbnailView);
itemView.setOnClickListener(view -> {
if (itemBuilder.getOnChannelSelectedListener() != null) {
diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java
index 1c8db26d6..d69be077d 100644
--- a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java
+++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java
@@ -97,7 +97,7 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
}
final CommentsInfoItem item = (CommentsInfoItem) infoItem;
- PicassoHelper.loadAvatar(item.getUploaderAvatarUrl()).into(itemThumbnailView);
+ PicassoHelper.loadAvatar(item.getUploaderAvatars()).into(itemThumbnailView);
if (PicassoHelper.getShouldLoadImages()) {
itemThumbnailView.setVisibility(View.VISIBLE);
itemRoot.setPadding(commentVerticalPadding, commentVerticalPadding,
diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java
index bf5f57db3..62c7c27eb 100644
--- a/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java
+++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java
@@ -46,7 +46,7 @@ public class PlaylistMiniInfoItemHolder extends InfoItemHolder {
.localizeStreamCountMini(itemStreamCountView.getContext(), item.getStreamCount()));
itemUploaderView.setText(item.getUploaderName());
- PicassoHelper.loadPlaylistThumbnail(item.getThumbnailUrl()).into(itemThumbnailView);
+ PicassoHelper.loadPlaylistThumbnail(item.getThumbnails()).into(itemThumbnailView);
itemView.setOnClickListener(view -> {
if (itemBuilder.getOnPlaylistSelectedListener() != null) {
diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java
index 6dd06e47f..796ea63b3 100644
--- a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java
+++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java
@@ -87,7 +87,7 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder {
}
// Default thumbnail is shown on error, while loading and if the url is empty
- PicassoHelper.loadThumbnail(item.getThumbnailUrl()).into(itemThumbnailView);
+ PicassoHelper.loadThumbnail(item.getThumbnails()).into(itemThumbnailView);
itemView.setOnClickListener(view -> {
if (itemBuilder.getOnStreamSelectedListener() != null) {
diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt
index dda4326e9..f428a7c1d 100644
--- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt
+++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt
@@ -58,6 +58,7 @@ import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard
import org.schabi.newpipe.streams.io.StoredFileHelper
import org.schabi.newpipe.util.NavigationHelper
import org.schabi.newpipe.util.OnClickGesture
+import org.schabi.newpipe.util.PicassoHelper
import org.schabi.newpipe.util.ServiceHelper
import org.schabi.newpipe.util.ThemeHelper.getGridSpanCountChannels
import org.schabi.newpipe.util.external_communication.ShareUtils
@@ -342,7 +343,7 @@ class SubscriptionFragment : BaseStateFragment() {
when (i) {
0 -> ShareUtils.shareText(
requireContext(), selectedItem.name, selectedItem.url,
- selectedItem.thumbnailUrl
+ PicassoHelper.choosePreferredImage(selectedItem.thumbnails)
)
1 -> ShareUtils.openUrlInBrowser(requireContext(), selectedItem.url)
2 -> deleteChannel(selectedItem)
diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt
index 3c11ce152..a74ff305c 100644
--- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt
+++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt
@@ -19,6 +19,7 @@ import org.schabi.newpipe.extractor.feed.FeedInfo
import org.schabi.newpipe.extractor.stream.StreamInfoItem
import org.schabi.newpipe.local.feed.FeedDatabaseManager
import org.schabi.newpipe.util.ExtractorHelper
+import org.schabi.newpipe.util.PicassoHelper
class SubscriptionManager(context: Context) {
private val database = NewPipeDatabase.getInstance(context)
@@ -71,7 +72,12 @@ class SubscriptionManager(context: Context) {
subscriptionTable.getSubscription(info.serviceId, info.url)
.flatMapCompletable {
Completable.fromRunnable {
- it.setData(info.name, info.avatarUrl, info.description, info.subscriberCount)
+ it.setData(
+ info.name,
+ PicassoHelper.choosePreferredImage(info.avatars),
+ info.description,
+ info.subscriberCount
+ )
subscriptionTable.update(it)
}
}
@@ -99,7 +105,7 @@ class SubscriptionManager(context: Context) {
} else if (info is ChannelInfo) {
subscriptionEntity.setData(
info.name,
- info.avatarUrl,
+ PicassoHelper.choosePreferredImage(info.avatars),
info.description,
info.subscriberCount
)
diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt
index bee2e910a..07a4f11ff 100644
--- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt
+++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt
@@ -39,7 +39,7 @@ class ChannelItem(
itemChannelDescriptionView.text = infoItem.description
}
- PicassoHelper.loadAvatar(infoItem.thumbnailUrl).into(itemThumbnailView)
+ PicassoHelper.loadAvatar(infoItem.thumbnails).into(itemThumbnailView)
gesturesListener?.run {
viewHolder.root.setOnClickListener { selected(infoItem) }
diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java
index 1a323176c..3ad03891e 100644
--- a/app/src/main/java/org/schabi/newpipe/player/Player.java
+++ b/app/src/main/java/org/schabi/newpipe/player/Player.java
@@ -87,6 +87,7 @@ import org.schabi.newpipe.error.ErrorInfo;
import org.schabi.newpipe.error.ErrorUtil;
import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.extractor.stream.AudioStream;
+import org.schabi.newpipe.extractor.Image;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.extractor.stream.VideoStream;
@@ -805,10 +806,10 @@ public final class Player implements PlaybackListener, Listener {
};
}
- private void loadCurrentThumbnail(final String url) {
+ private void loadCurrentThumbnail(final List thumbnails) {
if (DEBUG) {
- Log.d(TAG, "Thumbnail - loadCurrentThumbnail() called with url = ["
- + (url == null ? "null" : url) + "]");
+ Log.d(TAG, "Thumbnail - loadCurrentThumbnail() called with thumbnails = ["
+ + thumbnails.size() + "]");
}
// first cancel any previous loading
@@ -817,12 +818,12 @@ public final class Player implements PlaybackListener, Listener {
// Unset currentThumbnail, since it is now outdated. This ensures it is not used in media
// session metadata while the new thumbnail is being loaded by Picasso.
onThumbnailLoaded(null);
- if (isNullOrEmpty(url)) {
+ if (thumbnails.isEmpty()) {
return;
}
// scale down the notification thumbnail for performance
- PicassoHelper.loadScaledDownThumbnail(context, url)
+ PicassoHelper.loadScaledDownThumbnail(context, thumbnails)
.tag(PICASSO_PLAYER_THUMBNAIL_TAG)
.into(currentThumbnailTarget);
}
@@ -1792,7 +1793,7 @@ public final class Player implements PlaybackListener, Listener {
maybeAutoQueueNextStream(info);
- loadCurrentThumbnail(info.getThumbnailUrl());
+ loadCurrentThumbnail(info.getThumbnails());
registerStreamViewed();
notifyMetadataUpdateToListeners();
diff --git a/app/src/main/java/org/schabi/newpipe/player/mediaitem/ExceptionTag.java b/app/src/main/java/org/schabi/newpipe/player/mediaitem/ExceptionTag.java
index ebedf8c71..5a5360b34 100644
--- a/app/src/main/java/org/schabi/newpipe/player/mediaitem/ExceptionTag.java
+++ b/app/src/main/java/org/schabi/newpipe/player/mediaitem/ExceptionTag.java
@@ -3,6 +3,7 @@ package org.schabi.newpipe.player.mediaitem;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
+import org.schabi.newpipe.util.PicassoHelper;
import java.util.List;
import java.util.Optional;
@@ -74,7 +75,7 @@ public final class ExceptionTag implements MediaItemTag {
@Override
public String getThumbnailUrl() {
- return item.getThumbnailUrl();
+ return PicassoHelper.choosePreferredImage(item.getThumbnails());
}
@Override
diff --git a/app/src/main/java/org/schabi/newpipe/player/mediaitem/StreamInfoTag.java b/app/src/main/java/org/schabi/newpipe/player/mediaitem/StreamInfoTag.java
index 689f5c72b..eb3abec1f 100644
--- a/app/src/main/java/org/schabi/newpipe/player/mediaitem/StreamInfoTag.java
+++ b/app/src/main/java/org/schabi/newpipe/player/mediaitem/StreamInfoTag.java
@@ -6,6 +6,7 @@ import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.extractor.stream.VideoStream;
+import org.schabi.newpipe.util.PicassoHelper;
import java.util.Collections;
import java.util.List;
@@ -95,7 +96,7 @@ public final class StreamInfoTag implements MediaItemTag {
@Override
public String getThumbnailUrl() {
- return streamInfo.getThumbnailUrl();
+ return PicassoHelper.choosePreferredImage(streamInfo.getThumbnails());
}
@Override
diff --git a/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java b/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java
index 2e54b1129..327c2befe 100644
--- a/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java
+++ b/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java
@@ -20,6 +20,7 @@ import com.google.android.exoplayer2.util.Util;
import org.schabi.newpipe.player.Player;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
+import org.schabi.newpipe.util.PicassoHelper;
import java.util.ArrayList;
import java.util.Collections;
@@ -137,7 +138,8 @@ public class PlayQueueNavigator implements MediaSessionConnector.QueueNavigator
.putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, player.getPlayQueue().size());
descBuilder.setExtras(additionalMetadata);
- final Uri thumbnailUri = Uri.parse(item.getThumbnailUrl());
+ final Uri thumbnailUri = Uri.parse(
+ PicassoHelper.choosePreferredImage(item.getThumbnails()));
if (thumbnailUri != null) {
descBuilder.setIconUri(thumbnailUri);
}
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 bf31ea9b1..759c51267 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
@@ -3,12 +3,14 @@ package org.schabi.newpipe.player.playqueue;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import org.schabi.newpipe.extractor.Image;
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.util.ExtractorHelper;
import java.io.Serializable;
+import java.util.List;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.schedulers.Schedulers;
@@ -24,7 +26,7 @@ public class PlayQueueItem implements Serializable {
private final int serviceId;
private final long duration;
@NonNull
- private final String thumbnailUrl;
+ private final List thumbnails;
@NonNull
private final String uploader;
private final String uploaderUrl;
@@ -38,7 +40,7 @@ public class PlayQueueItem implements Serializable {
PlayQueueItem(@NonNull final StreamInfo info) {
this(info.getName(), info.getUrl(), info.getServiceId(), info.getDuration(),
- info.getThumbnailUrl(), info.getUploaderName(),
+ info.getThumbnails(), info.getUploaderName(),
info.getUploaderUrl(), info.getStreamType());
if (info.getStartPosition() > 0) {
@@ -48,20 +50,20 @@ public class PlayQueueItem implements Serializable {
PlayQueueItem(@NonNull final StreamInfoItem item) {
this(item.getName(), item.getUrl(), item.getServiceId(), item.getDuration(),
- item.getThumbnailUrl(), item.getUploaderName(),
+ item.getThumbnails(), item.getUploaderName(),
item.getUploaderUrl(), item.getStreamType());
}
@SuppressWarnings("ParameterNumber")
private PlayQueueItem(@Nullable final String name, @Nullable final String url,
final int serviceId, final long duration,
- @Nullable final String thumbnailUrl, @Nullable final String uploader,
+ final List thumbnails, @Nullable final String uploader,
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.thumbnails = thumbnails;
this.uploader = uploader != null ? uploader : EMPTY_STRING;
this.uploaderUrl = uploaderUrl;
this.streamType = streamType;
@@ -88,8 +90,8 @@ public class PlayQueueItem implements Serializable {
}
@NonNull
- public String getThumbnailUrl() {
- return thumbnailUrl;
+ public List getThumbnails() {
+ return thumbnails;
}
@NonNull
diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java
index e7aeb9638..19101a31d 100644
--- a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java
+++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java
@@ -33,7 +33,7 @@ public class PlayQueueItemBuilder {
holder.itemDurationView.setVisibility(View.GONE);
}
- PicassoHelper.loadThumbnail(item.getThumbnailUrl()).into(holder.itemThumbnailView);
+ PicassoHelper.loadThumbnail(item.getThumbnails()).into(holder.itemThumbnailView);
holder.itemRoot.setOnClickListener(view -> {
if (onItemClickListener != null) {
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
index 92e38a6a2..03f90a344 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java
@@ -740,7 +740,7 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh
String videoUrl = player.getVideoUrl();
videoUrl += ("&t=" + seconds);
ShareUtils.shareText(context, currentItem.getTitle(),
- videoUrl, currentItem.getThumbnailUrl());
+ videoUrl, currentItem.getThumbnails());
}
}
};
diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
index 119c43b95..b51aaa638 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java
@@ -226,7 +226,7 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa
final PlayQueueItem currentItem = player.getCurrentItem();
if (currentItem != null) {
ShareUtils.shareText(context, currentItem.getTitle(),
- player.getVideoUrlAtCurrentTime(), currentItem.getThumbnailUrl());
+ player.getVideoUrlAtCurrentTime(), currentItem.getThumbnails());
}
}));
binding.share.setOnLongClickListener(v -> {
diff --git a/app/src/main/java/org/schabi/newpipe/util/PicassoHelper.java b/app/src/main/java/org/schabi/newpipe/util/PicassoHelper.java
index ece0c7e87..5f3876d78 100644
--- a/app/src/main/java/org/schabi/newpipe/util/PicassoHelper.java
+++ b/app/src/main/java/org/schabi/newpipe/util/PicassoHelper.java
@@ -1,13 +1,14 @@
package org.schabi.newpipe.util;
import static org.schabi.newpipe.MainActivity.DEBUG;
-import static org.schabi.newpipe.extractor.utils.Utils.isBlank;
+import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.BitmapCompat;
@@ -19,9 +20,13 @@ import com.squareup.picasso.RequestCreator;
import com.squareup.picasso.Transformation;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.extractor.Image;
+import org.schabi.newpipe.extractor.Image.ResolutionLevel;
import java.io.File;
import java.io.IOException;
+import java.util.Comparator;
+import java.util.List;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
@@ -42,6 +47,7 @@ public final class PicassoHelper {
private static Picasso picassoInstance;
private static boolean shouldLoadImages;
+ private static ResolutionLevel preferredResolutionLevel = ResolutionLevel.HIGH;
public static void init(final Context context) {
picassoCache = new LruCache(10 * 1024 * 1024);
@@ -96,20 +102,33 @@ public final class PicassoHelper {
}
+ public static RequestCreator loadAvatar(final List images) {
+ return loadImageDefault(images, R.drawable.placeholder_person);
+ }
+
public static RequestCreator loadAvatar(final String url) {
return loadImageDefault(url, R.drawable.placeholder_person);
}
+ public static RequestCreator loadThumbnail(final List images) {
+ return loadImageDefault(images, R.drawable.placeholder_thumbnail_video);
+ }
+
public static RequestCreator loadThumbnail(final String url) {
return loadImageDefault(url, R.drawable.placeholder_thumbnail_video);
}
- public static RequestCreator loadDetailsThumbnail(final String url) {
- return loadImageDefault(url, R.drawable.placeholder_thumbnail_video, false);
+ public static RequestCreator loadDetailsThumbnail(final List images) {
+ return loadImageDefault(choosePreferredImage(images),
+ R.drawable.placeholder_thumbnail_video, false);
}
- public static RequestCreator loadBanner(final String url) {
- return loadImageDefault(url, R.drawable.placeholder_channel_banner);
+ public static RequestCreator loadBanner(final List images) {
+ return loadImageDefault(images, R.drawable.placeholder_channel_banner);
+ }
+
+ public static RequestCreator loadPlaylistThumbnail(final List images) {
+ return loadImageDefault(images, R.drawable.placeholder_thumbnail_playlist);
}
public static RequestCreator loadPlaylistThumbnail(final String url) {
@@ -125,9 +144,10 @@ public final class PicassoHelper {
}
- public static RequestCreator loadScaledDownThumbnail(final Context context, final String url) {
+ public static RequestCreator loadScaledDownThumbnail(final Context context,
+ final List images) {
// scale down the notification thumbnail for performance
- return PicassoHelper.loadThumbnail(url)
+ return PicassoHelper.loadThumbnail(images)
.transform(new Transformation() {
@Override
public Bitmap transform(final Bitmap source) {
@@ -180,13 +200,20 @@ public final class PicassoHelper {
}
- private static RequestCreator loadImageDefault(final String url, final int placeholderResId) {
+ private static RequestCreator loadImageDefault(final List images,
+ final int placeholderResId) {
+ return loadImageDefault(choosePreferredImage(images), placeholderResId);
+ }
+
+ private static RequestCreator loadImageDefault(final String url,
+ final int placeholderResId) {
return loadImageDefault(url, placeholderResId, true);
}
- private static RequestCreator loadImageDefault(final String url, final int placeholderResId,
+ private static RequestCreator loadImageDefault(@Nullable final String url,
+ final int placeholderResId,
final boolean showPlaceholderWhileLoading) {
- if (!shouldLoadImages || isBlank(url)) {
+ if (isNullOrEmpty(url)) {
return picassoInstance
.load((String) null)
.placeholder(placeholderResId) // show placeholder when no image should load
@@ -201,4 +228,44 @@ public final class PicassoHelper {
return requestCreator;
}
}
+
+ @Nullable
+ public static String choosePreferredImage(final List images) {
+ if (!shouldLoadImages) {
+ return null;
+ }
+
+ final Comparator comparator;
+ switch (preferredResolutionLevel) {
+ case HIGH:
+ comparator = Comparator.comparingInt(Image::getHeight).reversed();
+ break;
+ default:
+ case UNKNOWN:
+ case MEDIUM:
+ comparator = Comparator.comparingInt(image -> Math.abs(image.getHeight() - 450));
+ break;
+ case LOW:
+ comparator = Comparator.comparingInt(Image::getHeight);
+ break;
+ }
+
+ return images.stream()
+ .filter(image -> image.getEstimatedResolutionLevel() != ResolutionLevel.UNKNOWN)
+ .min(comparator)
+ .map(Image::getUrl)
+ .orElseGet(() -> images.stream()
+ .findAny()
+ .map(Image::getUrl)
+ .orElse(null));
+ }
+
+ @NonNull
+ public static List urlToImageList(@Nullable final String url) {
+ if (url == null) {
+ return List.of();
+ } else {
+ return List.of(new Image(url, -1, -1, ResolutionLevel.UNKNOWN));
+ }
+ }
}
diff --git a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java
index 118b77026..f14f22069 100644
--- a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java
+++ b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java
@@ -23,10 +23,12 @@ import androidx.core.content.FileProvider;
import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.extractor.Image;
import org.schabi.newpipe.util.PicassoHelper;
import java.io.File;
import java.io.FileOutputStream;
+import java.util.List;
public final class ShareUtils {
private static final String TAG = ShareUtils.class.getSimpleName();
@@ -261,6 +263,29 @@ public final class ShareUtils {
openAppChooser(context, shareIntent, false);
}
+ /**
+ * Open the android share sheet to share a content.
+ *
+ *
+ * For Android 10+ users, a content preview is shown, which includes the title of the shared
+ * content and an image preview the content, if its URL is not null or empty and its
+ * corresponding image is in the image cache.
+ *
@@ -140,12 +154,13 @@ public final class SettingMigrations {
MIGRATION_2_3,
MIGRATION_3_4,
MIGRATION_4_5,
+ MIGRATION_5_6,
};
/**
* Version number for preferences. Must be incremented every time a migration is necessary.
*/
- private static final int VERSION = 5;
+ private static final int VERSION = 6;
public static void runMigrationsIfNeeded(@NonNull final Context context,
diff --git a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java
index f14f22069..8150d4030 100644
--- a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java
+++ b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java
@@ -24,7 +24,7 @@ import androidx.core.content.FileProvider;
import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.Image;
-import org.schabi.newpipe.util.PicassoHelper;
+import org.schabi.newpipe.util.image.PicassoHelper;
import java.io.File;
import java.io.FileOutputStream;
@@ -251,7 +251,7 @@ public final class ShareUtils {
// If loading of images has been disabled, don't try to generate a content preview
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
&& !TextUtils.isEmpty(imagePreviewUrl)
- && PicassoHelper.getShouldLoadImages()) {
+ && PicassoHelper.shouldLoadImages()) {
final ClipData clipData = generateClipDataForImagePreview(context, imagePreviewUrl);
if (clipData != null) {
diff --git a/app/src/main/java/org/schabi/newpipe/util/PicassoHelper.java b/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java
similarity index 94%
rename from app/src/main/java/org/schabi/newpipe/util/PicassoHelper.java
rename to app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java
index 5f3876d78..3177e83f4 100644
--- a/app/src/main/java/org/schabi/newpipe/util/PicassoHelper.java
+++ b/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java
@@ -1,4 +1,4 @@
-package org.schabi.newpipe.util;
+package org.schabi.newpipe.util.image;
import static org.schabi.newpipe.MainActivity.DEBUG;
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
@@ -46,8 +46,7 @@ public final class PicassoHelper {
@SuppressLint("StaticFieldLeak")
private static Picasso picassoInstance;
- private static boolean shouldLoadImages;
- private static ResolutionLevel preferredResolutionLevel = ResolutionLevel.HIGH;
+ private static PreferredImageQuality preferredImageQuality = PreferredImageQuality.MEDIUM;
public static void init(final Context context) {
picassoCache = new LruCache(10 * 1024 * 1024);
@@ -93,12 +92,12 @@ public final class PicassoHelper {
picassoInstance.setIndicatorsEnabled(enabled); // useful for debugging
}
- public static void setShouldLoadImages(final boolean shouldLoadImages) {
- PicassoHelper.shouldLoadImages = shouldLoadImages;
+ public static void setPreferredImageQuality(final PreferredImageQuality preferredImageQuality) {
+ PicassoHelper.preferredImageQuality = preferredImageQuality;
}
- public static boolean getShouldLoadImages() {
- return shouldLoadImages;
+ public static boolean shouldLoadImages() {
+ return preferredImageQuality != PreferredImageQuality.NONE;
}
@@ -231,17 +230,14 @@ public final class PicassoHelper {
@Nullable
public static String choosePreferredImage(final List images) {
- if (!shouldLoadImages) {
- return null;
- }
-
final Comparator comparator;
- switch (preferredResolutionLevel) {
+ switch (preferredImageQuality) {
+ case NONE:
+ return null;
case HIGH:
comparator = Comparator.comparingInt(Image::getHeight).reversed();
break;
default:
- case UNKNOWN:
case MEDIUM:
comparator = Comparator.comparingInt(image -> Math.abs(image.getHeight() - 450));
break;
diff --git a/app/src/main/java/org/schabi/newpipe/util/image/PreferredImageQuality.java b/app/src/main/java/org/schabi/newpipe/util/image/PreferredImageQuality.java
new file mode 100644
index 000000000..9f17082ea
--- /dev/null
+++ b/app/src/main/java/org/schabi/newpipe/util/image/PreferredImageQuality.java
@@ -0,0 +1,24 @@
+package org.schabi.newpipe.util.image;
+
+import android.content.Context;
+
+import org.schabi.newpipe.R;
+
+public enum PreferredImageQuality {
+ NONE,
+ LOW,
+ MEDIUM,
+ HIGH;
+
+ public static PreferredImageQuality fromPreferenceKey(final Context context, final String key) {
+ if (context.getString(R.string.image_quality_none_key).equals(key)) {
+ return NONE;
+ } else if (context.getString(R.string.image_quality_low_key).equals(key)) {
+ return LOW;
+ } else if (context.getString(R.string.image_quality_high_key).equals(key)) {
+ return HIGH;
+ } else {
+ return MEDIUM; // default to medium
+ }
+ }
+}
diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml
index d0cf90db4..0c9f2c74c 100644
--- a/app/src/main/res/values-ar/strings.xml
+++ b/app/src/main/res/values-ar/strings.xml
@@ -243,7 +243,6 @@
الإشارات المرجعيةاستعمال التقديم السريع الغير دقيقخاصية التقديم الغير دقيق تسمح للمشغل بالقفز خلال الفديو بشكل أسرع مع دقة قفز أقل. خاصية القفز ل5، 15 او 25 لا تعمل مع القفز الغير دقيق
- تحميل الصور المصغرةتم إفراغ مساحة ذاكرة التخزين المؤقتة الخاصة بالصورالملفلا يوجد مثل هذا المجلد
@@ -260,7 +259,6 @@
عملية التصدير جارية …إستيراد ملفمعرفك, soundcloud.com/هويتك
- قم بإيقاف تشغيله لمنع تحميل الصور المصغرة وحفظ البيانات واستخدام الذاكرة. تمسح التغييرات كلاً من ذاكرة التخزين المؤقت للصورة الموجودة في الذاكرة والموجودة على القرصامسح البيانات الوصفيّة المخزّنة مؤقّتًاإزالة جميع بيانات صفحات الويب المخزنة مؤقّتًاتم محو ذاكرة التخزين المؤقتّة للبيانات الوصفيّة
diff --git a/app/src/main/res/values-as/strings.xml b/app/src/main/res/values-as/strings.xml
index 93e9e363e..fc9d5b2b6 100644
--- a/app/src/main/res/values-as/strings.xml
+++ b/app/src/main/res/values-as/strings.xml
@@ -62,7 +62,6 @@
লোড ব্যৱধানৰ আকাৰ সলনি কৰক (বৰ্তমানে %s) । এটা কম মানে প্ৰাৰম্ভিক ভিডিঅ\' লোডিং দ্ৰুত কৰিব পাৰে। পৰিৱৰ্তনৰ বাবে এটা খেলুৱৈ পুনৰাৰম্ভৰ প্ৰয়োজনথাম্বনেইলত থকা মূল ৰং অনুসৰি এণ্ড্ৰইডক জাননীৰ ৰং কাষ্টমাইজ কৰিবলৈ কওক (মন কৰিব যে এইটো সকলো ডিভাইচতে উপলব্ধ নহয়)সক্ৰিয় প্লেয়াৰৰ queue সলনি কৰা হ’ব
- থাম্বনেইল লোড কৰকমন্তব্য দেখুৱাওকবিৱৰণ দেখুৱাওকমেটা তথ্য দেখুৱাওক
@@ -96,6 +95,5 @@
ভিডিঅ\'ৰ বিৱৰণ আৰু অতিৰিক্ত তথ্য লুকুৱাবলৈ বন্ধ কৰকমন্তব্য লুকুৱাবলৈ বন্ধ কৰক\'পৰৱৰ্তী\' আৰু \'সাদৃশ্য থকা\' ভিডিঅ\' দেখুৱাওক
- থাম্বনেইলসমূহ লোড কৰা, তথ্য আৰু মেমৰি ব্যৱহাৰ সংৰক্ষণ কৰা ৰোধ কৰিবলে বন্ধ কৰক। পৰিবৰ্তনসমূহে ইন-মেমৰি আৰু অন-ডিস্ক কেশ্ব দুয়োটা পৰিষ্কাৰ কৰেষ্ট্ৰিমৰ সৃষ্টিকৰ্তা, ষ্ট্ৰিমৰ বিষয়বস্তু বা এটা সন্ধান অনুৰোধৰ বিষয়ে অতিৰিক্ত তথ্যৰ সৈতে মেটা তথ্যৰ বাকচসমূহ লুকুৱাবলৈ বন্ধ কৰক
\ No newline at end of file
diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml
index a238758af..06273f9cf 100644
--- a/app/src/main/res/values-az/strings.xml
+++ b/app/src/main/res/values-az/strings.xml
@@ -136,7 +136,6 @@
\nOnu görmək istəyirsinizsə, tənzimləmələrdə \"%1$s\" seçimini aktivləşdirin.
YouTube potensial yetkin məzmunu gizlədən \"Məhdud Rejim\" təmin edir\"PeerTube\" nümunələri
- Miniatürləri yükləYığcam bildirişdə göstərmək üçün ən çoxu üç fəaliyyət seçə bilərsiniz!Həmişə yeniləAxın
@@ -287,7 +286,6 @@
Səs yayımı tapılmadıDigər tətbiqlərin üzərində göstərməyə icazə verİlkin tənzimləmələri qaytarmaq istəyirsiniz\?
- Miniatürləri yükləməyi, məlumata qənaət və yaddaş istifadəsin azaltmaq üçün söndür. Dəyişikliklər həm yaddaşdaxilində, həm də diskdə təsvir keşini təmizləyirNövbətini növbələTəkrar Cəhd EtCari oynatma yayımı bildirişini konfiqurasiya et
diff --git a/app/src/main/res/values-b+ast/strings.xml b/app/src/main/res/values-b+ast/strings.xml
index f9c6109e6..b9a57f1c2 100644
--- a/app/src/main/res/values-b+ast/strings.xml
+++ b/app/src/main/res/values-b+ast/strings.xml
@@ -206,8 +206,6 @@
\n3. Anicia sesión cuando se te pida
\n4. Copia la URL del perfil al que te redirixeron.soundcloud.com/LaToID
- Cargar les miniatures
- Desactiva esta opción pa eviar la carga de miniatures y aforrar datos y usu de memoria. Los cambeos llimpien la caché d\'imáxenes temporal y permanente.Minimizar al cambiar d\'aplicaciónMinimizar al reproductor en segundu planuMinimizar al reproductor en ventanu
diff --git a/app/src/main/res/values-b+uz+Latn/strings.xml b/app/src/main/res/values-b+uz+Latn/strings.xml
index affa805e6..76924b0d4 100644
--- a/app/src/main/res/values-b+uz+Latn/strings.xml
+++ b/app/src/main/res/values-b+uz+Latn/strings.xml
@@ -24,10 +24,8 @@
Barcha keshlangan veb-sahifa ma\'lumotlarini olib tashlashKeshlangan metadatalarni o\'chirishRasm keshi o\'chirildi
- Eskizlarni yuklash, ma\'lumotlarni tejash va xotiradan foydalanishni oldini olish uchun o\'chirib qo\'ying. O\'zgarishlar xotiradagi va diskdagi rasm keshini tozalaydi.sharhlarni yashirishni o\'chirishIzohlarni ko\'rsatish
- Eskizlarni yuklangAktiv ijro etish navbati almashtiriladiBir ijro etishdan boshqasiga o\'tish sizning navbatingizni almashtirishi mumkinNavbatni tozalashdan oldin tasdiqlashni so\'rash
diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml
index 979553372..e176d2bc9 100644
--- a/app/src/main/res/values-be/strings.xml
+++ b/app/src/main/res/values-be/strings.xml
@@ -55,8 +55,6 @@
Запамінаць памер і становішча ўсплываючага акнаХуткі пошук пазіцыіНедакладны пошук дазваляе плэеру знаходзіць пазіцыі хутчэй са зніжанай дакладнасцю. Пошук цягам 5, 15 ці 25 секунд пры гэтым немажлівы
- Загружаць мініяцюры
- Адключыце, каб не загружаць мініяцюры і зэканоміць трафік і памяць. Змена налады ачысьціць кэш малюнкаўКэш малюнкаў ачышчаныАчысціць кэш метададзеныхВыдаліць усе загружаныя дадзеныя вэб-старонак
diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml
index 24bf7a764..59091553d 100644
--- a/app/src/main/res/values-bg/strings.xml
+++ b/app/src/main/res/values-bg/strings.xml
@@ -151,7 +151,6 @@
Добавяне къмИзползвай бързо, но неточно превъртанеПо-бързо превъртане с по-ниска прецизност. Превъртане с по 5, 15 или 25 секунди няма да работи с тази опция
- Зареждай миниатюриКеш-паметта с изображения е изтритаИзтрий кешираните метаданниПремахни всички метаданни за уебстраници от кеш-паметта
@@ -205,7 +204,6 @@
Прочетете нашата политика за поверителностЛицензът на NewPipeЛипсва стрийм плейър (можете да изтеглите VLC, за да пуснете стрийма).
- Изключете, за да спрете зареждането на всички миниатюри, спестявайки трафик и памет. При промяна на тази настройка, текущата кеш-памет на изображенията ще бъде изтритаПоказвай подсказка при избор на фоновия режим или режим в прозорец от екрана за „Детайли“ към видеоИзтрива историята на възпроизвежданите стриймове и позицията на възпроизвежданетоНе са намерени видео стриймове
diff --git a/app/src/main/res/values-bn-rBD/strings.xml b/app/src/main/res/values-bn-rBD/strings.xml
index 4e6655e45..e660cb7bd 100644
--- a/app/src/main/res/values-bn-rBD/strings.xml
+++ b/app/src/main/res/values-bn-rBD/strings.xml
@@ -140,8 +140,6 @@
দ্রুত-ফরওয়ার্ড/-পুনরায় সন্ধান সময়কালমন্তব্যসমূহ লুকাতে বন্ধ করুনমন্তব্যসমূহ দেখাও
- থাম্বনেইল লোড করো
- থাম্বনেইল প্রদর্শন বন্ধ করার মাধ্যমে, ডাটা এবং মেমোরি সংরক্ষণ করুন। অপশনটি পরিবর্তনে ইন-মেমোরি এবং অন-ডিস্ক ইমেজ ক্যাশ উভয়ই মুছে যাবে।ছবির ক্যাশ মোছা হয়েছেসব ক্যাশড ওয়েবপেজ ডেটা মুছে ফেলোক্যাশ করা মেটাডেটা মোছ
diff --git a/app/src/main/res/values-bn-rIN/strings.xml b/app/src/main/res/values-bn-rIN/strings.xml
index 162dfde39..1f664ce26 100644
--- a/app/src/main/res/values-bn-rIN/strings.xml
+++ b/app/src/main/res/values-bn-rIN/strings.xml
@@ -79,10 +79,8 @@
সব ক্যাশড ওয়েবপেজ ডেটা মুছে ফেলোক্যাশ করা মেটাডেটা মুছোছবির ক্যাশ মুছে ফেলা হয়েছে
- থাম্বনেইল প্রদর্শন বন্ধ করার মাধ্যমে, ডাটা এবং মেমোরি সংরক্ষণ করুন। অপশনটি পরিবর্তনে ইন-মেমোরি এবং অন-ডিস্ক ইমেজ ক্যাশ উভয়ই মুছে যাবেমতামত প্রদর্শন বন্ধ করতে অপশনটি বন্ধ করুনমতামত প্রদর্শন করুন
- থাম্বনেইল লোড করুনদ্রুত-ফরওয়ার্ড/-পুনরায় সন্ধান সময়কালঅনির্দিষ্ট সন্ধান প্লেয়ারকে আরো দ্রুত গতিতে সন্ধান করার সুবিধা দেয়, কিন্তু এটি সম্পূর্ণ নির্ভুল নাও হতে পারে ৷ ৫, ১৫ ও ২৫ সেকেন্ডের জন্য এটা কাজ করবে না ৷দ্রুত টানা ব্যাবহার করুন
diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml
index 6c3cca7a1..d3f3a845b 100644
--- a/app/src/main/res/values-bn/strings.xml
+++ b/app/src/main/res/values-bn/strings.xml
@@ -225,10 +225,8 @@
সব ক্যাশড ওয়েবপেজ ডেটা মুছে ফেলোক্যাশ করা মেটাডেটা মুছোছবির ক্যাশ মুছে ফেলা হয়েছে
- থাম্বনেইল প্রদর্শন বন্ধ করার মাধ্যমে, ডাটা এবং মেমোরি সংরক্ষণ করুন। অপশনটি পরিবর্তনে ইন-মেমোরি এবং অন-ডিস্ক ইমেজ ক্যাশ উভয়ই মুছে যাবেমতামত প্রদর্শন বন্ধ করতে অপশনটি বন্ধ করুনমতামত প্রদর্শন করুন
- থাম্বনেইল লোড করুনদ্রুত-ফরওয়ার্ড/-পুনরায় সন্ধান সময়কালঅনির্দিষ্ট সন্ধান, চালককে আরো দ্রুত গতিতে সন্ধান করার সুবিধা দেয়, কিন্তু এটি সম্পূর্ণ নির্ভুল নাও হতে পারে ৷ ৫, ১৫ ও ২৫ সেকেন্ডের জন্য এটা কাজ করবে না।দ্রুত টানা ব্যাবহার করুন
diff --git a/app/src/main/res/values-bs/strings.xml b/app/src/main/res/values-bs/strings.xml
index 50dcf839c..4921a6aa8 100644
--- a/app/src/main/res/values-bs/strings.xml
+++ b/app/src/main/res/values-bs/strings.xml
@@ -73,7 +73,6 @@
Prebacivanje sa jednog pokretača na drugi bi van moglo zamijeniti pokretni redIsključite da sakrijete komentarePitajte za potvrdu prije isčišćavanja reda
- Isključite kako bi ste spriječili učitavanje sličica, sto če vam spasiti korištenje podataka i memorije. Promjene čiste slike oboje u memoriji i predmešiju na diskuPrikažite komentarePokažite \'Sljedeće\' i \'Slične\' video zapisePrikažite opis
@@ -115,5 +114,4 @@
Pokrenite s KODI-jemVrijeme premotavanja naprijed/nazadAktivni pokretni red će biti zamijenjen
- Učitajte sličice
\ No newline at end of file
diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml
index 010823e43..bd3a5c61b 100644
--- a/app/src/main/res/values-ca/strings.xml
+++ b/app/src/main/res/values-ca/strings.xml
@@ -121,7 +121,6 @@
Recorda la darrera mida i posició del reproductor emergentCerca ràpida poc precisaLa cerca poc precisa permet que el reproductor cerqui una posició més ràpidament amb menys precisió. Cerques de 5, 15 o 25 segons no funcionaran
- Carrega les miniaturesS\'ha eliminat la memòria cau d\'imatgesElimina les metadades de la memòria cauS\'ha esborrat la memòria cau de metadades
@@ -217,7 +216,6 @@
Toca \"Cerca\" per començar.Elimina l\'àudio en algunes resolucionsReproductor d\'àudio extern
- Desactiveu-ho per no guardar miniatures i estalviar dades i memòria. Canviant aquesta opció, s\'eliminarà la memòria cau d\'imatges tant de la memòria com de l\'emmagatzematgeEmmagatzema les cerques localmentCrea un historial de vídeos visualitzatsReprèn la reproducció
diff --git a/app/src/main/res/values-ckb/strings.xml b/app/src/main/res/values-ckb/strings.xml
index f761323f9..bae9fb822 100644
--- a/app/src/main/res/values-ckb/strings.xml
+++ b/app/src/main/res/values-ckb/strings.xml
@@ -16,7 +16,6 @@
پڕۆژەی نیوپایپ زانیارییە تایبەتییەکانت بە وردی دەپارێزێت. هەروەها بهرنامهكه هیچ زانایارییەکت بەبێ ئاگاداری تۆ بەکارنابات.
\nسیاسەتی تایبەتی نیوپایپ بە وردی ڕوونکردنەوەت دەداتێ لەسەر ئەو زانیاریانەی وەریاندەگرێت و بەکاریاندەبات.ناتوانرێت لە بیرگەی دەرەکیدا داببەزێنرێت . شوێنی فۆڵدهری دابهزاندنەکان ڕێکبخرێتەوە؟
- ناکارای بكه بۆ وەستاندنی باركردنی وێنۆچكهكان، داتا دەپارێزێت و کەمتر بیرگە بەکاردەبات, گۆڕینی ئهمه دهبێته هۆی سڕینهوهیان لهسهر بیرگهی مۆبایلهكهتئایا مەبەستت ئهمهیه \"%1$s\"؟ماوەی نوێكردنهوهی فییدهێڵەکی
@@ -111,7 +110,6 @@
زمان دەگۆڕدرێت لەدوای داگیرساندنەوەی بهرنامهكهلادانی سەیرکراوپیشاندانی نیشانەکەری شوێنی کارپێکەر لە خشتەکاندا
- باركردنی وێنۆچكهكانشوێنەکان لە خشتەکاندابهژداریتبەهۆی گۆڕانکاری لە شێوەی ژێرنووسکردنەکە. پێویستە بهرنامهكه دابگیرسێنیتهوه
diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml
index 1eb38085c..dab312d3b 100644
--- a/app/src/main/res/values-cs/strings.xml
+++ b/app/src/main/res/values-cs/strings.xml
@@ -251,8 +251,6 @@
Vynutit hlášení nedoručitelných výjimek Rx mimo životnost fragmentu nebo aktivity po odstraněníPoužít rychlé nepřesné hledáníNepřesné hledání umožní přehrávači posouvat se rychleji, ale se sníženou přesností. Posouvání po 5, 15 nebo 25 vteřinách s tímto nefunguje
- Načítat náhledy
- Vypnutím zabráníte načítání miniatur, ukládání dat a spotřebě paměti. Změny vymažou mezipaměť obrázků v paměti i na diskuMezipaměť obrázků vymazánaVymazat metadata v mezipamětiOdstranit všechna data webových stránek v mezipaměti
diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml
index 0bd7e9875..ef6197414 100644
--- a/app/src/main/res/values-da/strings.xml
+++ b/app/src/main/res/values-da/strings.xml
@@ -57,8 +57,6 @@
Husk sidste størrelse og placering af pop op-afspillerBrug hurtig og upræcis søgningUpræcis søgning lader afspilleren finde placeringer hurtigere, men mindre præcist. Søgninger på 5, 15 eller 25 sekunder fungerer ikke med denne indstilling slået til
- Indlæs miniaturebilleder
- Slå fra for at undgå indlæsning af billeder, hvorved der spares data og hukommelse. Ændringer sletter billedcachen i både ram og lagerBilledcache slettetSlet metadata-cachenSlet alle websidedata fra cachen
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 5283f1afa..e9b710c63 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -253,7 +253,6 @@
Beachte, dass diese Aktion das Netzwerk stark belasten kann.
\n
\nMöchtest du fortfahren\?
- Vorschaubilder ladenBilder-Cache gelöschtZwischengespeicherte (Metadaten) löschenAlle zwischengespeicherten Website-Daten entfernen
@@ -270,7 +269,6 @@
GeschwindigkeitTonhöheEntkoppeln (kann zu Verzerrungen führen)
- Ausschalten, um das Laden von Vorschaubildern zu verhindern, was Daten- und Speicherverbrauch spart. Änderungen löschen den Bildzwischenspeicher sowohl im Arbeitsspeicher als auch auf dem internen SpeicherNächsten Stream automatisch einreihenWiedergabe durch Anhängen eines verwandten Streams an die Warteschlange (ohne Wiederholungsschleife) fortsetzenWiedergabeliste mit Lesezeichen versehen
diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml
index 094ac0ccd..ced70b787 100644
--- a/app/src/main/res/values-el/strings.xml
+++ b/app/src/main/res/values-el/strings.xml
@@ -90,8 +90,6 @@
Ενθύμηση του τελευταίου μεγέθους και θέσης του παραθύρουΧρήση γρήγορης ανακριβούς αναζήτησηςΗ μην ακριβής αναζήτηση επιτρέπει στην εφαρμογή να αναζητεί θέσεις στο βίντεο γρηγορότερα με μειωμένη ακρίβεια. Δε λειτουργεί για διαστήματα των 5, 15 ή 25 δευτερολέπτων
- Φόρτωση μικρογραφιών
- Με την απενεργοποίηση δε φορτώνονται οι μικρογραφίες, εξοικονομώντας δεδομένα και μνήμη. Οι αλλαγές σβήνουν τις προσωρινά αποθηκευμένες εικόνες στη μνήμη και στον δίσκοΕκκαθαρίστηκε η προσωρινή μνήμη εικόνωνΕκκαθάριση προσωρινά αποθηκευμένων μεταδεδομένωνΑφαίρεση όλων των προσωρινά αποθηκευμένων δεδομένων ιστοσελίδων
diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml
index c8cc728b5..808aa2573 100644
--- a/app/src/main/res/values-en-rGB/strings.xml
+++ b/app/src/main/res/values-en-rGB/strings.xml
@@ -76,7 +76,6 @@
BehaviourSelect your favourite PeerTube instancesContinue playing after interruptions (e.g. phone calls)
- Turn off to prevent loading thumbnails, saving data and memory usage. Changes clear both in-memory and on-disc image cache.Published on %1$sReport this error via e-mailSelect your favorite night theme – %s
diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml
index a3a7a6af4..2d0951db4 100644
--- a/app/src/main/res/values-eo/strings.xml
+++ b/app/src/main/res/values-eo/strings.xml
@@ -80,7 +80,6 @@
Memori lastan grandon kaj pozicion de ŝprucfenestroUzi rapidan malekzaktan serĉonMalekzakta serĉo permesas ke, la ludilo serĉi poziciojn pli rapide sed kun malpli ekzakto. Serĉi por 5, 15 aŭ 25 sekundoj ne funckias kun ĉi tio opcio
- Ŝarĝi bildetojnNe povis konstrui la dosierujon de elŝutoEnhavo limigita al aĝoNuna
@@ -181,7 +180,6 @@
\n2. Iru tien: %1$s
\n3. Ensalutu kiam oni petas vin
\n4. Kopiu la ligilon de profilo ke oni kondikis vin.
- Malŝaltu por malebligi ŝarĝajn bildetojn por konservi datumuzadon kaj memoruzadon. Ŝanĝoj vakigi ambaŭ en memoran kaj en diskan bildkaŝmemoronBildokaŝmemoro vakigisVakigi kaŝmemorigitajn metadatumojnVakigi tutajn kaŝmemorigitajn retpaĝajn datumojn
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index d1d7fdcd4..6ffadca81 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -288,8 +288,6 @@
Esta operación puede causar un uso intensivo de la red.
\n
\n¿Quieres continuar\?
- Cargar miniaturas
- Desactivar para evitar la carga de miniaturas y ahorrar datos y memoria. Se vaciará la caché de imágenes en la memoria volátil y en el discoSe vació la caché de imágenesVaciar metadatos en memoria cachéQuitar todos los datos guardados de páginas web
diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml
index b55870c75..ab478ec11 100644
--- a/app/src/main/res/values-et/strings.xml
+++ b/app/src/main/res/values-et/strings.xml
@@ -55,8 +55,6 @@
Pea hüpikakna viimane suurus ja asukoht meelesKasuta ebatäpset kerimistEbatäpne kerimine lubab meediamängijal otsida asukohta kiiremini täpsuse arvel. Sellega ei tööta 5, 15 või 25 sekundi kaupa kerimine
- Laadi pisipildid
- Lülita välja, et keelata pisipiltide laadimist, andmete salvestamist ja mälukasutust. Muutmine puhastab vahemälu nii kettal kui ka mälusPildid kustutati vahemälustKustuta metaandmed vahemälustKustuta veebilehtede andmed vahemälust
diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml
index c8d16b698..6003de6fd 100644
--- a/app/src/main/res/values-eu/strings.xml
+++ b/app/src/main/res/values-eu/strings.xml
@@ -211,7 +211,6 @@
Gogoko erreprodukzio-zerrendakGehitu honaErabili bilaketa azkar ez zehatza
- Kargatu iruditxoakIrudien cachea ezabatutaEzabatu cacheko metadatuakKendu cachetik webguneen datu guztiak
@@ -307,7 +306,6 @@
Desaktibatu (distortsioa sor lezake)Ezarpenak ere inportatu nahi dituzu?Bilaketa ez zehatzak posizioak azkarrago baina prezisio gutxiagoz bilatzea ahalbidetzen du. 5, 15 edo 25 segundo bilatzea ez du honekin funtzionatzen
- Desgaitu koadro txikiak ez kargatzeko, datuak eta memoria aurreztuz. Aldaketak memoria eta diskoko irudien cacheak garbituko dituNewPipe Software Librea eta Copyleft da: Erabili, ikertu, partekatu eta hobetu dezakezu. Zehazki, elkarbanatzea eta aldatzea Free Software Foundation-ek argitaratutako GNU General Public License-ren 3. bertsioa edo berriagoren baten terminoen arabera egiteko baimena duzu.Behartu aktibitatearen bizitza ziklotik kanpo baztertu eta gero entregatu ezin diren Rx salbuespenen inguruko txostenaNewPipe pribatutasun politika
diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml
index 3d8e8da9b..35db56515 100644
--- a/app/src/main/res/values-fa/strings.xml
+++ b/app/src/main/res/values-fa/strings.xml
@@ -96,7 +96,6 @@
تنها برخی دستگاهها توانایی پخش ویدیوهای 2K و 4K را دارندقالب ویدیویی پیشگزیدهسیاه
- بار کردن بندانگشتیهاقرار دادن خودکار جریان بعدی در صفپیشنهادهای جستجوگزینش پیشنهادها برای نمایش هنگام جستوجو
@@ -270,7 +269,6 @@
پخش ادامه یابدذخیره محلی نتایج جستجوصف پخش در حال پایان (بدون تکرار) را با افزودن یک جریان مرتبط ادامه دهید
- برای پیشگیری از بار کردن بندانگشتیها و ذخیرهٔ داده و فضای ذخیره، خاموش کنید. تغییرات، انبارهٔ تصاویر روی حافظه و دیسک را پاک میکندادامه پخشبازگرداندن آخرین موقعیت پخشموقعیت در فهرستها
diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml
index 641e55b21..397f2fef0 100644
--- a/app/src/main/res/values-fi/strings.xml
+++ b/app/src/main/res/values-fi/strings.xml
@@ -196,8 +196,6 @@
Lisää soittolistaanKäytä nopeampaa epätarkkaa pikakelaustaEpätarkka kelaus mahdollistaa videon kelauksen nopeammin huonommalla tarkkuudella. Kelaaminen 5, 15 tai 25 sekunnin hyppäyksin ei toimi tämän kanssa
- Lataa esikatselukuvat
- Poista käytöstä estääksesi esikatselukuvien lataus. Tämä säästää dataa ja vähentää muistin käyttöä. Asetuksen muuttaminen poistaa muistissa ja levyllä olevan kuvavälimuistinKuvavälimuisti tyhjennettyPoista tallennettu metatietoPoista kaikki tallennettu sivutieto
diff --git a/app/src/main/res/values-fil/strings.xml b/app/src/main/res/values-fil/strings.xml
index 4cafaff85..0fb7a0a1d 100644
--- a/app/src/main/res/values-fil/strings.xml
+++ b/app/src/main/res/values-fil/strings.xml
@@ -48,7 +48,6 @@
Pangalawang action buttonPangatlong action buttonPinapayagan ng di-saktong seek ang player na mag-seek sa mga posisyon nang mabilis ngunit na may pinababang kasaktuhan. Di ito gagana sa pag-seek nang 5, 15, o 25 segundo.
- Patayin para mapigilan ang pag-load sa mga thumbnail, para makatipid ng data at paggamit sa memory. Lilinisin ang parehong image cache na nasa memory at nasa diskPiliin ang mga mungkahing ipapakita habang naghahanapPatayin para itago ang paglalarawan ng video at karagdagang impormasyonI-edit ang bawat action sa abiso sa baba sa pamamagitan ng pagpindot sa mga ito. Pumili ng hanggang tatlong ipapakita sa siksik na abiso gamit ang mga checkbox sa kanan
@@ -70,7 +69,6 @@
Kumpirmahin muna bago linisin ang pilaMaaaring mapalitan ang pila mo kung magpapalit ka ng playerPapalitan ang aktibong pila sa player
- I-load ang mga thumbnailIpakita ang paglalarawanIpakita ang meta infoPatayin para itago ang mga meta infobox na may karagdagang impormasyon tungkol sa creator ng stream, laman nito o ng hinanap
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index b899ec7f8..51f258166 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -244,8 +244,6 @@
ZoomerUtiliser la recherche rapide approximativePermet au lecteur d’accéder plus rapidement à une position au détriment de la précision. Se déplacer de 5, 15 ou 25 secondes est impossible avec cette option
- Charger les miniatures
- Désactivez pour empêcher le chargement des miniatures afin de réduire l’utilisation de la bande passante et de la mémoire. La modification de cette option vide le cache en mémoire vive et sur le disqueImages en cache effacéesEffacer les métadonnées en cacheEfface toutes les données des pages Web en cache
diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml
index 98d3d472b..8b5aaa497 100644
--- a/app/src/main/res/values-gl/strings.xml
+++ b/app/src/main/res/values-gl/strings.xml
@@ -55,8 +55,6 @@
Lembrar o tamaño e a posición anteriores do «popup»Usar un salto inexacto mais inexactoA busca inexacta permite ao reprodutor procurar posicións máis rápidas con precisión reducida. A busca de 5, 15 ou 25 segundos non funciona con isto
- Carregar miniaturas
- Desactíveo para evitar a carga de miniaturas e poupar datos e memoria. Modificar esta opción limpa a caché de imaxes da memoria e do discoA caché de imaxes foi limpadaOs metadatos da caché foron eliminadosEliminar todos os datos de páxinas en caché
diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml
index 5c55d0bad..4dec4c819 100644
--- a/app/src/main/res/values-he/strings.xml
+++ b/app/src/main/res/values-he/strings.xml
@@ -268,8 +268,6 @@
קצבשימוש בחיפוש מהיר ולא מדויקחיפוש גס מאפשר לנגן לחפש נקודת זמן מהר יותר, ברמת דיוק נמוכה יותר. חיפוש של 5, 15 או 25 שניות לא עובד עם ההגדרה הזאת
- טעינת תמונות ממוזערות
- כיבוי האפשרות מונע את טעינת התמונות הממוזערות, חוסך בתקשורת נתונים ובניצולת הזיכרון. שינויים באפשרות זו מוחקים את המטמון בזיכרון ובכונןהסרת כל נתוני העמודים שבמטמוןהוספת התזרים הבא לרשימת הנגינה אוטומטיתלהמשיך תור נגינה סופית (בלתי מחזורית) על ידי הוספת תזרים קשור
diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml
index a2bbaf672..80ab6209c 100644
--- a/app/src/main/res/values-hi/strings.xml
+++ b/app/src/main/res/values-hi/strings.xml
@@ -245,10 +245,8 @@
ऑटो-जनरेटेडहीप डंप करने के दौरान मेमोरी लीक मॉनिटरिंग ऐप को अनुत्तरदायी बना सकता हैOut-of-Lifecycle त्रुटियों की रिपोर्ट करें
- थंमनेल लोड करेंतेज और अनिश्चित तलाश का प्रयोग करेंअनिश्चित खोज से प्लेयर में कम सटीकता से लेकिन तेजी से वीडियो पोजीशन्स की तलाश कर सकता हैं। 5, 15 या 25 सेकंड की तलाश में यह काम नहीं करता
- डेटा खपत, मेमोरी उपयोग की बचत और थंमनेल लोड होने से रोकने के लिए बंद करें। इस बदलाव से इन-मेमोरी और ऑन-डिस्क छवि कैश दोनों मिट जाते हैंचित्र कैश मिटाया गयाकैश मेटाडेटा मिटाएंकैश किए गए सभी वेबपेज का डेटा हटाएं
diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml
index 80b734fcd..c625955f7 100644
--- a/app/src/main/res/values-hr/strings.xml
+++ b/app/src/main/res/values-hr/strings.xml
@@ -218,7 +218,6 @@
Prikaži informacijeZabilježene playlisteDodaj u
- Učitaj sličiceSlikovna predmemorija obrisanaIzbriši metapodatke iz predmemorijeKanali
@@ -312,7 +311,6 @@
Dostupna je nova verzija za NewPipe!Preuzimanje nije uspjeloPrikaži pogrešku
- Isključi za sprečavanje učitavanja sličica, čime se štedi korištenje podataka i memorije. Promjene čiste predmemoriju slika radne memorije i diskaIzbriši sve podatke web-stranica iz predmemorijeMetapodaci su izbrisaniAutomatski dodaj sljedeći stream u popisa izvođenja
diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml
index 9f3ddf9cf..26f4ee3cf 100644
--- a/app/src/main/res/values-hu/strings.xml
+++ b/app/src/main/res/values-hu/strings.xml
@@ -136,8 +136,6 @@
Hozzáadás ehhezGyorsabb, de pontatlan tekerés használataA pontatlan tekerés lehetővé teszi, hogy gyorsabban ugorjon a pozíciókra, de kisebb pontossággal. Az 5, 15, vagy 25 másodperces tekerés nem működik ebben a módban
- Bélyegképek betöltése
- Kapcsolja ki, hogy a megelőzze a bélyegképek betöltését, így csökkentve az adat- és memóriahasználatot. A megváltoztatása törli a memóriában és a meghajtón lévő képgyorsítótáratA bélyegkép gyorsítótár törölveGyorsítótárazott metaadatok törléseMinden gyorsítótárazott weboldaladat törlése
diff --git a/app/src/main/res/values-ia/strings.xml b/app/src/main/res/values-ia/strings.xml
index d4ae5b455..512598eaa 100644
--- a/app/src/main/res/values-ia/strings.xml
+++ b/app/src/main/res/values-ia/strings.xml
@@ -227,7 +227,6 @@
InterneAperir conSuggestiones de recerca remote
- Cargar miniaturasMonstrante resultatos pro: %sSolmente alicun apparatos pote reproducer videos 2K/4KInitiar le reproductor principal in schermo plen
diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml
index 292430861..b68b36a47 100644
--- a/app/src/main/res/values-in/strings.xml
+++ b/app/src/main/res/values-in/strings.xml
@@ -132,8 +132,6 @@
Notifikasi NewPipeRiwayatRiwayat
- Muat thumbnail
- Matikan agar thumbnail tidak dimuat, menghemat penggunaan data dan memori. Perubahan menghapus cache gambar baik di memori dan diskCache gambar dihapusHapus cache metadataHapus semua data cache halaman web
diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml
index e27217971..98f73e294 100644
--- a/app/src/main/res/values-is/strings.xml
+++ b/app/src/main/res/values-is/strings.xml
@@ -177,7 +177,6 @@
Nota hraða en ónákvæma leitLengd skrefsBiðja um staðfestingu áður en röð er hreinsuð
- Sækja smámyndirSýna ummæliSjálfvirk biðröðHreinsa gögn
@@ -613,7 +612,6 @@
Stærð forhleðsluBreyta stærð forhleðslu (nú %s). Lægra gildi gæti flýtt fyrir upphaflegu hleðslu myndbands. Breytingar krefjast endurræsingar spilaraBiðröð spilarans verður skipt út
- Slökktu á til að hlaða ekki niður smámyndum til að spara bandbreidd og vinnsluminni. Breytingar eyða myndskyndiminni í bæði vinnsluminni og geymsluSlökktu á til að fela lýsigagnareiti með viðbótarupplýsingum um straumhöfund, straumefni eða leitarbeiðniFjarlæga öll síðugögn úr skyndiminniBæta svipuðum straumum við biðröðina þegar síðasta er spilað og endurspilun er ekki virkjuð
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 05604e998..48cc84328 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -287,8 +287,6 @@
Tieni presente che questa operazione può consumare una grande quantità di traffico dati.
\n
\nVuoi continuare?
- Carica copertine
- Disabilita per prevenire il caricamento delle copertine, risparmiando dati e memoria. La modifica di questa opzione cancellerà la cache delle immagini in memoria e sul discoCache immagini svuotataSvuota la cache dei metadatiElimina i dati delle pagine web memorizzati nella cache
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
index 0eeeaf8dd..8fa73a002 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -196,7 +196,6 @@
動画をダウンロード情報を表示ブックマークしたプレイリスト
- サムネイルを読み込む画像キャッシュを消去しましたキャッシュを消去アプリ内のキャッシュデータをすべて削除します
@@ -254,7 +253,6 @@
プライバシーポリシーを確認おおまかなシークおおまかなシークを使用することで精度が下がる代わりに高速にシークができます。5 秒、15 秒または 25 秒間隔のシークはできません
- サムネイルの読み込みと保存を無効化します。(このオプションを切り替えるとメモリとディスク上の画像キャッシュが消去されます)キューに関連動画を追加して再生を続ける (繰り返ししない場合)すべての再生履歴を削除しますか?すべての検索履歴を削除しますか?
diff --git a/app/src/main/res/values-jv/strings.xml b/app/src/main/res/values-jv/strings.xml
index 2f68f9bc9..7f71a2f41 100644
--- a/app/src/main/res/values-jv/strings.xml
+++ b/app/src/main/res/values-jv/strings.xml
@@ -10,11 +10,9 @@
Antri otomatis stream bareSampah metadata wes dibusakBusak kabeh sampah ora kanggo
- Pateni ben gambar cilik ora ketok, ora boros data lan memori. Iku bakal ngresiki sampah gambar.Sampah gambar wes resikPateni gawe ngumpetke komentarDuduhke komentar
- Duduhke gambar cilikDurasi cepet maju/mundureEling-eling ukuran lan posisi ngambang terakhirEling-eling ukuran lan posisi ngambang
diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml
index 89c2193da..47e105183 100644
--- a/app/src/main/res/values-ka/strings.xml
+++ b/app/src/main/res/values-ka/strings.xml
@@ -42,7 +42,6 @@
არაზუსტი ძიება საშუალებას აძლევს მოთამაშეს უფრო სწრაფად მოიძიოს პოზიციები შემცირებული სიზუსტით. 5, 15 ან 25 წამის ძიება ამით არ მუშაობსსწრაფი წინსვლა/-გადახვევა ძიების ხანგრძლივობაერთი მოთამაშიდან მეორეზე გადართვამ შესაძლოა შეცვალოს თქვენი რიგი
- გამორთეთ ესკიზების ჩატვირთვის თავიდან ასაცილებლად, მონაცემთა დაზოგვისა და მეხსიერების გამოყენების თავიდან ასაცილებლად. იცვლება როგორც მეხსიერებაში, ასევე დისკზე გამოსახულების ქეშის გასუფთავებაძიების შეთავაზებებიწაშალეთ ყველა ქეშირებული ვებგვერდის მონაცემებიშემდეგი ნაკადის ავტომატური შეყვანა
@@ -107,7 +106,6 @@
შავიდამახსოვრება ამომხტარი ფანჯრის თვისებებიაქტიური მოთამაშის რიგი შეიცვლება
- ჩატვირთეთ ესკიზებიკომენტარების ჩვენებაგამორთეთ კომენტარების დასამალად\"შემდეგი\" და \"მსგავსი\" ვიდეოების ჩვენება
diff --git a/app/src/main/res/values-kmr/strings.xml b/app/src/main/res/values-kmr/strings.xml
index 41f2742ab..b7478aa58 100644
--- a/app/src/main/res/values-kmr/strings.xml
+++ b/app/src/main/res/values-kmr/strings.xml
@@ -242,8 +242,6 @@
Vîdyoyên \'Pêş\' û \'Bi vî rengî\' nîşan bidinZivirandin da ku şîroveyan veşêrinŞîroveyan nîşan bide
- Ji bo pêşîgirtina li barkirina nîgarkêşan, daneya daneyê û karanîna bîranînê xilas bibe vemirînin. Guherandinên kaşeya wêneyê hem di bîra û hem jî li ser dîskê paqij dikin.
- Nîgarên barkêşDê rêza lîstikvanê çalak were guhertinGuhertina ji lîstikvanek bi yeke din dibe ku dewsa dorê we bigireBerî paqijkirina dorê ji pejirandinê bipirsin
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index 127db9bcb..30c381bcf 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -278,8 +278,6 @@
경고: 데이터가 많이 소모될 수 있습니다.
\n
\n계속하시겠습니까\?
- 썸네일 로드하기
- 동영상 썸네일을 로드하지 않으며, 데이터와 메모리 사용을 최대한 줄입니다. 이 옵션을 선택 시 모든 메모리 캐시와 저장소 캐시를 삭제합니다이미지 캐시 지워짐캐시된 메타데이터 지우기캐시된 모든 웹페이지 데이터 지우기
diff --git a/app/src/main/res/values-ku/strings.xml b/app/src/main/res/values-ku/strings.xml
index 8d1ffbab8..fc7e85616 100644
--- a/app/src/main/res/values-ku/strings.xml
+++ b/app/src/main/res/values-ku/strings.xml
@@ -53,9 +53,6 @@
ڕهشبیرهاتنهوهی شوێن و قهبارهی پهنجهرهبیرهاتنهوهی كۆتا قهباره و شوێنی پهنجهرهی بچووك
- باركردنی وێنۆچكهكان
- ناچالاكی بكه بۆ ڕاگرتنی وێنۆچكهكان له باركردن و پاشهكهوتبوون لهسهر بیرگهی ئامێرهكهت.
-\nگۆڕینی ئهمه دهبێته هۆی سڕینهوهیان لهسهر بیرگهی مۆبایلهكهت.پاشماوهی وێنۆچكهكان سڕایهوهبەکارهێنانی گەڕانی ناوردی خێراخاوێنکردنەوەی پاشماوەی داتا
diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml
index 1c8ba59ae..58b25709b 100644
--- a/app/src/main/res/values-lt/strings.xml
+++ b/app/src/main/res/values-lt/strings.xml
@@ -374,8 +374,6 @@
Atstatyti paskutinį atkūrimo laikąTęsti atkūrimąRodyti aprašymą
- Norėdami taupyti duomenų srautą, atminties naudojimą išjunkite. Pakeitimai išvalys duomenis atmintyje ir diske
- Įkelti miniatiūrasAktyvaus grotuvo eilė bus pakeistaPerjungimas iš vieno grotuvo į kitą gali pakeisti jūsų eilęPrieš išvalant eilę prašyti patvirtinimo
diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml
index c8d3221eb..a613dd70a 100644
--- a/app/src/main/res/values-lv/strings.xml
+++ b/app/src/main/res/values-lv/strings.xml
@@ -517,8 +517,6 @@
Rādīt \'Nākošos\' un \'Līdzīgos\' videoklipusIzslēdziet, lai paslēptu komentārusRādīt komentārus
- Izslēdziet, ja vēlaties nelādēt video attēlus, ietaupot datus un atmiņu. Opcija notīra kešatmiņu, izdzēšot visus saglabātos video attēlus
- Ielādēt video attēlusTagadējā atskaņošanas rinda tiks aizvietotaMainoties vienam video uz citu, iespējams, notīrīsies jūsu atskaņošanas rindaPrasīt apstiprinājumu, pirms notīrīt atskaņošanas rindu
diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml
index 524c82aef..e39172c72 100644
--- a/app/src/main/res/values-mk/strings.xml
+++ b/app/src/main/res/values-mk/strings.xml
@@ -55,8 +55,6 @@
Запамти ја последната големина и место на прозорчетоБрзо, непрецизно премотувањеСо непрецизното премотување се пребарува побрзо, но со намалена презицност.
- Прочитај мали видео-сликички
- Оневозможете, за да не се читаат малите видео-сликички за штедење на меморија и интернет. Промената на оваа опцијата ќе ја избрише кеш-меморијата.Кешираните слики се избришаниИзбришете ги кешираните мета-податоциИзбришете ги сите кеш-податоци од веб-страни
diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml
index 29769acae..d03ae0a38 100644
--- a/app/src/main/res/values-ml/strings.xml
+++ b/app/src/main/res/values-ml/strings.xml
@@ -331,10 +331,8 @@
കാഷെ ആയ ഡേറ്റ നീക്കംചെയ്യുകകാഷെ ആയ മെറ്റാഡേറ്റ തുടച്ചുനീക്കിഇമേജ് കാചെ തുടച്ചുമാറ്റി
- ലഘുചിങ്ങൾ ലോഡ് ചെയ്യാതിരിക്കാനും ഡേറ്റയും മെമ്മറിയും ലാഭിക്കാനുമായി ഓഫ്ചെയ്യുക. എസ് ഡീ കാർഡിലെയും മെമ്മറിയിലെയും കാച്ചേ ക്ലിയർ ചെയ്യുംകമന്റുകൾ മറയ്ക്കാനായി ഓഫ് ചെയ്യുകകമന്റുകൾ കാണിക്കുക
- ലഘുചിത്രങ്ങൾ ലോഡ് ചെയ്യുകഫാസ്റ്റ്-ഫോർവേർഡ്/റീവൈൻഡ് സമയദൈർഘ്യംInexact seek ഉപയോഗിക്കുകകുറഞ്ഞ കൃത്യതയോടെ സീക് ചെയ്യാൻ ഇൻ എക്സക്ട് സഹായിക്കുന്നു. 5,15,25 സെക്കൻഡ് സീക് ഈ മോഡിൽ പ്രവർത്തിക്കുകയില്ല
diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml
index 648849205..d9e4f12ef 100644
--- a/app/src/main/res/values-ms/strings.xml
+++ b/app/src/main/res/values-ms/strings.xml
@@ -57,8 +57,6 @@
Mengingat saiz dan posisi popup terakhirGunakan tinjau laju tidak tepatMembolehkan pemain untuk meninjau ke posisi lebih laju dengan kurang ketepatan. Mencari 5, 15 atau 25 saat tidak berfungsi dengan ini
- Muatkan thumbnail
- Matikan untuk mengelakkan pemuatan thumbnail, menjimat penggunaan data dan ingatan. Perubahan akan menghapus cache imej dari ingatan dan diskCache imej dihapuskanHapuskan cache metadataHapuskan semua cache data halaman web
diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml
index da6193e90..1637fe1f7 100644
--- a/app/src/main/res/values-nb-rNO/strings.xml
+++ b/app/src/main/res/values-nb-rNO/strings.xml
@@ -257,7 +257,6 @@
Eksporterer…Importer filForrige eksport
- Last miniatyrbilderBildehurtiglager tømtTøm hurtiglagret metadataFjern all hurtiglagret nettsidedata
@@ -304,7 +303,6 @@
\n3. Logg inn når forespurt
\n4. Kopier profil-nettadressen du ble videresendt til.Unøyaktig spoling lar spilleren søke posisjoner raskere med redusert presisjon. Å søke i 5, 15 eller 25 sekunder fungerer ikke med dette
- Skru av for å stoppe innlasting av miniatyrbilder, noe som sparer data- og minnebruk. Endring av dette vil tømme både disk- og minne-hurtiglagerFortsett fullendt (ikke-repeterende) avspillingskø ved å legge til en relatert strømOvervåkning av minnelekkasjer kan forårsake at appen ikke svarer under heap dumpingRapporter feil utenfor livssyklusen
diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml
index 05c82808e..d1d0d15b0 100644
--- a/app/src/main/res/values-ne/strings.xml
+++ b/app/src/main/res/values-ne/strings.xml
@@ -56,10 +56,8 @@
पछिल्लो आकार र पपअप को स्थिति सम्झनातेज \'inexact\' खोज्न प्रयोग गर्नुहोस\'Inexact\' प्लेयर कम सटीक छिटो स्थितिहरू गर्न खोज्न अनुमति दिन्छ खोज्छन्। 5, 15 वा 25 सेकेन्ड को लागि खोजी यो काम गर्दैन।
- थम्बनेल लोडटिप्पणीहरू देखाऊटिप्पणीहरू लुकाउन, बन्द गर्नुहोस
- डाटा र स्मृति उपयोग सुरक्षित गर्न, थम्बनेलहरू लोड रोक्न, बन्द गर्नुहोस। परिवर्तनहरू दुवै मा-स्मृति र-डिस्क छवि क्यास खाली गर्छ।छवि क्यास सखापक्यास मेटाडाटा हटाउसबै क्यास वेबपेज डाटा हटाउ
diff --git a/app/src/main/res/values-nl-rBE/strings.xml b/app/src/main/res/values-nl-rBE/strings.xml
index bf77f9da3..0d582f6de 100644
--- a/app/src/main/res/values-nl-rBE/strings.xml
+++ b/app/src/main/res/values-nl-rBE/strings.xml
@@ -55,8 +55,6 @@
Onthoud laatste grootte en positie van pop-upSnel, minder exact spoelen gebruikenMinder exact spoelen laat de speler sneller posities zoeken met verminderde precisie. 5, 15 en 25 seconden werken niet
- Miniatuurvoorbeelden laden
- Schakel dit uit voor het laden van miniatuurvoorbeelden te verhinderen; dit bespaart mobiele gegevens en geheugen. Het wijzigen van deze instelling wist het geheugen en de afbeeldingscacheAfbeeldingscache gewistGecachete metagegevens wissenAlle gecachete webpagina-gegevens wissen
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index b6622c210..e5b7f0f82 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -284,8 +284,6 @@
Let op: deze actie kan veel MB’s van je mobiele netwerk gebruiken.
\n
\nWil je doorgaan?
- Miniatuurvoorbeelden laden
- Schakel dit uit om het laden van miniatuurvoorbeelden te verhinderen; dit bespaart mobiele data en geheugen. Het wijzigen van deze instelling wist het geheugen en de afbeeldingscacheAfbeeldingscache gewistGecachete metagegevens wissenAlle gecachete webpagina-gegevens wissen
diff --git a/app/src/main/res/values-oc/strings.xml b/app/src/main/res/values-oc/strings.xml
index d440d8a89..6341e6700 100644
--- a/app/src/main/res/values-oc/strings.xml
+++ b/app/src/main/res/values-oc/strings.xml
@@ -58,7 +58,6 @@
Utilzar la recèrca rapida inexactaLa recèrca inexacta permet a l\'utilizaire de recercar mai rapidament una posicion amb mens de precisionDurada d\'avançada/reculada rapida
- Cargar las miniaturasAfichar los comentarisDesactivar per afichar pas mai los comentarisApondre la vidèo seguenta dins la coa de lectura
diff --git a/app/src/main/res/values-or/strings.xml b/app/src/main/res/values-or/strings.xml
index 084f21ca2..519a0f199 100644
--- a/app/src/main/res/values-or/strings.xml
+++ b/app/src/main/res/values-or/strings.xml
@@ -101,7 +101,6 @@
ଏକ ଧାଡି ସଫା କରିବା ପୂର୍ବରୁ ନିଶ୍ଚିତକରଣ ମାଗନ୍ତୁଗୋଟିଏ ଖେଳାଳୀରୁ ଅନ୍ୟ ଖେଳାଳୀକୁ ପରିବର୍ତ୍ତନ କରିବା ଆପଣଙ୍କ ଧାଡି ବଦଳାଇପାରେସକ୍ରିୟ ପ୍ଲେୟାର କ୍ୟୁ ବଦଳାଯିବ
- ଥମ୍ୱନେଲ୍ ଲୋଡ୍ କରନ୍ତୁ\'ପରବର୍ତ୍ତୀ\' ଏବଂ \'ସମାନ\' ଭିଡିଓଗୁଡିକ ଦେଖାନ୍ତୁବର୍ଣ୍ଣନା ଦେଖାନ୍ତୁପ୍ରତିଛବି କ୍ୟାଚ୍ ପୋଛି ଦିଆଗଲା
@@ -149,7 +148,6 @@
ଵିଡ଼ିଓ ଓ ଅଡ଼ିଓମିନି ପ୍ଲେୟାରରେ ଭିଡିଓ ଆରମ୍ଭ କରନ୍ତୁ ନାହିଁ, କିନ୍ତୁ ଅଟୋ ଘୂର୍ଣ୍ଣନ ବନ୍ଦ ହୋଇଗଲେ ସିଧାସଳଖ ଫୁଲ୍ ସ୍କ୍ରିନ୍ ମୋଡ୍ କୁ ଯାଆନ୍ତୁ। ଫୁଲ୍ ସ୍କ୍ରିନ୍ ଛାଡି ଆପଣ ଏପର୍ଯ୍ୟନ୍ତ ମିନି ପ୍ଲେୟାରକୁ ପ୍ରବେଶ କରିପାରିବେଏହା ଉପରେ ଟ୍ୟାପ୍ କରି ନିମ୍ନରେ ପ୍ରତ୍ୟେକ ବିଜ୍ଞପ୍ତି କାର୍ଯ୍ୟ ସଂପାଦନ କରନ୍ତୁ। ଡାହାଣରେ ଥିବା ଚେକ୍ ବକ୍ସ ବ୍ୟବହାର କରି କମ୍ପାକ୍ଟ ବିଜ୍ଞପ୍ତିରେ ଦେଖାଯିବାକୁ ସେମାନଙ୍କ ମଧ୍ୟରୁ ତିନୋଟି ପର୍ଯ୍ୟନ୍ତ ଚୟନ କରନ୍ତୁ
- ଥମ୍ବନେଲ ଲୋଡିଂ, ଡାଟା ଏବଂ ମେମୋରୀ ବ୍ୟବହାରକୁ ରୋକିବା ପାଇଁ ବନ୍ଦ କରନ୍ତୁ । ପରିବର୍ତ୍ତନଗୁଡ଼ିକ ଉଭୟ ଇନ-ମେମୋରୀ ଏବଂ ଅନ୍-ଡିସ୍କ ଇମେଜ୍ କ୍ୟାଚ୍ ସଫା କରେଷ୍ଟ୍ରିମ୍ ସୃଷ୍ଟିକର୍ତ୍ତା, ଷ୍ଟ୍ରିମ୍ ବିଷୟବସ୍ତୁ କିମ୍ବା ଏକ ସନ୍ଧାନ ଅନୁରୋଧ ବିଷୟରେ ଅତିରିକ୍ତ ସୂଚନା ସହିତ ମେଟା ସୂଚନା ବାକ୍ସଗୁଡ଼ିକୁ ଲୁଚାଇବାକୁ ବନ୍ଦ କରନ୍ତୁପିଲାମାନଙ୍କ ପାଇଁ ସମ୍ଭବତ content ଅନୁପଯୁକ୍ତ ବିଷୟବସ୍ତୁ ଦେଖାନ୍ତୁ କାରଣ ଏହାର ବୟସ ସୀମା ଅଛି (ଯେପରିକି 18+)ଏହି ଭିଡିଓ ବୟସ-ସୀମିତ ଅଟେ ।
diff --git a/app/src/main/res/values-pa-rPK/strings.xml b/app/src/main/res/values-pa-rPK/strings.xml
index 534ac790f..0233bbc8b 100644
--- a/app/src/main/res/values-pa-rPK/strings.xml
+++ b/app/src/main/res/values-pa-rPK/strings.xml
@@ -38,7 +38,6 @@
گوڑیاگے لنگھاؤݨ یا پچھے کرن دی سماں معدسرگرم پکیئر کتار جاوےگا
- تھمنیل لوڈ کروکتار نوں خالی کرن توں پہلاں تصویر کرن لئی پچھوٹپݨیاں وکھاؤݨا روکݨ لئی ایسنوں بند کروٹپݨیاں دِکھاؤ
diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml
index a10ddd125..253a87740 100644
--- a/app/src/main/res/values-pa/strings.xml
+++ b/app/src/main/res/values-pa/strings.xml
@@ -55,8 +55,6 @@
ਪੌਪ-ਅਪ ਦਾ ਆਖਰੀ ਅਕਾਰ ਅਤੇ ਸਥਿਤੀ ਯਾਦ ਰੱਖੋਤੇਜ਼ ਪਰ ਅਸਪੱਸ਼ਟ ਸੀਕ ਵਰਤੋਅਸਪੱਸ਼ਟ ਸੀਕ ਵੀਡੀਓ ਨੂੰ ਤੇਜ਼ ਪਰ ਅਣ-ਸਟੀਕ ਢੰਗ ਨਾਲ ਅੱਗੇ-ਪਿੱਛੇ ਲਿਜਾਂਦਾ ਹੈ । ਇਸ ਨਾਲ ਅੱਗੇ-ਪਿੱਛੇ 5,15 ਜਾਂ 25 ਸਕਿੰਟ ਜਾਣਾ ਕੰਮ ਨਹੀਂ ਕਰੇਗਾ
- ਥੰਮਨੇਲ ਲੋਡ ਕਰੋ
- ਡਾਟਾ ਤੇ ਮੈਮੋਰੀ ਖਪਤ ਦੀ ਬੱਚਤ ਅਤੇ ਥੰਮਨੇਲ ਲੋਡ ਹੋਣ ਤੋਂ ਰੋਕਣ ਲਈ ਬੰਦ ਕਰੋ। ਇਸ ਵਿਚ ਤਬਦੀਲੀ ਕਰਨ ਨਾਲ ਇਨ-ਮੈਮੋਰੀ ਅਤੇ ਆਨ-ਡਿਸਕ ਚਿੱਤਰ ਕੈਸ਼ੇ ਦੋਵੇਂ ਮਿਟ ਜਾਣਗੇਚਿੱਤਰ cache ਮਿਟਾ ਦਿੱਤੀ ਗਈ ਹੈਕੈਸ਼ ਕੀਤਾ ਮੈਟਾ-ਡਾਟਾ ਮਿਟਾਓਸਾਰੇ ਕੈਸ਼ ਕੀਤੇ ਵੈੱਬ-ਪੇਜਾਂ ਦਾ ਡਾਟਾ ਮਿਟਾਓ
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 613433f5e..b250901ff 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -254,8 +254,6 @@
Wymuś raportowanie niedostarczonych wyjątków Rx poza cyklem życia fragmentu lub aktywności po usunięciuUżywaj szybkiego, niedokładnego przewijaniaNiedokładne przewijanie umożliwia szybsze przewijanie ze zmniejszoną dokładnością. Przewijanie o 5, 15 lub 25 sekund nie działa w tym przypadku
- Wczytuj miniatury
- Wyłącz, aby nie wczytywać miniatur, oszczędzając dane i zużycie pamięci. Zmiana tej opcji czyści pamięć podręczną obrazówWyczyszczono pamięć podręczną miniaturWyczyść pamięć podręczną metadanychUsuwa całą pamięć podręczną stron
diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml
index 831adfe9e..c344fa826 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -284,14 +284,12 @@
Tenha em mente que esta operação poderá consumir muitos dados.
\n
\nVocê deseja continuar\?
- Carregar miniaturasCache de imagens limpoLimpar cache de metadadosRemove todos os dados de páginas em cacheCache de metadados limpoControles de velocidade de reproduçãoVelocidade
- Desative para não carregar miniaturas e economizar no uso de dados e memória. A alteração limpa todo o cache de imagens em memória e em discoAfinaçãoDesvincular (pode causar distorção)Ação de \'abrir\' preferida
diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml
index 24a8185db..dc3c8e48c 100644
--- a/app/src/main/res/values-pt-rPT/strings.xml
+++ b/app/src/main/res/values-pt-rPT/strings.xml
@@ -137,7 +137,6 @@
Mostrar resoluções mais altasSem subscritoresUtilizar reprodutor de áudio externo
- Desative para parar o carregamento de miniaturas, poupar dados e utilização da memória. As alterações limpam a cache de imagens do disco e da memóriaSerá que queria dizer \"%1$s\"\?Mostrar uma notificação para pedir a atualização da aplicação se existir uma nova versãoEnfileirar
@@ -442,7 +441,6 @@
Formato padrão de áudioO ficheiro não existe ou não tem permissões para ler e/ou escreverO nome do grupo está vazio
- Carregar miniaturasPartilhar comTempo após a última atualização antes de a subscrição ser considerada desatualizada - %sPesquisar
diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml
index 87b475a8b..c3c981fad 100644
--- a/app/src/main/res/values-pt/strings.xml
+++ b/app/src/main/res/values-pt/strings.xml
@@ -204,8 +204,6 @@
Adicionar aUtilizar pesquisa rápidaEste tipo de pesquisa e mais rápida mas reduz a precisão. Procurar por 5, 15 ou 25 segundos não funciona corretamente
- Carregar miniaturas
- Desative para parar o carregamento de miniaturas, poupar dados e utilização da memória. As alterações limpam a cache de imagens do disco e da memóriaCache de imagens limpaPaís padrão para conteúdoDepuração
diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml
index ad379c5ca..0a6920b6b 100644
--- a/app/src/main/res/values-ro/strings.xml
+++ b/app/src/main/res/values-ro/strings.xml
@@ -181,8 +181,6 @@
Salvare înFolosește parcurgerea rapidă inexactăDerularea inexactă permite player-ului să deruleze mai rapid, cu o precizie redusă. Derularea timp de 5, 15 sau 25 de secunde nu funcționează cu aceasta
- Încarcă miniaturi
- Dezactivați pentru a preveni încărcarea miniaturilor, economisirea datelor și utilizarea memoriei. Modificările șterg atât memoria cache a imaginilor în memorie, cât și pe discDatele cache de imagini au fost șterseȘterge cache-ul pentru metadataȘterge cache-ul pentru datele de pagini web
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index f033b6cf6..4b03f15c7 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -298,8 +298,6 @@
Это действие может вызвать большой расход трафика.
\n
\nПродолжить?
- Загружать миниатюры
- Отключите, чтобы не загружать миниатюры и сэкономить трафик и память. Изменение настройки очистит кэш изображенийКэш изображений очищенОчистить кэш метаданныхКэш метаданных очищен
diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml
index 2f44a8664..7846eb274 100644
--- a/app/src/main/res/values-sc/strings.xml
+++ b/app/src/main/res/values-sc/strings.xml
@@ -473,10 +473,8 @@
Boga totu sos datos de sa pàgina web in sa memòria temporàneaIscantzella sos metadatos in sa memòria temporàneaMemòria temporànea de sas immàgines isboidada
- Istuda pro prevènnere su carrigamentu de sas miniaduras, su sarvamentu de sos datos e s\'impreu de sa memòria. Sas modìficas ant a isbodiare siat sa memòria temporànea de sa memòria siat cussa de su discuIstuda pro cuare sos cummentosAmmustra sos cummentos
- Càrriga sas miniadurasLongària de s\'avantzamentu e de sa torrada in segus lestrosSu moimentu inesatu permitit a su riproduidore de si mòere cara a una positzione in manera prus lestra ma prus pagu pretzisa. Su de si mòere de 5, 15 o 25 segundos non funtzionat, cun custa optzioneImprea su moimentu inesatu lestru
diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml
index 6e218e16c..51f9eb490 100644
--- a/app/src/main/res/values-sk/strings.xml
+++ b/app/src/main/res/values-sk/strings.xml
@@ -246,8 +246,6 @@
ZväčšiťPoužívať rýchly posunRýchly posun umožňuje prejsť na novú pozíciu rýchlejšie, ale s menšou presnosťou. Posun o 5, 15 alebo 25 sekúnd v tomto prípade nie je možný
- Načítanie miniatúr
- Vypnutím tejto funkcie sa nebudú vytvárať miniatúry a tým sa ušetrí miesto a pamäť. Zmena nastavení spôsobuje vyčistenie vyrovnávacej pamäteVyrovnávacia pamäť obrázkov vymazanáVymazať metadáta uložené vo vyrovnávacej pamätiOdstrániť všetky údaje webových stránok vo vyrovnávacej pamäti
diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml
index 7e89a1ed5..be6027620 100644
--- a/app/src/main/res/values-sl/strings.xml
+++ b/app/src/main/res/values-sl/strings.xml
@@ -198,7 +198,6 @@
UstvariOpustiPreimenuj
- Naloži sličiceJezik aplikacijeUporabi SAFVprašaj kam shraniti
@@ -309,7 +308,6 @@
Predpomnjeni metapodatki so bili odstranjeniPrikaži meta informacijeOnemogoči da se ustavi prikazovanje komentarjev
- Izklopite, če želite preprečiti nalaganje sličic, s tem bo varčeval na podatkih in uporabi spomina. Spremembe bodo izbrisale predpomnilnik v spominu in na diskuDejavna vrsta bo zamenjanaPreklop na drugi predvajanik lahko zamenja vašo čakalno vrstoVprašaj za potrditev pred čiščenjem vrste
diff --git a/app/src/main/res/values-so/strings.xml b/app/src/main/res/values-so/strings.xml
index b2ec76d77..b3f4051c4 100644
--- a/app/src/main/res/values-so/strings.xml
+++ b/app/src/main/res/values-so/strings.xml
@@ -401,10 +401,8 @@
Tirtir waxyaabaha K/G ah ee boga website-kaTirtir faahfaahinada yaryarkaydkii kumeelgaadhka ahaa ee sawirka waa la tirtiray
- Xidh si aad u joojiso soo bandhiga galka muuqaalada, adigoo yaraynaya isticmalka khadka iyo maskaxda aalada. Wax ka baddalkan wuxuu nadiifin doonaa waxa kaydka hore iyo ka caadiga ah kumeelgaadh ahaan ugu jiraXidh si aad uqariso faallooyinkaTus faallooyinka
- Soodhig galalkaHormada daareha hadda wax shidaya waa la baddali doonaaKala baddalka daareha waxay badali kartaa hormada sidaas darteed waydii in la xaqiijiyo intaan hormada la tirtirinXaqiijinta tirtirka hormada
diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml
index 41d9f22ad..5bfe72573 100644
--- a/app/src/main/res/values-sq/strings.xml
+++ b/app/src/main/res/values-sq/strings.xml
@@ -18,7 +18,6 @@
Luaj me KodiAudioE zezë
- Ngarko pamjet miniaturëSugjerimet e kërkimitTë shikuaratRuaji videot e shikuara
@@ -487,7 +486,6 @@
Depoja e të dhënave meta u boshatisBoshatis depon e të gjitha të dhënave të faqeve të internetitBoshatis depon e të dhënave meta
- Fikeni për të ndaluar shfaqjen e pamjeve statike, duke kursyer internet dhe memorje. Ndryshimet boshatisin depon e imazheve në memorje dhe në diskDepoja e imazheve u boshatisFikeni për të fshehur komentetShfaq komentet
diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml
index 208b7f6e9..b31ee604b 100644
--- a/app/src/main/res/values-sr/strings.xml
+++ b/app/src/main/res/values-sr/strings.xml
@@ -201,8 +201,6 @@
Задржи за стављање у редКористи брзо, непрецизно премотавањеНепрецизно премотавање омогућава плејеру да брже долази до позиције уз смањену прецизност. Премотавање за 5, 15 или 25 секунди са овом опцијом не ради
- Учитај сличице
- Искључите да спречите преузимање сличица, смањујући утрошак преноса података и меморије. Изменом ће се очистити и меморијски и диск кешОчишћен кеш са сликамаУклони кеширане метаподаткеУклања све податке кешираних веб-страна
diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml
index 01b503d3f..02e472e4d 100644
--- a/app/src/main/res/values-sv/strings.xml
+++ b/app/src/main/res/values-sv/strings.xml
@@ -193,8 +193,6 @@
Bokmärkta SpellistorLägg till iAnvänd snabb icke-exakt sökning
- Läs in miniatyrbilder
- Stäng av för att förhindra att miniatyrbilder läses in, vilket sparar data- och minnesanvändning. Ändringarna rensar både bildcacheminnet i minnet och på diskenCacheminnet för bilder rensatDebugAlltid
diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml
index 0a4f30670..0383d7197 100644
--- a/app/src/main/res/values-ta/strings.xml
+++ b/app/src/main/res/values-ta/strings.xml
@@ -50,7 +50,6 @@
கருமைதிரைமேல் பண்புகளை நினைவுகொள்திரைமேல் நிலையின் கடைசி அளவையும் இடத்தையும் நினைவுகொள்
- சிறுபடத்தைக் இறக்குபட பதுக்ககம் அழிக்கப்பட்டதுமேல்நிலைத்தரவின் பதுக்ககம் அழிக்கப்பட்டதுபதுக்ககப்படுத்திய வலைப்பக்கத் தரவை நீக்கு
@@ -264,7 +263,6 @@
ஆப.லஇயக்கியைச் சிதை
- சிறுபடங்களேற்றுவதை தவிர்த்து தரவு மற்றும் நினைவகப் பயன்பாட்டைச் சேமிக்க அணை. மாற்றங்கள் நினைவகத்துள் மற்றும் வட்டின்மீதுள்ள பிடிதரவைத் துடைக்கும்பட்டியல்களில் இயக்கக குறியட நிலைகாட்டிகளைக் காட்டுதுணையியக்கியில் காணொளிகளை துவக்காதே, ஆனால் தானாக சுழற்றல் பூட்டப்பட்டிருந்தால் நேரடியாக முழுதிரைக்குத் திரும்பு. முழுதிரையை வெளியேறி நீங்கள் இன்னும் துணையியக்கியை அணுகலாம்உரலியை அங்கீகரக்க முடியவில்லை. மற்றொரு செயலியில் திறக்கவா\?
diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml
index 2351be263..86f3e17c2 100644
--- a/app/src/main/res/values-te/strings.xml
+++ b/app/src/main/res/values-te/strings.xml
@@ -165,13 +165,11 @@
అధిక స్పష్టతను చూపుమునలుపుపాప్అప్ లక్షణాలను గుర్తుంచుకో
- సూక్ష్మచిత్రాలను లోడ్ చేయండివ్యాఖ్యలను చూపించువ్యాఖ్యలను దాచడాన్ని ఆఫ్ చేయండి%sలో మీకు నచ్చిన సందర్భాలను కనుగొనండిపీర్ట్యూబ్ ఉదాహరణలుమూడవ చర్య బటన్
- థంబ్నెయిల్లను లోడ్ చేయడం, డేటాను సేవ్ చేయడం మరియు మెమరీ వినియోగాన్ని నిరోధించడానికి ఆఫ్ చేయండి. మార్పులు ఇన్-మెమరీ మరియు ఆన్-డిస్క్ ఇమేజ్ కాష్ రెండింటినీ క్లియర్ చేస్తాయిఖచ్చితమైన శోధన తగ్గిన ఖచ్చితత్వంతో వేగంగా స్థానాలను పొందేందుకు ఆటగాడిని అనుమతిస్తుంది. 5, 15 లేదా 25 సెకన్ల పాటు కోరడం దీనితో పని చేయదువేగవంతమైన ఖచ్చితమైన శోధనను ఉపయోగించండిజోడించండి
diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml
index 2b31bb988..17f20c1e4 100644
--- a/app/src/main/res/values-th/strings.xml
+++ b/app/src/main/res/values-th/strings.xml
@@ -56,10 +56,8 @@
จำขนาดและตำแหน่งสุดท้ายของป๊อปอัพใช้การข้ามที่ไม่แม่นยำการข้ามช่วงที่ไม่แม่นยำจะทำให้เลื่อนไปยังตำแหน่งเวลาที่ต้องการได้เร็วขึ้น แต่จะลดความแม่นยำในการลากตำแหน่งลง
- โหลดภาพขนาดย่อแสดงความคิดเห็นปิดใช้งานเพื่อซ่อนความคิดเห็น
- ปิดเพื่อป้องกันการโหลดรูปขนาดย่อ ลดการใช้ข้อมูลและหน่วยความจำ การเปลี่ยนแปลงล้างแคชภาพในหน่วยความจำและบนดิสก์ล้างแคชของรูปภาพแล้วลบข้อมูลเว็บเพจที่แคชไว้ทั้งหมดคิววีดีโอถัดไปโดยอัตโนมัติ
diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml
index 2400a8bd5..28bc92347 100644
--- a/app/src/main/res/values-tr/strings.xml
+++ b/app/src/main/res/values-tr/strings.xml
@@ -280,8 +280,6 @@
Bu sürecin ağa yük olabileceğini unutmayın.
\n
\nSürdürmek istiyor musunuz\?
- Küçük resimleri yükle
- Küçük resimlerin yüklenmesini önleyerek veri ve hafıza kullanımından tasarruf etmek için kapatın. Değişiklikler, hem bellek içi hem de diskteki resim önbelleğini temizlerResim önbelleği silindiÖnbelleğe alınmış üstverileri temizleÖnbelleğe alınmış tüm web sayfası verilerini kaldır
diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml
index 25b3a43d2..0b024c861 100644
--- a/app/src/main/res/values-uk/strings.xml
+++ b/app/src/main/res/values-uk/strings.xml
@@ -292,8 +292,6 @@
Майте на увазі: ця операція може потребувати багато трафіку.
\n
\nБажаєте продовжити\?
- Завантажувати ескізи
- Вимкніть для запобігання завантаженню ескізів, що заощадить трафік і внутрішню пам\'ять. Зміни призведуть до очищення кешу зображеньКеш зображень стертоСтерти кеш метаданихВидалити всі кешовані дані вебсторінок
diff --git a/app/src/main/res/values-und/strings.xml b/app/src/main/res/values-und/strings.xml
index f22a117c5..94e4f9dd6 100644
--- a/app/src/main/res/values-und/strings.xml
+++ b/app/src/main/res/values-und/strings.xml
@@ -118,7 +118,6 @@
کتار نوں خالی کرن توں پہلاں تصویر کرن لئی پچھوپلیئر بدلݨ نال تہاڈی بدل سکدی اےسرگرم پکیئر کتار جاوےگا
- تھمنیل لوڈ کرووہروا دِکھاؤکھوج دا اتیتڈیٹا پٹاؤ
diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml
index c05fc095c..9632f5ff4 100644
--- a/app/src/main/res/values-ur/strings.xml
+++ b/app/src/main/res/values-ur/strings.xml
@@ -55,8 +55,6 @@
پچھلی جسامت اور پوپ اپ کا مقام یاد رکھیںبالواسطہ رسائی استعمال کریںبالواسطہ تلاش مشکلات کو کم کر کے پلیئر کو تیز رفتاری سے مقامات تک رسائی کرنے دیتی ہے۔ 5 ، 15 یا 25 سیکنڈ کی تلاش اس کے ساتھ کام نہیں کرتی ہے:
- نظرِ انگشتی لوڈ کریں
- ڈیٹا کی بچت اور میموری کے استعمال کو روکنے کیلئے تھمب نیل کو بند کریں۔ تبدیلیاں میموری اور آن ڈسک ایمیج کیشے کو صاف کریں گیتصویری کیشے کی صفائی ہوئیکیشے میٹا ڈیٹا کو صاف کریںویب پیج کے سبھی کیشے ڈیٹا کو ہٹا دیں
diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml
index 871fb9c12..9609943ca 100644
--- a/app/src/main/res/values-vi/strings.xml
+++ b/app/src/main/res/values-vi/strings.xml
@@ -133,8 +133,6 @@
Thêm vàoSử dụng tìm kiếm nhanh không chính xácTua không chính xác cho phép trình phát tua đến các vị trí nhanh hơn với độ chính xác bị giảm. Tua 5, 15 hay 25 giây không dùng được với chế độ này
- Tải hình thu nhỏ
- Tắt để ngăn chặn việc tải các hình thu nhỏ, việc này sẽ tiết kiệm lưu lượng mạng và bộ nhớ. Các thay đổi sẽ xóa bộ nhớ đệm hình ảnh cả trong RAM và trong bộ nhớĐã xóa bộ nhớ cache hình ảnhXóa siêu dữ liệu đã lưu vào bộ nhớ cacheXóa tất cả dữ liệu trang web được lưu trong bộ nhớ cache
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index 9a888c74d..d1d91dcd2 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -46,7 +46,6 @@
仅一次添加至文件
- 加载封面清空播放历史无最小化至后台播放
@@ -310,7 +309,6 @@
该操作消耗大量流量,
\n
\n你想继续吗?
- 关闭可禁止加载封面,节省流量和内存使用。切换该选项将立即清除内存与存储中的图片缓存清空图像缓存成功清空已缓存的元数据清空已缓存的网页数据
diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml
index b465d887d..91f2f3fc8 100644
--- a/app/src/main/res/values-zh-rHK/strings.xml
+++ b/app/src/main/res/values-zh-rHK/strings.xml
@@ -159,7 +159,6 @@
撳下面嘅掣去更改對應嘅通知動作。用右手邊嘅格仔剔選最多三個,擺喺精簡通知度精簡通知最多淨係擺到三個動作!循環播放
- 載入縮圖顯示留言關閉去隱藏留言搜尋紀錄
@@ -168,7 +167,6 @@
顯示描述抹除咗影像快取移除所有網頁嘅快取資料
- 關閉佢去避免載入條片嘅縮圖,慳返啲數據同埋用少啲 RAM。更改會抹走記憶體以及磁碟機上面嘅影像快取粗略嘅快轉允許播放器比較籠統咁快轉去其他位置。快轉 5、15 或 25 秒就太仔細,做唔到播放器預設嘅國家內容
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 8eb964406..225e4562f 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -278,8 +278,6 @@
\n2. 移至此網址: %1$s
\n3. 當被提示時登入帳號
\n4. 複製您被重新導向到的個人設定檔網址。
- 載入縮圖
- 關閉以防止載入縮圖,減少數據和儲存空間的用量。改變時將清除記憶體和磁碟上的縮圖快取已抹除圖片快取抹除已快取的中介資料移除所有已快取的網頁資料
diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml
index 51abe14fb..19188bb6c 100644
--- a/app/src/main/res/values/settings_keys.xml
+++ b/app/src/main/res/values/settings_keys.xml
@@ -396,8 +396,6 @@
clear_cookie
- download_thumbnail_key
-
cache_wipe_keyclear_play_historyclear_playback_states
@@ -1433,4 +1431,24 @@
media_tunneling_device_blacklist_versionuse_exoplayer_decoder_fallback_keyalways_use_exoplayer_set_output_surface_workaround_key
+
+
+ image_quality_key
+ image_quality_none
+ image_quality_low
+ image_quality_medium
+ image_quality_high
+ @string/image_quality_medium_key
+
+ @string/image_quality_none
+ @string/image_quality_low
+ @string/image_quality_medium
+ @string/image_quality_high
+
+
+ @string/image_quality_none_key
+ @string/image_quality_low_key
+ @string/image_quality_medium_key
+ @string/image_quality_high_key
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e5bbffaff..705a84aab 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -85,8 +85,6 @@
The active player queue will be replacedIgnore hardware media button eventsUseful, for instance, if you are using a headset with broken physical buttons
- Load thumbnails
- Turn off to prevent loading thumbnails, saving data and memory usage. Changes clear both in-memory and on-disk image cacheShow commentsTurn off to hide commentsShow \'Next\' and \'Similar\' videos
@@ -822,4 +820,10 @@
DurationRewindForward
+ Image quality
+ Choose the quality of images and whether to load images at all, to reduce data and memory usage. Changes clear both in-memory and on-disk image cache — %s
+ Do not load images
+ Low quality
+ Medium quality
+ High quality
\ No newline at end of file
diff --git a/app/src/main/res/xml/content_settings.xml b/app/src/main/res/xml/content_settings.xml
index 73a849af7..45f187452 100644
--- a/app/src/main/res/xml/content_settings.xml
+++ b/app/src/main/res/xml/content_settings.xml
@@ -85,11 +85,13 @@
app:singleLineTitle="false"
app:iconSpaceReserved="false" />
-
From 35073c780d21cba874893b5f75d9e9d99236a1e8 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Tue, 2 May 2023 12:30:27 +0200
Subject: [PATCH 011/162] Implement better image selection strategy
---
app/src/main/java/org/schabi/newpipe/App.java | 3 +-
.../database/playlist/PlaylistStreamEntry.kt | 4 +-
.../playlist/model/PlaylistRemoteEntity.java | 6 +-
.../database/stream/StreamStatisticsEntry.kt | 4 +-
.../database/stream/model/StreamEntity.kt | 10 +-
.../subscription/SubscriptionEntity.java | 6 +-
.../fragments/detail/DescriptionFragment.java | 4 +-
.../list/channel/ChannelAboutFragment.java | 6 +-
.../list/channel/ChannelFragment.java | 7 +-
.../holder/CommentsMiniInfoItemHolder.java | 3 +-
.../subscription/SubscriptionFragment.kt | 4 +-
.../local/subscription/SubscriptionManager.kt | 6 +-
.../player/mediaitem/ExceptionTag.java | 4 +-
.../player/mediaitem/StreamInfoTag.java | 4 +-
.../mediasession/PlayQueueNavigator.java | 4 +-
.../settings/ContentSettingsFragment.java | 3 +-
.../external_communication/ShareUtils.java | 7 +-
.../newpipe/util/image/ImageStrategy.java | 115 ++++++++++++++++++
.../newpipe/util/image/PicassoHelper.java | 50 +-------
19 files changed, 161 insertions(+), 89 deletions(-)
create mode 100644 app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java
diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java
index b394c7039..ee352ae4a 100644
--- a/app/src/main/java/org/schabi/newpipe/App.java
+++ b/app/src/main/java/org/schabi/newpipe/App.java
@@ -20,6 +20,7 @@ import org.schabi.newpipe.extractor.downloader.Downloader;
import org.schabi.newpipe.ktx.ExceptionUtils;
import org.schabi.newpipe.settings.NewPipeSettings;
import org.schabi.newpipe.util.Localization;
+import org.schabi.newpipe.util.image.ImageStrategy;
import org.schabi.newpipe.util.image.PicassoHelper;
import org.schabi.newpipe.util.ServiceHelper;
import org.schabi.newpipe.util.StateSaver;
@@ -100,7 +101,7 @@ public class App extends Application {
// Initialize image loader
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
PicassoHelper.init(this);
- PicassoHelper.setPreferredImageQuality(PreferredImageQuality.fromPreferenceKey(this,
+ ImageStrategy.setPreferredImageQuality(PreferredImageQuality.fromPreferenceKey(this,
prefs.getString(getString(R.string.image_quality_key),
getString(R.string.image_quality_default))));
PicassoHelper.setIndicatorsEnabled(MainActivity.DEBUG
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 e7db1d603..47dc1d06a 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
@@ -7,7 +7,7 @@ import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity
import org.schabi.newpipe.database.stream.model.StreamEntity
import org.schabi.newpipe.database.stream.model.StreamStateEntity
import org.schabi.newpipe.extractor.stream.StreamInfoItem
-import org.schabi.newpipe.util.image.PicassoHelper
+import org.schabi.newpipe.util.image.ImageStrategy
data class PlaylistStreamEntry(
@Embedded
@@ -29,7 +29,7 @@ data class PlaylistStreamEntry(
item.duration = streamEntity.duration
item.uploaderName = streamEntity.uploader
item.uploaderUrl = streamEntity.uploaderUrl
- item.thumbnails = PicassoHelper.urlToImageList(streamEntity.thumbnailUrl)
+ item.thumbnails = ImageStrategy.urlToImageList(streamEntity.thumbnailUrl)
return item
}
diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java
index 569f6721c..5e8977821 100644
--- a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java
+++ b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java
@@ -11,7 +11,7 @@ import androidx.room.PrimaryKey;
import org.schabi.newpipe.database.playlist.PlaylistLocalItem;
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
import org.schabi.newpipe.util.Constants;
-import org.schabi.newpipe.util.image.PicassoHelper;
+import org.schabi.newpipe.util.image.ImageStrategy;
import static org.schabi.newpipe.database.LocalItem.LocalItemType.PLAYLIST_REMOTE_ITEM;
import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_NAME;
@@ -70,7 +70,7 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem {
@Ignore
public PlaylistRemoteEntity(final PlaylistInfo info) {
this(info.getServiceId(), info.getName(), info.getUrl(),
- PicassoHelper.choosePreferredImage(info.getThumbnails()),
+ ImageStrategy.choosePreferredImage(info.getThumbnails()),
info.getUploaderName(), info.getStreamCount());
}
@@ -85,7 +85,7 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem {
&& TextUtils.equals(getName(), info.getName())
&& TextUtils.equals(getUrl(), info.getUrl())
&& TextUtils.equals(getThumbnailUrl(),
- PicassoHelper.choosePreferredImage(info.getThumbnails()))
+ ImageStrategy.choosePreferredImage(info.getThumbnails()))
&& TextUtils.equals(getUploader(), info.getUploaderName());
}
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 6d005351d..81e17b720 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
@@ -7,7 +7,7 @@ import org.schabi.newpipe.database.history.model.StreamHistoryEntity
import org.schabi.newpipe.database.stream.model.StreamEntity
import org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_PROGRESS_MILLIS
import org.schabi.newpipe.extractor.stream.StreamInfoItem
-import org.schabi.newpipe.util.image.PicassoHelper
+import org.schabi.newpipe.util.image.ImageStrategy
import java.time.OffsetDateTime
class StreamStatisticsEntry(
@@ -31,7 +31,7 @@ class StreamStatisticsEntry(
item.duration = streamEntity.duration
item.uploaderName = streamEntity.uploader
item.uploaderUrl = streamEntity.uploaderUrl
- item.thumbnails = PicassoHelper.urlToImageList(streamEntity.thumbnailUrl)
+ item.thumbnails = ImageStrategy.urlToImageList(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 bb2c0e0d7..4eecc9373 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
@@ -13,7 +13,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfo
import org.schabi.newpipe.extractor.stream.StreamInfoItem
import org.schabi.newpipe.extractor.stream.StreamType
import org.schabi.newpipe.player.playqueue.PlayQueueItem
-import org.schabi.newpipe.util.image.PicassoHelper
+import org.schabi.newpipe.util.image.ImageStrategy
import java.io.Serializable
import java.time.OffsetDateTime
@@ -68,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,
- uploaderUrl = item.uploaderUrl, thumbnailUrl = PicassoHelper.choosePreferredImage(item.thumbnails), viewCount = item.viewCount,
+ uploaderUrl = item.uploaderUrl, thumbnailUrl = ImageStrategy.choosePreferredImage(item.thumbnails), viewCount = item.viewCount,
textualUploadDate = item.textualUploadDate, uploadDate = item.uploadDate?.offsetDateTime(),
isUploadDateApproximation = item.uploadDate?.isApproximation
)
@@ -77,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,
- uploaderUrl = info.uploaderUrl, thumbnailUrl = PicassoHelper.choosePreferredImage(info.thumbnails), viewCount = info.viewCount,
+ uploaderUrl = info.uploaderUrl, thumbnailUrl = ImageStrategy.choosePreferredImage(info.thumbnails), viewCount = info.viewCount,
textualUploadDate = info.textualUploadDate, uploadDate = info.uploadDate?.offsetDateTime(),
isUploadDateApproximation = info.uploadDate?.isApproximation
)
@@ -87,7 +87,7 @@ data class StreamEntity(
serviceId = item.serviceId, url = item.url, title = item.title,
streamType = item.streamType, duration = item.duration, uploader = item.uploader,
uploaderUrl = item.uploaderUrl,
- thumbnailUrl = PicassoHelper.choosePreferredImage(item.thumbnails)
+ thumbnailUrl = ImageStrategy.choosePreferredImage(item.thumbnails)
)
fun toStreamInfoItem(): StreamInfoItem {
@@ -95,7 +95,7 @@ data class StreamEntity(
item.duration = duration
item.uploaderName = uploader
item.uploaderUrl = uploaderUrl
- item.thumbnails = PicassoHelper.urlToImageList(thumbnailUrl)
+ item.thumbnails = ImageStrategy.urlToImageList(thumbnailUrl)
if (viewCount != null) item.viewCount = viewCount as Long
item.textualUploadDate = textualUploadDate
diff --git a/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java b/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java
index 1f1722814..3fb474423 100644
--- a/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java
+++ b/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java
@@ -10,7 +10,7 @@ import androidx.room.PrimaryKey;
import org.schabi.newpipe.extractor.channel.ChannelInfo;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.util.Constants;
-import org.schabi.newpipe.util.image.PicassoHelper;
+import org.schabi.newpipe.util.image.ImageStrategy;
import static org.schabi.newpipe.database.subscription.SubscriptionEntity.SUBSCRIPTION_SERVICE_ID;
import static org.schabi.newpipe.database.subscription.SubscriptionEntity.SUBSCRIPTION_TABLE;
@@ -58,7 +58,7 @@ public class SubscriptionEntity {
final SubscriptionEntity result = new SubscriptionEntity();
result.setServiceId(info.getServiceId());
result.setUrl(info.getUrl());
- result.setData(info.getName(), PicassoHelper.choosePreferredImage(info.getAvatars()),
+ result.setData(info.getName(), ImageStrategy.choosePreferredImage(info.getAvatars()),
info.getDescription(), info.getSubscriberCount());
return result;
}
@@ -139,7 +139,7 @@ public class SubscriptionEntity {
@Ignore
public ChannelInfoItem toChannelInfoItem() {
final ChannelInfoItem item = new ChannelInfoItem(getServiceId(), getUrl(), getName());
- item.setThumbnails(PicassoHelper.urlToImageList(getAvatarUrl()));
+ item.setThumbnails(ImageStrategy.urlToImageList(getAvatarUrl()));
item.setSubscriberCount(getSubscriberCount());
item.setDescription(getDescription());
return item;
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java
index ff1a01466..60a2a2ed3 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java
@@ -17,7 +17,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.util.Localization;
import java.util.List;
-import org.schabi.newpipe.util.image.PicassoHelper;
+import org.schabi.newpipe.util.image.ImageStrategy;
import icepick.State;
@@ -114,7 +114,7 @@ public class DescriptionFragment extends BaseDescriptionFragment {
addMetadataItem(inflater, layout, true, R.string.metadata_host,
streamInfo.getHost());
addMetadataItem(inflater, layout, true, R.string.metadata_thumbnail_url,
- PicassoHelper.choosePreferredImage(streamInfo.getThumbnails()));
+ ImageStrategy.choosePreferredImage(streamInfo.getThumbnails()));
}
private void addPrivacyMetadataItem(final LayoutInflater inflater, final LinearLayout layout) {
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java
index 5ea25bf15..9a035d0ab 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java
@@ -17,7 +17,7 @@ import org.schabi.newpipe.extractor.stream.Description;
import org.schabi.newpipe.fragments.detail.BaseDescriptionFragment;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.Localization;
-import org.schabi.newpipe.util.image.PicassoHelper;
+import org.schabi.newpipe.util.image.ImageStrategy;
import java.util.List;
@@ -101,8 +101,8 @@ public class ChannelAboutFragment extends BaseDescriptionFragment {
}
addMetadataItem(inflater, layout, true, R.string.metadata_avatar_url,
- PicassoHelper.choosePreferredImage(channelInfo.getAvatars()));
+ ImageStrategy.choosePreferredImage(channelInfo.getAvatars()));
addMetadataItem(inflater, layout, true, R.string.metadata_banner_url,
- PicassoHelper.choosePreferredImage(channelInfo.getBanners()));
+ ImageStrategy.choosePreferredImage(channelInfo.getBanners()));
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
index 7436f50fd..3ece760ca 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
@@ -49,6 +49,7 @@ import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.StateSaver;
+import org.schabi.newpipe.util.image.ImageStrategy;
import org.schabi.newpipe.util.image.PicassoHelper;
import org.schabi.newpipe.util.ThemeHelper;
import org.schabi.newpipe.util.external_communication.ShareUtils;
@@ -147,7 +148,7 @@ public class ChannelFragment extends BaseStateFragment
setTitle(name);
binding.channelTitleView.setText(name);
- if (!PicassoHelper.shouldLoadImages()) {
+ if (!ImageStrategy.shouldLoadImages()) {
// do not waste space for the banner if it is not going to be loaded
binding.channelBannerImage.setImageDrawable(null);
}
@@ -354,7 +355,7 @@ public class ChannelFragment extends BaseStateFragment
channel.setServiceId(info.getServiceId());
channel.setUrl(info.getUrl());
channel.setData(info.getName(),
- PicassoHelper.choosePreferredImage(info.getAvatars()),
+ ImageStrategy.choosePreferredImage(info.getAvatars()),
info.getDescription(),
info.getSubscriberCount());
channelSubscription = null;
@@ -578,7 +579,7 @@ public class ChannelFragment extends BaseStateFragment
currentInfo = result;
setInitialData(result.getServiceId(), result.getOriginalUrl(), result.getName());
- if (PicassoHelper.shouldLoadImages() && !result.getBanners().isEmpty()) {
+ if (ImageStrategy.shouldLoadImages() && !result.getBanners().isEmpty()) {
PicassoHelper.loadBanner(result.getBanners()).tag(PICASSO_CHANNEL_TAG)
.into(binding.channelBannerImage);
} else {
diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java
index 69e1bf5f6..d6a08e6cb 100644
--- a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java
+++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java
@@ -31,6 +31,7 @@ import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper;
+import org.schabi.newpipe.util.image.ImageStrategy;
import org.schabi.newpipe.util.image.PicassoHelper;
import org.schabi.newpipe.util.external_communication.ShareUtils;
import org.schabi.newpipe.util.text.CommentTextOnTouchListener;
@@ -98,7 +99,7 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
final CommentsInfoItem item = (CommentsInfoItem) infoItem;
PicassoHelper.loadAvatar(item.getUploaderAvatars()).into(itemThumbnailView);
- if (PicassoHelper.shouldLoadImages()) {
+ if (ImageStrategy.shouldLoadImages()) {
itemThumbnailView.setVisibility(View.VISIBLE);
itemRoot.setPadding(commentVerticalPadding, commentVerticalPadding,
commentVerticalPadding, commentVerticalPadding);
diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt
index f84d9865f..ac82d5c91 100644
--- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt
+++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt
@@ -61,7 +61,7 @@ import org.schabi.newpipe.util.OnClickGesture
import org.schabi.newpipe.util.ServiceHelper
import org.schabi.newpipe.util.ThemeHelper.getGridSpanCountChannels
import org.schabi.newpipe.util.external_communication.ShareUtils
-import org.schabi.newpipe.util.image.PicassoHelper
+import org.schabi.newpipe.util.image.ImageStrategy
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@@ -343,7 +343,7 @@ class SubscriptionFragment : BaseStateFragment() {
when (i) {
0 -> ShareUtils.shareText(
requireContext(), selectedItem.name, selectedItem.url,
- PicassoHelper.choosePreferredImage(selectedItem.thumbnails)
+ ImageStrategy.choosePreferredImage(selectedItem.thumbnails)
)
1 -> ShareUtils.openUrlInBrowser(requireContext(), selectedItem.url)
2 -> deleteChannel(selectedItem)
diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt
index 70bac6168..cfd5196be 100644
--- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt
+++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt
@@ -19,7 +19,7 @@ import org.schabi.newpipe.extractor.feed.FeedInfo
import org.schabi.newpipe.extractor.stream.StreamInfoItem
import org.schabi.newpipe.local.feed.FeedDatabaseManager
import org.schabi.newpipe.util.ExtractorHelper
-import org.schabi.newpipe.util.image.PicassoHelper
+import org.schabi.newpipe.util.image.ImageStrategy
class SubscriptionManager(context: Context) {
private val database = NewPipeDatabase.getInstance(context)
@@ -74,7 +74,7 @@ class SubscriptionManager(context: Context) {
Completable.fromRunnable {
it.setData(
info.name,
- PicassoHelper.choosePreferredImage(info.avatars),
+ ImageStrategy.choosePreferredImage(info.avatars),
info.description,
info.subscriberCount
)
@@ -105,7 +105,7 @@ class SubscriptionManager(context: Context) {
} else if (info is ChannelInfo) {
subscriptionEntity.setData(
info.name,
- PicassoHelper.choosePreferredImage(info.avatars),
+ ImageStrategy.choosePreferredImage(info.avatars),
info.description,
info.subscriberCount
)
diff --git a/app/src/main/java/org/schabi/newpipe/player/mediaitem/ExceptionTag.java b/app/src/main/java/org/schabi/newpipe/player/mediaitem/ExceptionTag.java
index 9ec6513dc..95a4f74af 100644
--- a/app/src/main/java/org/schabi/newpipe/player/mediaitem/ExceptionTag.java
+++ b/app/src/main/java/org/schabi/newpipe/player/mediaitem/ExceptionTag.java
@@ -3,7 +3,7 @@ package org.schabi.newpipe.player.mediaitem;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
-import org.schabi.newpipe.util.image.PicassoHelper;
+import org.schabi.newpipe.util.image.ImageStrategy;
import java.util.List;
import java.util.Optional;
@@ -75,7 +75,7 @@ public final class ExceptionTag implements MediaItemTag {
@Override
public String getThumbnailUrl() {
- return PicassoHelper.choosePreferredImage(item.getThumbnails());
+ return ImageStrategy.choosePreferredImage(item.getThumbnails());
}
@Override
diff --git a/app/src/main/java/org/schabi/newpipe/player/mediaitem/StreamInfoTag.java b/app/src/main/java/org/schabi/newpipe/player/mediaitem/StreamInfoTag.java
index a96f49f2f..e24a93615 100644
--- a/app/src/main/java/org/schabi/newpipe/player/mediaitem/StreamInfoTag.java
+++ b/app/src/main/java/org/schabi/newpipe/player/mediaitem/StreamInfoTag.java
@@ -6,7 +6,7 @@ import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.extractor.stream.VideoStream;
-import org.schabi.newpipe.util.image.PicassoHelper;
+import org.schabi.newpipe.util.image.ImageStrategy;
import java.util.Collections;
import java.util.List;
@@ -96,7 +96,7 @@ public final class StreamInfoTag implements MediaItemTag {
@Override
public String getThumbnailUrl() {
- return PicassoHelper.choosePreferredImage(streamInfo.getThumbnails());
+ return ImageStrategy.choosePreferredImage(streamInfo.getThumbnails());
}
@Override
diff --git a/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java b/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java
index 3e0736f82..f925bff16 100644
--- a/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java
+++ b/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java
@@ -20,7 +20,7 @@ import com.google.android.exoplayer2.util.Util;
import org.schabi.newpipe.player.Player;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
-import org.schabi.newpipe.util.image.PicassoHelper;
+import org.schabi.newpipe.util.image.ImageStrategy;
import java.util.ArrayList;
import java.util.Collections;
@@ -139,7 +139,7 @@ public class PlayQueueNavigator implements MediaSessionConnector.QueueNavigator
descBuilder.setExtras(additionalMetadata);
final Uri thumbnailUri = Uri.parse(
- PicassoHelper.choosePreferredImage(item.getThumbnails()));
+ ImageStrategy.choosePreferredImage(item.getThumbnails()));
if (thumbnailUri != null) {
descBuilder.setIconUri(thumbnailUri);
}
diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java
index 2297e3e93..c7d107acb 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java
@@ -31,6 +31,7 @@ import org.schabi.newpipe.extractor.localization.Localization;
import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard;
import org.schabi.newpipe.streams.io.StoredFileHelper;
import org.schabi.newpipe.util.NavigationHelper;
+import org.schabi.newpipe.util.image.ImageStrategy;
import org.schabi.newpipe.util.image.PicassoHelper;
import org.schabi.newpipe.util.ZipHelper;
import org.schabi.newpipe.util.image.PreferredImageQuality;
@@ -109,7 +110,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
final Preference imageQualityPreference = requirePreference(R.string.image_quality_key);
imageQualityPreference.setOnPreferenceChangeListener(
(preference, newValue) -> {
- PicassoHelper.setPreferredImageQuality(PreferredImageQuality
+ ImageStrategy.setPreferredImageQuality(PreferredImageQuality
.fromPreferenceKey(requireContext(), (String) newValue));
try {
PicassoHelper.clearCache(preference.getContext());
diff --git a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java
index 8150d4030..fc057de41 100644
--- a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java
+++ b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java
@@ -24,6 +24,7 @@ import androidx.core.content.FileProvider;
import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.Image;
+import org.schabi.newpipe.util.image.ImageStrategy;
import org.schabi.newpipe.util.image.PicassoHelper;
import java.io.File;
@@ -251,7 +252,7 @@ public final class ShareUtils {
// If loading of images has been disabled, don't try to generate a content preview
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
&& !TextUtils.isEmpty(imagePreviewUrl)
- && PicassoHelper.shouldLoadImages()) {
+ && ImageStrategy.shouldLoadImages()) {
final ClipData clipData = generateClipDataForImagePreview(context, imagePreviewUrl);
if (clipData != null) {
@@ -276,14 +277,14 @@ public final class ShareUtils {
* @param title the title of the content
* @param content the content to share
* @param images a set of possible {@link Image}s of the subject, among which to choose with
- * {@link PicassoHelper#choosePreferredImage(List)} since that's likely to
+ * {@link ImageStrategy#choosePreferredImage(List)} since that's likely to
* provide an image that is in Picasso's cache
*/
public static void shareText(@NonNull final Context context,
@NonNull final String title,
final String content,
final List images) {
- shareText(context, title, content, PicassoHelper.choosePreferredImage(images));
+ shareText(context, title, content, ImageStrategy.choosePreferredImage(images));
}
/**
diff --git a/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java b/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java
new file mode 100644
index 000000000..5de0b52f4
--- /dev/null
+++ b/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java
@@ -0,0 +1,115 @@
+package org.schabi.newpipe.util.image;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import org.schabi.newpipe.extractor.Image;
+
+import java.util.Comparator;
+import java.util.List;
+
+public final class ImageStrategy {
+
+ // the height thresholds also used by the extractor (TODO move them to the extractor)
+ private static final int LOW_MEDIUM = 175;
+ private static final int MEDIUM_HIGH = 720;
+
+ private static PreferredImageQuality preferredImageQuality = PreferredImageQuality.MEDIUM;
+
+ private ImageStrategy() {
+ }
+
+ public static void setPreferredImageQuality(final PreferredImageQuality preferredImageQuality) {
+ ImageStrategy.preferredImageQuality = preferredImageQuality;
+ }
+
+ public static boolean shouldLoadImages() {
+ return preferredImageQuality != PreferredImageQuality.NONE;
+ }
+
+
+ private static double estimatePixelCount(final Image image,
+ final double widthOverHeight,
+ final boolean unknownsLast) {
+ if (image.getHeight() == Image.HEIGHT_UNKNOWN) {
+ if (image.getWidth() == Image.WIDTH_UNKNOWN) {
+ switch (image.getEstimatedResolutionLevel()) {
+ case LOW:
+ return unknownsLast
+ ? (LOW_MEDIUM - 1) * (LOW_MEDIUM - 1) * widthOverHeight
+ : 0;
+ case MEDIUM:
+ return unknownsLast
+ ? (MEDIUM_HIGH - 1) * (MEDIUM_HIGH - 1) * widthOverHeight
+ : LOW_MEDIUM * LOW_MEDIUM * widthOverHeight;
+ case HIGH:
+ return unknownsLast
+ ? 1e20 // less than 1e21 to prefer over fully unknown image sizes
+ : MEDIUM_HIGH * MEDIUM_HIGH * widthOverHeight;
+ default:
+ case UNKNOWN:
+ // images whose size is completely unknown will be avoided when possible
+ return unknownsLast ? 1e21 : -1;
+ }
+
+ } else {
+ return image.getWidth() * image.getWidth() / widthOverHeight;
+ }
+
+ } else if (image.getWidth() == Image.WIDTH_UNKNOWN) {
+ return image.getHeight() * image.getHeight() * widthOverHeight;
+
+ } else {
+ return image.getHeight() * image.getWidth();
+ }
+ }
+
+ @Nullable
+ public static String choosePreferredImage(@NonNull final List images) {
+ if (preferredImageQuality == PreferredImageQuality.NONE) {
+ return null; // do not load images
+ }
+
+ final double widthOverHeight = images.stream()
+ .filter(image -> image.getHeight() != Image.HEIGHT_UNKNOWN
+ && image.getWidth() != Image.WIDTH_UNKNOWN)
+ .mapToDouble(image -> ((double) image.getWidth()) / image.getHeight())
+ .findFirst()
+ .orElse(1.0);
+
+ final Comparator comparator;
+ switch (preferredImageQuality) {
+ case LOW:
+ comparator = Comparator.comparingDouble(
+ image -> estimatePixelCount(image, widthOverHeight, true));
+ break;
+ default:
+ case MEDIUM:
+ comparator = Comparator.comparingDouble(image -> {
+ final double pixelCount = estimatePixelCount(image, widthOverHeight, true);
+ final double mediumHeight = (LOW_MEDIUM + MEDIUM_HIGH) / 2.0;
+ return Math.abs(pixelCount - mediumHeight * mediumHeight * widthOverHeight);
+ });
+ break;
+ case HIGH:
+ comparator = Comparator.comparingDouble(
+ image -> estimatePixelCount(image, widthOverHeight, false))
+ .reversed();
+ break;
+ }
+
+ return images.stream()
+ .min(comparator)
+ .map(Image::getUrl)
+ .orElse(null);
+ }
+
+ @NonNull
+ public static List urlToImageList(@Nullable final String url) {
+ if (url == null) {
+ return List.of();
+ } else {
+ return List.of(new Image(url, -1, -1, Image.ResolutionLevel.UNKNOWN));
+ }
+ }
+}
diff --git a/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java b/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java
index 3177e83f4..ccf7c3737 100644
--- a/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java
+++ b/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java
@@ -2,13 +2,13 @@ package org.schabi.newpipe.util.image;
import static org.schabi.newpipe.MainActivity.DEBUG;
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
+import static org.schabi.newpipe.util.image.ImageStrategy.choosePreferredImage;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
-import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.BitmapCompat;
@@ -21,11 +21,9 @@ import com.squareup.picasso.Transformation;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.Image;
-import org.schabi.newpipe.extractor.Image.ResolutionLevel;
import java.io.File;
import java.io.IOException;
-import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -46,7 +44,6 @@ public final class PicassoHelper {
@SuppressLint("StaticFieldLeak")
private static Picasso picassoInstance;
- private static PreferredImageQuality preferredImageQuality = PreferredImageQuality.MEDIUM;
public static void init(final Context context) {
picassoCache = new LruCache(10 * 1024 * 1024);
@@ -92,14 +89,6 @@ public final class PicassoHelper {
picassoInstance.setIndicatorsEnabled(enabled); // useful for debugging
}
- public static void setPreferredImageQuality(final PreferredImageQuality preferredImageQuality) {
- PicassoHelper.preferredImageQuality = preferredImageQuality;
- }
-
- public static boolean shouldLoadImages() {
- return preferredImageQuality != PreferredImageQuality.NONE;
- }
-
public static RequestCreator loadAvatar(final List images) {
return loadImageDefault(images, R.drawable.placeholder_person);
@@ -227,41 +216,4 @@ public final class PicassoHelper {
return requestCreator;
}
}
-
- @Nullable
- public static String choosePreferredImage(final List images) {
- final Comparator comparator;
- switch (preferredImageQuality) {
- case NONE:
- return null;
- case HIGH:
- comparator = Comparator.comparingInt(Image::getHeight).reversed();
- break;
- default:
- case MEDIUM:
- comparator = Comparator.comparingInt(image -> Math.abs(image.getHeight() - 450));
- break;
- case LOW:
- comparator = Comparator.comparingInt(Image::getHeight);
- break;
- }
-
- return images.stream()
- .filter(image -> image.getEstimatedResolutionLevel() != ResolutionLevel.UNKNOWN)
- .min(comparator)
- .map(Image::getUrl)
- .orElseGet(() -> images.stream()
- .findAny()
- .map(Image::getUrl)
- .orElse(null));
- }
-
- @NonNull
- public static List urlToImageList(@Nullable final String url) {
- if (url == null) {
- return List.of();
- } else {
- return List.of(new Image(url, -1, -1, ResolutionLevel.UNKNOWN));
- }
- }
}
From 4f7d2067368c058314a7b7cd176486b861a07134 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Tue, 2 May 2023 18:56:02 +0200
Subject: [PATCH 012/162] Display all thumbnails in description tab
---
.../detail/BaseDescriptionFragment.java | 75 +++++++++++++++++++
.../fragments/detail/DescriptionFragment.java | 10 ++-
.../list/channel/ChannelAboutFragment.java | 9 +--
app/src/main/res/values-ar/strings.xml | 1 -
app/src/main/res/values-az/strings.xml | 1 -
app/src/main/res/values-be/strings.xml | 1 -
app/src/main/res/values-bg/strings.xml | 1 -
app/src/main/res/values-bn/strings.xml | 1 -
app/src/main/res/values-ca/strings.xml | 1 -
app/src/main/res/values-ckb/strings.xml | 1 -
app/src/main/res/values-cs/strings.xml | 1 -
app/src/main/res/values-da/strings.xml | 1 -
app/src/main/res/values-de/strings.xml | 1 -
app/src/main/res/values-el/strings.xml | 1 -
app/src/main/res/values-es/strings.xml | 1 -
app/src/main/res/values-et/strings.xml | 1 -
app/src/main/res/values-eu/strings.xml | 1 -
app/src/main/res/values-fa/strings.xml | 1 -
app/src/main/res/values-fi/strings.xml | 1 -
app/src/main/res/values-fil/strings.xml | 1 -
app/src/main/res/values-fr/strings.xml | 1 -
app/src/main/res/values-gl/strings.xml | 1 -
app/src/main/res/values-he/strings.xml | 1 -
app/src/main/res/values-hi/strings.xml | 1 -
app/src/main/res/values-hr/strings.xml | 1 -
app/src/main/res/values-hu/strings.xml | 1 -
app/src/main/res/values-in/strings.xml | 1 -
app/src/main/res/values-is/strings.xml | 1 -
app/src/main/res/values-it/strings.xml | 1 -
app/src/main/res/values-ja/strings.xml | 1 -
app/src/main/res/values-ka/strings.xml | 1 -
app/src/main/res/values-ko/strings.xml | 1 -
app/src/main/res/values-lt/strings.xml | 1 -
app/src/main/res/values-lv/strings.xml | 1 -
app/src/main/res/values-ml/strings.xml | 1 -
app/src/main/res/values-nb-rNO/strings.xml | 1 -
app/src/main/res/values-nl/strings.xml | 1 -
app/src/main/res/values-or/strings.xml | 1 -
app/src/main/res/values-pa/strings.xml | 1 -
app/src/main/res/values-pl/strings.xml | 1 -
app/src/main/res/values-pt-rBR/strings.xml | 1 -
app/src/main/res/values-pt-rPT/strings.xml | 1 -
app/src/main/res/values-pt/strings.xml | 1 -
app/src/main/res/values-ro/strings.xml | 1 -
app/src/main/res/values-ru/strings.xml | 1 -
app/src/main/res/values-sc/strings.xml | 1 -
app/src/main/res/values-sk/strings.xml | 1 -
app/src/main/res/values-so/strings.xml | 1 -
app/src/main/res/values-sq/strings.xml | 1 -
app/src/main/res/values-sr/strings.xml | 1 -
app/src/main/res/values-sv/strings.xml | 1 -
app/src/main/res/values-tr/strings.xml | 1 -
app/src/main/res/values-uk/strings.xml | 1 -
app/src/main/res/values-vi/strings.xml | 1 -
app/src/main/res/values-zh-rCN/strings.xml | 1 -
app/src/main/res/values-zh-rHK/strings.xml | 1 -
app/src/main/res/values-zh-rTW/strings.xml | 1 -
app/src/main/res/values/strings.xml | 8 +-
58 files changed, 91 insertions(+), 65 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java
index ae334b761..2bd5906bc 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java
@@ -4,7 +4,13 @@ import static android.text.TextUtils.isEmpty;
import static org.schabi.newpipe.extractor.utils.Utils.isBlank;
import static org.schabi.newpipe.util.text.TextLinkifier.SET_LINK_MOVEMENT_METHOD;
+import android.graphics.Typeface;
import android.os.Bundle;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
+import android.text.style.StyleSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -23,10 +29,12 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.databinding.FragmentDescriptionBinding;
import org.schabi.newpipe.databinding.ItemMetadataBinding;
import org.schabi.newpipe.databinding.ItemMetadataTagsBinding;
+import org.schabi.newpipe.extractor.Image;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.stream.Description;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.external_communication.ShareUtils;
+import org.schabi.newpipe.util.image.ImageStrategy;
import org.schabi.newpipe.util.text.TextLinkifier;
import java.util.List;
@@ -176,6 +184,73 @@ public abstract class BaseDescriptionFragment extends BaseFragment {
layout.addView(itemBinding.getRoot());
}
+ private String imageSizeToText(final int heightOrWidth) {
+ if (heightOrWidth < 0) {
+ return "?";
+ } else {
+ return String.valueOf(heightOrWidth);
+ }
+ }
+
+ protected void addImagesMetadataItem(final LayoutInflater inflater,
+ final LinearLayout layout,
+ @StringRes final int type,
+ final List images) {
+ final String preferredImageUrl = ImageStrategy.choosePreferredImage(images);
+ if (preferredImageUrl == null) {
+ return; // null will be returned in case there is no image
+ }
+
+ final ItemMetadataBinding itemBinding =
+ ItemMetadataBinding.inflate(inflater, layout, false);
+ itemBinding.metadataTypeView.setText(type);
+
+ final SpannableStringBuilder urls = new SpannableStringBuilder();
+ for (final Image image : images) {
+ if (urls.length() != 0) {
+ urls.append(", ");
+ }
+ final int entryBegin = urls.length();
+
+ if (image.getHeight() != Image.HEIGHT_UNKNOWN
+ || image.getWidth() != Image.WIDTH_UNKNOWN
+ // if even the resolution level is unknown, ?x? will be shown
+ || image.getEstimatedResolutionLevel() == Image.ResolutionLevel.UNKNOWN) {
+ urls.append(imageSizeToText(image.getHeight()));
+ urls.append('x');
+ urls.append(imageSizeToText(image.getWidth()));
+ } else {
+ switch (image.getEstimatedResolutionLevel()) {
+ case LOW:
+ urls.append(getString(R.string.image_quality_low));
+ break;
+ case MEDIUM:
+ urls.append(getString(R.string.image_quality_medium));
+ break;
+ case HIGH:
+ urls.append(getString(R.string.image_quality_high));
+ break;
+ }
+ }
+
+ urls.setSpan(new ClickableSpan() {
+ @Override
+ public void onClick(@NonNull final View widget) {
+ ShareUtils.openUrlInBrowser(requireContext(), image.getUrl());
+ }
+ }, entryBegin, urls.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ if (preferredImageUrl.equals(image.getUrl())) {
+ urls.setSpan(new StyleSpan(Typeface.BOLD), entryBegin, urls.length(),
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ }
+
+ itemBinding.metadataContentView.setText(urls);
+ itemBinding.metadataContentView.setMovementMethod(LinkMovementMethod.getInstance());
+ layout.addView(itemBinding.getRoot());
+ }
+
private void addTagsMetadataItem(final LayoutInflater inflater, final LinearLayout layout) {
final List tags = getTags();
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java
index 60a2a2ed3..ada12fc8e 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java
@@ -17,7 +17,6 @@ import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.util.Localization;
import java.util.List;
-import org.schabi.newpipe.util.image.ImageStrategy;
import icepick.State;
@@ -113,8 +112,13 @@ public class DescriptionFragment extends BaseDescriptionFragment {
streamInfo.getSupportInfo());
addMetadataItem(inflater, layout, true, R.string.metadata_host,
streamInfo.getHost());
- addMetadataItem(inflater, layout, true, R.string.metadata_thumbnail_url,
- ImageStrategy.choosePreferredImage(streamInfo.getThumbnails()));
+
+ addImagesMetadataItem(inflater, layout, R.string.metadata_thumbnails,
+ streamInfo.getThumbnails());
+ addImagesMetadataItem(inflater, layout, R.string.metadata_uploader_avatars,
+ streamInfo.getUploaderAvatars());
+ addImagesMetadataItem(inflater, layout, R.string.metadata_subchannel_avatars,
+ streamInfo.getSubChannelAvatars());
}
private void addPrivacyMetadataItem(final LayoutInflater inflater, final LinearLayout layout) {
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java
index 9a035d0ab..56418800d 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java
@@ -17,7 +17,6 @@ import org.schabi.newpipe.extractor.stream.Description;
import org.schabi.newpipe.fragments.detail.BaseDescriptionFragment;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.Localization;
-import org.schabi.newpipe.util.image.ImageStrategy;
import java.util.List;
@@ -100,9 +99,9 @@ public class ChannelAboutFragment extends BaseDescriptionFragment {
Localization.localizeNumber(context, channelInfo.getSubscriberCount()));
}
- addMetadataItem(inflater, layout, true, R.string.metadata_avatar_url,
- ImageStrategy.choosePreferredImage(channelInfo.getAvatars()));
- addMetadataItem(inflater, layout, true, R.string.metadata_banner_url,
- ImageStrategy.choosePreferredImage(channelInfo.getBanners()));
+ addImagesMetadataItem(inflater, layout, R.string.metadata_avatars,
+ channelInfo.getAvatars());
+ addImagesMetadataItem(inflater, layout, R.string.metadata_banners,
+ channelInfo.getBanners());
}
}
diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml
index 0c9f2c74c..78b59d4f9 100644
--- a/app/src/main/res/values-ar/strings.xml
+++ b/app/src/main/res/values-ar/strings.xml
@@ -642,7 +642,6 @@
خاصغير مدرجعامة
- رابط الصورة المصغرةالمضيفالدعماللغة
diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml
index 06273f9cf..1b8109b41 100644
--- a/app/src/main/res/values-az/strings.xml
+++ b/app/src/main/res/values-az/strings.xml
@@ -629,7 +629,6 @@
SahibSiyahıdan kənarŞəxsi
- Miniatür URLYaş həddiDilİctimai
diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml
index e176d2bc9..f79db16a8 100644
--- a/app/src/main/res/values-be/strings.xml
+++ b/app/src/main/res/values-be/strings.xml
@@ -698,7 +698,6 @@
ТэгіЛіцэнзіяХост
- URL мініяцюрыНе ў спісеПрыватная,
diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml
index 59091553d..56dfb9a9a 100644
--- a/app/src/main/res/values-bg/strings.xml
+++ b/app/src/main/res/values-bg/strings.xml
@@ -422,7 +422,6 @@
ПоддръжкаСървърПубличен
- Миниатюра линкЕзик на интерфейсаСпри звукапост-обработката
diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml
index d3f3a845b..24eed9eb0 100644
--- a/app/src/main/res/values-bn/strings.xml
+++ b/app/src/main/res/values-bn/strings.xml
@@ -548,7 +548,6 @@
প্রক্রিয়াকরণ ফিডে ত্রুটিওয়েবসাইট খুলুনঅ্যাকাউন্ট ধ্বংসকৃত
- প্রতিচ্ছবি সংযোগবয়সসীমাঅভ্যন্তরীণব্যক্তিগত
diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml
index bd3a5c61b..8ee3d6df4 100644
--- a/app/src/main/res/values-ca/strings.xml
+++ b/app/src/main/res/values-ca/strings.xml
@@ -600,7 +600,6 @@
PrivatDescatalogatPúblic
- URL de la miniaturaAmfitrióSuportIdioma
diff --git a/app/src/main/res/values-ckb/strings.xml b/app/src/main/res/values-ckb/strings.xml
index bae9fb822..841edef63 100644
--- a/app/src/main/res/values-ckb/strings.xml
+++ b/app/src/main/res/values-ckb/strings.xml
@@ -588,7 +588,6 @@
تایبەتیخشتەنەکراوگشتی
- بەستەری وێنۆچکەهۆستپشتگیریزمان
diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml
index dab312d3b..1864f3c65 100644
--- a/app/src/main/res/values-cs/strings.xml
+++ b/app/src/main/res/values-cs/strings.xml
@@ -613,7 +613,6 @@
SoukroméNeuvedeno v seznamuVeřejné
- URL miniaturyServerPodporaJazyk
diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml
index ef6197414..59e112918 100644
--- a/app/src/main/res/values-da/strings.xml
+++ b/app/src/main/res/values-da/strings.xml
@@ -669,7 +669,6 @@
\nAktiver systemet mappevælger (SAF), hvis du vil downloade til et eksternt SD-kortOriginaltekster fra tjenester vil være synlige i stream-emnerIngen videostreams er tilgængelige for eksterne afspillere
- URL til miniaturebilledeFraTablet-tilstandDenne video er kun tilgængelig for YouTube Music Premium-medlemmer, så den kan ikke streames eller downloades af NewPipe.
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index e9b710c63..01aa2de34 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -615,7 +615,6 @@
SchlagwörterKategorieNicht gelistet
- Vorschaubild-URLServerUnterstützungAbonnenten
diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml
index ced70b787..ddbc4c28b 100644
--- a/app/src/main/res/values-el/strings.xml
+++ b/app/src/main/res/values-el/strings.xml
@@ -602,7 +602,6 @@
ΙδιωτικόΕκτός λίσταςΔημόσιο
- URL εικονιδίουΥποστήριξηΓλώσσαΌριο ηλικίας
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 6ffadca81..781325886 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -614,7 +614,6 @@
PrivadoNo listadoPúblico
- URL de la miniaturaSoporteLenguajeLímite de edad
diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml
index ab478ec11..de29df8d3 100644
--- a/app/src/main/res/values-et/strings.xml
+++ b/app/src/main/res/values-et/strings.xml
@@ -584,7 +584,6 @@
SiseminePrivaatneAvalik
- Pisipildi URLKasutajatugiKeelVanusepiir
diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml
index 6003de6fd..fa2c885ed 100644
--- a/app/src/main/res/values-eu/strings.xml
+++ b/app/src/main/res/values-eu/strings.xml
@@ -624,7 +624,6 @@
Kontua ezabatu daJario azkarrak ez du honi buruz informazio gehiagorik ematen.Adin muga
- Miniaturaren URL-aBarnekoaZerrendatu gabeaOstalaria
diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml
index 35db56515..341b34102 100644
--- a/app/src/main/res/values-fa/strings.xml
+++ b/app/src/main/res/values-fa/strings.xml
@@ -567,7 +567,6 @@
حالت رایانکگشودن پایگاه وبحساب از بین رفت
- نشانی بندانگشتیکرانهٔ عمرموارد مرتبطنمایش شرح
diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml
index 397f2fef0..34a38ec33 100644
--- a/app/src/main/res/values-fi/strings.xml
+++ b/app/src/main/res/values-fi/strings.xml
@@ -595,7 +595,6 @@
Tämä video on ikärajoitettu.
\nYouTuben uusien ikärajoitusperiaatteiden mukaisesti NewPipella ei ole pääsyä videoon eikä sitä voida toistaa.Yöteema
- Pienoiskuvakkeen osoitePoista käytöstä tekstinvalinta kuvauskentän sisältäVoit nyt valita tekstin kuvauskentän sisältä. Huomioithan, että valintatilan aikana sivu voi vilkkua ja linkit eivät ehkä ole klikattavia.%s tuo tämän syyn:
diff --git a/app/src/main/res/values-fil/strings.xml b/app/src/main/res/values-fil/strings.xml
index 0fb7a0a1d..28b344af3 100644
--- a/app/src/main/res/values-fil/strings.xml
+++ b/app/src/main/res/values-fil/strings.xml
@@ -157,7 +157,6 @@
LisensyaWikaPribado
- URL ng ThumbnailHindi nakalistaNakapatayBago at patok
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 51f258166..bab3f6f47 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -616,7 +616,6 @@
PrivéNon répertoriéPublic
- URL de la miniatureHôteSupportLangue
diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml
index 8b5aaa497..957415790 100644
--- a/app/src/main/res/values-gl/strings.xml
+++ b/app/src/main/res/values-gl/strings.xml
@@ -547,7 +547,6 @@
InternoPrivadoPúblico
- URL da miniaturaApoioIdiomaLímite de idade
diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml
index 4dec4c819..6d067e5e5 100644
--- a/app/src/main/res/values-he/strings.xml
+++ b/app/src/main/res/values-he/strings.xml
@@ -622,7 +622,6 @@
פרטילא מופיע ברשימותציבורי
- כתובת תמונה ממוזערתאירוחתמיכהשפה
diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml
index 80ab6209c..5d2d3be10 100644
--- a/app/src/main/res/values-hi/strings.xml
+++ b/app/src/main/res/values-hi/strings.xml
@@ -616,7 +616,6 @@
ऐप को क्रैश करेंश्रेणीआपसे पूछा जाएगा कि प्रत्येक डाउनलोड को कहां सहेजना है
- थंमनेल यूआरएलऑफ़हमेशा अपडेट करेंविवरण में पाठ का चयन अक्षम करें
diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml
index c625955f7..cea08931d 100644
--- a/app/src/main/res/values-hr/strings.xml
+++ b/app/src/main/res/values-hr/strings.xml
@@ -616,7 +616,6 @@
PrivatnoNenavedenoJavno
- URL sličicePoslužiteljPodrškaJezik
diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml
index 26f4ee3cf..264eb2c86 100644
--- a/app/src/main/res/values-hu/strings.xml
+++ b/app/src/main/res/values-hu/strings.xml
@@ -605,7 +605,6 @@
LicencKorhatárKiszolgáló
- Bélyegkép URLNyilvánosNem listázottKi
diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml
index b68b36a47..9961a71c6 100644
--- a/app/src/main/res/values-in/strings.xml
+++ b/app/src/main/res/values-in/strings.xml
@@ -592,7 +592,6 @@
PrivasiTidak didaftarPublik
- Alamat URL gambar mini/thumbnailHostDukunganBahasa
diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml
index 98f73e294..50d8b2220 100644
--- a/app/src/main/res/values-is/strings.xml
+++ b/app/src/main/res/values-is/strings.xml
@@ -485,7 +485,6 @@
Frá %sReikningi lokaðAldurstakmark
- Vefslóð smámyndarFest ummæliSpjaldtölvuhamurVirkt
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 48cc84328..5408fe7ec 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -612,7 +612,6 @@
PrivatoNon in elencoPubblico
- URL copertinaHostSupportoLingua
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
index 8fa73a002..65280130d 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -600,7 +600,6 @@
言語サポートホスト
- サムネイルの URLウェブサイトを開くダウンロードのたびに保存する場所を尋ねますダウンロードフォルダーがまだ設定されていません。今すぐデフォルトのフォルダーを選択してください
diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml
index 47e105183..0c663ac49 100644
--- a/app/src/main/res/values-ka/strings.xml
+++ b/app/src/main/res/values-ka/strings.xml
@@ -565,7 +565,6 @@
Ასაკობრივი შეზღუდვაᲔნამასპინძელი
- მინიატურების URLსაჯაროდამალულიპირადი
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index 30c381bcf..057118bef 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -625,7 +625,6 @@
창작자의 마음비공개비공개
- 썸네일 URL호스트이제 이 채널을 구독했습니다알림 받기
diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml
index 58b25709b..b6264fbf5 100644
--- a/app/src/main/res/values-lt/strings.xml
+++ b/app/src/main/res/values-lt/strings.xml
@@ -617,7 +617,6 @@
ViešasPrivatusNeįtrauktas į sąrašą
- Paveikslėlio URLServerisPagalbaKalba
diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml
index a613dd70a..c312062b1 100644
--- a/app/src/main/res/values-lv/strings.xml
+++ b/app/src/main/res/values-lv/strings.xml
@@ -653,7 +653,6 @@
Zemas kvalitātes (mazāks)PrivātumsSarakstā neiekļauts
- Video attēla URLUzņēmumsAttālinātie meklēšanas ieteikumiAtzīmēt kā skatītu
diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml
index d03ae0a38..3687a325e 100644
--- a/app/src/main/res/values-ml/strings.xml
+++ b/app/src/main/res/values-ml/strings.xml
@@ -609,7 +609,6 @@
സ്വകാര്യംലിസ്റ്റ് ചെയ്യപ്പെടാത്തത്പൊതുവായത്
- ചെറുചിത്രം URLഹോസ്റ്റ്പിന്തുണഭാഷ
diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml
index 1637fe1f7..ae503b551 100644
--- a/app/src/main/res/values-nb-rNO/strings.xml
+++ b/app/src/main/res/values-nb-rNO/strings.xml
@@ -621,7 +621,6 @@
PrivatUlistetOffentlig
- Miniatyrbilde-nettadresseTjenerStøtteSpråk
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index e5b7f0f82..564ca873a 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -600,7 +600,6 @@
PrivéNiet vermeldOpenbaar
- Miniatuur-URLHostOndersteuningTaal
diff --git a/app/src/main/res/values-or/strings.xml b/app/src/main/res/values-or/strings.xml
index 519a0f199..fdbe665a5 100644
--- a/app/src/main/res/values-or/strings.xml
+++ b/app/src/main/res/values-or/strings.xml
@@ -419,7 +419,6 @@
ଟୋଗଲ୍ ସେବା, ବର୍ତ୍ତମାନ ମନୋନୀତ:ଫେରସ୍ତ କରଓଭର୍ ରାଇଟ୍ କରନ୍ତୁ
- ଥମ୍ବନେଲ୍ URLହୋଷ୍ଟସାର୍ଵଜନୀନତାଲିକାଭୁକ୍ତ ନୁହେଁ
diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml
index 253a87740..521931aae 100644
--- a/app/src/main/res/values-pa/strings.xml
+++ b/app/src/main/res/values-pa/strings.xml
@@ -441,7 +441,6 @@
ਨਿੱਜੀ (ਪ੍ਰਾਈਵੇਟ)ਗੈਰ-ਸੂਚੀਬੱਧਜਨਤਕ
- ਥੰਮਨੇਲ URLਮੇਜ਼ਬਾਨਸਹਾਇਤਾਭਾਸ਼ਾ/ਬੋਲੀ
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index b250901ff..9df249f39 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -619,7 +619,6 @@
WewnętrznyPrywatnyPubliczny
- Adres URL miniaturyHostWsparcieJęzyk
diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml
index c344fa826..7fec3d54c 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -613,7 +613,6 @@
Não ListadoPúblicoLimite de Idade
- URL da MiniaturaHospedado emSuporteIdioma
diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml
index dc3c8e48c..c7897a4a1 100644
--- a/app/src/main/res/values-pt-rPT/strings.xml
+++ b/app/src/main/res/values-pt-rPT/strings.xml
@@ -617,7 +617,6 @@
PrivadoNão listadoPúblico
- URL da miniaturaServidorApoioIdioma
diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml
index c3c981fad..efa6060d8 100644
--- a/app/src/main/res/values-pt/strings.xml
+++ b/app/src/main/res/values-pt/strings.xml
@@ -630,7 +630,6 @@
PrivadoNão listadoPúblico
- URL da miniaturaServidorApoioIdioma
diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml
index 0a6920b6b..5d69144df 100644
--- a/app/src/main/res/values-ro/strings.xml
+++ b/app/src/main/res/values-ro/strings.xml
@@ -618,7 +618,6 @@
PrivatNelistatPublic
- URL miniaturăGazdăSprijinLimbă
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 4b03f15c7..f54c0318e 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -629,7 +629,6 @@
ПриватнаяНе в спискеПубличная
- URL миниатюрыСерверДоступностьВ быстром режиме обновления подробности об этом не предоставляются.
diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml
index 7846eb274..1e915a3c0 100644
--- a/app/src/main/res/values-sc/strings.xml
+++ b/app/src/main/res/values-sc/strings.xml
@@ -602,7 +602,6 @@
No elencaduPrivaduPùblicu
- URL de sa miniaduraIstrangiadoreSuportuLimba
diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml
index 51f9eb490..9d6117bb9 100644
--- a/app/src/main/res/values-sk/strings.xml
+++ b/app/src/main/res/values-sk/strings.xml
@@ -611,7 +611,6 @@
InternéSúkromnéNezaradené
- URL miniatúryVerejnéHostiteľPodpora
diff --git a/app/src/main/res/values-so/strings.xml b/app/src/main/res/values-so/strings.xml
index b3f4051c4..f36983526 100644
--- a/app/src/main/res/values-so/strings.xml
+++ b/app/src/main/res/values-so/strings.xml
@@ -602,7 +602,6 @@
Gaar ahAan liistada kujirinLawada arko
- Tixraaca galkaMartigaliyeTaageeroLuuqada
diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml
index 5bfe72573..ab5b914fe 100644
--- a/app/src/main/res/values-sq/strings.xml
+++ b/app/src/main/res/values-sq/strings.xml
@@ -587,7 +587,6 @@
PrivateE palistuarPublike
- URL e pamjes statikeMundësuesiMbështetjeGjuha
diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml
index b31ee604b..ddb07544b 100644
--- a/app/src/main/res/values-sr/strings.xml
+++ b/app/src/main/res/values-sr/strings.xml
@@ -612,7 +612,6 @@
личноненаведенојавно
- УРЛ сличицеДомаћинПодршкаЈезик
diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml
index 02e472e4d..939f5aa5c 100644
--- a/app/src/main/res/values-sv/strings.xml
+++ b/app/src/main/res/values-sv/strings.xml
@@ -628,7 +628,6 @@
AktuelltNatt-temaAviseringar för videohashningsframsteg
- Miniatyrbild-webbadressInaktivera medietunnel om du upplever en svart skärm eller att videouppspelningen hackar.Inaktivera medietunnelHjärtmärkt av innehållsskaparen
diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml
index 28bc92347..52f4d7697 100644
--- a/app/src/main/res/values-tr/strings.xml
+++ b/app/src/main/res/values-tr/strings.xml
@@ -601,7 +601,6 @@
GizliListelenmemişHerkese Açık
- Küçük Resim URL\'siKonakçıDestekDil
diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml
index 0b024c861..d65e1e435 100644
--- a/app/src/main/res/values-uk/strings.xml
+++ b/app/src/main/res/values-uk/strings.xml
@@ -618,7 +618,6 @@
ПублічнеПриватнеПоза списком
- URL мініатюриВласникПідтримкаМова
diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml
index 9609943ca..7f38d3c34 100644
--- a/app/src/main/res/values-vi/strings.xml
+++ b/app/src/main/res/values-vi/strings.xml
@@ -596,7 +596,6 @@
Riêng tưChưa được liệt kêCông khai
- URL hình thu nhỏNơi chứaHỗ trợNgôn ngữ
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index d1d91dcd2..b663b1953 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -593,7 +593,6 @@
私享未分类公开
- 缩略图 URL所在服务器支持语言
diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml
index 91f2f3fc8..01eb91a8c 100644
--- a/app/src/main/res/values-zh-rHK/strings.xml
+++ b/app/src/main/res/values-zh-rHK/strings.xml
@@ -508,7 +508,6 @@
分類標籤公開設定
- 縮圖 URL公開憑網址瀏覽置頂留言
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 225e4562f..18d67f34f 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -592,7 +592,6 @@
私人未列出公開
- 縮圖 URL主機支援語言
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 705a84aab..2ccc6a412 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -753,9 +753,11 @@
LanguageSupportHost
- Thumbnail URL
- Avatar URL
- Banner URL
+ Thumbnails
+ Uploader avatars
+ Sub-channel avatars
+ Avatars
+ BannersPublicUnlistedPrivate
From 8d463b95777ecddca14ff16e5cf9a6a5fd6ae968 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Tue, 2 May 2023 20:10:52 +0200
Subject: [PATCH 013/162] Further improve image resolution strategy
Now using multiple comparison steps instead of magic values
---
.../newpipe/util/image/ImageStrategy.java | 108 ++++++++++--------
.../util/image/PreferredImageQuality.java | 15 +++
2 files changed, 73 insertions(+), 50 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java b/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java
index 5de0b52f4..89e63af3f 100644
--- a/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java
+++ b/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java
@@ -1,5 +1,8 @@
package org.schabi.newpipe.util.image;
+import static org.schabi.newpipe.extractor.Image.HEIGHT_UNKNOWN;
+import static org.schabi.newpipe.extractor.Image.WIDTH_UNKNOWN;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -10,9 +13,10 @@ import java.util.List;
public final class ImageStrategy {
- // the height thresholds also used by the extractor (TODO move them to the extractor)
- private static final int LOW_MEDIUM = 175;
- private static final int MEDIUM_HIGH = 720;
+ // when preferredImageQuality is LOW or MEDIUM, images are sorted by how close their preferred
+ // image quality is to these values (H stands for "Height")
+ private static final int BEST_LOW_H = 75;
+ private static final int BEST_MEDIUM_H = 250;
private static PreferredImageQuality preferredImageQuality = PreferredImageQuality.MEDIUM;
@@ -28,35 +32,18 @@ public final class ImageStrategy {
}
- private static double estimatePixelCount(final Image image,
- final double widthOverHeight,
- final boolean unknownsLast) {
- if (image.getHeight() == Image.HEIGHT_UNKNOWN) {
- if (image.getWidth() == Image.WIDTH_UNKNOWN) {
- switch (image.getEstimatedResolutionLevel()) {
- case LOW:
- return unknownsLast
- ? (LOW_MEDIUM - 1) * (LOW_MEDIUM - 1) * widthOverHeight
- : 0;
- case MEDIUM:
- return unknownsLast
- ? (MEDIUM_HIGH - 1) * (MEDIUM_HIGH - 1) * widthOverHeight
- : LOW_MEDIUM * LOW_MEDIUM * widthOverHeight;
- case HIGH:
- return unknownsLast
- ? 1e20 // less than 1e21 to prefer over fully unknown image sizes
- : MEDIUM_HIGH * MEDIUM_HIGH * widthOverHeight;
- default:
- case UNKNOWN:
- // images whose size is completely unknown will be avoided when possible
- return unknownsLast ? 1e21 : -1;
- }
+ static double estimatePixelCount(final Image image, final double widthOverHeight) {
+ if (image.getHeight() == HEIGHT_UNKNOWN) {
+ if (image.getWidth() == WIDTH_UNKNOWN) {
+ // images whose size is completely unknown will be in their own subgroups, so
+ // any one of them will do, hence returning the same value for all of them
+ return 0;
} else {
return image.getWidth() * image.getWidth() / widthOverHeight;
}
- } else if (image.getWidth() == Image.WIDTH_UNKNOWN) {
+ } else if (image.getWidth() == WIDTH_UNKNOWN) {
return image.getHeight() * image.getHeight() * widthOverHeight;
} else {
@@ -70,36 +57,57 @@ public final class ImageStrategy {
return null; // do not load images
}
+ // this will be used to estimate the pixel count for images where only one of height or
+ // width are known
final double widthOverHeight = images.stream()
- .filter(image -> image.getHeight() != Image.HEIGHT_UNKNOWN
- && image.getWidth() != Image.WIDTH_UNKNOWN)
+ .filter(image -> image.getHeight() != HEIGHT_UNKNOWN
+ && image.getWidth() != WIDTH_UNKNOWN)
.mapToDouble(image -> ((double) image.getWidth()) / image.getHeight())
.findFirst()
.orElse(1.0);
- final Comparator comparator;
- switch (preferredImageQuality) {
- case LOW:
- comparator = Comparator.comparingDouble(
- image -> estimatePixelCount(image, widthOverHeight, true));
- break;
- default:
- case MEDIUM:
- comparator = Comparator.comparingDouble(image -> {
- final double pixelCount = estimatePixelCount(image, widthOverHeight, true);
- final double mediumHeight = (LOW_MEDIUM + MEDIUM_HIGH) / 2.0;
- return Math.abs(pixelCount - mediumHeight * mediumHeight * widthOverHeight);
- });
- break;
- case HIGH:
- comparator = Comparator.comparingDouble(
- image -> estimatePixelCount(image, widthOverHeight, false))
- .reversed();
- break;
- }
+ final Image.ResolutionLevel preferredLevel = preferredImageQuality.toResolutionLevel();
+ final Comparator initialComparator = Comparator
+ // the first step splits the images into groups of resolution levels
+ .comparingInt(i -> {
+ if (i.getEstimatedResolutionLevel() == Image.ResolutionLevel.UNKNOWN) {
+ return 3; // avoid unknowns as much as possible
+ } else if (i.getEstimatedResolutionLevel() == preferredLevel) {
+ return 0; // prefer a matching resolution level
+ } else if (i.getEstimatedResolutionLevel() == Image.ResolutionLevel.MEDIUM) {
+ return 1; // the preferredLevel is only 1 "step" away (either HIGH or LOW)
+ } else {
+ return 2; // the preferredLevel is the furthest away possible (2 "steps")
+ }
+ })
+ // then each level's group is further split into two subgroups, one with known image
+ // size (which is also the preferred subgroup) and the other without
+ .thenComparing(image ->
+ image.getHeight() == HEIGHT_UNKNOWN && image.getWidth() == WIDTH_UNKNOWN);
+
+ // The third step chooses, within each subgroup with known image size, the best image based
+ // on how close its size is to BEST_LOW_H or BEST_MEDIUM_H (with proper units). Subgroups
+ // without known image size will be left untouched since estimatePixelCount always returns
+ // the same number for those.
+ final Comparator finalComparator = switch (preferredImageQuality) {
+ case NONE -> initialComparator; // unreachable
+ case LOW -> initialComparator.thenComparingDouble(image -> {
+ final double pixelCount = estimatePixelCount(image, widthOverHeight);
+ return Math.abs(pixelCount - BEST_LOW_H * BEST_LOW_H * widthOverHeight);
+ });
+ case MEDIUM -> initialComparator.thenComparingDouble(image -> {
+ final double pixelCount = estimatePixelCount(image, widthOverHeight);
+ return Math.abs(pixelCount - BEST_MEDIUM_H * BEST_MEDIUM_H * widthOverHeight);
+ });
+ case HIGH -> initialComparator.thenComparingDouble(
+ // this is reversed with a - so that the highest resolution is chosen
+ i -> -estimatePixelCount(i, widthOverHeight));
+ };
return images.stream()
- .min(comparator)
+ // using "min" basically means "take the first group, then take the first subgroup,
+ // then choose the best image, while ignoring all other groups and subgroups"
+ .min(finalComparator)
.map(Image::getUrl)
.orElse(null);
}
diff --git a/app/src/main/java/org/schabi/newpipe/util/image/PreferredImageQuality.java b/app/src/main/java/org/schabi/newpipe/util/image/PreferredImageQuality.java
index 9f17082ea..7106359b3 100644
--- a/app/src/main/java/org/schabi/newpipe/util/image/PreferredImageQuality.java
+++ b/app/src/main/java/org/schabi/newpipe/util/image/PreferredImageQuality.java
@@ -3,6 +3,7 @@ package org.schabi.newpipe.util.image;
import android.content.Context;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.extractor.Image;
public enum PreferredImageQuality {
NONE,
@@ -21,4 +22,18 @@ public enum PreferredImageQuality {
return MEDIUM; // default to medium
}
}
+
+ public Image.ResolutionLevel toResolutionLevel() {
+ switch (this) {
+ case LOW:
+ return Image.ResolutionLevel.LOW;
+ case MEDIUM:
+ return Image.ResolutionLevel.MEDIUM;
+ case HIGH:
+ return Image.ResolutionLevel.HIGH;
+ default:
+ case NONE:
+ return Image.ResolutionLevel.UNKNOWN;
+ }
+ }
}
From bf908f0b7dc44338f24c7a2b3d745070023a8704 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Tue, 2 May 2023 21:06:12 +0200
Subject: [PATCH 014/162] Add documentation and fix SonarCloud issue
---
.../playlist/model/PlaylistRemoteEntity.java | 6 +++-
.../detail/BaseDescriptionFragment.java | 1 +
.../external_communication/ShareUtils.java | 4 +--
.../newpipe/util/image/ImageStrategy.java | 22 +++++++++++--
.../newpipe/util/image/PicassoHelper.java | 31 ++++++++++---------
5 files changed, 43 insertions(+), 21 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java
index 5e8977821..a64f2952c 100644
--- a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java
+++ b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java
@@ -70,7 +70,9 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem {
@Ignore
public PlaylistRemoteEntity(final PlaylistInfo info) {
this(info.getServiceId(), info.getName(), info.getUrl(),
- ImageStrategy.choosePreferredImage(info.getThumbnails()),
+ // use uploader avatar when no thumbnail is available
+ ImageStrategy.choosePreferredImage(info.getThumbnails().isEmpty()
+ ? info.getUploaderAvatars() : info.getThumbnails()),
info.getUploaderName(), info.getStreamCount());
}
@@ -84,6 +86,8 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem {
&& getStreamCount() == info.getStreamCount()
&& TextUtils.equals(getName(), info.getName())
&& TextUtils.equals(getUrl(), info.getUrl())
+ // we want to update the local playlist data even when either the remote thumbnail
+ // URL changes, or the preferred image quality setting is changed by the user
&& TextUtils.equals(getThumbnailUrl(),
ImageStrategy.choosePreferredImage(info.getThumbnails()))
&& TextUtils.equals(getUploader(), info.getUploaderName());
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java
index 2bd5906bc..ffd10d827 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java
@@ -224,6 +224,7 @@ public abstract class BaseDescriptionFragment extends BaseFragment {
case LOW:
urls.append(getString(R.string.image_quality_low));
break;
+ default: // unreachable, Image.ResolutionLevel.UNKNOWN is already filtered out
case MEDIUM:
urls.append(getString(R.string.image_quality_medium));
break;
diff --git a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java
index fc057de41..7524e5413 100644
--- a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java
+++ b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java
@@ -269,8 +269,8 @@ public final class ShareUtils {
*
*
* For Android 10+ users, a content preview is shown, which includes the title of the shared
- * content and an image preview the content, if its URL is not null or empty and its
- * corresponding image is in the image cache.
+ * content and an image preview the content, if the preferred image chosen by {@link
+ * ImageStrategy#choosePreferredImage(List)} is in the image cache.
*
*
* @param context the context to use
diff --git a/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java b/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java
index 89e63af3f..1583c0b09 100644
--- a/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java
+++ b/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java
@@ -38,19 +38,35 @@ public final class ImageStrategy {
// images whose size is completely unknown will be in their own subgroups, so
// any one of them will do, hence returning the same value for all of them
return 0;
-
} else {
return image.getWidth() * image.getWidth() / widthOverHeight;
}
-
} else if (image.getWidth() == WIDTH_UNKNOWN) {
return image.getHeight() * image.getHeight() * widthOverHeight;
-
} else {
return image.getHeight() * image.getWidth();
}
}
+ /**
+ * Chooses an image amongst the provided list based on the user preference previously set with
+ * {@link #setPreferredImageQuality(PreferredImageQuality)}. {@code null} will be returned in
+ * case the list is empty or the user preference is to not show images.
+ *
+ * These properties will be preferred, from most to least important:
+ *
+ *
The image's {@link Image#getEstimatedResolutionLevel()} is not unknown and is close
+ * to {@link #preferredImageQuality}
+ *
At least one of the image's width or height are known
+ *
The highest resolution image is finally chosen if the user's preference is {@link
+ * PreferredImageQuality#HIGH}, otherwise the chosen image is the one that has the closest
+ * height to {@link #BEST_LOW_H} or {@link #BEST_MEDIUM_H}
+ *
+ *
+ * @param images the images from which to choose
+ * @return the chosen preferred image, or {@link null} if the list is empty or the user disabled
+ * images
+ */
@Nullable
public static String choosePreferredImage(@NonNull final List images) {
if (preferredImageQuality == PreferredImageQuality.NONE) {
diff --git a/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java b/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java
index ccf7c3737..fb0c97fe1 100644
--- a/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java
+++ b/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java
@@ -9,6 +9,7 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.BitmapCompat;
@@ -49,7 +50,7 @@ public final class PicassoHelper {
picassoCache = new LruCache(10 * 1024 * 1024);
picassoDownloaderClient = new OkHttpClient.Builder()
.cache(new okhttp3.Cache(new File(context.getExternalCacheDir(), "picasso"),
- 50 * 1024 * 1024))
+ 50L * 1024L * 1024L))
// this should already be the default timeout in OkHttp3, but just to be sure...
.callTimeout(15, TimeUnit.SECONDS)
.build();
@@ -90,50 +91,50 @@ public final class PicassoHelper {
}
- public static RequestCreator loadAvatar(final List images) {
+ public static RequestCreator loadAvatar(@NonNull final List images) {
return loadImageDefault(images, R.drawable.placeholder_person);
}
- public static RequestCreator loadAvatar(final String url) {
+ public static RequestCreator loadAvatar(@Nullable final String url) {
return loadImageDefault(url, R.drawable.placeholder_person);
}
- public static RequestCreator loadThumbnail(final List images) {
+ public static RequestCreator loadThumbnail(@NonNull final List images) {
return loadImageDefault(images, R.drawable.placeholder_thumbnail_video);
}
- public static RequestCreator loadThumbnail(final String url) {
+ public static RequestCreator loadThumbnail(@Nullable final String url) {
return loadImageDefault(url, R.drawable.placeholder_thumbnail_video);
}
- public static RequestCreator loadDetailsThumbnail(final List images) {
+ public static RequestCreator loadDetailsThumbnail(@NonNull final List images) {
return loadImageDefault(choosePreferredImage(images),
R.drawable.placeholder_thumbnail_video, false);
}
- public static RequestCreator loadBanner(final List images) {
+ public static RequestCreator loadBanner(@NonNull final List images) {
return loadImageDefault(images, R.drawable.placeholder_channel_banner);
}
- public static RequestCreator loadPlaylistThumbnail(final List images) {
+ public static RequestCreator loadPlaylistThumbnail(@NonNull final List images) {
return loadImageDefault(images, R.drawable.placeholder_thumbnail_playlist);
}
- public static RequestCreator loadPlaylistThumbnail(final String url) {
+ public static RequestCreator loadPlaylistThumbnail(@Nullable final String url) {
return loadImageDefault(url, R.drawable.placeholder_thumbnail_playlist);
}
- public static RequestCreator loadSeekbarThumbnailPreview(final String url) {
+ public static RequestCreator loadSeekbarThumbnailPreview(@Nullable final String url) {
return picassoInstance.load(url);
}
- public static RequestCreator loadNotificationIcon(final String url) {
+ public static RequestCreator loadNotificationIcon(@Nullable final String url) {
return loadImageDefault(url, R.drawable.ic_newpipe_triangle_white);
}
public static RequestCreator loadScaledDownThumbnail(final Context context,
- final List images) {
+ @NonNull final List images) {
// scale down the notification thumbnail for performance
return PicassoHelper.loadThumbnail(images)
.transform(new Transformation() {
@@ -182,18 +183,18 @@ public final class PicassoHelper {
}
@Nullable
- public static Bitmap getImageFromCacheIfPresent(final String imageUrl) {
+ public static Bitmap getImageFromCacheIfPresent(@NonNull final String imageUrl) {
// URLs in the internal cache finish with \n so we need to add \n to image URLs
return picassoCache.get(imageUrl + "\n");
}
- private static RequestCreator loadImageDefault(final List images,
+ private static RequestCreator loadImageDefault(@NonNull final List images,
final int placeholderResId) {
return loadImageDefault(choosePreferredImage(images), placeholderResId);
}
- private static RequestCreator loadImageDefault(final String url,
+ private static RequestCreator loadImageDefault(@Nullable final String url,
final int placeholderResId) {
return loadImageDefault(url, placeholderResId, true);
}
From 37af2c87e8a275f8168e76a1dc38cb6a631202b7 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Tue, 2 May 2023 21:12:32 +0200
Subject: [PATCH 015/162] Fix possible NPE in PlayQueueNavigator
---
.../player/mediasession/PlayQueueNavigator.java | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java b/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java
index f925bff16..3339869c1 100644
--- a/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java
+++ b/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java
@@ -138,10 +138,12 @@ public class PlayQueueNavigator implements MediaSessionConnector.QueueNavigator
.putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, player.getPlayQueue().size());
descBuilder.setExtras(additionalMetadata);
- final Uri thumbnailUri = Uri.parse(
- ImageStrategy.choosePreferredImage(item.getThumbnails()));
- if (thumbnailUri != null) {
- descBuilder.setIconUri(thumbnailUri);
+ try {
+ descBuilder.setIconUri(Uri.parse(
+ ImageStrategy.choosePreferredImage(item.getThumbnails())));
+ } catch (final Throwable e) {
+ // no thumbnail available at all, or the user disabled image loading,
+ // or the obtained url is not a valid `Uri`
}
return descBuilder.build();
From 87dca0f7ec6a22c8218489cb82454c4d6ed6beb6 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Tue, 2 May 2023 21:36:11 +0200
Subject: [PATCH 016/162] Separate imageListToDbUrl from choosePreferredImage
imageListToDbUrl should be used if the URL is going to be saved to the database, to avoid saving nothing in case at the moment of saving the user preference is to not show images.
---
.../database/playlist/PlaylistStreamEntry.kt | 2 +-
.../playlist/model/PlaylistRemoteEntity.java | 4 +-
.../database/stream/StreamStatisticsEntry.kt | 2 +-
.../database/stream/model/StreamEntity.kt | 10 +-
.../subscription/SubscriptionEntity.java | 4 +-
.../list/channel/ChannelFragment.java | 2 +-
.../subscription/SubscriptionFragment.kt | 4 +-
.../local/subscription/SubscriptionManager.kt | 4 +-
.../newpipe/util/image/ImageStrategy.java | 104 ++++++++++++++----
9 files changed, 96 insertions(+), 40 deletions(-)
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 47dc1d06a..1d74c6d31 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
@@ -29,7 +29,7 @@ data class PlaylistStreamEntry(
item.duration = streamEntity.duration
item.uploaderName = streamEntity.uploader
item.uploaderUrl = streamEntity.uploaderUrl
- item.thumbnails = ImageStrategy.urlToImageList(streamEntity.thumbnailUrl)
+ item.thumbnails = ImageStrategy.dbUrlToImageList(streamEntity.thumbnailUrl)
return item
}
diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java
index a64f2952c..7c6b4a8b0 100644
--- a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java
+++ b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java
@@ -71,7 +71,7 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem {
public PlaylistRemoteEntity(final PlaylistInfo info) {
this(info.getServiceId(), info.getName(), info.getUrl(),
// use uploader avatar when no thumbnail is available
- ImageStrategy.choosePreferredImage(info.getThumbnails().isEmpty()
+ ImageStrategy.imageListToDbUrl(info.getThumbnails().isEmpty()
? info.getUploaderAvatars() : info.getThumbnails()),
info.getUploaderName(), info.getStreamCount());
}
@@ -89,7 +89,7 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem {
// we want to update the local playlist data even when either the remote thumbnail
// URL changes, or the preferred image quality setting is changed by the user
&& TextUtils.equals(getThumbnailUrl(),
- ImageStrategy.choosePreferredImage(info.getThumbnails()))
+ ImageStrategy.imageListToDbUrl(info.getThumbnails()))
&& TextUtils.equals(getUploader(), info.getUploaderName());
}
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 81e17b720..1f3654e7a 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
@@ -31,7 +31,7 @@ class StreamStatisticsEntry(
item.duration = streamEntity.duration
item.uploaderName = streamEntity.uploader
item.uploaderUrl = streamEntity.uploaderUrl
- item.thumbnails = ImageStrategy.urlToImageList(streamEntity.thumbnailUrl)
+ item.thumbnails = ImageStrategy.dbUrlToImageList(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 4eecc9373..d9c160b89 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
@@ -68,7 +68,8 @@ 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,
- uploaderUrl = item.uploaderUrl, thumbnailUrl = ImageStrategy.choosePreferredImage(item.thumbnails), viewCount = item.viewCount,
+ uploaderUrl = item.uploaderUrl,
+ thumbnailUrl = ImageStrategy.imageListToDbUrl(item.thumbnails), viewCount = item.viewCount,
textualUploadDate = item.textualUploadDate, uploadDate = item.uploadDate?.offsetDateTime(),
isUploadDateApproximation = item.uploadDate?.isApproximation
)
@@ -77,7 +78,8 @@ 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,
- uploaderUrl = info.uploaderUrl, thumbnailUrl = ImageStrategy.choosePreferredImage(info.thumbnails), viewCount = info.viewCount,
+ uploaderUrl = info.uploaderUrl,
+ thumbnailUrl = ImageStrategy.imageListToDbUrl(info.thumbnails), viewCount = info.viewCount,
textualUploadDate = info.textualUploadDate, uploadDate = info.uploadDate?.offsetDateTime(),
isUploadDateApproximation = info.uploadDate?.isApproximation
)
@@ -87,7 +89,7 @@ data class StreamEntity(
serviceId = item.serviceId, url = item.url, title = item.title,
streamType = item.streamType, duration = item.duration, uploader = item.uploader,
uploaderUrl = item.uploaderUrl,
- thumbnailUrl = ImageStrategy.choosePreferredImage(item.thumbnails)
+ thumbnailUrl = ImageStrategy.imageListToDbUrl(item.thumbnails)
)
fun toStreamInfoItem(): StreamInfoItem {
@@ -95,7 +97,7 @@ data class StreamEntity(
item.duration = duration
item.uploaderName = uploader
item.uploaderUrl = uploaderUrl
- item.thumbnails = ImageStrategy.urlToImageList(thumbnailUrl)
+ item.thumbnails = ImageStrategy.dbUrlToImageList(thumbnailUrl)
if (viewCount != null) item.viewCount = viewCount as Long
item.textualUploadDate = textualUploadDate
diff --git a/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java b/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java
index 3fb474423..a61a22a84 100644
--- a/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java
+++ b/app/src/main/java/org/schabi/newpipe/database/subscription/SubscriptionEntity.java
@@ -58,7 +58,7 @@ public class SubscriptionEntity {
final SubscriptionEntity result = new SubscriptionEntity();
result.setServiceId(info.getServiceId());
result.setUrl(info.getUrl());
- result.setData(info.getName(), ImageStrategy.choosePreferredImage(info.getAvatars()),
+ result.setData(info.getName(), ImageStrategy.imageListToDbUrl(info.getAvatars()),
info.getDescription(), info.getSubscriberCount());
return result;
}
@@ -139,7 +139,7 @@ public class SubscriptionEntity {
@Ignore
public ChannelInfoItem toChannelInfoItem() {
final ChannelInfoItem item = new ChannelInfoItem(getServiceId(), getUrl(), getName());
- item.setThumbnails(ImageStrategy.urlToImageList(getAvatarUrl()));
+ item.setThumbnails(ImageStrategy.dbUrlToImageList(getAvatarUrl()));
item.setSubscriberCount(getSubscriberCount());
item.setDescription(getDescription());
return item;
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
index 3ece760ca..b16f40a4a 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
@@ -355,7 +355,7 @@ public class ChannelFragment extends BaseStateFragment
channel.setServiceId(info.getServiceId());
channel.setUrl(info.getUrl());
channel.setData(info.getName(),
- ImageStrategy.choosePreferredImage(info.getAvatars()),
+ ImageStrategy.imageListToDbUrl(info.getAvatars()),
info.getDescription(),
info.getSubscriberCount());
channelSubscription = null;
diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt
index ac82d5c91..fe2321059 100644
--- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt
+++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt
@@ -61,7 +61,6 @@ import org.schabi.newpipe.util.OnClickGesture
import org.schabi.newpipe.util.ServiceHelper
import org.schabi.newpipe.util.ThemeHelper.getGridSpanCountChannels
import org.schabi.newpipe.util.external_communication.ShareUtils
-import org.schabi.newpipe.util.image.ImageStrategy
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@@ -342,8 +341,7 @@ class SubscriptionFragment : BaseStateFragment() {
val actions = DialogInterface.OnClickListener { _, i ->
when (i) {
0 -> ShareUtils.shareText(
- requireContext(), selectedItem.name, selectedItem.url,
- ImageStrategy.choosePreferredImage(selectedItem.thumbnails)
+ requireContext(), selectedItem.name, selectedItem.url, selectedItem.thumbnails
)
1 -> ShareUtils.openUrlInBrowser(requireContext(), selectedItem.url)
2 -> deleteChannel(selectedItem)
diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt
index cfd5196be..bd42bbe41 100644
--- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt
+++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionManager.kt
@@ -74,7 +74,7 @@ class SubscriptionManager(context: Context) {
Completable.fromRunnable {
it.setData(
info.name,
- ImageStrategy.choosePreferredImage(info.avatars),
+ ImageStrategy.imageListToDbUrl(info.avatars),
info.description,
info.subscriberCount
)
@@ -105,7 +105,7 @@ class SubscriptionManager(context: Context) {
} else if (info is ChannelInfo) {
subscriptionEntity.setData(
info.name,
- ImageStrategy.choosePreferredImage(info.avatars),
+ ImageStrategy.imageListToDbUrl(info.avatars),
info.description,
info.subscriberCount
)
diff --git a/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java b/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java
index 1583c0b09..da97179b6 100644
--- a/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java
+++ b/app/src/main/java/org/schabi/newpipe/util/image/ImageStrategy.java
@@ -49,30 +49,16 @@ public final class ImageStrategy {
}
/**
- * Chooses an image amongst the provided list based on the user preference previously set with
- * {@link #setPreferredImageQuality(PreferredImageQuality)}. {@code null} will be returned in
- * case the list is empty or the user preference is to not show images.
- *
- * These properties will be preferred, from most to least important:
- *
- *
The image's {@link Image#getEstimatedResolutionLevel()} is not unknown and is close
- * to {@link #preferredImageQuality}
- *
At least one of the image's width or height are known
- *
The highest resolution image is finally chosen if the user's preference is {@link
- * PreferredImageQuality#HIGH}, otherwise the chosen image is the one that has the closest
- * height to {@link #BEST_LOW_H} or {@link #BEST_MEDIUM_H}
- *
+ * {@link #choosePreferredImage(List)} contains the description for this function's logic.
*
- * @param images the images from which to choose
- * @return the chosen preferred image, or {@link null} if the list is empty or the user disabled
- * images
+ * @param images the images from which to choose
+ * @param nonNoneQuality the preferred quality (must NOT be {@link PreferredImageQuality#NONE})
+ * @return the chosen preferred image, or {@link null} if the list is empty
+ * @see #choosePreferredImage(List)
*/
@Nullable
- public static String choosePreferredImage(@NonNull final List images) {
- if (preferredImageQuality == PreferredImageQuality.NONE) {
- return null; // do not load images
- }
-
+ static String choosePreferredImage(@NonNull final List images,
+ final PreferredImageQuality nonNoneQuality) {
// this will be used to estimate the pixel count for images where only one of height or
// width are known
final double widthOverHeight = images.stream()
@@ -82,7 +68,7 @@ public final class ImageStrategy {
.findFirst()
.orElse(1.0);
- final Image.ResolutionLevel preferredLevel = preferredImageQuality.toResolutionLevel();
+ final Image.ResolutionLevel preferredLevel = nonNoneQuality.toResolutionLevel();
final Comparator initialComparator = Comparator
// the first step splits the images into groups of resolution levels
.comparingInt(i -> {
@@ -105,7 +91,7 @@ public final class ImageStrategy {
// on how close its size is to BEST_LOW_H or BEST_MEDIUM_H (with proper units). Subgroups
// without known image size will be left untouched since estimatePixelCount always returns
// the same number for those.
- final Comparator finalComparator = switch (preferredImageQuality) {
+ final Comparator finalComparator = switch (nonNoneQuality) {
case NONE -> initialComparator; // unreachable
case LOW -> initialComparator.thenComparingDouble(image -> {
final double pixelCount = estimatePixelCount(image, widthOverHeight);
@@ -128,8 +114,78 @@ public final class ImageStrategy {
.orElse(null);
}
+ /**
+ * Chooses an image amongst the provided list based on the user preference previously set with
+ * {@link #setPreferredImageQuality(PreferredImageQuality)}. {@code null} will be returned in
+ * case the list is empty or the user preference is to not show images.
+ *
+ * These properties will be preferred, from most to least important:
+ *
+ *
The image's {@link Image#getEstimatedResolutionLevel()} is not unknown and is close
+ * to {@link #preferredImageQuality}
+ *
At least one of the image's width or height are known
+ *
The highest resolution image is finally chosen if the user's preference is {@link
+ * PreferredImageQuality#HIGH}, otherwise the chosen image is the one that has the height
+ * closest to {@link #BEST_LOW_H} or {@link #BEST_MEDIUM_H}
*
* @param context app context
* @return Comparator
@@ -746,7 +746,7 @@ public final class ListHelper {
/**
* Get a {@link Comparator} to compare {@link AudioStream}s by their format and bitrate.
*
- *
The prefered stream will be ordered last.
+ *
The preferred stream will be ordered last.
*
* @param defaultFormat the default format to look for
* @param limitDataUsage choose low bitrate audio stream
@@ -788,7 +788,7 @@ public final class ListHelper {
*
Language is English
*
*
- *
The prefered track will be ordered last.
+ *
The preferred track will be ordered last.
*
* @param context App context
* @return Comparator
@@ -825,7 +825,7 @@ public final class ListHelper {
*
Language is English
*
*
- *
The prefered track will be ordered last.
+ *
The preferred track will be ordered last.
*
* @param preferredLanguage Preferred audio stream language
* @param preferOriginalAudio Get the original audio track regardless of its language
From 77bbbc88f8e1cefca0a4d2ec9b1a6a0c6a592637 Mon Sep 17 00:00:00 2001
From: AudricV <74829229+AudricV@users.noreply.github.com>
Date: Sun, 24 Sep 2023 18:23:00 +0200
Subject: [PATCH 047/162] Use ListHelper to get secondary audio streams for
video-only streams
Instead of searching for the first audio stream matching a compatible media
format, this change makes SecondaryStreamHelper.getAudioStreamFor use methods
isLimitingDataUsage, getAudioFormatComparator and getAudioIndexByHighestRank of
ListHelper to get an audio stream which can be muxed into a video-only stream,
if available.
This allows users to download videos with the highest audio quality available
if no resolution limit on mobile data usage has been set.
The order of formats used to search a compatible audio stream has been kept.
---
.../newpipe/download/DownloadDialog.java | 4 +-
.../newpipe/util/SecondaryStreamHelper.java | 46 +++++++++++--------
2 files changed, 29 insertions(+), 21 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java
index 9e9909e85..2e0a421da 100644
--- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java
+++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java
@@ -267,8 +267,8 @@ public class DownloadDialog extends DialogFragment
if (!videoStreams.get(i).isVideoOnly()) {
continue;
}
- final AudioStream audioStream = SecondaryStreamHelper
- .getAudioStreamFor(audioStreams.getStreamsList(), videoStreams.get(i));
+ final AudioStream audioStream = SecondaryStreamHelper.getAudioStreamFor(
+ context, audioStreams.getStreamsList(), videoStreams.get(i));
if (audioStream != null) {
secondaryStreams.append(i, new SecondaryStreamHelper<>(audioStreams, audioStream));
diff --git a/app/src/main/java/org/schabi/newpipe/util/SecondaryStreamHelper.java b/app/src/main/java/org/schabi/newpipe/util/SecondaryStreamHelper.java
index 9415135cf..42a6ca361 100644
--- a/app/src/main/java/org/schabi/newpipe/util/SecondaryStreamHelper.java
+++ b/app/src/main/java/org/schabi/newpipe/util/SecondaryStreamHelper.java
@@ -1,5 +1,7 @@
package org.schabi.newpipe.util;
+import android.content.Context;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -9,6 +11,7 @@ import org.schabi.newpipe.extractor.stream.Stream;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.util.StreamItemAdapter.StreamInfoWrapper;
+import java.util.Comparator;
import java.util.List;
public class SecondaryStreamHelper {
@@ -27,12 +30,14 @@ public class SecondaryStreamHelper {
/**
* Find the correct audio stream for the desired video stream.
*
+ * @param context Android context
* @param audioStreams list of audio streams
* @param videoStream desired video ONLY stream
* @return selected audio stream or null if a candidate was not found
*/
@Nullable
- public static AudioStream getAudioStreamFor(@NonNull final List audioStreams,
+ public static AudioStream getAudioStreamFor(@NonNull final Context context,
+ @NonNull final List audioStreams,
@NonNull final VideoStream videoStream) {
final MediaFormat mediaFormat = videoStream.getFormat();
if (mediaFormat == null) {
@@ -41,33 +46,36 @@ public class SecondaryStreamHelper {
switch (mediaFormat) {
case WEBM:
- case MPEG_4:// ¿is mpeg-4 DASH?
+ case MPEG_4: // Is MPEG-4 DASH?
break;
default:
return null;
}
- final boolean m4v = (mediaFormat == MediaFormat.MPEG_4);
+ final boolean m4v = mediaFormat == MediaFormat.MPEG_4;
+ final boolean isLimitingDataUsage = ListHelper.isLimitingDataUsage(context);
- for (final AudioStream audio : audioStreams) {
- if (audio.getFormat() == (m4v ? MediaFormat.M4A : MediaFormat.WEBMA)) {
- return audio;
+ Comparator comparator = ListHelper.getAudioFormatComparator(
+ m4v ? MediaFormat.M4A : MediaFormat.WEBMA, isLimitingDataUsage);
+ int preferredAudioStreamIndex = ListHelper.getAudioIndexByHighestRank(
+ audioStreams, comparator);
+
+ if (preferredAudioStreamIndex == -1) {
+ if (m4v) {
+ return null;
+ }
+
+ comparator = ListHelper.getAudioFormatComparator(
+ MediaFormat.WEBMA_OPUS, isLimitingDataUsage);
+ preferredAudioStreamIndex = ListHelper.getAudioIndexByHighestRank(
+ audioStreams, comparator);
+
+ if (preferredAudioStreamIndex == -1) {
+ return null;
}
}
- if (m4v) {
- return null;
- }
-
- // retry, but this time in reverse order
- for (int i = audioStreams.size() - 1; i >= 0; i--) {
- final AudioStream audio = audioStreams.get(i);
- if (audio.getFormat() == MediaFormat.WEBMA_OPUS) {
- return audio;
- }
- }
-
- return null;
+ return audioStreams.get(preferredAudioStreamIndex);
}
public T getStream() {
From 609f0a2eeee7eeac030a8da4226dd599e6e5090c Mon Sep 17 00:00:00 2001
From: Tobi
Date: Sun, 24 Sep 2023 20:24:57 +0200
Subject: [PATCH 048/162] Add write permission to PR labeler workflow
---
.github/workflows/pr-labeler.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml
index 8aad9b125..6d63ec505 100644
--- a/.github/workflows/pr-labeler.yml
+++ b/.github/workflows/pr-labeler.yml
@@ -1,5 +1,7 @@
name: "PR size labeler"
on: [pull_request]
+permissions:
+ pull-requests: write
jobs:
changed-lines-count-labeler:
From db4619f5a4ac990e52d79dc95230ed7ffcb0964b Mon Sep 17 00:00:00 2001
From: Tobi
Date: Tue, 26 Sep 2023 10:40:17 +0200
Subject: [PATCH 049/162] Add content: read permission to PR size labeler
workflow
---
.github/workflows/pr-labeler.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml
index 6d63ec505..5d7e48517 100644
--- a/.github/workflows/pr-labeler.yml
+++ b/.github/workflows/pr-labeler.yml
@@ -1,6 +1,7 @@
name: "PR size labeler"
on: [pull_request]
permissions:
+ contents: read
pull-requests: write
jobs:
From e80b6b3057ac91aa42b71aa90f0e935fc6161d5c Mon Sep 17 00:00:00 2001
From: Siddhesh Naik <87667048+snaik20@users.noreply.github.com>
Date: Tue, 26 Sep 2023 14:41:33 +0530
Subject: [PATCH 050/162] Add playlist name and video name to playlist sharing
content (#10427)
- Currently, only a list of videos separated by newline are added in
the share content.
- This makes it difficult to identify a specific video in a list of
Urls.
- Used string resources for the sharing content formats.
- Added a confirmation dialog for users to choose between sharing
playlist formats.
- Added Playlist name as the header and corresponding video name for
each video url in following format.
Playlist
- Music1: https://media-url1
- Music2: https://media-url2
- Music3: https://media-url3
Co-authored-by: TobiGr
---
.../local/playlist/LocalPlaylistFragment.java | 48 ++++++++++++++++---
app/src/main/res/values/strings.xml | 8 +++-
2 files changed, 49 insertions(+), 7 deletions(-)
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 0d8f81334..28711c6fe 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
@@ -51,8 +51,8 @@ import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture;
-import org.schabi.newpipe.util.external_communication.ShareUtils;
import org.schabi.newpipe.util.PlayButtonHelper;
+import org.schabi.newpipe.util.external_communication.ShareUtils;
import java.util.ArrayList;
import java.util.Collections;
@@ -346,7 +346,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment Single.just(playlist.stream()
.map(PlaylistStreamEntry::getStreamEntity)
- .map(StreamEntity::getUrl)
+ .map(streamEntity -> {
+ if (shouldSharePlaylistDetails) {
+ return context.getString(R.string.video_details_list_item,
+ streamEntity.getTitle(), streamEntity.getUrl());
+ } else {
+ return streamEntity.getUrl();
+ }
+ })
.collect(Collectors.joining("\n"))))
.observeOn(AndroidSchedulers.mainThread())
- .subscribe(urlsText -> ShareUtils.shareText(requireContext(), name, urlsText),
+ .subscribe(urlsText -> ShareUtils.shareText(
+ context, name, shouldSharePlaylistDetails
+ ? context.getString(R.string.share_playlist_content_details,
+ name, urlsText) : urlsText),
throwable -> showUiErrorSnackbar(this, "Sharing playlist", throwable)));
}
@@ -841,5 +858,24 @@ public class LocalPlaylistFragment extends BaseLocalListFragment
+ sharePlaylist(/* shouldSharePlaylistDetails= */ true)
+ )
+ .setNegativeButton(R.string.share_playlist_with_list, (dialog, which) ->
+ sharePlaylist(/* shouldSharePlaylistDetails= */ false)
+ )
+ .show();
+ }
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 9dfca8294..bf618739c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -832,4 +832,10 @@
Medium qualityHigh quality\?
-
\ No newline at end of file
+ Share Playlist
+ Share playlist with details such as playlist name and video titles or as a simple list of video URLs
+ Share with Titles
+ Share URL list
+ - %s: %s
+ %s\n%s
+
From 0758cd6980d2cda88803930d34227b11f10d05d2 Mon Sep 17 00:00:00 2001
From: TobiGr
Date: Tue, 26 Sep 2023 11:22:22 +0200
Subject: [PATCH 051/162] Fix wrongly formatted string ressources
There were multiple substitutions specified in non-positional format in the ressources video_details_list_item and share_playlist_content_details
---
app/src/main/res/values/strings.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index bf618739c..435e9a382 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -836,6 +836,6 @@
Share playlist with details such as playlist name and video titles or as a simple list of video URLsShare with TitlesShare URL list
- - %s: %s
- %s\n%s
+ - %1$s: %2$s
+ %1$s\n%2$s
From fe7d1692c374b442801659ffa608866f12cabe55 Mon Sep 17 00:00:00 2001
From: Tobi
Date: Wed, 27 Sep 2023 10:04:27 +0200
Subject: [PATCH 052/162] Fix PR labeler permissions
Although the permission to modify PRs is granted to the entire workflow, the job still reports that it does not the permission to do so:
GITHUB_TOKEN Permissions
Contents: read
Metadata: read
PullRequests: read
This adds the permission to the job directly
---
.github/workflows/pr-labeler.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml
index 5d7e48517..1108b526c 100644
--- a/.github/workflows/pr-labeler.yml
+++ b/.github/workflows/pr-labeler.yml
@@ -8,6 +8,8 @@ jobs:
changed-lines-count-labeler:
runs-on: ubuntu-latest
name: Automatically labelling pull requests based on the changed lines count
+ permissions:
+ pull-requests: write
steps:
- name: Set a label
uses: vkirilichev/changed-lines-count-labeler@v0.2
From b50e3c07d2fbb4c2efe06b6a19e47a376bdc3e7e Mon Sep 17 00:00:00 2001
From: Tobi
Date: Mon, 2 Oct 2023 02:12:24 +0200
Subject: [PATCH 053/162] Use PR labeler fork
This updates some libs
---
.github/workflows/pr-labeler.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml
index 1108b526c..e0dba3111 100644
--- a/.github/workflows/pr-labeler.yml
+++ b/.github/workflows/pr-labeler.yml
@@ -12,7 +12,7 @@ jobs:
pull-requests: write
steps:
- name: Set a label
- uses: vkirilichev/changed-lines-count-labeler@v0.2
+ uses: TeamNewPipe/changed-lines-count-labeler@main
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
configuration-path: .github/changed-lines-count-labeler.yml
From 1cf670dad95fd6f7c03b613a571885e11c1faa8b Mon Sep 17 00:00:00 2001
From: Yingwei Zheng
Date: Mon, 18 Apr 2022 00:35:59 +0800
Subject: [PATCH 054/162] Fix inconsistency between user interaction and
database commit order when re-adding videos to the playlist
---
.../fragments/detail/VideoDetailFragment.java | 17 +++++++++++++++--
.../local/playlist/LocalPlaylistFragment.java | 9 +++++++++
2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
index 0314c2540..fe8845742 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
@@ -54,6 +54,7 @@ import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.widget.Toolbar;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.content.ContextCompat;
+import androidx.fragment.app.Fragment;
import androidx.preference.PreferenceManager;
import com.google.android.exoplayer2.PlaybackException;
@@ -89,6 +90,7 @@ import org.schabi.newpipe.fragments.list.videos.RelatedItemsFragment;
import org.schabi.newpipe.ktx.AnimationType;
import org.schabi.newpipe.local.dialog.PlaylistDialog;
import org.schabi.newpipe.local.history.HistoryRecordManager;
+import org.schabi.newpipe.local.playlist.LocalPlaylistFragment;
import org.schabi.newpipe.player.Player;
import org.schabi.newpipe.player.PlayerService;
import org.schabi.newpipe.player.PlayerType;
@@ -472,10 +474,21 @@ public final class VideoDetailFragment
binding.detailControlsBackground.setOnClickListener(v -> openBackgroundPlayer(false));
binding.detailControlsPopup.setOnClickListener(v -> openPopupPlayer(false));
- binding.detailControlsPlaylistAppend.setOnClickListener(makeOnClickListener(info ->
+ binding.detailControlsPlaylistAppend.setOnClickListener(makeOnClickListener(info -> {
+ if (getFM() != null && currentInfo != null) {
+ final Fragment fragment = getParentFragmentManager().
+ findFragmentById(R.id.fragment_holder);
+
+ // commit previous pending changes to database
+ if (fragment instanceof LocalPlaylistFragment) {
+ ((LocalPlaylistFragment) fragment).commitChanges();
+ }
+
disposables.add(PlaylistDialog.createCorrespondingDialog(requireContext(),
List.of(new StreamEntity(info)),
- dialog -> dialog.show(getParentFragmentManager(), TAG)))));
+ dialog -> dialog.show(getParentFragmentManager(), TAG)));
+ }
+ }));
binding.detailControlsDownload.setOnClickListener(v -> {
if (PermissionHelper.checkStoragePermissions(activity,
PermissionHelper.DOWNLOAD_DIALOG_REQUEST_CODE)) {
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 28711c6fe..9a75c7dbe 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
@@ -158,6 +158,15 @@ public class LocalPlaylistFragment extends BaseLocalListFragment
Date: Wed, 16 Aug 2023 23:28:02 +0200
Subject: [PATCH 055/162] Fix inconsistency when LocalPlaylist is used as
MainFragment tab
---
.../newpipe/fragments/MainFragment.java | 25 ++++++++++++++-
.../fragments/detail/VideoDetailFragment.java | 3 ++
.../local/playlist/LocalPlaylistFragment.java | 32 +++++++++++++++----
3 files changed, 52 insertions(+), 8 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java
index 023642955..96b13922b 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java
@@ -38,6 +38,7 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.databinding.FragmentMainBinding;
import org.schabi.newpipe.error.ErrorUtil;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
+import org.schabi.newpipe.local.playlist.LocalPlaylistFragment;
import org.schabi.newpipe.settings.tabs.Tab;
import org.schabi.newpipe.settings.tabs.TabsManager;
import org.schabi.newpipe.util.NavigationHelper;
@@ -217,6 +218,12 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
setTitle(tabsList.get(tabPosition).getTabName(requireContext()));
}
+ public void commitPlaylistTabs() {
+ pagerAdapter.getLocalPlaylistFragments()
+ .stream()
+ .forEach(LocalPlaylistFragment::commitChanges);
+ }
+
private void updateTabLayoutPosition() {
final ScrollableTabLayout tabLayout = binding.mainTabLayout;
final ViewPager viewPager = binding.pager;
@@ -268,10 +275,18 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
updateTitleForTab(tab.getPosition());
}
- private static final class SelectedTabsPagerAdapter
+ public static final class SelectedTabsPagerAdapter
extends FragmentStatePagerAdapterMenuWorkaround {
private final Context context;
private final List internalTabsList;
+ /**
+ * Keep reference to LocalPlaylistFragments, because their data can be modified by the user
+ * during runtime and changes are not committed immediately. However, in some cases,
+ * the changes need to be committed immediately by calling
+ * {@link LocalPlaylistFragment#commitChanges()}.
+ * The fragments are removed when {@link LocalPlaylistFragment#onDestroy()} is called.
+ */
+ private final List localPlaylistFragments = new ArrayList<>();
private SelectedTabsPagerAdapter(final Context context,
final FragmentManager fragmentManager,
@@ -298,9 +313,17 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
((BaseFragment) fragment).useAsFrontPage(true);
}
+ if (fragment instanceof LocalPlaylistFragment) {
+ localPlaylistFragments.add((LocalPlaylistFragment) fragment);
+ }
+
return fragment;
}
+ public List getLocalPlaylistFragments() {
+ return localPlaylistFragments;
+ }
+
@Override
public int getItemPosition(@NonNull final Object object) {
// Causes adapter to reload all Fragments when
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
index fe8845742..a25d0fae4 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
@@ -85,6 +85,7 @@ import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.fragments.BackPressable;
import org.schabi.newpipe.fragments.BaseStateFragment;
import org.schabi.newpipe.fragments.EmptyFragment;
+import org.schabi.newpipe.fragments.MainFragment;
import org.schabi.newpipe.fragments.list.comments.CommentsFragment;
import org.schabi.newpipe.fragments.list.videos.RelatedItemsFragment;
import org.schabi.newpipe.ktx.AnimationType;
@@ -482,6 +483,8 @@ public final class VideoDetailFragment
// commit previous pending changes to database
if (fragment instanceof LocalPlaylistFragment) {
((LocalPlaylistFragment) fragment).commitChanges();
+ } else if (fragment instanceof MainFragment) {
+ ((MainFragment) fragment).commitPlaylistTabs();
}
disposables.add(PlaylistDialog.createCorrespondingDialog(requireContext(),
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 9a75c7dbe..51da52ae0 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
@@ -41,6 +41,7 @@ import org.schabi.newpipe.databinding.PlaylistControlBinding;
import org.schabi.newpipe.error.ErrorInfo;
import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
+import org.schabi.newpipe.fragments.MainFragment;
import org.schabi.newpipe.fragments.list.playlist.PlaylistControlViewHolder;
import org.schabi.newpipe.info_list.dialog.InfoItemDialog;
import org.schabi.newpipe.info_list.dialog.StreamDialogDefaultEntry;
@@ -71,7 +72,7 @@ import io.reactivex.rxjava3.subjects.PublishSubject;
public class LocalPlaylistFragment extends BaseLocalListFragment, Void>
implements PlaylistControlViewHolder {
- // Save the list 10 seconds after the last change occurred
+ /** Save the list 10 seconds after the last change occurred. */
private static final long SAVE_DEBOUNCE_MILLIS = 10000;
private static final int MINIMUM_INITIAL_DRAG_VELOCITY = 12;
@State
@@ -92,13 +93,20 @@ public class LocalPlaylistFragment extends BaseLocalListFragment debouncedSaveSignal;
private CompositeDisposable disposables;
- /* Has the playlist been fully loaded from db */
+ /** Whether the playlist has been fully loaded from db. */
private AtomicBoolean isLoadingComplete;
- /* Has the playlist been modified (e.g. items reordered or deleted) */
+ /** Whether the playlist has been modified (e.g. items reordered or deleted) */
private AtomicBoolean isModified;
- /* Flag to prevent simultaneous rewrites of the playlist */
+ /** Flag to prevent simultaneous rewrites of the playlist. */
private boolean isRewritingPlaylist = false;
+ /**
+ * The pager adapter that the fragment is created from when it is used as frontpage, i.e.
+ * {@link #useAsFrontPage} is {@link true}.
+ */
+ @Nullable
+ private MainFragment.SelectedTabsPagerAdapter tabsPagerAdapter = null;
+
public static LocalPlaylistFragment getInstance(final long playlistId, final String name) {
final LocalPlaylistFragment instance = new LocalPlaylistFragment();
instance.setInitialData(playlistId, name);
@@ -158,9 +166,11 @@ public class LocalPlaylistFragment extends BaseLocalListFragmentCommit changes immediately if the playlist has been modified.
+ * Delete operations and other modifications will be committed to ensure that the database
+ * is up to date, e.g. when the user adds the just deleted stream from another fragment.
+ */
public void commitChanges() {
if (isModified != null && isModified.get()) {
saveImmediate();
@@ -300,6 +310,9 @@ public class LocalPlaylistFragment extends BaseLocalListFragment
Date: Mon, 2 Oct 2023 15:58:26 +0200
Subject: [PATCH 056/162] Create Serbian README (#10465)
---
README.md | 2 +-
doc/README.asm.md | 2 +-
doc/README.de.md | 2 +-
doc/README.es.md | 2 +-
doc/README.fr.md | 2 +-
doc/README.hi.md | 2 +-
doc/README.it.md | 2 +-
doc/README.ja.md | 2 +-
doc/README.ko.md | 2 +-
doc/README.pa.md | 2 +-
doc/README.pl.md | 2 +-
doc/README.pt_BR.md | 2 +-
doc/README.ro.md | 2 +-
doc/README.ru.md | 2 +-
doc/README.ryu.md | 2 +-
doc/README.so.md | 2 +-
doc/README.sr.md | 141 ++++++++++++++++++++++++++++++++++++++++++++
doc/README.tr.md | 2 +-
doc/README.zh_TW.md | 2 +-
19 files changed, 159 insertions(+), 18 deletions(-)
create mode 100644 doc/README.sr.md
diff --git a/README.md b/README.md
index fe7154fe1..ed25bfa41 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@
-*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md)*
+*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md), [Српски](doc/README.sr.md)*
WARNUNG: DIESE APP BEFINDET SICH IN EINER BETA-PHASE, DAHER KÖNNTEST DU BUGS BEGEGNEN. FALLS DIES PASSIERT, ERSTELLE EIN ISSUE (AUF ENGLISCH) IN UNSEREM GITHUB REPOSITORY, INDEM DU DIE VORLAGE DORT AUSFÜLLST.
diff --git a/doc/README.es.md b/doc/README.es.md
index 29356cdcd..54c2b4253 100644
--- a/doc/README.es.md
+++ b/doc/README.es.md
@@ -18,7 +18,7 @@
-*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md)*
+*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md), [Српски](doc/README.sr.md)*
AVISO: ESTA ES UNA VERSIÓN BETA, POR LO TANTO, PUEDES ENCONTRAR BUGS. SI ENCUENTRAS UNO ABRA UN ISSUE A TRAVÉS DE NUESTRO REPOSITORIO DE GITHUB.
diff --git a/doc/README.fr.md b/doc/README.fr.md
index dd752b051..d9b378f3c 100644
--- a/doc/README.fr.md
+++ b/doc/README.fr.md
@@ -17,7 +17,7 @@
-*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md)*
+*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md), [Српски](doc/README.sr.md)*
ATTENTION: CETTE APP EST EN BETA, VOUS POUVEZ DONC RENCONTRER DES BUGS. SI C'EST LE CAS, OUVREZ UNE ISSUE DANS NOTRE DÉPÔT GITHUB EN REMPLISSANT LE MODÈLE D'ISSUE.
diff --git a/doc/README.hi.md b/doc/README.hi.md
index 7ce4605ea..c87b3626c 100644
--- a/doc/README.hi.md
+++ b/doc/README.hi.md
@@ -17,7 +17,7 @@
-*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md)*
+*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md), [Српски](doc/README.sr.md)*
चेतावनी: यह एक बीटा संस्करण है, तो अगर आपको इसमें बग्स नज़र आते हैं, कृपया हमारे GitHub रिपॉज़िटरी के ज़रिए एक समस्या खोल दें।
diff --git a/doc/README.it.md b/doc/README.it.md
index 76b90318e..c5af6516f 100644
--- a/doc/README.it.md
+++ b/doc/README.it.md
@@ -17,7 +17,7 @@
-*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md)*
+*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md), [Српски](doc/README.sr.md)*
ВНИМАНИЕ: ЭТО ПРИЛОЖЕНИЕ НАХОДИТСЯ В СТАДИИ БЕТА, ПОЭТОМУ ВЫ МОЖЕТЕ ОБНАРУЖИТЬ ОШИБКИ. ЕСЛИ ЭТО СЛУЧИТСЯ, ОТКРОЙТЕ ВОПРОС В НАШЕМ РЕПОЗИТОРИИ GITHUB, ЗАПОЛНЯ ЕГО ПО ШАБЛОНУ.
diff --git a/doc/README.ryu.md b/doc/README.ryu.md
index f68645b07..b74f18f95 100644
--- a/doc/README.ryu.md
+++ b/doc/README.ryu.md
@@ -17,7 +17,7 @@
+
+
+*Прочитајте овај документ на другим језицима: [Deutsch](doc/README.de.md), [English](README.md), [Español](doc/README.es.md), [Français](doc/README.fr.md), [हिन्दी](doc/README.hi.md), [Italiano](doc/README.it.md), [한국어](doc/README.ko.md), [Português Brasil](doc/README.pt_BR.md), [Polski](doc/README.pl.md), [ਪੰਜਾਬੀ ](doc/README.pa.md), [日本語](doc/README.ja.md), [Română](doc/README.ro.md), [Soomaali](doc/README.so.md), [Türkçe](doc/README.tr.md), [正體中文](doc/README.zh_TW.md), [অসমীয়া](doc/README.asm.md), [Српски](doc/README.sr.md)*
+
+УПОЗОРЕЊЕ: ОВА АПЛИКАЦИЈА ЈЕ У БЕТА ВЕРЗИЈИ, ТАКО ДА МОЖЕТЕ НАИЋИ НА ГРЕШКЕ. АКО НАИЂЕТЕ, НАПИШИТЕ ИЗВЕШТАЈ У НАШЕМ GITHUB РЕПОЗИТОРИЈУМУ ПОПУЊАВАЊЕМ ШАБЛОНА ИЗВЕШТАЈА.
+
+ПОСТАВЉАЊЕ АПЛИКАЦИЈЕ NEWPIPE ИЛИ БИЛО КОГ ЊЕНОГ ФОРКА, У GOOGLE PLAY ПРОДАВНИЦУ КРШИ ЊИХОВЕ УСЛОВЕ И ОДРЕДБЕ.
+
+## Снимци екрана
+
+[](../fastlane/metadata/android/en-US/images/phoneScreenshots/00.png)
+[](../fastlane/metadata/android/en-US/images/phoneScreenshots/01.png)
+[](../fastlane/metadata/android/en-US/images/phoneScreenshots/02.png)
+[](../fastlane/metadata/android/en-US/images/phoneScreenshots/03.png)
+[](../fastlane/metadata/android/en-US/images/phoneScreenshots/04.png)
+[](../fastlane/metadata/android/en-US/images/phoneScreenshots/05.png)
+[](../fastlane/metadata/android/en-US/images/phoneScreenshots/06.png)
+[](../fastlane/metadata/android/en-US/images/phoneScreenshots/07.png)
+[](../fastlane/metadata/android/en-US/images/phoneScreenshots/08.png)
+
+[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/09.png)
+[](../fastlane/metadata/android/en-US/images/tenInchScreenshots/10.png)
+
+### Подржане услуге
+
+NewPipe тренутно подржава ове услуге:
+
+
+* YouTube ([веб-сајт](https://www.youtube.com/)) и YouTube Music ([веб-сајт](https://music.youtube.com/)) ([вики](https://en.wikipedia.org/wiki/YouTube))
+* PeerTube ([веб-сајт](https://joinpeertube.org/)) и све његове инстанце (отворите веб-сајт да бисте сазнали шта то значи!) ([вики](https://en.wikipedia.org/wiki/PeerTube))
+* Bandcamp ([веб-сајт](https://bandcamp.com/)) ([вики](https://en.wikipedia.org/wiki/Bandcamp))
+* SoundCloud ([веб-сајт](https://soundcloud.com/)) ([вики](https://en.wikipedia.org/wiki/SoundCloud))
+* media.ccc.de ([веб-сајт](https://media.ccc.de/)) ([вики](https://en.wikipedia.org/wiki/Chaos_Computer_Club))
+
+Као што видите, NewPipe подржава више видео и аудио услуга. Иако је почело са YouTube-ом, други људи су додали више услуга током година, чинећи NewPipe све разноврснијим!
+
+Делимично због околности, а делимично због своје популарности, YouTube је најбоље подржан од ових услуга. Ако користите или сте упознати са било којом од ових других услуга, помозите нам да побољшамо подршку за њих! Тражимо одржаваоце за SoundCloud и PeerTube.
+
+Ако намеравате да додате нову услугу, прво нас контактирајте! Наши [документи](https://teamnewpipe.github.io/documentation/) пружају више информација о томе како се нова услуга може додати у апликацију и у [NewPipe Extractor](https://github.com/TeamNewPipe/NewPipeExtractor).
+
+## Опис
+
+NewPipe ради тако што преузима потребне податке из званичног API-ја (нпр. PeerTube) услуге коју користите. Ако је званични API ограничен (нпр. YouTube) за наше сврхе или је власнички, апликација анализира веб-сајт или уместо тога користи унутрашњи API. То значи да вам није потребан налог ни на једној услузи да бисте користили NewPipe.
+
+Такође, пошто су бесплатни и отвореног кода, ни апликација, ни Extractor не користе никакве власничке библиотеке или радне оквире, као што су Google Play услуге. То значи да можете да користите NewPipe на уређајима или прилагођеним ROM-овима који немају инсталиране Google апликације.
+
+### Карактеристике
+
+ * Гледајте видео снимке у резолуцијама до 4К
+ * Слушајте аудио снимке у позадини, само учитавајући аудио стрим да бисте сачували податке
+ * Искачући режим (плутајући плејер, познат као „Слика у слици”)
+ * Гледајте стримове уживо
+ * Прикажите/сакријте титлове/скривене титлове
+ * Претражујте видео и аудио снимке (на YouTube-у можете одредити и језик садржаја)
+ * Ставите видео снимке у ред чекања (и опционо их сачувајте као локалне плејлисте)
+ * Прикажите/сакријте опште информације о видео снимцима (као што су опис и ознаке)
+ * Прикажите/сакријте следеће/сродне видео снимке
+ * Прикажите/сакријте коментаре
+ * Претражујте видео снимке, аудио снимке, канале, плејлисте и албуме
+ * Прегледајте видео и аудио снимке унутар канала
+ * Претплатите се на канале (да, без пријављивања на било који налог!)
+ * Добијајте обавештења о новим видео снимцима са канала на које сте претплаћени
+ * Креирајте и уређујте групе канала (за лакше прегледање и управљање)
+ * Прегледајте фидове видео снимака генерисане из ваших група канала
+ * Прегледајте и претражујте историју гледања
+ * Претражујте и гледајте плејлисте (ово су даљинске плејлисте, што значи да се преузимају са услуге коју прегледате)
+ * Направите и уређујте локалне плејлисте (оне се креирају и чувају у апликацији и немају никакве везе са било којом услугом)
+ * Преузмите видео снимке/аудио снимке/титлове (скривене титлове)
+ * Отварајте у Kodi-ју
+ * Гледајте/блокирајте старосно ограничени материјал
+
+## Инсталација и ажурирања
+Можете да инсталирате NewPipe користећи један од следећих начина:
+ 1. Додајте наш прилагођени репозиторијум на F-Droid и инсталирајте га одатле. Упутства су овде: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/
+ 2. Преузмите APK са [GitHub издања](https://github.com/TeamNewPipe/NewPipe/releases) и инсталирајте га.
+ 3. Ажурирајте преко F-Droid-а. Ово је најспорији начин добијања ажурирања, јер F-Droid мора да препозна промене, да направи сам APK, да га потпише, а затим да ажурирање пошаље корисницима.
+ 4. Сами направите APK за отклањање грешака. Ово је најбржи начин да добијете нове функције на свом уређају, али је много компликованији, па препоручујемо да користите неки од других начина.
+ 5. Ако сте заинтересовани за одређену функцију или исправку грешке која се налази у захтеву за повлачење у овом репозиторијуму, такође можете преузети његов APK из захтева за повлачење. Прочитајте опис захтева за повлачење за упутства. Одлична ствар у вези са APK-овима специфичним за захтев за повлачење је то што су инсталирани упоредо са званичном апликацијом, тако да не морате да бринете да ћете изгубити своје податке или нешто забрљати.
+
+Препоручујемо 1. начин за већину корисника. APK-ови инсталирани коришћењем 1. или 2. начина су компатибилни један са другим (што значи да ако сте инсталирали NewPipe користећи било који 1. или 2. начин, можете, такође, да ажурирате NewPipe користећи други начин), али не и са онима инсталираним коришћењем 3. начина. То је због истог кључа за потписивање (нашег) који се користи за 1. и 2. начин, али се други кључ за потписивање (F-Droid-ови) користи за 3. начин. Израда APK-а за отклањање грешака коришћењем 4. начина искључује кључ у потпуности. Кључеви за потписивање помажу да се осигура да корисник не буде преварен да инсталира злонамерно ажурирање за апликацију. Када користите 5. начин, сваки APK је потписан различитим, насумичним кључем који обезбеђује GitHub Actions, тако да не можете ни да га ажурирате. Мораћете да направите резервну копију и вратите податке апликације сваки пут када желите да користите нови APK.
+
+У међувремену, ако желите да промените изворе из неког разлога (нпр. основна функционалност NewPipe-а се прекида, а F-Droid још увек нема најновије ажурирање), препоручујемо вам да следите ову процедуру: 1. Направите резервну копију података преко Подешавања > Садржај > Извези базу података, да бисте задржали своју историју, претплате и листе песама 2. Деинсталирајте NewPipe 3. Преузмите APK са новог извора и инсталирајте га 4. Увезите податке из 1. корака преко Подешавања > Садржај > Увези базу података
+
+Напомена: када увозите базу података у званичну апликацију, увек се уверите да је то она коју сте извезли _из_ званичне апликације. Ако увезете базу података извезену из APK-а, који није званична апликација, то може покварити ствари. Таква радња није подржана и требало би да то урадите само када сте потпуно сигурни да знате шта радите.
+
+## Допринос
+Без обзира да ли имате идеје, преводе, промене дизајна, чишћење кода или чак велике промене кода, помоћ је увек добродошла. Апликација постаје све боља и боља са сваким доприносом, без обзира колико је он велики или мали! Ако желите да се укључите, погледајте наше [напомене о доприносима](.github/CONTRIBUTING.md).
+
+
+
+
+
+## Донација
+Ако вам се свиђа NewPipe, можете послати донацију. Више волимо Liberapay, јер је отвореног кода и непрофитан. За више информација о донирању апликацији NewPipe, посетите наш [веб-сајт](https://newpipe.net/donate).
+
+
+
+
+
+
+
+
+
+
+
16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
+
+
+
+
+
+
+
+
+## Политика приватности
+
+Пројекат NewPipe има за циљ да обезбеди приватно, анонимно искуство за коришћење медијских услуга заснованих на вебу. Стога, апликација не прикупља никакве податке без вашег пристанка. Политика приватности апликације NewPipe детаљно објашњава који се подаци шаљу и чувају када пошаљете извештај о отказивању или оставите коментар на нашем блогу. Документ можете пронаћи [овде](https://newpipe.net/legal/privacy/).
+
+## Лиценца
+[![GNU GPLv3 Image](https://www.gnu.org/graphics/gplv3-127x51.png)](https://www.gnu.org/licenses/gpl-3.0.en.html)
+
+NewPipe је бесплатан софтвер: можете га користити, проучавати, делити и побољшавати по жељи. Конкретно, можете га редистрибуирати и/или модификовати под условима [GNU General Public License](https://www.gnu.org/licenses/gpl.html), коју је објавила Фондација за слободни софтвер, било верзију 3 лиценце или (по вашем избору) било коју каснију верзију.
diff --git a/doc/README.tr.md b/doc/README.tr.md
index d51144e56..2f68ecffe 100644
--- a/doc/README.tr.md
+++ b/doc/README.tr.md
@@ -17,7 +17,7 @@
-*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md), [Српски](doc/README.sr.md)*
+*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md), [Српски](README.sr.md)*
WARNUNG: DIESE APP BEFINDET SICH IN EINER BETA-PHASE, DAHER KÖNNTEST DU BUGS BEGEGNEN. FALLS DIES PASSIERT, ERSTELLE EIN ISSUE (AUF ENGLISCH) IN UNSEREM GITHUB REPOSITORY, INDEM DU DIE VORLAGE DORT AUSFÜLLST.
diff --git a/doc/README.es.md b/doc/README.es.md
index 54c2b4253..78c44b9fb 100644
--- a/doc/README.es.md
+++ b/doc/README.es.md
@@ -18,7 +18,7 @@
-*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md), [Српски](doc/README.sr.md)*
+*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md), [Српски](README.sr.md)*
AVISO: ESTA ES UNA VERSIÓN BETA, POR LO TANTO, PUEDES ENCONTRAR BUGS. SI ENCUENTRAS UNO ABRA UN ISSUE A TRAVÉS DE NUESTRO REPOSITORIO DE GITHUB.
diff --git a/doc/README.fr.md b/doc/README.fr.md
index d9b378f3c..4ca1f1e94 100644
--- a/doc/README.fr.md
+++ b/doc/README.fr.md
@@ -17,7 +17,7 @@
-*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md), [Српски](doc/README.sr.md)*
+*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md), [Српски](README.sr.md)*
ATTENTION: CETTE APP EST EN BETA, VOUS POUVEZ DONC RENCONTRER DES BUGS. SI C'EST LE CAS, OUVREZ UNE ISSUE DANS NOTRE DÉPÔT GITHUB EN REMPLISSANT LE MODÈLE D'ISSUE.
diff --git a/doc/README.hi.md b/doc/README.hi.md
index c87b3626c..ec9965be6 100644
--- a/doc/README.hi.md
+++ b/doc/README.hi.md
@@ -17,7 +17,7 @@
-*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md), [Српски](doc/README.sr.md)*
+*Read this document in other languages: [Deutsch](README.de.md), [English](../README.md), [Español](README.es.md), [Français](README.fr.md), [हिन्दी](README.hi.md), [Italiano](README.it.md), [한국어](README.ko.md), [Português Brasil](README.pt_BR.md), [Polski](README.pl.md), [ਪੰਜਾਬੀ ](README.pa.md), [日本語](README.ja.md), [Română](README.ro.md), [Soomaali](README.so.md), [Türkçe](README.tr.md), [正體中文](README.zh_TW.md), [অসমীয়া](README.asm.md), [うちなーぐち](README.ryu.md), [Српски](README.sr.md)*
ВНИМАНИЕ: ЭТО ПРИЛОЖЕНИЕ НАХОДИТСЯ В СТАДИИ БЕТА, ПОЭТОМУ ВЫ МОЖЕТЕ ОБНАРУЖИТЬ ОШИБКИ. ЕСЛИ ЭТО СЛУЧИТСЯ, ОТКРОЙТЕ ВОПРОС В НАШЕМ РЕПОЗИТОРИИ GITHUB, ЗАПОЛНЯ ЕГО ПО ШАБЛОНУ.
diff --git a/doc/README.ryu.md b/doc/README.ryu.md
index b74f18f95..ce1a38bd9 100644
--- a/doc/README.ryu.md
+++ b/doc/README.ryu.md
@@ -17,7 +17,7 @@
## Privacy Policy
diff --git a/doc/README.asm.md b/doc/README.asm.md
index 98253371e..8f39d26a1 100644
--- a/doc/README.asm.md
+++ b/doc/README.asm.md
@@ -110,7 +110,7 @@ NewPipe এ আপুনি ব্যৱহাৰ কৰা সেৱাৰ অ
## অনুদান
-যদি আপুনি NewPipe ভাল পায় তেন্তে অনুদান প্ৰেৰণ কৰিব পাৰে। আমি Liberapay পছন্দ কৰো, কাৰণ ই মুক্ত উৎস(Open Source) আৰু অলাভজনক(Non-profit) দুয়োটা। NewPipe লৈ দান দিয়াৰ বিষয়ে অধিক তথ্যৰ বাবে অনুগ্ৰহ কৰি আমাৰ [ৱেবচাইট](https://newpipe.net/donate) চাওক.
16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
+যদি আপুনি NewPipe ভাল পায় তেন্তে অনুদান প্ৰেৰণ কৰিব পাৰে। আমি Liberapay পছন্দ কৰো, কাৰণ ই মুক্ত উৎস(Open Source) আৰু অলাভজনক(Non-profit) দুয়োটা। NewPipe লৈ দান দিয়াৰ বিষয়ে অধিক তথ্যৰ বাবে অনুগ্ৰহ কৰি আমাৰ [ৱেবচাইট](https://newpipe.net/donate) চাওক.
## গোপনীয়তা নীতি
diff --git a/doc/README.de.md b/doc/README.de.md
index b84fadeae..cc9c313fa 100644
--- a/doc/README.de.md
+++ b/doc/README.de.md
@@ -143,16 +143,6 @@ Für weitere Informationen über Spenden an NewPipe, besuche unsere [Website](ht
-
-
-
-
16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
-
-
-
-
-
-
## Privacy Policy
diff --git a/doc/README.es.md b/doc/README.es.md
index 78c44b9fb..c2959fe04 100644
--- a/doc/README.es.md
+++ b/doc/README.es.md
@@ -115,21 +115,11 @@ Si quiere involucrarse, fíjese en nuestras [notas de contribución](../.github/
Si te gusta NewPipe, estaremos felices con una donación. Puede enviar bitcoin o donar a través de Bountysource o Liberapay. Visita nuestro [sitio web](https://newpipe.net/donate) para más información.
-
-
-
-
16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
-
-
-
-
-
-
## Política de Privacidad
diff --git a/doc/README.fr.md b/doc/README.fr.md
index 4ca1f1e94..2e56e7ff1 100644
--- a/doc/README.fr.md
+++ b/doc/README.fr.md
@@ -123,16 +123,6 @@ Si vous aimez NewPipe, vous êtes invités à envoyer un don. Nous préferons Li
-
-
-
-
16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
-
-
-
-
-
-
## Politique de confidentialité
diff --git a/doc/README.hi.md b/doc/README.hi.md
index ec9965be6..36669cc19 100644
--- a/doc/README.hi.md
+++ b/doc/README.hi.md
@@ -115,21 +115,11 @@ NewPipe पर कई सेवाएँ उपलब्ध हैं। हम
अगर आपको NewPipe पसंद है, एक छोटे-से दान से हम खुश होंगे। आप या तो बिटकॉइन भेज सकते हैं या फिर Bountysource या Liberapay से दान कर सकते हैं। NewPipe को दान करने के बारे में अधिक जानकारी के लिए कृपया हमारी [वेबसाइट](https://newpipe.net/donate) देखें।
-
-
-
-
16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
-
-
-
-
-
-
## गोपनीयता और शर्तें
diff --git a/doc/README.it.md b/doc/README.it.md
index ec5361dc0..cd8cb10a8 100644
--- a/doc/README.it.md
+++ b/doc/README.it.md
@@ -123,16 +123,6 @@ Se ti piace NewPipe, le donazioni sono benvenute. Preferiamo Liberapay, siccome
## プライバシーポリシー
diff --git a/doc/README.ko.md b/doc/README.ko.md
index 9ebc66be2..b690e659a 100644
--- a/doc/README.ko.md
+++ b/doc/README.ko.md
@@ -115,21 +115,11 @@ NewPipe는 서비스의 공식 API를 이용하여 정보를 받아오는 방식
만약 NewPipe가 마음에 들었다면, 우리는 기부에 대해 기꺼이 환영합니다. bitcoin을 보내거나, Bountysource 또는 Liberapay를 통해 기부할 수 있습니다. NewPipe에 기부하는 것에 대한 자세한 정보를 원한다면, 우리의 [웹사이트](https://newpipe.net/donate)를 방문하여 주십시오.
-
-
-
-
16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
-
-
-
-
-
-
## 개인정보 보호 정책
diff --git a/doc/README.pa.md b/doc/README.pa.md
index 2a3ae69af..ac52e3b31 100644
--- a/doc/README.pa.md
+++ b/doc/README.pa.md
@@ -120,16 +120,6 @@ NewPipe ਤੁਹਾਡੇ ਦੁਆਰਾ ਵਰਤੀ ਜਾ ਰਹੀ ਸੇ
-
-
-
-
16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
-
-
-
-
-
-
## ਗੋਪਨੀਅਤਾ ਨੀਤੀ
diff --git a/doc/README.pl.md b/doc/README.pl.md
index 5ba201eb0..bcd37e515 100644
--- a/doc/README.pl.md
+++ b/doc/README.pl.md
@@ -112,21 +112,11 @@ Jeśli chcesz pomóc, przeczytaj [Notkę o wkładzie](../.github/CONTRIBUTING.md
Jeśli podoba Ci się NewPipe, bardzo ucieszylibyśmy się z dotacji. Możesz wysłać bitcoin lub przekazać darowiznę przez Bountysource lub Liberapay. Po więcej informacji o darowiznach dla NewPipe, proszę zobacz naszą [stronę](https://newpipe.net/donate).
-
-
-
-
16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
-
-
-
-
-
-
## Polityka prywatności
diff --git a/doc/README.pt_BR.md b/doc/README.pt_BR.md
index 850d03e89..9945a3969 100644
--- a/doc/README.pt_BR.md
+++ b/doc/README.pt_BR.md
@@ -112,21 +112,11 @@ Se você quiser se envolver, verifique nossa [notas de contribuição](../.githu
Se você gosta de NewPipe, ficaríamos felizes com uma doação. Você pode enviar bitcoin ou doar via Bountysource ou Liberapay. Para obter mais informações sobre como doar para a NewPipe, visite nosso [site](https://newpipe.net/donate).
-
-
-
-
16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
-
-
-
-
-
-
## Política de Privacidade
diff --git a/doc/README.ro.md b/doc/README.ro.md
index 11319b5a0..3eac39563 100644
--- a/doc/README.ro.md
+++ b/doc/README.ro.md
@@ -115,21 +115,11 @@ Dacă doriţi să vă implicaţi, accesaţi [notele noastre de contribuţie](../
Dacă vă place NewPipe, am fi bucuroşi să primim o donaţie. Puteţi să ne trimiteţi bitcoin sau să ne donaţi cu Bountysource sau Liberapay. Pentru mai multe informaţii în legătură cu donaţiile către NewPipe, vă rugăm vizitaţi [website-ul nostru](https://newpipe.net/donate).
-
-
-
-
16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
-
-
-
-
-
-
## Politica de Confidenţialitate
diff --git a/doc/README.ru.md b/doc/README.ru.md
index a226b72a8..a11e88783 100644
--- a/doc/README.ru.md
+++ b/doc/README.ru.md
@@ -121,16 +121,6 @@ NewPipe работает, извлекая необходимые данные
-
-
-
-
16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
-
-
-
-
-
-
## Политика конфиденциальности
diff --git a/doc/README.ryu.md b/doc/README.ryu.md
index ce1a38bd9..56e037541 100644
--- a/doc/README.ryu.md
+++ b/doc/README.ryu.md
@@ -120,21 +120,11 @@ NewPipeーふくすんぬサービスんかいたいおうそーいびーん。[
むし、NewPipeちーがんじいただけいねー、ちーふしいただけいねーうっさいびーん。BitcoinあらんでぃBountysource,Liberapayからちーふするくとぅがなやびーん。NewPipeんかいどぅちふにちいてー、[ウェブサイト](https://newpipe.net/donate)からうにげーさびら。
-
-
-
-
16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
-
-
-
-
-
-
## プライバシーポリシー
diff --git a/doc/README.so.md b/doc/README.so.md
index 1e400b219..fdcc11fe6 100644
--- a/doc/README.so.md
+++ b/doc/README.so.md
@@ -110,21 +110,11 @@ Hadaad jeceshahay inaad qayb ka noqoto, fiiri [ogaysiisyada kusoo kordhinta](../
Hadaad jeceshahay NewPipe waan ku faraxsanaan lahayn deeq. Waxaad soo diri kartaa bitcoin ama sidoo kale waxaad deeqda kusoo diri kartaa xaga Bountysource ama Liberapay. Faahfaahin dheeraad ah oo kusaabsan ugu deeqida NewPipe, fadlan booqo [website-kanaga](https://newpipe.net/donate).
-
-
-
-
16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
-
-
-
-
-
-
## Siyaasada Sirdhawrka
diff --git a/doc/README.sr.md b/doc/README.sr.md
index 320558fc9..930eccd33 100644
--- a/doc/README.sr.md
+++ b/doc/README.sr.md
@@ -119,16 +119,6 @@ NewPipe ради тако што преузима потребне податк
-
-
-
-
16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
-
-
-
-
-
-
## Политика приватности
diff --git a/doc/README.tr.md b/doc/README.tr.md
index b2d4f2c56..3ff88c81a 100644
--- a/doc/README.tr.md
+++ b/doc/README.tr.md
@@ -114,21 +114,11 @@ Eğer yer almak istiyorsanız, [katkı sağlayanlar için hazırladığımız no
NewPipe'ı beğendiyseniz, yapacağınız bağışlar bizi motive eder. Bitcoin gönderebilir veya Bountysource veya Liberapay aracılığıyla bağış yapabilirsiniz. NewPipe'a bağış yapma hakkında daha fazla bilgi için lütfen [web sitemizi](https://newpipe.net/donate) ziyaret edin.
From 5265b767cb50005fc6346d5cc93ea1d5f7f5523b Mon Sep 17 00:00:00 2001
From: TobiGr
Date: Sat, 14 Oct 2023 18:31:33 +0200
Subject: [PATCH 071/162] Fix notifiying about old "new" streams
Add tests for `FeedDAO.unlinkStreamsOlderThan(:offsetDateTime) `
Closes #10237
---
.../schabi/newpipe/database/FeedDAOTest.kt | 124 ++++++++++++++++++
.../newpipe/database/feed/dao/FeedDAO.kt | 30 +++--
2 files changed, 144 insertions(+), 10 deletions(-)
create mode 100644 app/src/androidTest/java/org/schabi/newpipe/database/FeedDAOTest.kt
diff --git a/app/src/androidTest/java/org/schabi/newpipe/database/FeedDAOTest.kt b/app/src/androidTest/java/org/schabi/newpipe/database/FeedDAOTest.kt
new file mode 100644
index 000000000..9fa87c31b
--- /dev/null
+++ b/app/src/androidTest/java/org/schabi/newpipe/database/FeedDAOTest.kt
@@ -0,0 +1,124 @@
+package org.schabi.newpipe.database
+
+import android.content.Context
+import androidx.room.Room
+import androidx.test.core.app.ApplicationProvider
+import io.reactivex.rxjava3.core.Single
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Before
+import org.junit.Test
+import org.schabi.newpipe.database.feed.dao.FeedDAO
+import org.schabi.newpipe.database.feed.model.FeedEntity
+import org.schabi.newpipe.database.feed.model.FeedGroupEntity
+import org.schabi.newpipe.database.stream.StreamWithState
+import org.schabi.newpipe.database.stream.dao.StreamDAO
+import org.schabi.newpipe.database.stream.model.StreamEntity
+import org.schabi.newpipe.database.subscription.SubscriptionDAO
+import org.schabi.newpipe.database.subscription.SubscriptionEntity
+import org.schabi.newpipe.extractor.ServiceList
+import org.schabi.newpipe.extractor.channel.ChannelInfo
+import org.schabi.newpipe.extractor.stream.StreamType
+import java.io.IOException
+import java.time.OffsetDateTime
+import kotlin.streams.toList
+
+class FeedDAOTest {
+ private lateinit var db: AppDatabase
+ private lateinit var feedDAO: FeedDAO
+ private lateinit var streamDAO: StreamDAO
+ private lateinit var subscriptionDAO: SubscriptionDAO
+
+ private val serviceId = ServiceList.YouTube.serviceId
+
+ private val stream1 = StreamEntity(1, serviceId, "https://youtube.com/watch?v=1", "stream 1", StreamType.VIDEO_STREAM, 1000, "channel-1", "https://youtube.com/channel/1", "https://i.ytimg.com/vi/1/hqdefault.jpg", 100, "2023-01-01", OffsetDateTime.parse("2023-01-01T00:00:00Z"))
+ private val stream2 = StreamEntity(2, serviceId, "https://youtube.com/watch?v=2", "stream 2", StreamType.VIDEO_STREAM, 1000, "channel-1", "https://youtube.com/channel/1", "https://i.ytimg.com/vi/1/hqdefault.jpg", 100, "2023-01-02", OffsetDateTime.parse("2023-01-02T00:00:00Z"))
+ private val stream3 = StreamEntity(3, serviceId, "https://youtube.com/watch?v=3", "stream 3", StreamType.LIVE_STREAM, 1000, "channel-1", "https://youtube.com/channel/1", "https://i.ytimg.com/vi/1/hqdefault.jpg", 100, "2023-01-03", OffsetDateTime.parse("2023-01-03T00:00:00Z"))
+ private val stream4 = StreamEntity(4, serviceId, "https://youtube.com/watch?v=4", "stream 4", StreamType.VIDEO_STREAM, 1000, "channel-2", "https://youtube.com/channel/2", "https://i.ytimg.com/vi/1/hqdefault.jpg", 100, "2023-08-10", OffsetDateTime.parse("2023-08-10T00:00:00Z"))
+ private val stream5 = StreamEntity(5, serviceId, "https://youtube.com/watch?v=5", "stream 5", StreamType.VIDEO_STREAM, 1000, "channel-2", "https://youtube.com/channel/2", "https://i.ytimg.com/vi/1/hqdefault.jpg", 100, "2023-08-20", OffsetDateTime.parse("2023-08-20T00:00:00Z"))
+ private val stream6 = StreamEntity(6, serviceId, "https://youtube.com/watch?v=6", "stream 6", StreamType.VIDEO_STREAM, 1000, "channel-3", "https://youtube.com/channel/3", "https://i.ytimg.com/vi/1/hqdefault.jpg", 100, "2023-09-01", OffsetDateTime.parse("2023-09-01T00:00:00Z"))
+ private val stream7 = StreamEntity(7, serviceId, "https://youtube.com/watch?v=7", "stream 7", StreamType.VIDEO_STREAM, 1000, "channel-4", "https://youtube.com/channel/4", "https://i.ytimg.com/vi/1/hqdefault.jpg", 100, "2023-08-10", OffsetDateTime.parse("2023-08-10T00:00:00Z"))
+
+ private val allStreams = listOf(
+ stream1, stream2, stream3, stream4, stream5, stream6, stream7
+ )
+
+ @Before
+ fun createDb() {
+ val context = ApplicationProvider.getApplicationContext()
+ db = Room.inMemoryDatabaseBuilder(
+ context, AppDatabase::class.java
+ ).build()
+ feedDAO = db.feedDAO()
+ streamDAO = db.streamDAO()
+ subscriptionDAO = db.subscriptionDAO()
+ }
+
+ @After
+ @Throws(IOException::class)
+ fun closeDb() {
+ db.close()
+ }
+
+ @Test
+ fun testUnlinkStreamsOlderThan_KeepOne() {
+ setupUnlinkDelete("2023-08-15T00:00:00Z")
+ val streams = feedDAO.getStreams(
+ FeedGroupEntity.GROUP_ALL_ID, includePlayed = true, includePartiallyPlayed = true, null
+ )
+ .blockingGet()
+ val allowedStreams = listOf(stream3, stream5, stream6, stream7)
+ assertEqual(streams, allowedStreams)
+ }
+
+ @Test
+ fun testUnlinkStreamsOlderThan_KeepMultiple() {
+ setupUnlinkDelete("2023-08-01T00:00:00Z")
+ val streams = feedDAO.getStreams(
+ FeedGroupEntity.GROUP_ALL_ID, includePlayed = true, includePartiallyPlayed = true, null
+ )
+ .blockingGet()
+ val allowedStreams = listOf(stream3, stream4, stream5, stream6, stream7)
+ assertEqual(streams, allowedStreams)
+ }
+
+ private fun assertEqual(streams: List?, allowedStreams: List) {
+ assertNotNull(streams)
+ assertEquals(allowedStreams, streams!!.stream().map { it.stream }.toList().sortedBy { it.uid })
+ }
+
+ private fun setupUnlinkDelete(time: String) {
+ clearAndFillTables()
+ Single.fromCallable {
+ feedDAO.unlinkStreamsOlderThan(OffsetDateTime.parse(time))
+ }.blockingSubscribe()
+ Single.fromCallable {
+ streamDAO.deleteOrphans()
+ }.blockingSubscribe()
+ }
+
+ private fun clearAndFillTables() {
+ db.clearAllTables()
+ streamDAO.insertAll(allStreams)
+ subscriptionDAO.insertAll(
+ listOf(
+ SubscriptionEntity.from(ChannelInfo(serviceId, "1", "https://youtube.com/channel/1", "https://youtube.com/channel/1", "channel-1")),
+ SubscriptionEntity.from(ChannelInfo(serviceId, "2", "https://youtube.com/channel/2", "https://youtube.com/channel/2", "channel-2")),
+ SubscriptionEntity.from(ChannelInfo(serviceId, "3", "https://youtube.com/channel/3", "https://youtube.com/channel/3", "channel-3")),
+ SubscriptionEntity.from(ChannelInfo(serviceId, "4", "https://youtube.com/channel/4", "https://youtube.com/channel/4", "channel-4")),
+ )
+ )
+ feedDAO.insertAll(
+ listOf(
+ FeedEntity(1, 1),
+ FeedEntity(2, 1),
+ FeedEntity(3, 1),
+ FeedEntity(4, 2),
+ FeedEntity(5, 2),
+ FeedEntity(6, 3),
+ FeedEntity(7, 4),
+ )
+ )
+ }
+}
diff --git a/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt b/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt
index 6947f66af..028ef04f7 100644
--- a/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt
+++ b/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt
@@ -93,18 +93,28 @@ abstract class FeedDAO {
uploadDateBefore: OffsetDateTime?
): Maybe>
+ /**
+ * Remove links to streams that are older than the given date
+ * **but keep at least one stream per uploader**.
+ *
+ * One stream per uploader is kept because it is needed as reference
+ * when fetching new streams to check if they are new or not.
+ * @param offsetDateTime the newest date to keep, older streams are removed
+ */
@Query(
"""
- DELETE FROM feed WHERE
-
- feed.stream_id IN (
- SELECT s.uid FROM streams s
-
- INNER JOIN feed f
- ON s.uid = f.stream_id
-
- WHERE s.upload_date < :offsetDateTime
- )
+ DELETE FROM feed
+ WHERE feed.stream_id IN (SELECT uid from (
+ SELECT s.uid,
+ (SELECT MAX(upload_date)
+ FROM streams
+ WHERE uploader_url = s.uploader_url) max_upload_date
+ FROM streams s
+ INNER JOIN feed f
+ ON s.uid = f.stream_id
+
+ WHERE s.upload_date < :offsetDateTime
+ AND s.upload_date <> max_upload_date))
"""
)
abstract fun unlinkStreamsOlderThan(offsetDateTime: OffsetDateTime)
From 9fab0ec94f84b2f8cba03f6d6e1b00a048633796 Mon Sep 17 00:00:00 2001
From: AudricV <74829229+AudricV@users.noreply.github.com>
Date: Wed, 15 Nov 2023 00:37:05 +0100
Subject: [PATCH 072/162] Fix crash when setting the masking of the new feed
items button if the context is null
As the fragment context can be null in some cases, we have to make sure that
the context is not null before calling
DeviceUtils.hasAnimationsAnimatorDurationEnabled.
If the context is null, the button will now not be hidden automatically.
---
.../java/org/schabi/newpipe/local/feed/FeedFragment.kt | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
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 83882d35f..0b61f45fb 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
@@ -607,9 +607,13 @@ class FeedFragment : BaseStateFragment() {
execOnEnd = {
// Disabled animations would result in immediately hiding the button
// after it showed up
- if (DeviceUtils.hasAnimationsAnimatorDurationEnabled(context)) {
- // Hide the new items-"popup" after 10s
- hideNewItemsLoaded(true, 10000)
+ // Context can be null in some cases, so we have to make sure it is not null in
+ // order to avoid a NullPointerException
+ context?.let {
+ if (DeviceUtils.hasAnimationsAnimatorDurationEnabled(it)) {
+ // Hide the new items button after 10s
+ hideNewItemsLoaded(true, 10000)
+ }
}
}
)
From 2cf77647146f8f839032c0fb9862c8da54aac77c Mon Sep 17 00:00:00 2001
From: AudricV <74829229+AudricV@users.noreply.github.com>
Date: Wed, 15 Nov 2023 19:22:49 +0100
Subject: [PATCH 073/162] Fix crash when building the play queue audio track
menu if the player is null
As the player can be null in some cases, we have to make sure that the player
is not null, by using Optionals on the player itself instead of its methods
returning Optionals.
If the player is null, the play queue audio track menu will now be hidden.
---
.../java/org/schabi/newpipe/player/PlayQueueActivity.java | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java b/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java
index defc8ba21..c012f6008 100644
--- a/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java
@@ -619,11 +619,13 @@ public final class PlayQueueActivity extends AppCompatActivity
final MenuItem audioTrackSelector = menu.findItem(R.id.action_audio_track);
final List availableStreams =
- Optional.ofNullable(player.getCurrentMetadata())
+ Optional.ofNullable(player)
+ .map(Player::getCurrentMetadata)
.flatMap(MediaItemTag::getMaybeAudioTrack)
.map(MediaItemTag.AudioTrack::getAudioStreams)
.orElse(null);
- final Optional selectedAudioStream = player.getSelectedAudioStream();
+ final Optional selectedAudioStream = Optional.ofNullable(player)
+ .flatMap(Player::getSelectedAudioStream);
if (availableStreams == null || availableStreams.size() < 2
|| selectedAudioStream.isEmpty()) {
From 84d50da009b5f82bdb6df54addc13b72c6e69f5b Mon Sep 17 00:00:00 2001
From: AudricV <74829229+AudricV@users.noreply.github.com>
Date: Sun, 17 Sep 2023 20:49:13 +0200
Subject: [PATCH 074/162] Restore player service start handling before player
UI separation
This behavior was present before 0.24.0 and the player UI separation and
avoided crashes for which their exception contained
"Context.startForegroundService() did not then call Service.startForeground()".
Some player nullability checks have been also added, and the player service is
now stopped when it has been started from a media button and there is nothing
to play.
---
.../schabi/newpipe/player/PlayerService.java | 47 +++++++++++++++----
.../notification/NotificationPlayerUi.java | 14 ++----
2 files changed, 43 insertions(+), 18 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/player/PlayerService.java b/app/src/main/java/org/schabi/newpipe/player/PlayerService.java
index ad6c9405d..e7abf4320 100644
--- a/app/src/main/java/org/schabi/newpipe/player/PlayerService.java
+++ b/app/src/main/java/org/schabi/newpipe/player/PlayerService.java
@@ -29,6 +29,7 @@ import android.os.IBinder;
import android.util.Log;
import org.schabi.newpipe.player.mediasession.MediaSessionPlayerUi;
+import org.schabi.newpipe.player.notification.NotificationPlayerUi;
import org.schabi.newpipe.util.ThemeHelper;
import java.lang.ref.WeakReference;
@@ -59,6 +60,14 @@ public final class PlayerService extends Service {
ThemeHelper.setTheme(this);
player = new Player(this);
+ /*
+ Create the player notification and start immediately the service in foreground,
+ otherwise if nothing is played or initializing the player and its components (especially
+ loading stream metadata) takes a lot of time, the app would crash on Android 8+ as the
+ service would never be put in the foreground while we said to the system we would do so
+ */
+ player.UIs().get(NotificationPlayerUi.class)
+ .ifPresent(NotificationPlayerUi::createNotificationAndStartForeground);
}
@Override
@@ -68,16 +77,38 @@ public final class PlayerService extends Service {
+ "], flags = [" + flags + "], startId = [" + startId + "]");
}
+ /*
+ Be sure that the player notification is set and the service is started in foreground,
+ otherwise, the app may crash on Android 8+ as the service would never be put in the
+ foreground while we said to the system we would do so
+ The service is always requested to be started in foreground, so always creating a
+ notification if there is no one already and starting the service in foreground should
+ not create any issues
+ If the service is already started in foreground, requesting it to be started shouldn't
+ do anything
+ */
+ if (player != null) {
+ player.UIs().get(NotificationPlayerUi.class)
+ .ifPresent(NotificationPlayerUi::createNotificationAndStartForeground);
+ }
+
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())
- && player.getPlayQueue() == null) {
- // No need to process media button's actions if the player is not working, otherwise the
- // player service would strangely start with nothing to play
+ && (player == null || player.getPlayQueue() == null)) {
+ /*
+ No need to process media button's actions if the player is not working, otherwise
+ the player service would strangely start with nothing to play
+ Stop the service in this case, which will be removed from the foreground and its
+ notification cancelled in its destruction
+ */
+ stopSelf();
return START_NOT_STICKY;
}
- player.handleIntent(intent);
- player.UIs().get(MediaSessionPlayerUi.class)
- .ifPresent(ui -> ui.handleMediaButtonIntent(intent));
+ if (player != null) {
+ player.handleIntent(intent);
+ player.UIs().get(MediaSessionPlayerUi.class)
+ .ifPresent(ui -> ui.handleMediaButtonIntent(intent));
+ }
return START_NOT_STICKY;
}
@@ -87,7 +118,7 @@ public final class PlayerService extends Service {
Log.d(TAG, "stopForImmediateReusing() called");
}
- if (!player.exoPlayerIsNull()) {
+ if (player != null && !player.exoPlayerIsNull()) {
// Releases wifi & cpu, disables keepScreenOn, etc.
// We can't just pause the player here because it will make transition
// from one stream to a new stream not smooth
@@ -98,7 +129,7 @@ public final class PlayerService extends Service {
@Override
public void onTaskRemoved(final Intent rootIntent) {
super.onTaskRemoved(rootIntent);
- if (!player.videoPlayerSelected()) {
+ if (player != null && !player.videoPlayerSelected()) {
return;
}
onDestroy();
diff --git a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationPlayerUi.java
index 4b1fc417f..75b27545c 100644
--- a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationPlayerUi.java
+++ b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationPlayerUi.java
@@ -17,7 +17,6 @@ import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.player.ui.PlayerUi;
public final class NotificationPlayerUi extends PlayerUi {
- private boolean foregroundNotificationAlreadyCreated = false;
private final NotificationUtil notificationUtil;
public NotificationPlayerUi(@NonNull final Player player) {
@@ -25,15 +24,6 @@ public final class NotificationPlayerUi extends PlayerUi {
notificationUtil = new NotificationUtil(player);
}
- @Override
- public void initPlayer() {
- super.initPlayer();
- if (!foregroundNotificationAlreadyCreated) {
- notificationUtil.createNotificationAndStartForeground();
- foregroundNotificationAlreadyCreated = true;
- }
- }
-
@Override
public void destroy() {
super.destroy();
@@ -122,4 +112,8 @@ public final class NotificationPlayerUi extends PlayerUi {
super.onPlayQueueEdited();
notificationUtil.createNotificationIfNeededAndUpdate(false);
}
+
+ public void createNotificationAndStartForeground() {
+ notificationUtil.createNotificationAndStartForeground();
+ }
}
From e5fda35c51ad07136bb4d9803bb8b1aafc1ac859 Mon Sep 17 00:00:00 2001
From: AudricV <74829229+AudricV@users.noreply.github.com>
Date: Wed, 15 Nov 2023 22:52:57 +0100
Subject: [PATCH 075/162] Remove OPUS HLS streams from playable streams
This format is not supported by ExoPlayer when returned as HLS streams, so we
can't play streams using this format and this delivery method.
Also improve the Javadoc of ListHelper.getPlayableStreams.
---
.../org/schabi/newpipe/util/ListHelper.java | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java
index 5918ece25..534d4fddd 100644
--- a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java
+++ b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java
@@ -189,13 +189,16 @@ public final class ListHelper {
/**
* Return a {@link Stream} list which only contains streams which can be played by the player.
- *
- * Some formats are not supported. For more info, see {@link #SUPPORTED_ITAG_IDS}.
- * Torrent streams are also removed, because they cannot be retrieved.
+ *
+ *
+ * Some formats are not supported, see {@link #SUPPORTED_ITAG_IDS} for more details.
+ * Torrent streams are also removed, because they cannot be retrieved, like OPUS streams using
+ * HLS as their delivery method, since they are not supported by ExoPlayer.
+ *
*
* @param the item type's class that extends {@link Stream}
* @param streamList the original stream list
- * @param serviceId
+ * @param serviceId the service ID from which the streams' list comes from
* @return a stream list which only contains streams that can be played the player
*/
@NonNull
@@ -204,6 +207,8 @@ public final class ListHelper {
final int youtubeServiceId = YouTube.getServiceId();
return getFilteredStreamList(streamList,
stream -> stream.getDeliveryMethod() != DeliveryMethod.TORRENT
+ && (stream.getDeliveryMethod() != DeliveryMethod.HLS
+ || stream.getFormat() != MediaFormat.OPUS)
&& (serviceId != youtubeServiceId
|| stream.getItagItem() == null
|| SUPPORTED_ITAG_IDS.contains(stream.getItagItem().id)));
@@ -295,7 +300,9 @@ public final class ListHelper {
final Comparator cmp = getAudioFormatComparator(context);
for (final AudioStream stream : audioStreams) {
- if (stream.getDeliveryMethod() == DeliveryMethod.TORRENT) {
+ if (stream.getDeliveryMethod() == DeliveryMethod.TORRENT
+ || (stream.getDeliveryMethod() == DeliveryMethod.HLS
+ && stream.getFormat() == MediaFormat.OPUS)) {
continue;
}
From b4a0e08d9de66994d8b6dd0404f8ac5dbb870e5e Mon Sep 17 00:00:00 2001
From: Tobi
Date: Thu, 23 Nov 2023 17:12:16 +0100
Subject: [PATCH 076/162] Update
app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt
Co-authored-by: Stypox
---
.../java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt b/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt
index 028ef04f7..e7ed93497 100644
--- a/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt
+++ b/app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt
@@ -107,8 +107,10 @@ abstract class FeedDAO {
WHERE feed.stream_id IN (SELECT uid from (
SELECT s.uid,
(SELECT MAX(upload_date)
- FROM streams
- WHERE uploader_url = s.uploader_url) max_upload_date
+ FROM streams s1
+ INNER JOIN feed f1
+ ON s1.uid = f1.stream_id
+ WHERE f1.subscription_id = f.subscription_id) max_upload_date
FROM streams s
INNER JOIN feed f
ON s.uid = f.stream_id
From ddd6d03e0b2555024daff560a879a01ac1657e05 Mon Sep 17 00:00:00 2001
From: opusforlife2 <53176348+opusforlife2@users.noreply.github.com>
Date: Wed, 6 Dec 2023 18:34:43 +0000
Subject: [PATCH 077/162] Add Matrix room link to ReadMe (#10632)
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index f26048ddc..ecfa19eb6 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,7 @@
+