From b822c5a039e2e478cab6661aa0c790c473125ad3 Mon Sep 17 00:00:00 2001
From: opusforlife2 <53176348+opusforlife2@users.noreply.github.com>
Date: Wed, 11 Nov 2020 15:20:42 +0000
Subject: [PATCH 01/57] Update Invidious URL list in the manifest
---
app/src/main/AndroidManifest.xml | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6fd62aebe..35e987cb8 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -227,20 +227,18 @@
+
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
From f7f00293cc5a7b37c10c29bb80e483a8091bc766 Mon Sep 17 00:00:00 2001
From: XiangRongLin <41164160+XiangRongLin@users.noreply.github.com>
Date: Tue, 1 Dec 2020 20:12:42 +0100
Subject: [PATCH 02/57] Extract export database logic into own class
- Separate it from the UI.
- Add happy path unit test.
---
.../settings/ContentSettingsFragment.java | 33 +++------
.../settings/ContentSettingsManager.kt | 45 ++++++++++++
.../settings/ContentSettingsManagerTest.kt | 72 +++++++++++++++++++
app/src/test/resources/settings/newpipe.db | 1 +
.../test/resources/settings/newpipe.settings | 0
checkstyle-suppressions.xml | 2 +-
6 files changed, 127 insertions(+), 26 deletions(-)
create mode 100644 app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt
create mode 100644 app/src/test/java/org/schabi/newpipe/settings/ContentSettingsManagerTest.kt
create mode 100644 app/src/test/resources/settings/newpipe.db
create mode 100644 app/src/test/resources/settings/newpipe.settings
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 b0425ebfa..6ef2f732e 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java
@@ -30,19 +30,15 @@ import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.FilePickerActivityHelper;
import org.schabi.newpipe.util.ZipHelper;
-import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.zip.ZipFile;
-import java.util.zip.ZipOutputStream;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
@@ -50,6 +46,8 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
private static final int REQUEST_IMPORT_PATH = 8945;
private static final int REQUEST_EXPORT_PATH = 30945;
+ private ContentSettingsManager manager;
+
private File databasesDir;
private File newpipeDb;
private File newpipeDbJournal;
@@ -131,6 +129,8 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
newpipeSettings = new File(homeDir + "/databases/newpipe.settings");
newpipeSettings.delete();
+ manager = new ContentSettingsManager(homeDir);
+
addPreferencesFromResource(R.xml.content_settings);
final Preference importDataPreference = findPreference(getString(R.string.import_data));
@@ -212,33 +212,16 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
//checkpoint before export
NewPipeDatabase.checkpoint();
- try (ZipOutputStream outZip = new ZipOutputStream(new BufferedOutputStream(
- new FileOutputStream(path)))) {
- ZipHelper.addFileToZip(outZip, newpipeDb.getPath(), "newpipe.db");
+ final SharedPreferences preferences = PreferenceManager
+ .getDefaultSharedPreferences(requireContext());
+ manager.exportDatabase(preferences, path);
- saveSharedPreferencesToFile(newpipeSettings);
- ZipHelper.addFileToZip(outZip, newpipeSettings.getPath(),
- "newpipe.settings");
- }
-
- Toast.makeText(getContext(), R.string.export_complete_toast, Toast.LENGTH_SHORT)
- .show();
+ Toast.makeText(getContext(), R.string.export_complete_toast, Toast.LENGTH_SHORT).show();
} catch (final Exception e) {
onError(e);
}
}
- private void saveSharedPreferencesToFile(final File dst) {
- try (ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream(dst))) {
- final SharedPreferences pref
- = PreferenceManager.getDefaultSharedPreferences(requireContext());
- output.writeObject(pref.getAll());
- output.flush();
- } catch (final IOException e) {
- e.printStackTrace();
- }
- }
-
private void importDatabase(final String filePath) {
// check if file is supported
try (ZipFile zipFile = new ZipFile(filePath)) {
diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt
new file mode 100644
index 000000000..b0ea89993
--- /dev/null
+++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt
@@ -0,0 +1,45 @@
+package org.schabi.newpipe.settings
+
+import android.content.SharedPreferences
+import org.schabi.newpipe.util.ZipHelper
+import java.io.BufferedOutputStream
+import java.io.File
+import java.io.FileOutputStream
+import java.io.IOException
+import java.io.ObjectOutputStream
+import java.lang.Exception
+import java.util.zip.ZipOutputStream
+
+class ContentSettingsManager(
+ private val newpipeDb: File,
+ private val newpipeSettings: File
+) {
+
+ constructor(homeDir: String) : this(
+ File("$homeDir/databases/newpipe.db"),
+ File("$homeDir/databases/newpipe.settings")
+ )
+
+ /**
+ * Exports given [SharedPreferences] to the file in given outputPath.
+ * It also creates the file.
+ */
+ @Throws(Exception::class)
+ fun exportDatabase(preferences: SharedPreferences, outputPath: String) {
+ ZipOutputStream(BufferedOutputStream(FileOutputStream(outputPath)))
+ .use { outZip ->
+ ZipHelper.addFileToZip(outZip, newpipeDb.path, "newpipe.db")
+
+ try {
+ ObjectOutputStream(FileOutputStream(newpipeSettings)).use { output ->
+ output.writeObject(preferences.all)
+ output.flush()
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+
+ ZipHelper.addFileToZip(outZip, newpipeSettings.path, "newpipe.settings")
+ }
+ }
+}
diff --git a/app/src/test/java/org/schabi/newpipe/settings/ContentSettingsManagerTest.kt b/app/src/test/java/org/schabi/newpipe/settings/ContentSettingsManagerTest.kt
new file mode 100644
index 000000000..9809fd5fc
--- /dev/null
+++ b/app/src/test/java/org/schabi/newpipe/settings/ContentSettingsManagerTest.kt
@@ -0,0 +1,72 @@
+package org.schabi.newpipe.settings
+
+import android.content.SharedPreferences
+import org.junit.Assert
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Suite
+import org.mockito.Mockito
+import org.mockito.Mockito.`when`
+import org.mockito.junit.MockitoJUnitRunner
+import org.schabi.newpipe.settings.ContentSettingsManagerTest.ExportTest
+import java.io.File
+import java.io.ObjectInputStream
+import java.util.zip.ZipFile
+
+@RunWith(Suite::class)
+@Suite.SuiteClasses(ExportTest::class)
+class ContentSettingsManagerTest {
+
+ @RunWith(MockitoJUnitRunner::class)
+ class ExportTest {
+
+ private lateinit var preferences: SharedPreferences
+ private lateinit var newpipeDb: File
+ private lateinit var newpipeSettings: File
+
+ @Before
+ fun beforeClass() {
+
+ val dbPath = javaClass.classLoader?.getResource("settings/newpipe.db")?.file
+ val settingsPath = javaClass.classLoader?.getResource("settings/newpipe.settings")?.path
+ Assume.assumeNotNull(dbPath)
+ Assume.assumeNotNull(settingsPath)
+
+ newpipeDb = File(dbPath!!)
+ newpipeSettings = File(settingsPath!!)
+ }
+
+ @Before
+ fun before() {
+ preferences = Mockito.mock(SharedPreferences::class.java, Mockito.withSettings().stubOnly())
+ }
+
+ @Test
+ fun `The settings must be exported successfully in the correct format`() {
+ val expectedPreferences = mapOf("such pref" to "much wow")
+ `when`(preferences.all).thenReturn(expectedPreferences)
+
+ val manager = ContentSettingsManager(newpipeDb, newpipeSettings)
+
+ val output = File.createTempFile("newpipe_", "")
+ manager.exportDatabase(preferences, output.absolutePath)
+
+ val zipFile = ZipFile(output.absoluteFile)
+ val entries = zipFile.entries().toList()
+ Assert.assertEquals(2, entries.size)
+
+ zipFile.getInputStream(entries.first { it.name == "newpipe.db" }).use { actual ->
+ newpipeDb.inputStream().use { expected ->
+ Assert.assertEquals(expected.reader().readText(), actual.reader().readText())
+ }
+ }
+
+ zipFile.getInputStream(entries.first { it.name == "newpipe.settings" }).use { actual ->
+ val actualPreferences = ObjectInputStream(actual).readObject()
+ Assert.assertEquals(expectedPreferences, actualPreferences)
+ }
+ }
+ }
+}
diff --git a/app/src/test/resources/settings/newpipe.db b/app/src/test/resources/settings/newpipe.db
new file mode 100644
index 000000000..cd3fc4717
--- /dev/null
+++ b/app/src/test/resources/settings/newpipe.db
@@ -0,0 +1 @@
+such db much wow
\ No newline at end of file
diff --git a/app/src/test/resources/settings/newpipe.settings b/app/src/test/resources/settings/newpipe.settings
new file mode 100644
index 000000000..e69de29bb
diff --git a/checkstyle-suppressions.xml b/checkstyle-suppressions.xml
index add17d42d..0a5190b29 100644
--- a/checkstyle-suppressions.xml
+++ b/checkstyle-suppressions.xml
@@ -17,7 +17,7 @@
+ lines="227,245"/>
Date: Sun, 6 Dec 2020 23:40:38 +0100
Subject: [PATCH 03/57] [FIX] - Crash while deleting a video from a playlist
while refreshing
---
.../database/playlist/PlaylistStreamEntry.kt | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt b/app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt
index d9c892099..28ce176f0 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,6 @@ 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 kotlin.jvm.Throws
class PlaylistStreamEntry(
@Embedded
@@ -36,4 +35,20 @@ class PlaylistStreamEntry(
override fun getLocalItemType(): LocalItem.LocalItemType {
return LocalItem.LocalItemType.PLAYLIST_STREAM_ITEM
}
+
+ override fun equals(other: Any?): Boolean {
+ if (other == null || other !is PlaylistStreamEntry || streamEntity != other.streamEntity ||
+ progressTime != other.progressTime || streamId != other.streamId || joinIndex != other.joinIndex
+ ) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ var result = streamEntity.hashCode()
+ result = 31 * result + progressTime.hashCode()
+ result = 31 * result + streamId.hashCode()
+ result = 31 * result + joinIndex
+ return result
+ }
}
From 5f3eb4871a69aeb6d5502fc48a66d6b2d45a56d5 Mon Sep 17 00:00:00 2001
From: hlloreda
Date: Mon, 7 Dec 2020 00:06:56 +0100
Subject: [PATCH 04/57] [IMPORT] - import got deleted
---
.../org/schabi/newpipe/database/playlist/PlaylistStreamEntry.kt | 1 +
1 file changed, 1 insertion(+)
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 28ce176f0..af741fdc8 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 kotlin.jvm.Throws
class PlaylistStreamEntry(
@Embedded
From b30e025bdac1167466d497a112d3510a2f575120 Mon Sep 17 00:00:00 2001
From: hlloreda
Date: Mon, 7 Dec 2020 10:53:33 +0100
Subject: [PATCH 05/57] [FIX] - Use of a Data class instead of overriding
equals method
---
.../database/playlist/PlaylistStreamEntry.kt | 18 +-----------------
1 file changed, 1 insertion(+), 17 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 af741fdc8..aff6205f2 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
@@ -9,7 +9,7 @@ import org.schabi.newpipe.database.stream.model.StreamStateEntity
import org.schabi.newpipe.extractor.stream.StreamInfoItem
import kotlin.jvm.Throws
-class PlaylistStreamEntry(
+data class PlaylistStreamEntry(
@Embedded
val streamEntity: StreamEntity,
@@ -36,20 +36,4 @@ class PlaylistStreamEntry(
override fun getLocalItemType(): LocalItem.LocalItemType {
return LocalItem.LocalItemType.PLAYLIST_STREAM_ITEM
}
-
- override fun equals(other: Any?): Boolean {
- if (other == null || other !is PlaylistStreamEntry || streamEntity != other.streamEntity ||
- progressTime != other.progressTime || streamId != other.streamId || joinIndex != other.joinIndex
- ) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = streamEntity.hashCode()
- result = 31 * result + progressTime.hashCode()
- result = 31 * result + streamId.hashCode()
- result = 31 * result + joinIndex
- return result
- }
}
From ac86fe80c85bae126d956484d9e27e9d8c2919ee Mon Sep 17 00:00:00 2001
From: mhmdanas <32234660+mhmdanas@users.noreply.github.com>
Date: Sun, 6 Dec 2020 18:28:46 +0300
Subject: [PATCH 06/57] Fix typos
---
app/src/main/java/org/schabi/newpipe/MainActivity.java | 6 +++---
.../java/org/schabi/newpipe/streams/Mp4FromDashWriter.java | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java
index f51ecf2d3..4a8582df2 100644
--- a/app/src/main/java/org/schabi/newpipe/MainActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java
@@ -369,8 +369,8 @@ public class MainActivity extends AppCompatActivity {
}
private void enhancePeertubeMenu(final StreamingService s, final MenuItem menuItem) {
- final PeertubeInstance currentInstace = PeertubeHelper.getCurrentInstance();
- menuItem.setTitle(currentInstace.getName() + (ServiceHelper.isBeta(s) ? " (beta)" : ""));
+ final PeertubeInstance currentInstance = PeertubeHelper.getCurrentInstance();
+ menuItem.setTitle(currentInstance.getName() + (ServiceHelper.isBeta(s) ? " (beta)" : ""));
final Spinner spinner = (Spinner) LayoutInflater.from(this)
.inflate(R.layout.instance_spinner_layout, null);
final List instances = PeertubeHelper.getInstanceList(this);
@@ -378,7 +378,7 @@ public class MainActivity extends AppCompatActivity {
int defaultSelect = 0;
for (final PeertubeInstance instance : instances) {
items.add(instance.getName());
- if (instance.getUrl().equals(currentInstace.getUrl())) {
+ if (instance.getUrl().equals(currentInstance.getUrl())) {
defaultSelect = items.size() - 1;
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/streams/Mp4FromDashWriter.java b/app/src/main/java/org/schabi/newpipe/streams/Mp4FromDashWriter.java
index 5efffe118..ca3da9d24 100644
--- a/app/src/main/java/org/schabi/newpipe/streams/Mp4FromDashWriter.java
+++ b/app/src/main/java/org/schabi/newpipe/streams/Mp4FromDashWriter.java
@@ -483,7 +483,7 @@ public class Mp4FromDashWriter {
// stsc_table_entry = [first_chunk, samples_per_chunk, sample_description_index]
tables.stscBEntries = new int[tables.stsc * 3];
- tables.stco = remainChunkOffset + 1; // total entrys in chunk offset box
+ tables.stco = remainChunkOffset + 1; // total entries in chunk offset box
tables.stscBEntries[index++] = 1;
tables.stscBEntries[index++] = firstCount;
From a00ac6b9ca53d69180ce419728cd3e7864f5c76a Mon Sep 17 00:00:00 2001
From: FireMasterK <20838718+FireMasterK@users.noreply.github.com>
Date: Wed, 9 Dec 2020 12:25:57 +0530
Subject: [PATCH 07/57] Migrate to GitHub actions from Travis.
---
.github/workflows/ci.yml | 30 ++++++++++++++++++++++++++++++
.travis.yml | 18 ------------------
2 files changed, 30 insertions(+), 18 deletions(-)
create mode 100644 .github/workflows/ci.yml
delete mode 100644 .travis.yml
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 000000000..6419c65dd
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,30 @@
+name: CI
+
+on: [push, pull_request]
+
+jobs:
+ build-and-test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: set up JDK 1.8
+ uses: actions/setup-java@v1.4.3
+ with:
+ java-version: 1.8
+
+ - name: Cache Gradle dependencies
+ uses: actions/cache@v2
+ with:
+ path: ~/.gradle/caches
+ key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
+ restore-keys: ${{ runner.os }}-gradle
+
+ - name: Build debug APK and run Tests
+ run: ./gradlew assembleDebug lintDebug testDebugUnitTest --stacktrace
+
+ - name: Upload APK
+ uses: actions/upload-artifact@v2
+ with:
+ name: app
+ path: app/build/outputs/apk/debug/*.apk
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 1714c70d5..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-language: android
-jdk:
- - oraclejdk8
-android:
- components:
- # The BuildTools version used by NewPipe
- - tools
- - build-tools-29.0.3
-
- # The SDK version used to compile NewPipe
- - android-29
-
-before_install:
- - yes | sdkmanager "platforms;android-29"
-script: ./gradlew -Dorg.gradle.jvmargs=-Xmx1536m assembleDebug lintDebug testDebugUnitTest
-
-licenses:
- - '.+'
From 567ffad41d1ce89d593ae9d313945e570f0908ab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?O=C4=9Fuz=20Ersen?=
Date: Thu, 10 Dec 2020 04:41:02 +0000
Subject: [PATCH 08/57] Translated using Weblate (Turkish)
Currently translated at 19.5% (8 of 41 strings)
Translation: NewPipe/Metadata
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/tr/
---
fastlane/metadata/android/tr/changelogs/960.txt | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 fastlane/metadata/android/tr/changelogs/960.txt
diff --git a/fastlane/metadata/android/tr/changelogs/960.txt b/fastlane/metadata/android/tr/changelogs/960.txt
new file mode 100644
index 000000000..70e1fb913
--- /dev/null
+++ b/fastlane/metadata/android/tr/changelogs/960.txt
@@ -0,0 +1,4 @@
+• Ayarlarda veri tabanı dışa aktarma seçeneğinin açıklaması iyileştirildi.
+• YouTube yorumlarının ayrıştırılması düzeltildi.
+• media.ccc.de hizmetinin görünen adı düzeltildi.
+• Çeviriler güncellendi.
From 8e2fd9ccceb99ee9d85a1aec157868396d848cb5 Mon Sep 17 00:00:00 2001
From: David Braz
Date: Wed, 9 Dec 2020 22:50:18 +0000
Subject: [PATCH 09/57] Translated using Weblate (Portuguese (Brazil))
Currently translated at 26.8% (11 of 41 strings)
Translation: NewPipe/Metadata
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pt_BR/
---
fastlane/metadata/android/pt_BR/changelogs/960.txt | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 fastlane/metadata/android/pt_BR/changelogs/960.txt
diff --git a/fastlane/metadata/android/pt_BR/changelogs/960.txt b/fastlane/metadata/android/pt_BR/changelogs/960.txt
new file mode 100644
index 000000000..6e0fa0924
--- /dev/null
+++ b/fastlane/metadata/android/pt_BR/changelogs/960.txt
@@ -0,0 +1,4 @@
+• Melhorada a descrição da opção de banco de dados de exportação nas configurações.
+• Corrigido os comentários do YouTube.
+• Corrigido o nome de exibição do serviço media.ccc.de.
+• Traduções atualizadas.
From 90150c42ed190fdfefb2e1cc47d655f136a837c9 Mon Sep 17 00:00:00 2001
From: Yaron Shahrabani
Date: Thu, 10 Dec 2020 04:36:44 +0000
Subject: [PATCH 10/57] Translated using Weblate (Hebrew)
Currently translated at 29.2% (12 of 41 strings)
Translation: NewPipe/Metadata
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/he/
---
fastlane/metadata/android/he/changelogs/960.txt | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 fastlane/metadata/android/he/changelogs/960.txt
diff --git a/fastlane/metadata/android/he/changelogs/960.txt b/fastlane/metadata/android/he/changelogs/960.txt
new file mode 100644
index 000000000..211acf887
--- /dev/null
+++ b/fastlane/metadata/android/he/changelogs/960.txt
@@ -0,0 +1,4 @@
+• תיאור מסד הנתונים המיוצא בהגדרות השתפר.
+• תוקן פענוח התגובות ב־YouTube.
+• תוקן שם התצוגה של השירות media.ccc.de.
+• התרגומים עודכנו.
From b967d7c148514e50e05b7d8e3c92359e895e33ec Mon Sep 17 00:00:00 2001
From: Terry Louwers
Date: Thu, 10 Dec 2020 06:38:14 +0000
Subject: [PATCH 11/57] Translated using Weblate (Dutch)
Currently translated at 17.0% (7 of 41 strings)
Translation: NewPipe/Metadata
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/nl/
---
fastlane/metadata/android/nl/changelogs/959.txt | 3 +++
fastlane/metadata/android/nl/changelogs/960.txt | 4 ++++
2 files changed, 7 insertions(+)
create mode 100644 fastlane/metadata/android/nl/changelogs/959.txt
create mode 100644 fastlane/metadata/android/nl/changelogs/960.txt
diff --git a/fastlane/metadata/android/nl/changelogs/959.txt b/fastlane/metadata/android/nl/changelogs/959.txt
new file mode 100644
index 000000000..d62971c4d
--- /dev/null
+++ b/fastlane/metadata/android/nl/changelogs/959.txt
@@ -0,0 +1,3 @@
+Probleem opgelost met oneindige reeks van crashes na het openen van de foutrapportage.
+Lijst met PeerTube instanties die automatisch kunnen worden geopend door NewPipe bijgewerkt.
+Vertalingen bijgewerkt.
diff --git a/fastlane/metadata/android/nl/changelogs/960.txt b/fastlane/metadata/android/nl/changelogs/960.txt
new file mode 100644
index 000000000..761028b71
--- /dev/null
+++ b/fastlane/metadata/android/nl/changelogs/960.txt
@@ -0,0 +1,4 @@
+• Verbeterde beschrijving van de export database optie in de instellingen.
+• Probleem opgelost met parsen van YouTube-reacties.
+• Probleem opgelost met de weergavenaam van de media.ccc.de service.
+• Vertalingen bijgewerkt.
From e8bd9920fd4ee923eed080d4d13dd753984602b9 Mon Sep 17 00:00:00 2001
From: Ajeje Brazorf
Date: Thu, 10 Dec 2020 13:36:44 +0000
Subject: [PATCH 12/57] Translated using Weblate (Sardinian)
Currently translated at 14.6% (6 of 41 strings)
Translation: NewPipe/Metadata
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/sc/
---
fastlane/metadata/android/sc/changelogs/960.txt | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 fastlane/metadata/android/sc/changelogs/960.txt
diff --git a/fastlane/metadata/android/sc/changelogs/960.txt b/fastlane/metadata/android/sc/changelogs/960.txt
new file mode 100644
index 000000000..f94c77f45
--- /dev/null
+++ b/fastlane/metadata/android/sc/changelogs/960.txt
@@ -0,0 +1,4 @@
+• Megioramentu de sa descritzione de s'optzione de esportatzione de sa base de datos in sas impostatziones.
+• Anàlisi de sos cummentos de YouTube acontzada.
+• Nùmene ammustradu in su servìtziu media.ccc.de acontzadu.
+• Tradutziones agiornadas.
From efb417dba70d4ca9341b2561a9d70ebb4b3bddf8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Allan=20Nordh=C3=B8y?=
Date: Wed, 9 Dec 2020 22:52:51 +0000
Subject: [PATCH 13/57] =?UTF-8?q?Translated=20using=20Weblate=20(Norwegian?=
=?UTF-8?q?=20Bokm=C3=A5l)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Currently translated at 17.0% (7 of 41 strings)
Translation: NewPipe/Metadata
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/nb_NO/
---
.../metadata/android/nb-NO/changelogs/958.txt | 15 +++++++++++++++
.../metadata/android/nb-NO/changelogs/960.txt | 4 ++++
2 files changed, 19 insertions(+)
create mode 100644 fastlane/metadata/android/nb-NO/changelogs/958.txt
create mode 100644 fastlane/metadata/android/nb-NO/changelogs/960.txt
diff --git a/fastlane/metadata/android/nb-NO/changelogs/958.txt b/fastlane/metadata/android/nb-NO/changelogs/958.txt
new file mode 100644
index 000000000..a0b664480
--- /dev/null
+++ b/fastlane/metadata/android/nb-NO/changelogs/958.txt
@@ -0,0 +1,15 @@
+Nytt og forbedret:
+• Skjuling av miniatyrbilde på låseskjermen er tilbake
+• Trykk for å gjenoppfriske strøm
+• Forbedret ytelse ved innhenting av lokale lister
+
+Fikset:
+• Krasj ved oppstart av NewPipe etter at det ble fjernet fra minne
+• Krasj ved oppstart når det ikke finnes noen internett-tilkobling
+• Repsektering av lys- og lyd- og håndvendingsinnstillinger
+• [YouTube] Lange spillelister
+
+Annet:
+• Kodeopprydding og interne forbedringer
+• Avhengighetsoppdateringer
+• Oversettelser
diff --git a/fastlane/metadata/android/nb-NO/changelogs/960.txt b/fastlane/metadata/android/nb-NO/changelogs/960.txt
new file mode 100644
index 000000000..92cbb6ca1
--- /dev/null
+++ b/fastlane/metadata/android/nb-NO/changelogs/960.txt
@@ -0,0 +1,4 @@
+• Forbedret beskrivelse av innstilling for eksport av database i innstillingene.
+• Fikset tolking av YouTube-kommentarer.
+• Fikset visningsnavn for media.ccc.de service.
+• Oppdaterte oversettelser.
From 69ed531a5c804a929b2a802b5ed9e9efa34144c6 Mon Sep 17 00:00:00 2001
From: Stefan Br
Date: Thu, 10 Dec 2020 18:54:31 +0000
Subject: [PATCH 14/57] Translated using Weblate (German)
Currently translated at 100.0% (609 of 609 strings)
---
app/src/main/res/values-de/strings.xml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 6effa7615..121f74ee1 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -105,7 +105,7 @@
Nicht unterstützter ServerKonnte Bild nicht ladenApp/UI abgestürzt
- Threads
+ ThemenNewPipe lädt herunterFür Details antippenUngültige URL oder Internet nicht verfügbar
@@ -317,7 +317,7 @@
\nMöchtest du fortfahren\?
Vorschaubilder ladenBilder-Cache gelöscht
- Zwischengespeicherte Metadaten löschen
+ Zwischengespeicherte (Metadaten) löschenAlle zwischengespeicherten Website-Daten entfernenMetadatencache gelöschtDebug
@@ -636,7 +636,7 @@
Automatische WarteschlangeDen Player zu wechseln könnte deine Warteschlange überschreibenBestätige das Leeren der Warteschlange
- Die aktive Wiedergabeliste wird ersetzt werden
+ Die aktive Player-Warteschlange wird ersetztEingereihtYouTube bietet einen „Eingeschränkten Modus“, der potenzielle Inhalte für Erwachsene ausblendetSpeicherlecks anzeigen
@@ -644,7 +644,7 @@
reCAPTCHA-Cookies wurden gelöschtreCAPTCHA-Cookies löschenZeige altersbeschränkte Inhalte (bspw. 18+), welche möglicherweise unpassend für Kinder sein könnten
- Wiedergabe einreihen
+ In Wiedergabe einreihenAndroid kann die Farbe der Benachrichtigung entsprechend der Hauptfarbe in der Miniaturansicht anpassen (beachte, dass dies nicht auf allen Geräten verfügbar ist)Benachrichtigung farblich anpassenVorschaubild auf dem Sperrbildschirm als Hintergrund und innerhalb von Benachrichtigungen anzeigen
From 5c2d4c4d9df672030fb2a56175463b256df8b720 Mon Sep 17 00:00:00 2001
From: Terry Louwers
Date: Thu, 10 Dec 2020 06:16:38 +0000
Subject: [PATCH 15/57] Translated using Weblate (Dutch)
Currently translated at 100.0% (609 of 609 strings)
---
app/src/main/res/values-nl/strings.xml | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index 0217368da..e120750fc 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -264,8 +264,8 @@
Bezig met laden van gevraagde inhoudDatabank importerenDatabank exporteren
- Dit overschrijft je huidige geschiedenis en abonnementen
- Exporteer geschiedenis, abonnementen en afspeellijsten
+ Dit overschrijft je huidige geschiedenis, abonnementen, afspeellijsten en (optionele) settings
+ Exporteer geschiedenis, abonnementen, afspeellijsten en settingsGeëxporteerdGeïmporteerdGeen geldig ZIP-bestand
@@ -647,4 +647,6 @@
Toon inhoud die mogelijk niet geschikt is voor kinderen omwille van een leeftijdslimiet (zoals 18+)Laat Android de kleur van de notificatie aanpassen, op basis van de meest voorkomende kleur in de thumbnail (let op: niet beschikbaar op elk apparaat)Notificatie kleur aanpassen
+ Toon miniatuurafbeelding op het vergrendelscherm als achtergrond en binnen meldingen
+ Toon miniatuurafbeelding
\ No newline at end of file
From 917f4595690f2ccd67cc8395caa41ca02ff4ea4e Mon Sep 17 00:00:00 2001
From: Isira Seneviratne
Date: Fri, 11 Dec 2020 07:29:24 +0530
Subject: [PATCH 16/57] Use a notification instead of a ProgressDialog in
MissionAdapter.
---
app/src/main/java/org/schabi/newpipe/App.java | 15 ++++++--
.../giga/ui/adapter/MissionAdapter.java | 37 ++++++++++---------
app/src/main/res/values/strings.xml | 4 ++
3 files changed, 36 insertions(+), 20 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java
index de401d4f5..e6dce4d67 100644
--- a/app/src/main/java/org/schabi/newpipe/App.java
+++ b/app/src/main/java/org/schabi/newpipe/App.java
@@ -242,8 +242,9 @@ public class App extends MultiDexApplication {
String name = getString(R.string.notification_channel_name);
String description = getString(R.string.notification_channel_description);
- // Keep this below DEFAULT to avoid making noise on every notification update
- final int importance = NotificationManager.IMPORTANCE_LOW;
+ // Keep this below DEFAULT to avoid making noise on every notification update for the main
+ // and update channels
+ int importance = NotificationManager.IMPORTANCE_LOW;
final NotificationChannel mainChannel = new NotificationChannel(id, name, importance);
mainChannel.setDescription(description);
@@ -255,9 +256,17 @@ public class App extends MultiDexApplication {
final NotificationChannel appUpdateChannel = new NotificationChannel(id, name, importance);
appUpdateChannel.setDescription(description);
+ id = getString(R.string.hash_channel_id);
+ name = getString(R.string.hash_channel_name);
+ description = getString(R.string.hash_channel_description);
+ importance = NotificationManager.IMPORTANCE_HIGH;
+
+ final NotificationChannel hashChannel = new NotificationChannel(id, name, importance);
+ hashChannel.setDescription(description);
+
final NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannels(Arrays.asList(mainChannel,
- appUpdateChannel));
+ appUpdateChannel, hashChannel));
}
protected boolean isDisposedRxExceptionsReported() {
diff --git a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java
index be7d78299..f102206c1 100644
--- a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java
+++ b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java
@@ -1,7 +1,7 @@
package us.shandian.giga.ui.adapter;
import android.annotation.SuppressLint;
-import android.app.ProgressDialog;
+import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
@@ -26,6 +26,8 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog;
+import androidx.core.app.NotificationCompat;
+import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.core.view.ViewCompat;
import androidx.recyclerview.widget.DiffUtil;
@@ -91,6 +93,7 @@ public class MissionAdapter extends Adapter implements Handler.Callb
private static final String DEFAULT_MIME_TYPE = "*/*";
private static final String UNDEFINED_ETA = "--:--";
+ private static final int HASH_NOTIFICATION_ID = 123790;
static {
ALGORITHMS.put(R.id.md5, "MD5");
@@ -678,28 +681,28 @@ public class MissionAdapter extends Adapter implements Handler.Callb
return true;
case R.id.md5:
case R.id.sha1:
- ProgressDialog progressDialog = null;
- if (mContext != null) {
- // Create dialog
- progressDialog = new ProgressDialog(mContext);
- progressDialog.setCancelable(false);
- progressDialog.setMessage(mContext.getString(R.string.msg_wait));
- progressDialog.show();
- }
- final ProgressDialog finalProgressDialog = progressDialog;
+ final NotificationManager notificationManager
+ = ContextCompat.getSystemService(mContext, NotificationManager.class);
+ final NotificationCompat.Builder progressNotificationBuilder
+ = new NotificationCompat.Builder(mContext,
+ mContext.getString(R.string.hash_channel_id))
+ .setPriority(NotificationCompat.PRIORITY_HIGH)
+ .setSmallIcon(R.drawable.ic_newpipe_triangle_white)
+ .setContentTitle(mContext.getString(R.string.msg_calculating_hash))
+ .setContentText(mContext.getString(R.string.msg_wait))
+ .setProgress(0, 0, true)
+ .setOngoing(true);
+
+ notificationManager.notify(HASH_NOTIFICATION_ID, progressNotificationBuilder
+ .build());
final StoredFileHelper storage = h.item.mission.storage;
compositeDisposable.add(
Observable.fromCallable(() -> Utility.checksum(storage, ALGORITHMS.get(id)))
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
- if (finalProgressDialog != null) {
- Utility.copyToClipboard(finalProgressDialog.getContext(),
- result);
- if (mContext != null) {
- finalProgressDialog.dismiss();
- }
- }
+ Utility.copyToClipboard(mContext, result);
+ notificationManager.cancel(HASH_NOTIFICATION_ID);
})
);
return true;
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f96518ccf..bc70e793b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -195,6 +195,9 @@
newpipeAppUpdateApp Update NotificationNotifications for new NewPipe version
+ newpipeHash
+ Video Hash Notification
+ Notifications for video hashing progress[Unknown]Toggle OrientationSwitch to Background
@@ -347,6 +350,7 @@
Malformed URL or Internet not availableNewPipe DownloadingTap for details
+ Calculating hashPlease wait…Copied to clipboardPlease define a download folder later in settings
From c2210330b6d70f08b194065accaef2a067b639fb Mon Sep 17 00:00:00 2001
From: Stypox
Date: Tue, 17 Mar 2020 18:41:39 +0100
Subject: [PATCH 17/57] Show radio instead of Youtube logo in mixes
YouTube mixes have YouTube as a creator, though YouTube's logo is not safe to use as it is a trademark (better safe than sorry)
---
app/build.gradle | 2 +-
.../list/playlist/PlaylistFragment.java | 29 +++++++++++++++----
.../ktx/OffsetDateTimeToCalendarTest.kt | 3 +-
3 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/app/build.gradle b/app/build.gradle
index 87215b385..5a8689f70 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -175,7 +175,7 @@ dependencies {
// NewPipe dependencies
// You can use a local version by uncommenting a few lines in settings.gradle
- implementation 'com.github.TeamNewPipe:NewPipeExtractor:b3835bd616ab28b861c83dcefd56e1754c6d20be'
+ implementation 'com.github.TeamNewPipe:NewPipeExtractor:85fa006214b003f21eacb76c445a167732f19981'
implementation "com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751"
implementation "org.jsoup:jsoup:1.13.1"
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 d1a964fb2..6fa7eb700 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
@@ -11,12 +11,12 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.content.res.AppCompatResources;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
@@ -26,8 +26,10 @@ import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe;
+import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
+import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
@@ -44,13 +46,13 @@ import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ShareUtils;
import org.schabi.newpipe.util.StreamDialogEntry;
-import org.schabi.newpipe.util.ThemeHelper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
+import de.hdodenhof.circleimageview.CircleImageView;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.core.Single;
@@ -58,6 +60,7 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.disposables.Disposable;
import static org.schabi.newpipe.util.AnimationUtils.animateView;
+import static org.schabi.newpipe.util.ThemeHelper.resolveResourceIdFromAttr;
public class PlaylistFragment extends BaseListInfoFragment {
private CompositeDisposable disposables;
@@ -74,7 +77,7 @@ public class PlaylistFragment extends BaseListInfoFragment {
private TextView headerTitleView;
private View headerUploaderLayout;
private TextView headerUploaderName;
- private ImageView headerUploaderAvatar;
+ private CircleImageView headerUploaderAvatar;
private TextView headerStreamCount;
private View playlistCtrl;
@@ -301,8 +304,22 @@ public class PlaylistFragment extends BaseListInfoFragment {
playlistCtrl.setVisibility(View.VISIBLE);
- IMAGE_LOADER.displayImage(result.getUploaderAvatarUrl(), headerUploaderAvatar,
- ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
+ final String avatarUrl = result.getUploaderAvatarUrl();
+ if (result.getServiceId() == ServiceList.YouTube.getServiceId()
+ && (YoutubeParsingHelper.isYoutubeMixId(result.getId())
+ || YoutubeParsingHelper.isYoutubeMusicMixId(result.getId()))) {
+ // this is an auto-generated playlist (e.g. Youtube mix), so a radio is shown
+ headerUploaderAvatar.setDisableCircularTransformation(true);
+ headerUploaderAvatar.setBorderColor(
+ getResources().getColor(R.color.transparent_background_color));
+ headerUploaderAvatar.setImageDrawable(AppCompatResources.getDrawable(requireContext(),
+ resolveResourceIdFromAttr(requireContext(), R.attr.ic_radio)));
+
+ } else {
+ IMAGE_LOADER.displayImage(avatarUrl, headerUploaderAvatar,
+ ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
+ }
+
headerStreamCount.setText(Localization
.localizeStreamCount(getContext(), result.getStreamCount()));
@@ -476,7 +493,7 @@ public class PlaylistFragment extends BaseListInfoFragment {
final int titleRes = playlistEntity == null
? R.string.bookmark_playlist : R.string.unbookmark_playlist;
- playlistBookmarkButton.setIcon(ThemeHelper.resolveResourceIdFromAttr(activity, iconAttr));
+ playlistBookmarkButton.setIcon(resolveResourceIdFromAttr(activity, iconAttr));
playlistBookmarkButton.setTitle(titleRes);
}
}
diff --git a/app/src/test/java/org/schabi/newpipe/ktx/OffsetDateTimeToCalendarTest.kt b/app/src/test/java/org/schabi/newpipe/ktx/OffsetDateTimeToCalendarTest.kt
index c93d36eb5..74da07998 100644
--- a/app/src/test/java/org/schabi/newpipe/ktx/OffsetDateTimeToCalendarTest.kt
+++ b/app/src/test/java/org/schabi/newpipe/ktx/OffsetDateTimeToCalendarTest.kt
@@ -4,7 +4,6 @@ import org.junit.Assert.assertEquals
import org.junit.Test
import java.time.LocalDate
import java.time.OffsetDateTime
-import java.time.ZoneId
import java.time.ZoneOffset
import java.util.Calendar
import java.util.TimeZone
@@ -13,7 +12,7 @@ class OffsetDateTimeToCalendarTest {
@Test
fun testRelativeTimeWithCurrentOffsetDateTime() {
val calendar = LocalDate.of(2020, 1, 1).atStartOfDay().atOffset(ZoneOffset.UTC)
- .toCalendar()
+ .toCalendar()
assertEquals(2020, calendar[Calendar.YEAR])
assertEquals(0, calendar[Calendar.MONTH])
From 30613b7064d3988e181b6e601269dc1cfd9e827a Mon Sep 17 00:00:00 2001
From: Isira Seneviratne
Date: Tue, 15 Dec 2020 08:02:25 +0530
Subject: [PATCH 18/57] Use ContextCompat.getDataDir().
---
.../settings/ContentSettingsFragment.java | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
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 b0425ebfa..1ef52cd82 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java
@@ -11,6 +11,7 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
@@ -120,15 +121,14 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
@Override
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
+ final File homeDir = ContextCompat.getDataDir(requireContext());
+ databasesDir = new File(homeDir, "/databases");
+ newpipeDb = new File(homeDir, "/databases/newpipe.db");
+ newpipeDbJournal = new File(homeDir, "/databases/newpipe.db-journal");
+ newpipeDbShm = new File(homeDir, "/databases/newpipe.db-shm");
+ newpipeDbWal = new File(homeDir, "/databases/newpipe.db-wal");
- final String homeDir = getActivity().getApplicationInfo().dataDir;
- databasesDir = new File(homeDir + "/databases");
- newpipeDb = new File(homeDir + "/databases/newpipe.db");
- newpipeDbJournal = new File(homeDir + "/databases/newpipe.db-journal");
- newpipeDbShm = new File(homeDir + "/databases/newpipe.db-shm");
- newpipeDbWal = new File(homeDir + "/databases/newpipe.db-wal");
-
- newpipeSettings = new File(homeDir + "/databases/newpipe.settings");
+ newpipeSettings = new File(homeDir, "/databases/newpipe.settings");
newpipeSettings.delete();
addPreferencesFromResource(R.xml.content_settings);
From 807e4d4af9122a30e5c83e37ce04452c3c88c23b Mon Sep 17 00:00:00 2001
From: Isira Seneviratne
Date: Tue, 15 Dec 2020 11:51:26 +0530
Subject: [PATCH 19/57] Use ActivityCompat.recreate().
---
app/src/main/java/org/schabi/newpipe/MainActivity.java | 8 +++-----
.../org/schabi/newpipe/player/ServicePlayerActivity.java | 3 ++-
.../newpipe/settings/AppearanceSettingsFragment.java | 3 ++-
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java
index 4a8582df2..a5c963ee6 100644
--- a/app/src/main/java/org/schabi/newpipe/MainActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java
@@ -50,6 +50,7 @@ import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
+import androidx.core.app.ActivityCompat;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
@@ -218,7 +219,7 @@ public class MainActivity extends AppCompatActivity {
toggleServices();
}
if (lastService != ServiceHelper.getSelectedServiceId(MainActivity.this)) {
- new Handler(Looper.getMainLooper()).post(MainActivity.this::recreate);
+ ActivityCompat.recreate(MainActivity.this);
}
}
});
@@ -497,10 +498,7 @@ public class MainActivity extends AppCompatActivity {
Log.d(TAG, "Theme has changed, recreating activity...");
}
sharedPreferences.edit().putBoolean(Constants.KEY_THEME_CHANGE, false).apply();
- // https://stackoverflow.com/questions/10844112/
- // Briefly, let the activity resume
- // properly posting the recreate call to end of the message queue
- new Handler(Looper.getMainLooper()).post(MainActivity.this::recreate);
+ ActivityCompat.recreate(this);
}
if (sharedPreferences.getBoolean(Constants.KEY_MAIN_PAGE_CHANGE, false)) {
diff --git a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java
index d1c2be014..4bf6ef9ae 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java
@@ -20,6 +20,7 @@ import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
+import androidx.core.app.ActivityCompat;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -140,7 +141,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
protected void onResume() {
super.onResume();
if (redraw) {
- recreate();
+ ActivityCompat.recreate(this);
redraw = false;
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java
index ab875ed5d..8126bd2c5 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java
@@ -8,6 +8,7 @@ import android.provider.Settings;
import android.widget.Toast;
import androidx.annotation.Nullable;
+import androidx.core.app.ActivityCompat;
import androidx.preference.Preference;
import org.schabi.newpipe.R;
@@ -31,7 +32,7 @@ public class AppearanceSettingsFragment extends BasePreferenceFragment {
if (!newValue.equals(startThemeKey) && getActivity() != null) {
// If it's not the current theme
- getActivity().recreate();
+ ActivityCompat.recreate(requireActivity());
}
return false;
From 99b59f012676e85eff88338cbd7fbb4e4f2c70b9 Mon Sep 17 00:00:00 2001
From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com>
Date: Tue, 15 Dec 2020 18:57:36 +0100
Subject: [PATCH 20/57] Update NewPipe's API url for new app's version check
---
app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java
index 916630ae6..0fecc3f96 100644
--- a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java
+++ b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java
@@ -48,7 +48,7 @@ public final class CheckForNewAppVersion {
private static final String GITHUB_APK_SHA1
= "B0:2E:90:7C:1C:D6:FC:57:C3:35:F0:88:D0:8F:50:5F:94:E4:D2:15";
- private static final String NEWPIPE_API_URL = "https://newpipe.schabi.org/api/data.json";
+ private static final String NEWPIPE_API_URL = "https://newpipe.net/api/data.json";
/**
* Method to get the APK's SHA1 key. See https://stackoverflow.com/questions/9293019/#22506133.
From 5397a4e410e340fc52a6ebf452338ab074bc3cd7 Mon Sep 17 00:00:00 2001
From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com>
Date: Tue, 15 Dec 2020 19:01:33 +0100
Subject: [PATCH 21/57] Update NewPipe website URL strings
---
app/src/main/res/values/strings.xml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index bc70e793b..ecb690044 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -391,14 +391,14 @@
View on GitHubDonateNewPipe is developed by volunteers spending their free time bringing you the best user experience. Give back to help developers make NewPipe even better while they enjoy a cup of coffee.
- https://newpipe.schabi.org/donate
+ https://newpipe.net/donateGive backWebsiteVisit the NewPipe Website for more info and news.
- https://newpipe.schabi.org/
+ https://newpipe.net/NewPipe\'s Privacy PolicyThe NewPipe project takes your privacy very seriously. Therefore, the app does not collect any data without your consent.\nNewPipe\'s privacy policy explains in detail what data is sent and stored when you send a crash report.
- https://newpipe.schabi.org/legal/privacy/
+ https://newpipe.net/legal/privacy/Read privacy policyNewPipe\'s LicenseNewPipe is copyleft libre software: You can use, study share and improve it at will. Specifically you can redistribute and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
From a7723373a0fc846323e34556c40688055e9f9a02 Mon Sep 17 00:00:00 2001
From: XiangRongLin <41164160+XiangRongLin@users.noreply.github.com>
Date: Tue, 15 Dec 2020 20:18:25 +0100
Subject: [PATCH 22/57] Fix compile error caused by auto merging
#5176 changed `homeDir` from type `String` to `File`. #5059 was based on `homeDir` being a `String`. It was incorrectly auto-resolved by git.
---
.../org/schabi/newpipe/settings/ContentSettingsManager.kt | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt
index b0ea89993..2682ac5e0 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt
+++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt
@@ -15,9 +15,9 @@ class ContentSettingsManager(
private val newpipeSettings: File
) {
- constructor(homeDir: String) : this(
- File("$homeDir/databases/newpipe.db"),
- File("$homeDir/databases/newpipe.settings")
+ constructor(homeDir: File) : this(
+ File(homeDir, "databases/newpipe.db"),
+ File(homeDir, "databases/newpipe.settings")
)
/**
From e0ee3dce40cb01567f2ebfb69dc1a134cd92d142 Mon Sep 17 00:00:00 2001
From: XiangRongLin <41164160+XiangRongLin@users.noreply.github.com>
Date: Thu, 17 Dec 2020 09:40:04 +0100
Subject: [PATCH 23/57] Use @BeforeClass for
ContentSettingsManagerTest.beforeClass
---
.../settings/ContentSettingsManagerTest.kt | 30 +++++++++++--------
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/app/src/test/java/org/schabi/newpipe/settings/ContentSettingsManagerTest.kt b/app/src/test/java/org/schabi/newpipe/settings/ContentSettingsManagerTest.kt
index 9809fd5fc..5ac132f7f 100644
--- a/app/src/test/java/org/schabi/newpipe/settings/ContentSettingsManagerTest.kt
+++ b/app/src/test/java/org/schabi/newpipe/settings/ContentSettingsManagerTest.kt
@@ -4,6 +4,7 @@ import android.content.SharedPreferences
import org.junit.Assert
import org.junit.Assume
import org.junit.Before
+import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Suite
@@ -22,24 +23,27 @@ class ContentSettingsManagerTest {
@RunWith(MockitoJUnitRunner::class)
class ExportTest {
- private lateinit var preferences: SharedPreferences
- private lateinit var newpipeDb: File
- private lateinit var newpipeSettings: File
+ companion object {
+ private lateinit var newpipeDb: File
+ private lateinit var newpipeSettings: File
- @Before
- fun beforeClass() {
+ @JvmStatic
+ @BeforeClass
+ fun setupFiles() {
+ val dbPath = ExportTest::class.java.classLoader?.getResource("settings/newpipe.db")?.file
+ val settingsPath = ExportTest::class.java.classLoader?.getResource("settings/newpipe.settings")?.path
+ Assume.assumeNotNull(dbPath)
+ Assume.assumeNotNull(settingsPath)
- val dbPath = javaClass.classLoader?.getResource("settings/newpipe.db")?.file
- val settingsPath = javaClass.classLoader?.getResource("settings/newpipe.settings")?.path
- Assume.assumeNotNull(dbPath)
- Assume.assumeNotNull(settingsPath)
-
- newpipeDb = File(dbPath!!)
- newpipeSettings = File(settingsPath!!)
+ newpipeDb = File(dbPath!!)
+ newpipeSettings = File(settingsPath!!)
+ }
}
+ private lateinit var preferences: SharedPreferences
+
@Before
- fun before() {
+ fun setupMocks() {
preferences = Mockito.mock(SharedPreferences::class.java, Mockito.withSettings().stubOnly())
}
From 10f79e13070b6e858b92a0bcfd55b32240e13197 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Thu, 17 Dec 2020 16:32:03 +0100
Subject: [PATCH 24/57] Remove pbj=1 parameter from YouYube urls in recaptcha
activity
---
.../org/schabi/newpipe/ReCaptchaActivity.java | 17 +++++++-----
.../schabi/newpipe/ReCaptchaActivityTest.kt | 27 +++++++++++++++++++
.../ktx/OffsetDateTimeToCalendarTest.kt | 3 +--
3 files changed, 39 insertions(+), 8 deletions(-)
create mode 100644 app/src/test/java/org/schabi/newpipe/ReCaptchaActivityTest.kt
diff --git a/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java b/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java
index c962ed99d..03c9ae4af 100644
--- a/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java
@@ -53,6 +53,16 @@ public class ReCaptchaActivity extends AppCompatActivity {
public static final String YT_URL = "https://www.youtube.com";
public static final String RECAPTCHA_COOKIES_KEY = "recaptcha_cookies";
+ public static String sanitizeRecaptchaUrl(@Nullable final String url) {
+ if (url == null || url.trim().isEmpty()) {
+ return YT_URL; // YouTube is the most likely service to have thrown a recaptcha
+ } else {
+ // remove "pbj=1" parameter from YouYube urls, as it makes the page JSON and not HTML
+ return url.replace("&pbj=1", "").replace("pbj=1&", "").replace("?pbj=1", "");
+ }
+ }
+
+
private WebView webView;
private String foundCookies = "";
@@ -64,15 +74,10 @@ public class ReCaptchaActivity extends AppCompatActivity {
final Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
- String url = getIntent().getStringExtra(RECAPTCHA_URL_EXTRA);
- if (url == null || url.isEmpty()) {
- url = YT_URL;
- }
-
+ final String url = sanitizeRecaptchaUrl(getIntent().getStringExtra(RECAPTCHA_URL_EXTRA));
// set return to Cancel by default
setResult(RESULT_CANCELED);
-
webView = findViewById(R.id.reCaptchaWebView);
// enable Javascript
diff --git a/app/src/test/java/org/schabi/newpipe/ReCaptchaActivityTest.kt b/app/src/test/java/org/schabi/newpipe/ReCaptchaActivityTest.kt
new file mode 100644
index 000000000..b9f6887f9
--- /dev/null
+++ b/app/src/test/java/org/schabi/newpipe/ReCaptchaActivityTest.kt
@@ -0,0 +1,27 @@
+package org.schabi.newpipe
+
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.schabi.newpipe.ReCaptchaActivity.YT_URL
+
+class ReCaptchaActivityTest {
+ private fun assertSanitized(expected: String, actual: String?) {
+ assertEquals(expected, ReCaptchaActivity.sanitizeRecaptchaUrl(actual))
+ }
+
+ @Test fun `null, empty or blank url is sanitized correctly`() {
+ assertSanitized(YT_URL, null)
+ assertSanitized(YT_URL, "")
+ assertSanitized(YT_URL, " \n \t ")
+ }
+
+ @Test fun `YouTube url containing pbj=1 is sanitized correctly`() {
+ val sanitizedUrl = "https://m.youtube.com/results?search_query=test"
+ assertSanitized(sanitizedUrl, "https://m.youtube.com/results?search_query=test")
+ assertSanitized(sanitizedUrl, "https://m.youtube.com/results?search_query=test&pbj=1&pbj=1")
+ assertSanitized(sanitizedUrl, "https://m.youtube.com/results?pbj=1&search_query=test")
+ assertSanitized("pbj://pbj.pbj.pbj/pbj", "pbj://pbj.pbj.pbj/pbj?pbj=1")
+ assertSanitized("http://www.host.com/b?p1=7&p2=9", "http://www.host.com/b?p1=7&pbj=1&p2=9")
+ assertSanitized("http://www.host.com/a?pbj=0", "http://www.host.com/a?pbj=0")
+ }
+}
diff --git a/app/src/test/java/org/schabi/newpipe/ktx/OffsetDateTimeToCalendarTest.kt b/app/src/test/java/org/schabi/newpipe/ktx/OffsetDateTimeToCalendarTest.kt
index c93d36eb5..74da07998 100644
--- a/app/src/test/java/org/schabi/newpipe/ktx/OffsetDateTimeToCalendarTest.kt
+++ b/app/src/test/java/org/schabi/newpipe/ktx/OffsetDateTimeToCalendarTest.kt
@@ -4,7 +4,6 @@ import org.junit.Assert.assertEquals
import org.junit.Test
import java.time.LocalDate
import java.time.OffsetDateTime
-import java.time.ZoneId
import java.time.ZoneOffset
import java.util.Calendar
import java.util.TimeZone
@@ -13,7 +12,7 @@ class OffsetDateTimeToCalendarTest {
@Test
fun testRelativeTimeWithCurrentOffsetDateTime() {
val calendar = LocalDate.of(2020, 1, 1).atStartOfDay().atOffset(ZoneOffset.UTC)
- .toCalendar()
+ .toCalendar()
assertEquals(2020, calendar[Calendar.YEAR])
assertEquals(0, calendar[Calendar.MONTH])
From aacb1f46a80d9dce55ab4d216279f4dbc205cbc0 Mon Sep 17 00:00:00 2001
From: Stypox
Date: Fri, 18 Dec 2020 18:36:40 +0100
Subject: [PATCH 25/57] Use user agent of DownloaderImpl also in
ReCapthaActivity
Does not contain device info and should also fix some issues about recaptchas not showing up
---
.../org/schabi/newpipe/ReCaptchaActivity.java | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java b/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java
index 03c9ae4af..b6f65c355 100644
--- a/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java
@@ -83,6 +83,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
// enable Javascript
final WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
+ webSettings.setUserAgentString(DownloaderImpl.USER_AGENT);
webView.setWebViewClient(new WebViewClient() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@@ -120,8 +121,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
webView.clearHistory();
final android.webkit.CookieManager cookieManager = CookieManager.getInstance();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- cookieManager.removeAllCookies(aBoolean -> {
- });
+ cookieManager.removeAllCookies(value -> { });
} else {
cookieManager.removeAllCookie();
}
@@ -150,14 +150,11 @@ public class ReCaptchaActivity extends AppCompatActivity {
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
- final int id = item.getItemId();
- switch (id) {
- case R.id.menu_item_done:
- saveCookiesAndFinish();
- return true;
- default:
- return false;
+ if (item.getItemId() == R.id.menu_item_done) {
+ saveCookiesAndFinish();
+ return true;
}
+ return false;
}
private void saveCookiesAndFinish() {
From 31bb70e3334ecb05a8624283058bb054c05e7a34 Mon Sep 17 00:00:00 2001
From: Isira Seneviratne
Date: Sat, 31 Oct 2020 10:07:18 +0530
Subject: [PATCH 26/57] Enable view binding.
---
app/build.gradle | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/app/build.gradle b/app/build.gradle
index 5a8689f70..4acff01bf 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -85,6 +85,10 @@ android {
sourceSets {
androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
}
+
+ buildFeatures {
+ viewBinding true
+ }
}
ext {
From 18d530021c04f63f5d153a3e527de58825485eb9 Mon Sep 17 00:00:00 2001
From: Isira Seneviratne
Date: Sat, 31 Oct 2020 11:19:07 +0530
Subject: [PATCH 27/57] Fix view binding issue.
---
app/src/main/res/layout-large-land/fragment_video_detail.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/src/main/res/layout-large-land/fragment_video_detail.xml b/app/src/main/res/layout-large-land/fragment_video_detail.xml
index 13e3c1b5f..8aee89ab0 100644
--- a/app/src/main/res/layout-large-land/fragment_video_detail.xml
+++ b/app/src/main/res/layout-large-land/fragment_video_detail.xml
@@ -2,12 +2,12 @@
Date: Sat, 31 Oct 2020 11:23:28 +0530
Subject: [PATCH 28/57] Use view binding in MainActivity.
---
.../java/org/schabi/newpipe/MainActivity.java | 168 +++++++++---------
app/src/main/res/layout/activity_main.xml | 9 +-
2 files changed, 87 insertions(+), 90 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java
index a5c963ee6..ff078fa2c 100644
--- a/app/src/main/java/org/schabi/newpipe/MainActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java
@@ -39,17 +39,13 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
-import android.widget.Button;
import android.widget.FrameLayout;
-import android.widget.ImageView;
import android.widget.Spinner;
-import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
@@ -58,8 +54,12 @@ import androidx.fragment.app.FragmentManager;
import androidx.preference.PreferenceManager;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
-import com.google.android.material.navigation.NavigationView;
+import org.schabi.newpipe.databinding.ActivityMainBinding;
+import org.schabi.newpipe.databinding.DrawerHeaderBinding;
+import org.schabi.newpipe.databinding.DrawerLayoutBinding;
+import org.schabi.newpipe.databinding.InstanceSpinnerLayoutBinding;
+import org.schabi.newpipe.databinding.ToolbarLayoutBinding;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
@@ -97,15 +97,14 @@ public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
+ private ActivityMainBinding mainBinding;
+ private DrawerHeaderBinding drawerHeaderBinding;
+ private DrawerLayoutBinding drawerLayoutBinding;
+ private ToolbarLayoutBinding toolbarLayoutBinding;
+
private ActionBarDrawerToggle toggle;
- private DrawerLayout drawer;
- private NavigationView drawerItems;
- private ImageView headerServiceIcon;
- private TextView headerServiceView;
- private Button toggleServiceButton;
private boolean servicesShown = false;
- private ImageView serviceArrow;
private BroadcastReceiver broadcastReceiver;
@@ -138,13 +137,19 @@ public class MainActivity extends AppCompatActivity {
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
+
+ mainBinding = ActivityMainBinding.inflate(getLayoutInflater());
+ drawerLayoutBinding = mainBinding.drawerLayout;
+ drawerHeaderBinding = DrawerHeaderBinding.bind(drawerLayoutBinding.navigation
+ .getHeaderView(0));
+ toolbarLayoutBinding = mainBinding.toolbarLayout;
+ setContentView(mainBinding.getRoot());
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
initFragments();
}
- setSupportActionBar(findViewById(R.id.toolbar));
+ setSupportActionBar(toolbarLayoutBinding.toolbar);
try {
setupDrawer();
} catch (final Exception e) {
@@ -158,10 +163,6 @@ public class MainActivity extends AppCompatActivity {
}
private void setupDrawer() throws Exception {
- final Toolbar toolbar = findViewById(R.id.toolbar);
- drawer = findViewById(R.id.drawer_layout);
- drawerItems = findViewById(R.id.navigation);
-
//Tabs
final int currentServiceId = ServiceHelper.getSelectedServiceId(this);
final StreamingService service = NewPipe.getService(currentServiceId);
@@ -169,43 +170,43 @@ public class MainActivity extends AppCompatActivity {
int kioskId = 0;
for (final String ks : service.getKioskList().getAvailableKiosks()) {
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_tabs_group, kioskId, 0, KioskTranslator
.getTranslatedKioskName(ks, this))
.setIcon(KioskTranslator.getKioskIcon(ks, this));
kioskId++;
}
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_tabs_group, ITEM_ID_SUBSCRIPTIONS, ORDER,
R.string.tab_subscriptions)
.setIcon(ThemeHelper.resolveResourceIdFromAttr(this, R.attr.ic_channel));
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_tabs_group, ITEM_ID_FEED, ORDER, R.string.fragment_feed_title)
.setIcon(ThemeHelper.resolveResourceIdFromAttr(this, R.attr.ic_rss));
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_tabs_group, ITEM_ID_BOOKMARKS, ORDER, R.string.tab_bookmarks)
.setIcon(ThemeHelper.resolveResourceIdFromAttr(this, R.attr.ic_bookmark));
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_tabs_group, ITEM_ID_DOWNLOADS, ORDER, R.string.downloads)
.setIcon(ThemeHelper.resolveResourceIdFromAttr(this, R.attr.ic_file_download));
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_tabs_group, ITEM_ID_HISTORY, ORDER, R.string.action_history)
.setIcon(ThemeHelper.resolveResourceIdFromAttr(this, R.attr.ic_history));
//Settings and About
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_options_about_group, ITEM_ID_SETTINGS, ORDER, R.string.settings)
.setIcon(ThemeHelper.resolveResourceIdFromAttr(this, R.attr.ic_settings));
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_options_about_group, ITEM_ID_ABOUT, ORDER, R.string.tab_about)
.setIcon(ThemeHelper.resolveResourceIdFromAttr(this, R.attr.ic_info_outline));
- toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.drawer_open,
- R.string.drawer_close);
+ toggle = new ActionBarDrawerToggle(this, mainBinding.getRoot(),
+ toolbarLayoutBinding.toolbar, R.string.drawer_open, R.string.drawer_close);
toggle.syncState();
- drawer.addDrawerListener(toggle);
- drawer.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
+ mainBinding.getRoot().addDrawerListener(toggle);
+ mainBinding.getRoot().addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
private int lastService;
@Override
@@ -224,7 +225,7 @@ public class MainActivity extends AppCompatActivity {
}
});
- drawerItems.setNavigationItemSelectedListener(this::drawerItemSelected);
+ drawerLayoutBinding.navigation.setNavigationItemSelectedListener(this::drawerItemSelected);
setupDrawerHeader();
}
@@ -247,15 +248,17 @@ public class MainActivity extends AppCompatActivity {
return false;
}
- drawer.closeDrawers();
+ mainBinding.getRoot().closeDrawers();
return true;
}
private void changeService(final MenuItem item) {
- drawerItems.getMenu().getItem(ServiceHelper.getSelectedServiceId(this))
+ drawerLayoutBinding.navigation.getMenu()
+ .getItem(ServiceHelper.getSelectedServiceId(this))
.setChecked(false);
ServiceHelper.setSelectedServiceId(this, item.getItemId());
- drawerItems.getMenu().getItem(ServiceHelper.getSelectedServiceId(this))
+ drawerLayoutBinding.navigation.getMenu()
+ .getItem(ServiceHelper.getSelectedServiceId(this))
.setChecked(true);
}
@@ -307,26 +310,19 @@ public class MainActivity extends AppCompatActivity {
}
private void setupDrawerHeader() {
- final NavigationView navigationView = findViewById(R.id.navigation);
- final View hView = navigationView.getHeaderView(0);
-
- serviceArrow = hView.findViewById(R.id.drawer_arrow);
- headerServiceIcon = hView.findViewById(R.id.drawer_header_service_icon);
- headerServiceView = hView.findViewById(R.id.drawer_header_service_view);
- toggleServiceButton = hView.findViewById(R.id.drawer_header_action_button);
- toggleServiceButton.setOnClickListener(view -> toggleServices());
+ drawerHeaderBinding.drawerHeaderActionButton.setOnClickListener(view -> toggleServices());
// If the current app name is bigger than the default "NewPipe" (7 chars),
// let the text view grow a little more as well.
if (getString(R.string.app_name).length() > "NewPipe".length()) {
- final TextView headerTitle = hView.findViewById(R.id.drawer_header_newpipe_title);
- final ViewGroup.LayoutParams layoutParams = headerTitle.getLayoutParams();
+ final ViewGroup.LayoutParams layoutParams =
+ drawerHeaderBinding.drawerHeaderNewpipeTitle.getLayoutParams();
layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
- headerTitle.setLayoutParams(layoutParams);
- headerTitle.setMaxLines(2);
- headerTitle.setMinWidth(getResources()
+ drawerHeaderBinding.drawerHeaderNewpipeTitle.setLayoutParams(layoutParams);
+ drawerHeaderBinding.drawerHeaderNewpipeTitle.setMaxLines(2);
+ drawerHeaderBinding.drawerHeaderNewpipeTitle.setMinWidth(getResources()
.getDimensionPixelSize(R.dimen.drawer_header_newpipe_title_default_width));
- headerTitle.setMaxWidth(getResources()
+ drawerHeaderBinding.drawerHeaderNewpipeTitle.setMaxWidth(getResources()
.getDimensionPixelSize(R.dimen.drawer_header_newpipe_title_max_width));
}
}
@@ -334,9 +330,9 @@ public class MainActivity extends AppCompatActivity {
private void toggleServices() {
servicesShown = !servicesShown;
- drawerItems.getMenu().removeGroup(R.id.menu_services_group);
- drawerItems.getMenu().removeGroup(R.id.menu_tabs_group);
- drawerItems.getMenu().removeGroup(R.id.menu_options_about_group);
+ drawerLayoutBinding.navigation.getMenu().removeGroup(R.id.menu_services_group);
+ drawerLayoutBinding.navigation.getMenu().removeGroup(R.id.menu_tabs_group);
+ drawerLayoutBinding.navigation.getMenu().removeGroup(R.id.menu_options_about_group);
if (servicesShown) {
showServices();
@@ -350,13 +346,13 @@ public class MainActivity extends AppCompatActivity {
}
private void showServices() {
- serviceArrow.setImageResource(R.drawable.ic_arrow_drop_up_white_24dp);
+ drawerHeaderBinding.drawerArrow.setImageResource(R.drawable.ic_arrow_drop_up_white_24dp);
for (final StreamingService s : NewPipe.getServices()) {
final String title = s.getServiceInfo().getName()
+ (ServiceHelper.isBeta(s) ? " (beta)" : "");
- final MenuItem menuItem = drawerItems.getMenu()
+ final MenuItem menuItem = drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_services_group, s.getServiceId(), ORDER, title)
.setIcon(ServiceHelper.getIcon(s.getServiceId()));
@@ -365,15 +361,16 @@ public class MainActivity extends AppCompatActivity {
enhancePeertubeMenu(s, menuItem);
}
}
- drawerItems.getMenu().getItem(ServiceHelper.getSelectedServiceId(this))
+ drawerLayoutBinding.navigation.getMenu()
+ .getItem(ServiceHelper.getSelectedServiceId(this))
.setChecked(true);
}
private void enhancePeertubeMenu(final StreamingService s, final MenuItem menuItem) {
final PeertubeInstance currentInstance = PeertubeHelper.getCurrentInstance();
menuItem.setTitle(currentInstance.getName() + (ServiceHelper.isBeta(s) ? " (beta)" : ""));
- final Spinner spinner = (Spinner) LayoutInflater.from(this)
- .inflate(R.layout.instance_spinner_layout, null);
+ final Spinner spinner = InstanceSpinnerLayoutBinding.inflate(LayoutInflater.from(this))
+ .getRoot();
final List instances = PeertubeHelper.getInstanceList(this);
final List items = new ArrayList<>();
int defaultSelect = 0;
@@ -398,7 +395,7 @@ public class MainActivity extends AppCompatActivity {
}
PeertubeHelper.selectInstance(newInstance, getApplicationContext());
changeService(menuItem);
- drawer.closeDrawers();
+ mainBinding.getRoot().closeDrawers();
new Handler(Looper.getMainLooper()).postDelayed(() -> {
getSupportFragmentManager().popBackStack(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
@@ -415,7 +412,7 @@ public class MainActivity extends AppCompatActivity {
}
private void showTabs() throws ExtractionException {
- serviceArrow.setImageResource(R.drawable.ic_arrow_drop_down_white_24dp);
+ drawerHeaderBinding.drawerArrow.setImageResource(R.drawable.ic_arrow_drop_down_white_24dp);
//Tabs
final int currentServiceId = ServiceHelper.getSelectedServiceId(this);
@@ -424,34 +421,34 @@ public class MainActivity extends AppCompatActivity {
int kioskId = 0;
for (final String ks : service.getKioskList().getAvailableKiosks()) {
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_tabs_group, kioskId, ORDER,
KioskTranslator.getTranslatedKioskName(ks, this))
.setIcon(KioskTranslator.getKioskIcon(ks, this));
kioskId++;
}
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_tabs_group, ITEM_ID_SUBSCRIPTIONS, ORDER, R.string.tab_subscriptions)
.setIcon(ThemeHelper.resolveResourceIdFromAttr(this, R.attr.ic_channel));
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_tabs_group, ITEM_ID_FEED, ORDER, R.string.fragment_feed_title)
.setIcon(ThemeHelper.resolveResourceIdFromAttr(this, R.attr.ic_rss));
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_tabs_group, ITEM_ID_BOOKMARKS, ORDER, R.string.tab_bookmarks)
.setIcon(ThemeHelper.resolveResourceIdFromAttr(this, R.attr.ic_bookmark));
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_tabs_group, ITEM_ID_DOWNLOADS, ORDER, R.string.downloads)
.setIcon(ThemeHelper.resolveResourceIdFromAttr(this, R.attr.ic_file_download));
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_tabs_group, ITEM_ID_HISTORY, ORDER, R.string.action_history)
.setIcon(ThemeHelper.resolveResourceIdFromAttr(this, R.attr.ic_history));
//Settings and About
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_options_about_group, ITEM_ID_SETTINGS, ORDER, R.string.settings)
.setIcon(ThemeHelper.resolveResourceIdFromAttr(this, R.attr.ic_settings));
- drawerItems.getMenu()
+ drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_options_about_group, ITEM_ID_ABOUT, ORDER, R.string.tab_about)
.setIcon(ThemeHelper.resolveResourceIdFromAttr(this, R.attr.ic_info_outline));
}
@@ -476,16 +473,18 @@ public class MainActivity extends AppCompatActivity {
// Close drawer on return, and don't show animation,
// so it looks like the drawer isn't open when the user returns to MainActivity
- drawer.closeDrawer(GravityCompat.START, false);
+ mainBinding.getRoot().closeDrawer(GravityCompat.START, false);
try {
final int selectedServiceId = ServiceHelper.getSelectedServiceId(this);
final String selectedServiceName = NewPipe.getService(selectedServiceId)
.getServiceInfo().getName();
- headerServiceView.setText(selectedServiceName);
- headerServiceIcon.setImageResource(ServiceHelper.getIcon(selectedServiceId));
+ drawerHeaderBinding.drawerHeaderServiceView.setText(selectedServiceName);
+ drawerHeaderBinding.drawerHeaderServiceIcon.setImageResource(ServiceHelper
+ .getIcon(selectedServiceId));
- headerServiceView.post(() -> headerServiceView.setSelected(true));
- toggleServiceButton.setContentDescription(
+ drawerHeaderBinding.drawerHeaderServiceView.post(() -> drawerHeaderBinding
+ .drawerHeaderServiceView.setSelected(true));
+ drawerHeaderBinding.drawerHeaderActionButton.setContentDescription(
getString(R.string.drawer_header_description) + selectedServiceName);
} catch (final Exception e) {
ErrorActivity.reportUiError(this, e);
@@ -511,7 +510,8 @@ public class MainActivity extends AppCompatActivity {
final boolean isHistoryEnabled = sharedPreferences.getBoolean(
getString(R.string.enable_watch_history_key), true);
- drawerItems.getMenu().findItem(ITEM_ID_HISTORY).setVisible(isHistoryEnabled);
+ drawerLayoutBinding.navigation.getMenu().findItem(ITEM_ID_HISTORY)
+ .setVisible(isHistoryEnabled);
}
@Override
@@ -555,9 +555,8 @@ public class MainActivity extends AppCompatActivity {
}
if (DeviceUtils.isTv(this)) {
- final View drawerPanel = findViewById(R.id.navigation);
- if (drawer.isDrawerOpen(drawerPanel)) {
- drawer.closeDrawers();
+ if (mainBinding.getRoot().isDrawerOpen(drawerLayoutBinding.navigation)) {
+ mainBinding.getRoot().closeDrawers();
return;
}
}
@@ -583,9 +582,7 @@ public class MainActivity extends AppCompatActivity {
// delegate the back press to it
if (fragmentPlayer instanceof BackPressable) {
if (!((BackPressable) fragmentPlayer).onBackPressed()) {
- final FrameLayout bottomSheetLayout =
- findViewById(R.id.fragment_player_holder);
- BottomSheetBehavior.from(bottomSheetLayout)
+ BottomSheetBehavior.from(mainBinding.fragmentPlayerHolder)
.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
return;
@@ -668,8 +665,7 @@ public class MainActivity extends AppCompatActivity {
final Fragment fragment
= getSupportFragmentManager().findFragmentById(R.id.fragment_holder);
if (!(fragment instanceof SearchFragment)) {
- findViewById(R.id.toolbar).findViewById(R.id.toolbar_search_container)
- .setVisibility(View.GONE);
+ toolbarLayoutBinding.toolbarSearchContainer.getRoot().setVisibility(View.GONE);
}
final ActionBar actionBar = getSupportActionBar();
@@ -730,21 +726,20 @@ public class MainActivity extends AppCompatActivity {
return;
}
- final Toolbar toolbar = findViewById(R.id.toolbar);
-
final Fragment fragment = getSupportFragmentManager()
.findFragmentById(R.id.fragment_holder);
if (fragment instanceof MainFragment) {
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
if (toggle != null) {
toggle.syncState();
- toolbar.setNavigationOnClickListener(v -> drawer.openDrawer(GravityCompat.START));
- drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNDEFINED);
+ toolbarLayoutBinding.toolbar.setNavigationOnClickListener(v -> mainBinding.getRoot()
+ .openDrawer(GravityCompat.START));
+ mainBinding.getRoot().setDrawerLockMode(DrawerLayout.LOCK_MODE_UNDEFINED);
}
} else {
- drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
+ mainBinding.getRoot().setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- toolbar.setNavigationOnClickListener(v -> onHomeButtonPressed());
+ toolbarLayoutBinding.toolbar.setNavigationOnClickListener(v -> onHomeButtonPressed());
}
}
@@ -852,9 +847,8 @@ public class MainActivity extends AppCompatActivity {
}
private boolean bottomSheetHiddenOrCollapsed() {
- final FrameLayout bottomSheetLayout = findViewById(R.id.fragment_player_holder);
final BottomSheetBehavior bottomSheetBehavior =
- BottomSheetBehavior.from(bottomSheetLayout);
+ BottomSheetBehavior.from(mainBinding.fragmentPlayerHolder);
final int sheetState = bottomSheetBehavior.getState();
return sheetState == BottomSheetBehavior.STATE_HIDDEN
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 4a8befa2c..6d25ed097 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,7 +1,6 @@
@@ -15,7 +14,9 @@
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize" />
-
+
-
+
From 4545b8e92d147354feae925377ec1f167b5f9cce Mon Sep 17 00:00:00 2001
From: Isira Seneviratne
Date: Sat, 31 Oct 2020 11:34:48 +0530
Subject: [PATCH 29/57] Use view binding in AboutActivity.
---
.../schabi/newpipe/about/AboutActivity.java | 59 ++++++-------------
1 file changed, 19 insertions(+), 40 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java
index e3e56816c..6ff691561 100644
--- a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java
@@ -6,22 +6,19 @@ import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
-import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.adapter.FragmentStateAdapter;
-import androidx.viewpager2.widget.ViewPager2;
-import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.databinding.ActivityAboutBinding;
+import org.schabi.newpipe.databinding.FragmentAboutBinding;
import org.schabi.newpipe.util.ThemeHelper;
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
@@ -68,40 +65,27 @@ public class AboutActivity extends AppCompatActivity {
private static final int POS_ABOUT = 0;
private static final int POS_LICENSE = 1;
private static final int TOTAL_COUNT = 2;
- /**
- * The {@link RecyclerView.Adapter} that will provide
- * fragments for each of the sections. We use a
- * {@link FragmentStateAdapter} derivative, which will keep every
- * loaded fragment in memory.
- */
- private SectionsPagerAdapter mSectionsPagerAdapter;
- /**
- * The {@link ViewPager2} that will host the section contents.
- */
- private ViewPager2 mViewPager;
@Override
protected void onCreate(final Bundle savedInstanceState) {
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState);
ThemeHelper.setTheme(this);
- this.setTitle(getString(R.string.title_activity_about));
+ setTitle(getString(R.string.title_activity_about));
- setContentView(R.layout.activity_about);
+ final ActivityAboutBinding aboutBinding = ActivityAboutBinding.inflate(getLayoutInflater());
+ setContentView(aboutBinding.getRoot());
- final Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ setSupportActionBar(aboutBinding.toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
- mSectionsPagerAdapter = new SectionsPagerAdapter(this);
+ final SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(this);
// Set up the ViewPager with the sections adapter.
- mViewPager = findViewById(R.id.container);
- mViewPager.setAdapter(mSectionsPagerAdapter);
+ aboutBinding.container.setAdapter(mSectionsPagerAdapter);
- final TabLayout tabLayout = findViewById(R.id.tabs);
- new TabLayoutMediator(tabLayout, mViewPager, (tab, position) -> {
+ new TabLayoutMediator(aboutBinding.tabs, aboutBinding.container, (tab, position) -> {
switch (position) {
default:
case POS_ABOUT:
@@ -143,33 +127,28 @@ public class AboutActivity extends AppCompatActivity {
}
@Override
- public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
+ public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container,
final Bundle savedInstanceState) {
- final View rootView = inflater.inflate(R.layout.fragment_about, container, false);
- final Context context = this.getContext();
+ final FragmentAboutBinding aboutBinding =
+ FragmentAboutBinding.inflate(inflater, container, false);
+ final Context context = getContext();
- final TextView version = rootView.findViewById(R.id.app_version);
- version.setText(BuildConfig.VERSION_NAME);
+ aboutBinding.appVersion.setText(BuildConfig.VERSION_NAME);
- final View githubLink = rootView.findViewById(R.id.github_link);
- githubLink.setOnClickListener(nv ->
+ aboutBinding.githubLink.setOnClickListener(nv ->
openUrlInBrowser(context, context.getString(R.string.github_url)));
- final View donationLink = rootView.findViewById(R.id.donation_link);
- donationLink.setOnClickListener(v ->
+ aboutBinding.donationLink.setOnClickListener(v ->
openUrlInBrowser(context, context.getString(R.string.donation_url)));
- final View websiteLink = rootView.findViewById(R.id.website_link);
- websiteLink.setOnClickListener(nv ->
+ aboutBinding.websiteLink.setOnClickListener(nv ->
openUrlInBrowser(context, context.getString(R.string.website_url)));
- final View privacyPolicyLink = rootView.findViewById(R.id.privacy_policy_link);
- privacyPolicyLink.setOnClickListener(v ->
+ aboutBinding.privacyPolicyLink.setOnClickListener(v ->
openUrlInBrowser(context, context.getString(R.string.privacy_policy_url)));
- return rootView;
+ return aboutBinding.getRoot();
}
-
}
/**
From a65ed7e914bdc8c75bfecc9856a7a452598c64db Mon Sep 17 00:00:00 2001
From: Isira Seneviratne
Date: Sat, 31 Oct 2020 13:41:01 +0530
Subject: [PATCH 30/57] Use view binding in DownloadActivity.
---
.../schabi/newpipe/download/DownloadActivity.java | 13 ++++++++-----
app/src/main/res/layout/activity_downloader.xml | 4 +++-
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java b/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java
index 979f8be75..37eefed96 100644
--- a/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java
@@ -9,10 +9,10 @@ import android.view.ViewTreeObserver;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.FragmentTransaction;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.databinding.ActivityDownloaderBinding;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ThemeHelper;
import org.schabi.newpipe.views.FocusOverlayView;
@@ -35,11 +35,14 @@ public class DownloadActivity extends AppCompatActivity {
assureCorrectAppLanguage(this);
ThemeHelper.setTheme(this);
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_downloader);
- final Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ super.onCreate(savedInstanceState);
+
+ final ActivityDownloaderBinding downloaderBinding =
+ ActivityDownloaderBinding.inflate(getLayoutInflater());
+ setContentView(downloaderBinding.getRoot());
+
+ setSupportActionBar(downloaderBinding.toolbarLayout.toolbar);
final ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
diff --git a/app/src/main/res/layout/activity_downloader.xml b/app/src/main/res/layout/activity_downloader.xml
index 272f6e76e..d91b943e7 100644
--- a/app/src/main/res/layout/activity_downloader.xml
+++ b/app/src/main/res/layout/activity_downloader.xml
@@ -3,7 +3,9 @@
android:layout_height="match_parent"
android:orientation="vertical">
-
+
Date: Sat, 31 Oct 2020 14:10:00 +0530
Subject: [PATCH 31/57] Use view binding in ReCaptchaActivity.
---
.../org/schabi/newpipe/ReCaptchaActivity.java | 29 +++++++++----------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java b/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java
index b6f65c355..dfe062a16 100644
--- a/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java
@@ -18,10 +18,10 @@ import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
import androidx.core.app.NavUtils;
import androidx.preference.PreferenceManager;
+import org.schabi.newpipe.databinding.ActivityRecaptchaBinding;
import org.schabi.newpipe.util.ThemeHelper;
import java.io.UnsupportedEncodingException;
@@ -62,30 +62,28 @@ public class ReCaptchaActivity extends AppCompatActivity {
}
}
-
- private WebView webView;
+ private ActivityRecaptchaBinding recaptchaBinding;
private String foundCookies = "";
@Override
protected void onCreate(final Bundle savedInstanceState) {
ThemeHelper.setTheme(this);
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_recaptcha);
- final Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+
+ recaptchaBinding = ActivityRecaptchaBinding.inflate(getLayoutInflater());
+ setContentView(recaptchaBinding.getRoot());
+ setSupportActionBar(recaptchaBinding.toolbar);
final String url = sanitizeRecaptchaUrl(getIntent().getStringExtra(RECAPTCHA_URL_EXTRA));
// set return to Cancel by default
setResult(RESULT_CANCELED);
- webView = findViewById(R.id.reCaptchaWebView);
-
// enable Javascript
- final WebSettings webSettings = webView.getSettings();
+ final WebSettings webSettings = recaptchaBinding.reCaptchaWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setUserAgentString(DownloaderImpl.USER_AGENT);
- webView.setWebViewClient(new WebViewClient() {
+ recaptchaBinding.reCaptchaWebView.setWebViewClient(new WebViewClient() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean shouldOverrideUrlLoading(final WebView view,
@@ -117,16 +115,16 @@ public class ReCaptchaActivity extends AppCompatActivity {
});
// cleaning cache, history and cookies from webView
- webView.clearCache(true);
- webView.clearHistory();
- final android.webkit.CookieManager cookieManager = CookieManager.getInstance();
+ recaptchaBinding.reCaptchaWebView.clearCache(true);
+ recaptchaBinding.reCaptchaWebView.clearHistory();
+ final CookieManager cookieManager = CookieManager.getInstance();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
cookieManager.removeAllCookies(value -> { });
} else {
cookieManager.removeAllCookie();
}
- webView.loadUrl(url);
+ recaptchaBinding.reCaptchaWebView.loadUrl(url);
}
@Override
@@ -158,7 +156,8 @@ public class ReCaptchaActivity extends AppCompatActivity {
}
private void saveCookiesAndFinish() {
- handleCookiesFromUrl(webView.getUrl()); // try to get cookies of unclosed page
+ // try to get cookies of unclosed page
+ handleCookiesFromUrl(recaptchaBinding.reCaptchaWebView.getUrl());
if (MainActivity.DEBUG) {
Log.d(TAG, "saveCookiesAndFinish: foundCookies=" + foundCookies);
}
From 22ec70e94d16408d165cb38fba77e1da40d70a9e Mon Sep 17 00:00:00 2001
From: Isira Seneviratne
Date: Sat, 31 Oct 2020 14:36:12 +0530
Subject: [PATCH 32/57] Use view binding in RouterActivity.
---
.../main/java/org/schabi/newpipe/RouterActivity.java | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java
index 9ad993de1..e04970e86 100644
--- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java
@@ -14,7 +14,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
-import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;
@@ -30,6 +29,8 @@ import androidx.core.widget.TextViewCompat;
import androidx.fragment.app.FragmentManager;
import androidx.preference.PreferenceManager;
+import org.schabi.newpipe.databinding.ListRadioIconItemBinding;
+import org.schabi.newpipe.databinding.SingleChoiceDialogViewBinding;
import org.schabi.newpipe.download.DownloadDialog;
import org.schabi.newpipe.extractor.Info;
import org.schabi.newpipe.extractor.NewPipe;
@@ -267,9 +268,8 @@ public class RouterActivity extends AppCompatActivity {
final Context themeWrapperContext = getThemeWrapperContext();
final LayoutInflater inflater = LayoutInflater.from(themeWrapperContext);
- final LinearLayout rootLayout = (LinearLayout) inflater.inflate(
- R.layout.single_choice_dialog_view, null, false);
- final RadioGroup radioGroup = rootLayout.findViewById(android.R.id.list);
+ final RadioGroup radioGroup = SingleChoiceDialogViewBinding.inflate(getLayoutInflater())
+ .list;
final DialogInterface.OnClickListener dialogButtonsClickListener = (dialog, which) -> {
final int indexOfChild = radioGroup.indexOfChild(
@@ -322,8 +322,7 @@ public class RouterActivity extends AppCompatActivity {
int id = 12345;
for (final AdapterChoiceItem item : choices) {
- final RadioButton radioButton
- = (RadioButton) inflater.inflate(R.layout.list_radio_icon_item, null);
+ final RadioButton radioButton = ListRadioIconItemBinding.inflate(inflater).getRoot();
radioButton.setText(item.description);
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(radioButton,
AppCompatResources.getDrawable(getApplicationContext(), item.icon),
From e6021465f677d91afe68ef17bacaf5251f4e200a Mon Sep 17 00:00:00 2001
From: Isira Seneviratne
Date: Sat, 31 Oct 2020 15:33:00 +0530
Subject: [PATCH 33/57] Use view binding in ServicePlayerActivity.
---
.../newpipe/player/ServicePlayerActivity.java | 214 ++++++++----------
1 file changed, 89 insertions(+), 125 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java
index 4bf6ef9ae..41d66dc90 100644
--- a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java
@@ -1,6 +1,7 @@
package org.schabi.newpipe.player;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
@@ -11,15 +12,10 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
import android.widget.PopupMenu;
-import android.widget.ProgressBar;
import android.widget.SeekBar;
-import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
@@ -29,6 +25,7 @@ import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.databinding.ActivityPlayerQueueControlBinding;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
@@ -70,30 +67,10 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
// Views
////////////////////////////////////////////////////////////////////////////
- private View rootView;
+ private ActivityPlayerQueueControlBinding queueControlBinding;
- private RecyclerView itemsList;
private ItemTouchHelper itemTouchHelper;
- private LinearLayout metadata;
- private TextView metadataTitle;
- private TextView metadataArtist;
-
- private SeekBar progressSeekBar;
- private TextView progressCurrentTime;
- private TextView progressEndTime;
- private TextView progressLiveSync;
- private TextView seekDisplay;
-
- private ImageButton repeatButton;
- private ImageButton backwardButton;
- private ImageButton fastRewindButton;
- private ImageButton playPauseButton;
- private ImageButton fastForwardButton;
- private ImageButton forwardButton;
- private ImageButton shuffleButton;
- private ProgressBar progressBar;
-
private Menu menu;
////////////////////////////////////////////////////////////////////////////
@@ -123,11 +100,11 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState);
ThemeHelper.setTheme(this);
- setContentView(R.layout.activity_player_queue_control);
- rootView = findViewById(R.id.main_content);
- final Toolbar toolbar = rootView.findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ queueControlBinding = ActivityPlayerQueueControlBinding.inflate(getLayoutInflater());
+ setContentView(queueControlBinding.getRoot());
+
+ setSupportActionBar(queueControlBinding.toolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(getSupportActionTitle());
@@ -230,14 +207,11 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
if (player != null && player.getPlayQueueAdapter() != null) {
player.getPlayQueueAdapter().unsetSelectedListener();
}
- if (itemsList != null) {
- itemsList.setAdapter(null);
- }
+ queueControlBinding.playQueue.setAdapter(null);
if (itemTouchHelper != null) {
itemTouchHelper.attachToRecyclerView(null);
}
- itemsList = null;
itemTouchHelper = null;
player = null;
}
@@ -284,58 +258,38 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
}
private void buildQueue() {
- itemsList = findViewById(R.id.play_queue);
- itemsList.setLayoutManager(new LinearLayoutManager(this));
- itemsList.setAdapter(player.getPlayQueueAdapter());
- itemsList.setClickable(true);
- itemsList.setLongClickable(true);
- itemsList.clearOnScrollListeners();
- itemsList.addOnScrollListener(getQueueScrollListener());
+ queueControlBinding.playQueue.setLayoutManager(new LinearLayoutManager(this));
+ queueControlBinding.playQueue.setAdapter(player.getPlayQueueAdapter());
+ queueControlBinding.playQueue.setClickable(true);
+ queueControlBinding.playQueue.setLongClickable(true);
+ queueControlBinding.playQueue.clearOnScrollListeners();
+ queueControlBinding.playQueue.addOnScrollListener(getQueueScrollListener());
itemTouchHelper = new ItemTouchHelper(getItemTouchCallback());
- itemTouchHelper.attachToRecyclerView(itemsList);
+ itemTouchHelper.attachToRecyclerView(queueControlBinding.playQueue);
player.getPlayQueueAdapter().setSelectedListener(getOnSelectedListener());
}
private void buildMetadata() {
- metadata = rootView.findViewById(R.id.metadata);
- metadataTitle = rootView.findViewById(R.id.song_name);
- metadataArtist = rootView.findViewById(R.id.artist_name);
-
- metadata.setOnClickListener(this);
- metadataTitle.setSelected(true);
- metadataArtist.setSelected(true);
+ queueControlBinding.metadata.setOnClickListener(this);
+ queueControlBinding.songName.setSelected(true);
+ queueControlBinding.artistName.setSelected(true);
}
private void buildSeekBar() {
- progressCurrentTime = rootView.findViewById(R.id.current_time);
- progressSeekBar = rootView.findViewById(R.id.seek_bar);
- progressEndTime = rootView.findViewById(R.id.end_time);
- progressLiveSync = rootView.findViewById(R.id.live_sync);
- seekDisplay = rootView.findViewById(R.id.seek_display);
-
- progressSeekBar.setOnSeekBarChangeListener(this);
- progressLiveSync.setOnClickListener(this);
+ queueControlBinding.seekBar.setOnSeekBarChangeListener(this);
+ queueControlBinding.liveSync.setOnClickListener(this);
}
private void buildControls() {
- repeatButton = rootView.findViewById(R.id.control_repeat);
- backwardButton = rootView.findViewById(R.id.control_backward);
- fastRewindButton = rootView.findViewById(R.id.control_fast_rewind);
- playPauseButton = rootView.findViewById(R.id.control_play_pause);
- fastForwardButton = rootView.findViewById(R.id.control_fast_forward);
- forwardButton = rootView.findViewById(R.id.control_forward);
- shuffleButton = rootView.findViewById(R.id.control_shuffle);
- progressBar = rootView.findViewById(R.id.control_progress_bar);
-
- repeatButton.setOnClickListener(this);
- backwardButton.setOnClickListener(this);
- fastRewindButton.setOnClickListener(this);
- playPauseButton.setOnClickListener(this);
- fastForwardButton.setOnClickListener(this);
- forwardButton.setOnClickListener(this);
- shuffleButton.setOnClickListener(this);
+ queueControlBinding.controlRepeat.setOnClickListener(this);
+ queueControlBinding.controlBackward.setOnClickListener(this);
+ queueControlBinding.controlFastRewind.setOnClickListener(this);
+ queueControlBinding.controlPlayPause.setOnClickListener(this);
+ queueControlBinding.controlFastForward.setOnClickListener(this);
+ queueControlBinding.controlForward.setOnClickListener(this);
+ queueControlBinding.controlShuffle.setOnClickListener(this);
}
private void buildItemPopupMenu(final PlayQueueItem item, final View view) {
@@ -391,8 +345,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
if (player != null && player.getPlayQueue() != null
&& !player.getPlayQueue().isComplete()) {
player.getPlayQueue().fetch();
- } else if (itemsList != null) {
- itemsList.clearOnScrollListeners();
+ } else {
+ queueControlBinding.playQueue.clearOnScrollListeners();
}
}
};
@@ -453,8 +407,9 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
final int currentPlayingIndex = player.getPlayQueue().getIndex();
final int currentVisibleIndex;
- if (itemsList.getLayoutManager() instanceof LinearLayoutManager) {
- final LinearLayoutManager layout = ((LinearLayoutManager) itemsList.getLayoutManager());
+ if (queueControlBinding.playQueue.getLayoutManager() instanceof LinearLayoutManager) {
+ final LinearLayoutManager layout =
+ (LinearLayoutManager) queueControlBinding.playQueue.getLayoutManager();
currentVisibleIndex = layout.findFirstVisibleItemPosition();
} else {
currentVisibleIndex = 0;
@@ -462,9 +417,9 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
final int distance = Math.abs(currentPlayingIndex - currentVisibleIndex);
if (distance < SMOOTH_SCROLL_MAXIMUM_DISTANCE) {
- itemsList.smoothScrollToPosition(currentPlayingIndex);
+ queueControlBinding.playQueue.smoothScrollToPosition(currentPlayingIndex);
} else {
- itemsList.scrollToPosition(currentPlayingIndex);
+ queueControlBinding.playQueue.scrollToPosition(currentPlayingIndex);
}
}
@@ -478,23 +433,23 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
return;
}
- if (view.getId() == repeatButton.getId()) {
+ if (view.getId() == queueControlBinding.controlRepeat.getId()) {
player.onRepeatClicked();
- } else if (view.getId() == backwardButton.getId()) {
+ } else if (view.getId() == queueControlBinding.controlBackward.getId()) {
player.onPlayPrevious();
- } else if (view.getId() == fastRewindButton.getId()) {
+ } else if (view.getId() == queueControlBinding.controlFastRewind.getId()) {
player.onFastRewind();
- } else if (view.getId() == playPauseButton.getId()) {
+ } else if (view.getId() == queueControlBinding.controlPlayPause.getId()) {
player.onPlayPause();
- } else if (view.getId() == fastForwardButton.getId()) {
+ } else if (view.getId() == queueControlBinding.controlFastForward.getId()) {
player.onFastForward();
- } else if (view.getId() == forwardButton.getId()) {
+ } else if (view.getId() == queueControlBinding.controlForward.getId()) {
player.onPlayNext();
- } else if (view.getId() == shuffleButton.getId()) {
+ } else if (view.getId() == queueControlBinding.controlShuffle.getId()) {
player.onShuffleClicked();
- } else if (view.getId() == metadata.getId()) {
+ } else if (view.getId() == queueControlBinding.metadata.getId()) {
scrollToSelected();
- } else if (view.getId() == progressLiveSync.getId()) {
+ } else if (view.getId() == queueControlBinding.liveSync.getId()) {
player.seekToDefault();
}
}
@@ -528,15 +483,15 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
final boolean fromUser) {
if (fromUser) {
final String seekTime = Localization.getDurationString(progress / 1000);
- progressCurrentTime.setText(seekTime);
- seekDisplay.setText(seekTime);
+ queueControlBinding.currentTime.setText(seekTime);
+ queueControlBinding.seekDisplay.setText(seekTime);
}
}
@Override
public void onStartTrackingTouch(final SeekBar seekBar) {
seeking = true;
- seekDisplay.setVisibility(View.VISIBLE);
+ queueControlBinding.seekDisplay.setVisibility(View.VISIBLE);
}
@Override
@@ -544,7 +499,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
if (player != null) {
player.seekTo(seekBar.getProgress());
}
- seekDisplay.setVisibility(View.GONE);
+ queueControlBinding.seekDisplay.setVisibility(View.GONE);
seeking = false;
}
@@ -602,45 +557,46 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
public void onProgressUpdate(final int currentProgress, final int duration,
final int bufferPercent) {
// Set buffer progress
- progressSeekBar.setSecondaryProgress((int) (progressSeekBar.getMax()
+ queueControlBinding.seekBar.setSecondaryProgress((int) (queueControlBinding.seekBar.getMax()
* ((float) bufferPercent / 100)));
// Set Duration
- progressSeekBar.setMax(duration);
- progressEndTime.setText(Localization.getDurationString(duration / 1000));
+ queueControlBinding.seekBar.setMax(duration);
+ queueControlBinding.endTime.setText(Localization.getDurationString(duration / 1000));
// Set current time if not seeking
if (!seeking) {
- progressSeekBar.setProgress(currentProgress);
- progressCurrentTime.setText(Localization.getDurationString(currentProgress / 1000));
+ queueControlBinding.seekBar.setProgress(currentProgress);
+ queueControlBinding.currentTime.setText(Localization
+ .getDurationString(currentProgress / 1000));
}
if (player != null) {
- progressLiveSync.setClickable(!player.isLiveEdge());
+ queueControlBinding.liveSync.setClickable(!player.isLiveEdge());
}
// this will make sure progressCurrentTime has the same width as progressEndTime
- final ViewGroup.LayoutParams endTimeParams = progressEndTime.getLayoutParams();
- final ViewGroup.LayoutParams currentTimeParams = progressCurrentTime.getLayoutParams();
- currentTimeParams.width = progressEndTime.getWidth();
- progressCurrentTime.setLayoutParams(currentTimeParams);
+ final ViewGroup.LayoutParams currentTimeParams =
+ queueControlBinding.currentTime.getLayoutParams();
+ currentTimeParams.width = queueControlBinding.endTime.getWidth();
+ queueControlBinding.currentTime.setLayoutParams(currentTimeParams);
}
@Override
public void onMetadataUpdate(final StreamInfo info, final PlayQueue queue) {
if (info != null) {
- metadataTitle.setText(info.getName());
- metadataArtist.setText(info.getUploaderName());
+ queueControlBinding.songName.setText(info.getName());
+ queueControlBinding.artistName.setText(info.getUploaderName());
- progressEndTime.setVisibility(View.GONE);
- progressLiveSync.setVisibility(View.GONE);
+ queueControlBinding.endTime.setVisibility(View.GONE);
+ queueControlBinding.liveSync.setVisibility(View.GONE);
switch (info.getStreamType()) {
case LIVE_STREAM:
case AUDIO_LIVE_STREAM:
- progressLiveSync.setVisibility(View.VISIBLE);
+ queueControlBinding.liveSync.setVisibility(View.VISIBLE);
break;
default:
- progressEndTime.setVisibility(View.VISIBLE);
+ queueControlBinding.endTime.setVisibility(View.VISIBLE);
break;
}
@@ -661,13 +617,16 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
private void onStateChanged(final int state) {
switch (state) {
case BasePlayer.STATE_PAUSED:
- playPauseButton.setImageResource(R.drawable.ic_play_arrow_white_24dp);
+ queueControlBinding.controlPlayPause
+ .setImageResource(R.drawable.ic_play_arrow_white_24dp);
break;
case BasePlayer.STATE_PLAYING:
- playPauseButton.setImageResource(R.drawable.ic_pause_white_24dp);
+ queueControlBinding.controlPlayPause
+ .setImageResource(R.drawable.ic_pause_white_24dp);
break;
case BasePlayer.STATE_COMPLETED:
- playPauseButton.setImageResource(R.drawable.ic_replay_white_24dp);
+ queueControlBinding.controlPlayPause
+ .setImageResource(R.drawable.ic_replay_white_24dp);
break;
default:
break;
@@ -677,14 +636,14 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
case BasePlayer.STATE_PAUSED:
case BasePlayer.STATE_PLAYING:
case BasePlayer.STATE_COMPLETED:
- playPauseButton.setClickable(true);
- playPauseButton.setVisibility(View.VISIBLE);
- progressBar.setVisibility(View.GONE);
+ queueControlBinding.controlPlayPause.setClickable(true);
+ queueControlBinding.controlPlayPause.setVisibility(View.VISIBLE);
+ queueControlBinding.progressBar.setVisibility(View.GONE);
break;
default:
- playPauseButton.setClickable(false);
- playPauseButton.setVisibility(View.INVISIBLE);
- progressBar.setVisibility(View.VISIBLE);
+ queueControlBinding.controlPlayPause.setClickable(false);
+ queueControlBinding.controlPlayPause.setVisibility(View.INVISIBLE);
+ queueControlBinding.progressBar.setVisibility(View.VISIBLE);
break;
}
}
@@ -692,18 +651,21 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
private void onPlayModeChanged(final int repeatMode, final boolean shuffled) {
switch (repeatMode) {
case Player.REPEAT_MODE_OFF:
- repeatButton.setImageResource(R.drawable.exo_controls_repeat_off);
+ queueControlBinding.controlRepeat
+ .setImageResource(R.drawable.exo_controls_repeat_off);
break;
case Player.REPEAT_MODE_ONE:
- repeatButton.setImageResource(R.drawable.exo_controls_repeat_one);
+ queueControlBinding.controlRepeat
+ .setImageResource(R.drawable.exo_controls_repeat_one);
break;
case Player.REPEAT_MODE_ALL:
- repeatButton.setImageResource(R.drawable.exo_controls_repeat_all);
+ queueControlBinding.controlRepeat
+ .setImageResource(R.drawable.exo_controls_repeat_all);
break;
}
final int shuffleAlpha = shuffled ? 255 : 77;
- shuffleButton.setImageAlpha(shuffleAlpha);
+ queueControlBinding.controlShuffle.setImageAlpha(shuffleAlpha);
}
private void onPlaybackParameterChanged(final PlaybackParameters parameters) {
@@ -716,12 +678,13 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
}
private void onMaybePlaybackAdapterChanged() {
- if (itemsList == null || player == null) {
+ if (player == null) {
return;
}
final PlayQueueAdapter maybeNewAdapter = player.getPlayQueueAdapter();
- if (maybeNewAdapter != null && itemsList.getAdapter() != maybeNewAdapter) {
- itemsList.setAdapter(maybeNewAdapter);
+ if (maybeNewAdapter != null
+ && queueControlBinding.playQueue.getAdapter() != maybeNewAdapter) {
+ queueControlBinding.playQueue.setAdapter(maybeNewAdapter);
}
}
@@ -735,7 +698,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
//2) Icon change accordingly to current App Theme
// using rootView.getContext() because getApplicationContext() didn't work
- item.setIcon(ThemeHelper.resolveResourceIdFromAttr(rootView.getContext(),
+ final Context context = queueControlBinding.getRoot().getContext();
+ item.setIcon(ThemeHelper.resolveResourceIdFromAttr(context,
player.isMuted()
? R.attr.ic_volume_off
: R.attr.ic_volume_up));
From b4d77df1be3f06f8a44f153f3ab23d8c7b5c3788 Mon Sep 17 00:00:00 2001
From: Isira Seneviratne
Date: Sat, 31 Oct 2020 15:44:11 +0530
Subject: [PATCH 34/57] Use view binding in ErrorActivity.
---
.../schabi/newpipe/report/ErrorActivity.java | 56 ++++++++-----------
app/src/main/res/layout/activity_error.xml | 4 +-
2 files changed, 25 insertions(+), 35 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java b/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java
index 3213821cd..a4b6af2ab 100644
--- a/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java
@@ -14,15 +14,11 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
import androidx.core.app.NavUtils;
import com.google.android.material.snackbar.Snackbar;
@@ -34,6 +30,7 @@ import org.schabi.newpipe.ActivityCommunicator;
import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.MainActivity;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.databinding.ActivityErrorBinding;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.ShareUtils;
import org.schabi.newpipe.util.ThemeHelper;
@@ -87,7 +84,8 @@ public class ErrorActivity extends AppCompatActivity {
private ErrorInfo errorInfo;
private Class returnActivity;
private String currentTimeStamp;
- private EditText userCommentBox;
+
+ private ActivityErrorBinding activityErrorBinding;
public static void reportUiError(final AppCompatActivity activity, final Throwable el) {
reportError(activity, el, activity.getClass(), null, ErrorInfo.make(UserAction.UI_ERROR,
@@ -181,12 +179,13 @@ public class ErrorActivity extends AppCompatActivity {
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceState);
ThemeHelper.setTheme(this);
- setContentView(R.layout.activity_error);
+
+ activityErrorBinding = ActivityErrorBinding.inflate(getLayoutInflater());
+ setContentView(activityErrorBinding.getRoot());
final Intent intent = getIntent();
- final Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ setSupportActionBar(activityErrorBinding.toolbarLayout.toolbar);
final ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
@@ -195,15 +194,6 @@ public class ErrorActivity extends AppCompatActivity {
actionBar.setDisplayShowTitleEnabled(true);
}
- final Button reportEmailButton = findViewById(R.id.errorReportEmailButton);
- final Button copyButton = findViewById(R.id.errorReportCopyButton);
- final Button reportGithubButton = findViewById(R.id.errorReportGitHubButton);
-
- userCommentBox = findViewById(R.id.errorCommentBox);
- final TextView errorView = findViewById(R.id.errorView);
- final TextView infoView = findViewById(R.id.errorInfosView);
- final TextView errorMessageView = findViewById(R.id.errorMessageView);
-
final ActivityCommunicator ac = ActivityCommunicator.getCommunicator();
returnActivity = ac.getReturnActivity();
errorInfo = intent.getParcelableExtra(ERROR_INFO);
@@ -213,28 +203,27 @@ public class ErrorActivity extends AppCompatActivity {
addGuruMeditation();
currentTimeStamp = getCurrentTimeStamp();
- reportEmailButton.setOnClickListener(v ->
+ activityErrorBinding.errorReportEmailButton.setOnClickListener(v ->
openPrivacyPolicyDialog(this, "EMAIL"));
- copyButton.setOnClickListener(v -> {
+ activityErrorBinding.errorReportCopyButton.setOnClickListener(v -> {
ShareUtils.copyToClipboard(this, buildMarkdown());
Toast.makeText(this, R.string.msg_copied, Toast.LENGTH_SHORT).show();
});
- reportGithubButton.setOnClickListener(v ->
+ activityErrorBinding.errorReportGitHubButton.setOnClickListener(v ->
openPrivacyPolicyDialog(this, "GITHUB"));
-
// normal bugreport
buildInfo(errorInfo);
if (errorInfo.getMessage() != 0) {
- errorMessageView.setText(errorInfo.getMessage());
+ activityErrorBinding.errorMessageView.setText(errorInfo.getMessage());
} else {
- errorMessageView.setVisibility(View.GONE);
- findViewById(R.id.messageWhatHappenedView).setVisibility(View.GONE);
+ activityErrorBinding.errorMessageView.setVisibility(View.GONE);
+ activityErrorBinding.messageWhatHappenedView.setVisibility(View.GONE);
}
- errorView.setText(formErrorText(errorList));
+ activityErrorBinding.errorView.setText(formErrorText(errorList));
// print stack trace once again for debugging:
for (final String e : errorList) {
@@ -339,11 +328,10 @@ public class ErrorActivity extends AppCompatActivity {
}
private void buildInfo(final ErrorInfo info) {
- final TextView infoLabelView = findViewById(R.id.errorInfoLabelsView);
- final TextView infoView = findViewById(R.id.errorInfosView);
String text = "";
- infoLabelView.setText(getString(R.string.info_labels).replace("\\n", "\n"));
+ activityErrorBinding.errorInfoLabelsView.setText(getString(R.string.info_labels)
+ .replace("\\n", "\n"));
text += getUserActionString(info.getUserAction()) + "\n"
+ info.getRequest() + "\n"
@@ -356,7 +344,7 @@ public class ErrorActivity extends AppCompatActivity {
+ BuildConfig.VERSION_NAME + "\n"
+ getOsString();
- infoView.setText(text);
+ activityErrorBinding.errorInfosView.setText(text);
}
private String buildJson() {
@@ -374,7 +362,8 @@ public class ErrorActivity extends AppCompatActivity {
.value("os", getOsString())
.value("time", currentTimeStamp)
.array("exceptions", Arrays.asList(errorList))
- .value("user_comment", userCommentBox.getText().toString())
+ .value("user_comment", activityErrorBinding.errorCommentBox.getText()
+ .toString())
.end()
.done();
} catch (final Throwable e) {
@@ -389,7 +378,7 @@ public class ErrorActivity extends AppCompatActivity {
try {
final StringBuilder htmlErrorReport = new StringBuilder();
- final String userComment = userCommentBox.getText().toString();
+ final String userComment = activityErrorBinding.errorCommentBox.getText().toString();
if (!userComment.isEmpty()) {
htmlErrorReport.append(userComment).append("\n");
}
@@ -473,10 +462,9 @@ public class ErrorActivity extends AppCompatActivity {
private void addGuruMeditation() {
//just an easter egg
- final TextView sorryView = findViewById(R.id.errorSorryView);
- String text = sorryView.getText().toString();
+ String text = activityErrorBinding.errorSorryView.getText().toString();
text += "\n" + getString(R.string.guru_meditation);
- sorryView.setText(text);
+ activityErrorBinding.errorSorryView.setText(text);
}
@Override
diff --git a/app/src/main/res/layout/activity_error.xml b/app/src/main/res/layout/activity_error.xml
index f265c2658..4feea549c 100644
--- a/app/src/main/res/layout/activity_error.xml
+++ b/app/src/main/res/layout/activity_error.xml
@@ -5,7 +5,9 @@
android:layout_height="match_parent"
tools:context=".report.ErrorActivity">
-
+
Date: Sat, 31 Oct 2020 15:46:46 +0530
Subject: [PATCH 35/57] Use view binding in SettingsActivity.
---
.../org/schabi/newpipe/settings/SettingsActivity.java | 10 ++++++----
app/src/main/res/layout/settings_layout.xml | 4 +++-
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java
index d2d4c2404..4de166a55 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java
@@ -7,12 +7,12 @@ import android.view.MenuItem;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.databinding.SettingsLayoutBinding;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ThemeHelper;
import org.schabi.newpipe.views.FocusOverlayView;
@@ -51,10 +51,12 @@ public class SettingsActivity extends AppCompatActivity
setTheme(ThemeHelper.getSettingsThemeStyle(this));
assureCorrectAppLanguage(this);
super.onCreate(savedInstanceBundle);
- setContentView(R.layout.settings_layout);
- final Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
+ final SettingsLayoutBinding settingsLayoutBinding =
+ SettingsLayoutBinding.inflate(getLayoutInflater());
+ setContentView(settingsLayoutBinding.getRoot());
+
+ setSupportActionBar(settingsLayoutBinding.toolbarLayout.toolbar);
if (savedInstanceBundle == null) {
getSupportFragmentManager().beginTransaction()
diff --git a/app/src/main/res/layout/settings_layout.xml b/app/src/main/res/layout/settings_layout.xml
index d50924c46..32c6c6b91 100644
--- a/app/src/main/res/layout/settings_layout.xml
+++ b/app/src/main/res/layout/settings_layout.xml
@@ -12,6 +12,8 @@
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize" />
-
+
From e4d94b1a4e4fbfdaeb1336f9a416e23dec60cb02 Mon Sep 17 00:00:00 2001
From: Isira Seneviratne
Date: Sat, 19 Dec 2020 04:25:42 +0530
Subject: [PATCH 36/57] Add AndroidX Webkit.
---
app/build.gradle | 1 +
1 file changed, 1 insertion(+)
diff --git a/app/build.gradle b/app/build.gradle
index 4acff01bf..15561b2d2 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -203,6 +203,7 @@ dependencies {
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.documentfile:documentfile:1.0.1'
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
+ implementation 'androidx.webkit:webkit:1.4.0'
implementation "androidx.lifecycle:lifecycle-livedata:${androidxLifecycleVersion}"
implementation "androidx.lifecycle:lifecycle-viewmodel:${androidxLifecycleVersion}"
From 173150591dcb91cb2e8e3f5c42c709087a9ec3bc Mon Sep 17 00:00:00 2001
From: Isira Seneviratne
Date: Sat, 19 Dec 2020 04:41:01 +0530
Subject: [PATCH 37/57] Use WebViewClientCompat in ReCaptchaActivity.
---
.../org/schabi/newpipe/ReCaptchaActivity.java | 19 ++-----------------
1 file changed, 2 insertions(+), 17 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java b/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java
index dfe062a16..463fc24ac 100644
--- a/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java
@@ -8,18 +8,16 @@ import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.CookieManager;
-import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
-import android.webkit.WebViewClient;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NavUtils;
import androidx.preference.PreferenceManager;
+import androidx.webkit.WebViewClientCompat;
import org.schabi.newpipe.databinding.ActivityRecaptchaBinding;
import org.schabi.newpipe.util.ThemeHelper;
@@ -83,20 +81,7 @@ public class ReCaptchaActivity extends AppCompatActivity {
webSettings.setJavaScriptEnabled(true);
webSettings.setUserAgentString(DownloaderImpl.USER_AGENT);
- recaptchaBinding.reCaptchaWebView.setWebViewClient(new WebViewClient() {
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
- @Override
- public boolean shouldOverrideUrlLoading(final WebView view,
- final WebResourceRequest request) {
- final String url = request.getUrl().toString();
- if (MainActivity.DEBUG) {
- Log.d(TAG, "shouldOverrideUrlLoading: request.url=" + url);
- }
-
- handleCookiesFromUrl(url);
- return false;
- }
-
+ recaptchaBinding.reCaptchaWebView.setWebViewClient(new WebViewClientCompat() {
@Override
public boolean shouldOverrideUrlLoading(final WebView view, final String url) {
if (MainActivity.DEBUG) {
From 0fe3fe7594d5815c71e6b667570e9cd7523dc9ea Mon Sep 17 00:00:00 2001
From: Isira Seneviratne
Date: Sat, 19 Dec 2020 16:52:17 +0530
Subject: [PATCH 38/57] Use ServiceCompat.stopForeground().
---
app/src/main/java/org/schabi/newpipe/RouterActivity.java | 3 ++-
.../org/schabi/newpipe/local/feed/service/FeedLoadService.kt | 3 ++-
.../local/subscription/services/BaseImportExportService.java | 3 ++-
.../java/org/schabi/newpipe/player/NotificationUtil.java | 3 ++-
.../us/shandian/giga/service/DownloadManagerService.java | 5 +++--
5 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java
index e04970e86..98a0921e4 100644
--- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java
@@ -25,6 +25,7 @@ import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.app.NotificationCompat;
+import androidx.core.app.ServiceCompat;
import androidx.core.widget.TextViewCompat;
import androidx.fragment.app.FragmentManager;
import androidx.preference.PreferenceManager;
@@ -695,7 +696,7 @@ public class RouterActivity extends AppCompatActivity {
@Override
public void onDestroy() {
super.onDestroy();
- stopForeground(true);
+ ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE);
if (fetcher != null) {
fetcher.dispose();
}
diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadService.kt b/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadService.kt
index ddbbea23d..2a0aa1c90 100644
--- a/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadService.kt
+++ b/app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadService.kt
@@ -30,6 +30,7 @@ import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
+import androidx.core.app.ServiceCompat
import androidx.preference.PreferenceManager
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Flowable
@@ -147,7 +148,7 @@ class FeedLoadService : Service() {
private fun stopService() {
disposeAll()
- stopForeground(true)
+ ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
notificationManager.cancel(NOTIFICATION_ID)
stopSelf()
}
diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java b/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java
index 73c0d23a0..34543b565 100644
--- a/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java
+++ b/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java
@@ -31,6 +31,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
+import androidx.core.app.ServiceCompat;
import org.reactivestreams.Publisher;
import org.schabi.newpipe.R;
@@ -162,7 +163,7 @@ public abstract class BaseImportExportService extends Service {
protected void postErrorResult(final String title, final String text) {
disposeAll();
- stopForeground(true);
+ ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE);
stopSelf();
if (title == null) {
diff --git a/app/src/main/java/org/schabi/newpipe/player/NotificationUtil.java b/app/src/main/java/org/schabi/newpipe/player/NotificationUtil.java
index 860ace84c..c1c2e4eba 100644
--- a/app/src/main/java/org/schabi/newpipe/player/NotificationUtil.java
+++ b/app/src/main/java/org/schabi/newpipe/player/NotificationUtil.java
@@ -15,6 +15,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
+import androidx.core.app.ServiceCompat;
import androidx.core.content.ContextCompat;
import org.schabi.newpipe.MainActivity;
@@ -188,7 +189,7 @@ public final class NotificationUtil {
}
void cancelNotificationAndStopForeground(final Service service) {
- service.stopForeground(true);
+ ServiceCompat.stopForeground(service, ServiceCompat.STOP_FOREGROUND_REMOVE);
if (notificationManager != null) {
notificationManager.cancel(NOTIFICATION_ID);
diff --git a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java
index b43733a51..e77196445 100755
--- a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java
+++ b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java
@@ -25,6 +25,7 @@ import android.os.IBinder;
import android.os.Message;
import android.os.Parcelable;
+import androidx.core.app.ServiceCompat;
import androidx.core.content.ContextCompat;
import androidx.preference.PreferenceManager;
import android.util.Log;
@@ -235,7 +236,7 @@ public class DownloadManagerService extends Service {
Log.d(TAG, "Destroying");
}
- stopForeground(true);
+ ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE);
if (mNotificationManager != null && downloadDoneNotification != null) {
downloadDoneNotification.setDeleteIntent(null);// prevent NewPipe running when is killed, cleared from recent, etc
@@ -363,7 +364,7 @@ public class DownloadManagerService extends Service {
if (state) {
startForeground(FOREGROUND_NOTIFICATION_ID, mNotification);
} else {
- stopForeground(true);
+ ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE);
}
manageLock(state);
From 908dff39319e01bc1e314f1ee89e285f538ff04e Mon Sep 17 00:00:00 2001
From: TobiGr
Date: Sun, 20 Dec 2020 01:18:39 +0100
Subject: [PATCH 39/57] Fix security vulnerability in checkstyle / guava
---
app/build.gradle | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/build.gradle b/app/build.gradle
index 15561b2d2..3ac8ff525 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -93,7 +93,7 @@ android {
ext {
icepickVersion = '3.2.0'
- checkstyleVersion = '8.37'
+ checkstyleVersion = '8.38'
stethoVersion = '1.5.1'
leakCanaryVersion = '2.5'
exoPlayerVersion = '2.11.8'
From 7a7a90bf79a613dad94fac4eea1af3747ccbb725 Mon Sep 17 00:00:00 2001
From: bopol
Date: Sun, 20 Dec 2020 00:03:19 +0100
Subject: [PATCH 40/57] remove timestamp from share url for all services except
youtube
It produces not found error for PeerTube, media.ccc.de, SoundCloud
---
.../org/schabi/newpipe/player/VideoPlayerImpl.java | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java b/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java
index 3cbcb87a3..a304b4430 100644
--- a/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java
+++ b/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java
@@ -103,6 +103,7 @@ import org.schabi.newpipe.util.ShareUtils;
import java.util.List;
+import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static org.schabi.newpipe.player.MainPlayer.ACTION_CLOSE;
import static org.schabi.newpipe.player.MainPlayer.ACTION_FAST_FORWARD;
import static org.schabi.newpipe.player.MainPlayer.ACTION_FAST_REWIND;
@@ -889,10 +890,17 @@ public class VideoPlayerImpl extends VideoPlayer
private void onShareClicked() {
// share video at the current time (youtube.com/watch?v=ID&t=SECONDS)
// Timestamp doesn't make sense in a live stream so drop it
- final String ts = isLive() ? "" : ("&t=" + (getPlaybackSeekBar().getProgress() / 1000));
+
+ final int ts = getPlaybackSeekBar().getProgress() / 1000;
+ final MediaSourceTag metadata = getCurrentMetadata();
+ String videoUrl = getVideoUrl();
+ if (!isLive() && ts >= 0 && metadata != null
+ && metadata.getMetadata().getServiceId() == YouTube.getServiceId()) {
+ videoUrl += ("&t=" + ts);
+ }
ShareUtils.shareUrl(service,
getVideoTitle(),
- getVideoUrl() + ts);
+ videoUrl);
}
private void onPlayWithKodiClicked() {
From 0a831ec84e7a3c822ce1822d97bc9b934a510f33 Mon Sep 17 00:00:00 2001
From: TobiGr
Date: Tue, 15 Dec 2020 17:41:21 +0100
Subject: [PATCH 41/57] Display meta info about search query, stream creator or
topic
Closes #4614
---
app/build.gradle | 2 +-
.../newpipe/fragments/MainFragment.java | 2 +-
.../fragments/detail/VideoDetailFragment.java | 77 +++++++++++++++----
.../fragments/list/search/SearchFragment.java | 48 ++++++++++++
.../fragment_video_detail.xml | 32 ++++++++
app/src/main/res/layout/fragment_search.xml | 14 +++-
.../main/res/layout/fragment_video_detail.xml | 33 ++++++++
app/src/main/res/values/settings_keys.xml | 1 +
app/src/main/res/values/strings.xml | 2 +
app/src/main/res/xml/content_settings.xml | 7 ++
10 files changed, 200 insertions(+), 18 deletions(-)
diff --git a/app/build.gradle b/app/build.gradle
index 15561b2d2..fadfc3221 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -179,7 +179,7 @@ dependencies {
// NewPipe dependencies
// You can use a local version by uncommenting a few lines in settings.gradle
- implementation 'com.github.TeamNewPipe:NewPipeExtractor:85fa006214b003f21eacb76c445a167732f19981'
+ implementation 'com.github.TeamNewPipe:NewPipeExtractor:79b5aa9760da52020821b68e2af41a9238943304'
implementation "com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751"
implementation "org.jsoup:jsoup:1.13.1"
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 866b324ec..a77109f86 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java
@@ -3,7 +3,6 @@ package org.schabi.newpipe.fragments;
import android.content.Context;
import android.content.res.ColorStateList;
import android.os.Bundle;
-import androidx.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -19,6 +18,7 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapterMenuWorkaround;
+import androidx.preference.PreferenceManager;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
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 427cff06e..b9cb4ab2b 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
@@ -16,7 +16,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
-import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
import android.text.util.Linkify;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -63,6 +63,7 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.ReCaptchaActivity;
import org.schabi.newpipe.download.DownloadDialog;
import org.schabi.newpipe.extractor.InfoItem;
+import org.schabi.newpipe.extractor.MetaInfo;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
@@ -122,8 +123,10 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
+import static android.text.TextUtils.isEmpty;
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.COMMENTS;
import static org.schabi.newpipe.extractor.stream.StreamExtractor.NO_AGE_LIMIT;
+import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
import static org.schabi.newpipe.player.helper.PlayerHelper.globalScreenOrientationLocked;
import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfirmationRequired;
import static org.schabi.newpipe.player.playqueue.PlayQueueItem.RECOVERY_UNSET;
@@ -218,6 +221,10 @@ public final class VideoDetailFragment
private TextView detailDurationView;
private TextView detailPositionView;
+ private LinearLayout detailMetadataInfo;
+ private View detailMetadataInfoSeparator;
+ private TextView detailMetadataInfoText;
+
private LinearLayout videoDescriptionRootLayout;
private TextView videoUploadDateView;
private TextView videoDescriptionView;
@@ -508,8 +515,8 @@ public final class VideoDetailFragment
}
break;
case R.id.detail_uploader_root_layout:
- if (TextUtils.isEmpty(currentInfo.getSubChannelUrl())) {
- if (!TextUtils.isEmpty(currentInfo.getUploaderUrl())) {
+ if (isEmpty(currentInfo.getSubChannelUrl())) {
+ if (!isEmpty(currentInfo.getUploaderUrl())) {
openChannel(currentInfo.getUploaderUrl(), currentInfo.getUploaderName());
}
@@ -583,7 +590,7 @@ public final class VideoDetailFragment
}
break;
case R.id.detail_uploader_root_layout:
- if (TextUtils.isEmpty(currentInfo.getSubChannelUrl())) {
+ if (isEmpty(currentInfo.getSubChannelUrl())) {
Log.w(TAG,
"Can't open parent channel because we got no parent channel URL");
} else {
@@ -644,6 +651,10 @@ public final class VideoDetailFragment
detailDurationView = rootView.findViewById(R.id.detail_duration_view);
detailPositionView = rootView.findViewById(R.id.detail_position_view);
+ detailMetadataInfo = rootView.findViewById(R.id.detail_metadata_info);
+ detailMetadataInfoSeparator = rootView.findViewById(R.id.detail_metadata_info_separator);
+ detailMetadataInfoText = rootView.findViewById(R.id.detail_metadata_info_text);
+
videoDescriptionRootLayout = rootView.findViewById(R.id.detail_description_root_layout);
videoUploadDateView = rootView.findViewById(R.id.detail_upload_date_view);
videoDescriptionView = rootView.findViewById(R.id.detail_description_view);
@@ -748,7 +759,7 @@ public final class VideoDetailFragment
private void initThumbnailViews(@NonNull final StreamInfo info) {
thumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark);
- if (!TextUtils.isEmpty(info.getThumbnailUrl())) {
+ if (!isEmpty(info.getThumbnailUrl())) {
final String infoServiceName = NewPipe.getNameOfService(info.getServiceId());
final ImageLoadingListener onFailListener = new SimpleImageLoadingListener() {
@Override
@@ -763,12 +774,12 @@ public final class VideoDetailFragment
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS, onFailListener);
}
- if (!TextUtils.isEmpty(info.getSubChannelAvatarUrl())) {
+ if (!isEmpty(info.getSubChannelAvatarUrl())) {
IMAGE_LOADER.displayImage(info.getSubChannelAvatarUrl(), subChannelThumb,
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
}
- if (!TextUtils.isEmpty(info.getUploaderAvatarUrl())) {
+ if (!isEmpty(info.getUploaderAvatarUrl())) {
IMAGE_LOADER.displayImage(info.getUploaderAvatarUrl(), uploaderThumb,
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
}
@@ -1217,7 +1228,7 @@ public final class VideoDetailFragment
}
private void prepareDescription(final Description description) {
- if (description == null || TextUtils.isEmpty(description.getContent())
+ if (description == null || isEmpty(description.getContent())
|| description == Description.emptyDescription) {
return;
}
@@ -1247,6 +1258,42 @@ public final class VideoDetailFragment
}
}
+ private void setMetaInfo(final StreamInfo info) {
+ final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(
+ requireContext());
+ final boolean showMetaInfo = sp.getBoolean(
+ requireContext().getString(R.string.show_meta_info_key), true);
+ if (info.getMetaInfo().isEmpty() || !showMetaInfo) {
+ detailMetadataInfo.setVisibility(View.GONE);
+ detailMetadataInfoSeparator.setVisibility(View.GONE);
+ } else {
+ final List metaIfs = info.getMetaInfo();
+ final StringBuilder stringBuilder = new StringBuilder();
+ for (final MetaInfo mi: metaIfs) {
+ if (!isNullOrEmpty(mi.getTitle())) {
+ stringBuilder.append("
").append(mi.getTitle()).append("
");
+ }
+ stringBuilder.append(mi.getContent().getContent());
+ for (int i = 0; i < mi.getUrls().size(); i++) {
+ stringBuilder
+ .append(" ")
+ .append(mi.getUrlTexts().get(i))
+ .append("");
+ if (i < mi.getUrls().size() - 1 && mi.getUrls().size() > 1) {
+ // append line break to all but the last URL if there are multiple URLs
+ stringBuilder.append(" ");
+ }
+ }
+ }
+
+ detailMetadataInfoSeparator.setVisibility(View.VISIBLE);
+ detailMetadataInfoText.setText(HtmlCompat.fromHtml(
+ stringBuilder.toString(), HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING));
+ detailMetadataInfoText.setMovementMethod(LinkMovementMethod.getInstance());
+ detailMetadataInfo.setVisibility(View.VISIBLE);
+ }
+ }
+
private final ViewTreeObserver.OnPreDrawListener preDrawListener =
new ViewTreeObserver.OnPreDrawListener() {
@Override
@@ -1462,9 +1509,9 @@ public final class VideoDetailFragment
animateView(thumbnailPlayButton, true, 200);
videoTitleTextView.setText(title);
- if (!TextUtils.isEmpty(info.getSubChannelName())) {
+ if (!isEmpty(info.getSubChannelName())) {
displayBothUploaderAndSubChannel(info);
- } else if (!TextUtils.isEmpty(info.getUploaderName())) {
+ } else if (!isEmpty(info.getUploaderName())) {
displayUploaderAsSubChannel(info);
} else {
uploaderTextView.setVisibility(View.GONE);
@@ -1559,6 +1606,8 @@ public final class VideoDetailFragment
prepareDescription(info.getDescription());
updateProgressInfo(info);
initThumbnailViews(info);
+ setMetaInfo(info);
+
if (player == null || player.isPlayerStopped()) {
updateOverlayData(info.getName(), info.getUploaderName(), info.getThumbnailUrl());
@@ -1610,7 +1659,7 @@ public final class VideoDetailFragment
subChannelThumb.setVisibility(View.VISIBLE);
- if (!TextUtils.isEmpty(info.getUploaderName())) {
+ if (!isEmpty(info.getUploaderName())) {
uploaderTextView.setText(
String.format(getString(R.string.video_detail_by), info.getUploaderName()));
uploaderTextView.setVisibility(View.VISIBLE);
@@ -2305,10 +2354,10 @@ public final class VideoDetailFragment
private void updateOverlayData(@Nullable final String overlayTitle,
@Nullable final String uploader,
@Nullable final String thumbnailUrl) {
- overlayTitleTextView.setText(TextUtils.isEmpty(overlayTitle) ? "" : overlayTitle);
- overlayChannelTextView.setText(TextUtils.isEmpty(uploader) ? "" : uploader);
+ overlayTitleTextView.setText(isEmpty(title) ? "" : title);
+ overlayChannelTextView.setText(isEmpty(uploader) ? "" : uploader);
overlayThumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark);
- if (!TextUtils.isEmpty(thumbnailUrl)) {
+ if (!isEmpty(thumbnailUrl)) {
IMAGE_LOADER.displayImage(thumbnailUrl, overlayThumbnailImageView,
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS, null);
}
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 02dbf176b..f44e5e330 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
@@ -9,6 +9,7 @@ import android.text.Editable;
import android.text.Html;
import android.text.TextUtils;
import android.text.TextWatcher;
+import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -39,6 +40,7 @@ import org.schabi.newpipe.ReCaptchaActivity;
import org.schabi.newpipe.database.history.model.SearchHistoryEntry;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
+import org.schabi.newpipe.extractor.MetaInfo;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.Page;
import org.schabi.newpipe.extractor.StreamingService;
@@ -78,6 +80,7 @@ import io.reactivex.rxjava3.subjects.PublishSubject;
import static androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags;
import static java.util.Arrays.asList;
+import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
import static org.schabi.newpipe.util.AnimationUtils.animateView;
public class SearchFragment extends BaseListFragment>
@@ -129,6 +132,9 @@ public class SearchFragment extends BaseListFragment cannot be bundled without creating some containers
+ metaInfo = new MetaInfo[result.getMetaInfo().size()];
+ metaInfo = result.getMetaInfo().toArray(metaInfo);
+
handleSearchSuggestion();
+ handleMetaInfo();
lastSearchedString = searchString;
nextPage = result.getNextPage();
@@ -1021,6 +1036,39 @@ public class SearchFragment extends BaseListFragment").append(mi.getTitle()).append("");
+ }
+ stringBuilder.append(mi.getContent().getContent());
+ for (int i = 0; i < mi.getUrls().size(); i++) {
+ stringBuilder
+ .append(" ")
+ .append(mi.getUrlTexts().get(i))
+ .append("");
+ if (i < mi.getUrls().size() - 1 && mi.getUrls().size() > 1) {
+ // append line break to all but the last URL if there are multiple URLs
+ stringBuilder.append(" ");
+ }
+ }
+ }
+
+ metaInfoTextView.setText(HtmlCompat.fromHtml(
+ stringBuilder.toString(), HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING));
+ metaInfoTextView.setMovementMethod(LinkMovementMethod.getInstance());
+ metaInfoTextView.setVisibility(View.VISIBLE);
+ }
+ }
+
@Override
public void handleNextItems(final ListExtractor.InfoItemsPage> result) {
showListFooter(false);
diff --git a/app/src/main/res/layout-large-land/fragment_video_detail.xml b/app/src/main/res/layout-large-land/fragment_video_detail.xml
index 8aee89ab0..d59d2db73 100644
--- a/app/src/main/res/layout-large-land/fragment_video_detail.xml
+++ b/app/src/main/res/layout-large-land/fragment_video_detail.xml
@@ -506,6 +506,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_video_detail.xml b/app/src/main/res/layout/fragment_video_detail.xml
index 0df85fe95..3bf2bb025 100644
--- a/app/src/main/res/layout/fragment_video_detail.xml
+++ b/app/src/main/res/layout/fragment_video_detail.xml
@@ -491,6 +491,39 @@
+
+
+
+
+
+
+
+
+
+
show_play_with_kodi
show_next_videoshow_comments
+ show_meta_infostream_info_selected_tabshow_hold_to_appendcontent_language
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index ecb690044..d2dd8afd5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -93,6 +93,8 @@
Show commentsTurn off to hide commentsTurn off to prevent loading thumbnails, saving data and memory usage. Changes clear both in-memory and on-disk image cache.
+ Show meta info
+ Turn off to hide meta info boxes with additional information about the stream creator, stream content or a search request.Image cache wipedWipe cached metadataRemove all cached webpage data
diff --git a/app/src/main/res/xml/content_settings.xml b/app/src/main/res/xml/content_settings.xml
index c885366ec..914fb2e59 100644
--- a/app/src/main/res/xml/content_settings.xml
+++ b/app/src/main/res/xml/content_settings.xml
@@ -85,6 +85,13 @@
android:title="@string/show_comments_title"
app:iconSpaceReserved="false" />
+
+
Date: Sun, 20 Dec 2020 15:05:37 +0100
Subject: [PATCH 42/57] Improve meta info layout and merge duplicate code
---
.../fragments/detail/VideoDetailFragment.java | 52 ++----------
.../fragments/list/search/SearchFragment.java | 46 ++---------
.../schabi/newpipe/util/ExtractorHelper.java | 79 +++++++++++++++++++
.../org/schabi/newpipe/util/Localization.java | 2 +-
.../fragment_video_detail.xml | 29 ++-----
app/src/main/res/layout/fragment_search.xml | 15 +++-
.../main/res/layout/fragment_video_detail.xml | 30 ++-----
7 files changed, 120 insertions(+), 133 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 b9cb4ab2b..6560ab404 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
@@ -16,7 +16,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
-import android.text.method.LinkMovementMethod;
import android.text.util.Linkify;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -63,7 +62,6 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.ReCaptchaActivity;
import org.schabi.newpipe.download.DownloadDialog;
import org.schabi.newpipe.extractor.InfoItem;
-import org.schabi.newpipe.extractor.MetaInfo;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
@@ -126,11 +124,11 @@ import io.reactivex.rxjava3.schedulers.Schedulers;
import static android.text.TextUtils.isEmpty;
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.COMMENTS;
import static org.schabi.newpipe.extractor.stream.StreamExtractor.NO_AGE_LIMIT;
-import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
import static org.schabi.newpipe.player.helper.PlayerHelper.globalScreenOrientationLocked;
import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfirmationRequired;
import static org.schabi.newpipe.player.playqueue.PlayQueueItem.RECOVERY_UNSET;
import static org.schabi.newpipe.util.AnimationUtils.animateView;
+import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView;
public final class VideoDetailFragment
extends BaseStateFragment
@@ -221,9 +219,8 @@ public final class VideoDetailFragment
private TextView detailDurationView;
private TextView detailPositionView;
- private LinearLayout detailMetadataInfo;
- private View detailMetadataInfoSeparator;
- private TextView detailMetadataInfoText;
+ private View detailMetaInfoSeparator;
+ private TextView detailMetaInfoTextView;
private LinearLayout videoDescriptionRootLayout;
private TextView videoUploadDateView;
@@ -651,9 +648,8 @@ public final class VideoDetailFragment
detailDurationView = rootView.findViewById(R.id.detail_duration_view);
detailPositionView = rootView.findViewById(R.id.detail_position_view);
- detailMetadataInfo = rootView.findViewById(R.id.detail_metadata_info);
- detailMetadataInfoSeparator = rootView.findViewById(R.id.detail_metadata_info_separator);
- detailMetadataInfoText = rootView.findViewById(R.id.detail_metadata_info_text);
+ detailMetaInfoSeparator = rootView.findViewById(R.id.detail_meta_info_separator);
+ detailMetaInfoTextView = rootView.findViewById(R.id.detail_meta_info_text_view);
videoDescriptionRootLayout = rootView.findViewById(R.id.detail_description_root_layout);
videoUploadDateView = rootView.findViewById(R.id.detail_upload_date_view);
@@ -1258,42 +1254,6 @@ public final class VideoDetailFragment
}
}
- private void setMetaInfo(final StreamInfo info) {
- final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(
- requireContext());
- final boolean showMetaInfo = sp.getBoolean(
- requireContext().getString(R.string.show_meta_info_key), true);
- if (info.getMetaInfo().isEmpty() || !showMetaInfo) {
- detailMetadataInfo.setVisibility(View.GONE);
- detailMetadataInfoSeparator.setVisibility(View.GONE);
- } else {
- final List metaIfs = info.getMetaInfo();
- final StringBuilder stringBuilder = new StringBuilder();
- for (final MetaInfo mi: metaIfs) {
- if (!isNullOrEmpty(mi.getTitle())) {
- stringBuilder.append("
").append(mi.getTitle()).append("
");
- }
- stringBuilder.append(mi.getContent().getContent());
- for (int i = 0; i < mi.getUrls().size(); i++) {
- stringBuilder
- .append(" ")
- .append(mi.getUrlTexts().get(i))
- .append("");
- if (i < mi.getUrls().size() - 1 && mi.getUrls().size() > 1) {
- // append line break to all but the last URL if there are multiple URLs
- stringBuilder.append(" ");
- }
- }
- }
-
- detailMetadataInfoSeparator.setVisibility(View.VISIBLE);
- detailMetadataInfoText.setText(HtmlCompat.fromHtml(
- stringBuilder.toString(), HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING));
- detailMetadataInfoText.setMovementMethod(LinkMovementMethod.getInstance());
- detailMetadataInfo.setVisibility(View.VISIBLE);
- }
- }
-
private final ViewTreeObserver.OnPreDrawListener preDrawListener =
new ViewTreeObserver.OnPreDrawListener() {
@Override
@@ -1606,7 +1566,7 @@ public final class VideoDetailFragment
prepareDescription(info.getDescription());
updateProgressInfo(info);
initThumbnailViews(info);
- setMetaInfo(info);
+ showMetaInfoInTextView(info.getMetaInfo(), detailMetaInfoTextView, detailMetaInfoSeparator);
if (player == null || player.isPlayerStopped()) {
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 f44e5e330..2dac6d11b 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
@@ -9,7 +9,6 @@ import android.text.Editable;
import android.text.Html;
import android.text.TextUtils;
import android.text.TextWatcher;
-import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -80,8 +79,8 @@ import io.reactivex.rxjava3.subjects.PublishSubject;
import static androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags;
import static java.util.Arrays.asList;
-import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
import static org.schabi.newpipe.util.AnimationUtils.animateView;
+import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView;
public class SearchFragment extends BaseListFragment>
implements BackPressable {
@@ -160,6 +159,7 @@ public class SearchFragment extends BaseListFragment").append(mi.getTitle()).append("");
- }
- stringBuilder.append(mi.getContent().getContent());
- for (int i = 0; i < mi.getUrls().size(); i++) {
- stringBuilder
- .append(" ")
- .append(mi.getUrlTexts().get(i))
- .append("");
- if (i < mi.getUrls().size() - 1 && mi.getUrls().size() > 1) {
- // append line break to all but the last URL if there are multiple URLs
- stringBuilder.append(" ");
- }
- }
- }
-
- metaInfoTextView.setText(HtmlCompat.fromHtml(
- stringBuilder.toString(), HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING));
- metaInfoTextView.setMovementMethod(LinkMovementMethod.getInstance());
- metaInfoTextView.setVisibility(View.VISIBLE);
- }
- }
-
@Override
public void handleNextItems(final ListExtractor.InfoItemsPage> result) {
showListFooter(false);
diff --git a/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java b/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java
index 650c5ae11..1f1b94545 100644
--- a/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java
+++ b/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java
@@ -22,9 +22,16 @@ package org.schabi.newpipe.util;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
+import android.text.method.LinkMovementMethod;
import android.util.Log;
+import android.view.View;
+import android.widget.TextView;
import android.widget.Toast;
+import androidx.annotation.Nullable;
+import androidx.core.text.HtmlCompat;
+import androidx.preference.PreferenceManager;
+
import org.schabi.newpipe.MainActivity;
import org.schabi.newpipe.R;
import org.schabi.newpipe.ReCaptchaActivity;
@@ -32,6 +39,7 @@ import org.schabi.newpipe.extractor.Info;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor.InfoItemsPage;
import org.schabi.newpipe.extractor.ListInfo;
+import org.schabi.newpipe.extractor.MetaInfo;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.Page;
import org.schabi.newpipe.extractor.StreamingService;
@@ -60,6 +68,8 @@ import java.util.List;
import io.reactivex.rxjava3.core.Maybe;
import io.reactivex.rxjava3.core.Single;
+import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
+
public final class ExtractorHelper {
private static final String TAG = ExtractorHelper.class.getSimpleName();
private static final InfoCache CACHE = InfoCache.getInstance();
@@ -306,4 +316,73 @@ public final class ExtractorHelper {
}
});
}
+
+ /**
+ * Formats the text contained in the meta info list as HTML and puts it into the text view,
+ * while also making the separator visible. If the list is null or empty, or the user chose not
+ * to see meta information, both the text view and the separator are hidden
+ * @param metaInfos a list of meta information, can be null or empty
+ * @param metaInfoTextView the text view in which to show the formatted HTML
+ * @param metaInfoSeparator another view to be shown or hidden accordingly to the text view
+ */
+ public static void showMetaInfoInTextView(@Nullable final List metaInfos,
+ final TextView metaInfoTextView,
+ final View metaInfoSeparator) {
+ final Context context = metaInfoTextView.getContext();
+ final boolean showMetaInfo = PreferenceManager.getDefaultSharedPreferences(context)
+ .getBoolean(context.getString(R.string.show_meta_info_key), true);
+
+ if (!showMetaInfo || metaInfos == null || metaInfos.isEmpty()) {
+ metaInfoTextView.setVisibility(View.GONE);
+ metaInfoSeparator.setVisibility(View.GONE);
+
+ } else {
+ final StringBuilder stringBuilder = new StringBuilder();
+ for (final MetaInfo metaInfo : metaInfos) {
+ if (!isNullOrEmpty(metaInfo.getTitle())) {
+ stringBuilder.append("").append(metaInfo.getTitle()).append("")
+ .append(Localization.DOT_SEPARATOR);
+ }
+
+ String content = metaInfo.getContent().getContent().trim();
+ if (content.endsWith(".")) {
+ content = content.substring(0, content.length() - 1); // remove . at end
+ }
+ stringBuilder.append(content);
+
+ for (int i = 0; i < metaInfo.getUrls().size(); i++) {
+ if (i == 0) {
+ stringBuilder.append(Localization.DOT_SEPARATOR);
+ } else {
+ stringBuilder.append("
");
+ }
+
+ stringBuilder
+ .append("")
+ .append(capitalizeIfAllUppercase(metaInfo.getUrlTexts().get(i).trim()))
+ .append("");
+ }
+ }
+
+ metaInfoTextView.setText(HtmlCompat.fromHtml(stringBuilder.toString(),
+ HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING));
+ metaInfoTextView.setMovementMethod(LinkMovementMethod.getInstance());
+ metaInfoTextView.setVisibility(View.VISIBLE);
+ metaInfoSeparator.setVisibility(View.VISIBLE);
+ }
+ }
+
+ private static String capitalizeIfAllUppercase(final String text) {
+ for (int i = 0; i < text.length(); i++) {
+ if (Character.isLowerCase(text.charAt(i))) {
+ return text; // there is at least a lowercase letter -> not all uppercase
+ }
+ }
+
+ if (text.isEmpty()) {
+ return text;
+ } else {
+ return text.substring(0, 1).toUpperCase() + text.substring(1).toLowerCase();
+ }
+ }
}
diff --git a/app/src/main/java/org/schabi/newpipe/util/Localization.java b/app/src/main/java/org/schabi/newpipe/util/Localization.java
index 710827864..978f558c4 100644
--- a/app/src/main/java/org/schabi/newpipe/util/Localization.java
+++ b/app/src/main/java/org/schabi/newpipe/util/Localization.java
@@ -57,7 +57,7 @@ import java.util.Locale;
public final class Localization {
- private static final String DOT_SEPARATOR = " • ";
+ public static final String DOT_SEPARATOR = " • ";
private static PrettyTime prettyTime;
private Localization() { }
diff --git a/app/src/main/res/layout-large-land/fragment_video_detail.xml b/app/src/main/res/layout-large-land/fragment_video_detail.xml
index d59d2db73..d90c782ef 100644
--- a/app/src/main/res/layout-large-land/fragment_video_detail.xml
+++ b/app/src/main/res/layout-large-land/fragment_video_detail.xml
@@ -507,36 +507,21 @@
-
-
-
-
-
-
+ android:gravity="center"
+ android:padding="12dp"
+ android:textSize="@dimen/video_item_detail_description_text_size"
+ tools:text="Stream meta info with link" />
+
diff --git a/app/src/main/res/layout/fragment_video_detail.xml b/app/src/main/res/layout/fragment_video_detail.xml
index 3bf2bb025..758a88f19 100644
--- a/app/src/main/res/layout/fragment_video_detail.xml
+++ b/app/src/main/res/layout/fragment_video_detail.xml
@@ -492,37 +492,21 @@
-
-
-
-
-
-
-
+ android:gravity="center"
+ android:padding="12dp"
+ android:textSize="@dimen/video_item_detail_description_text_size"
+ tools:text="Stream meta info with link" />
Date: Sun, 20 Dec 2020 18:31:51 +0100
Subject: [PATCH 43/57] Change NewPipe's domain in original ReadMe
---
README.md | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index 2568b7624..c66bcfa7f 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-
+
NewPipe
A libre lightweight streaming frontend for Android.
*Read this in other languages: [English](README.md), [한국어](README.ko.md).*
@@ -83,7 +83,7 @@ NewPipe supports multiple services. Our [docs](https://teamnewpipe.github.io/doc
## Updates
When a change to the NewPipe code occurs (due to either adding features or bug fixing), eventually a release will occur. These are in the format x.xx.x . In order to get this new version, you can:
1. Build a debug APK yourself. This is the fastest way to get new features on your device, but is much more complicated, so we recommend using one of the other methods.
- 2. Add our custom repo to F-Droid and install it from there as soon as we publish a release. The instructions are here: https://newpipe.schabi.org/FAQ/tutorials/install-add-fdroid-repo/
+ 2. Add our custom repo to F-Droid and install it from there as soon as we publish a release. The instructions are here: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/
3. Download the APK from [Github Releases](https://github.com/TeamNewPipe/NewPipe/releases) and install it as soon as we publish a release.
4. Update via F-droid. This is the slowest method of getting updates, as F-Droid must recognize changes, build the APK itself, sign it, then push the update to users.
@@ -106,7 +106,7 @@ If you'd like to get involved, check our [contribution notes](.github/CONTRIBUTI
## Donate
-If you like NewPipe we'd be happy about a donation. You can either send bitcoin or donate via Bountysource or Liberapay. For further info on donating to NewPipe, please visit our [website](https://newpipe.schabi.org/donate).
+If you like NewPipe we'd be happy about a donation. You can either send bitcoin or donate via Bountysource or Liberapay. For further info on donating to NewPipe, please visit our [website](https://newpipe.net/donate).
@@ -129,7 +129,7 @@ If you like NewPipe we'd be happy about a donation. You can either send bitcoin
## Privacy Policy
The NewPipe project aims to provide a private, anonymous experience for using media web services.
-Therefore, the app does not collect any data without your consent. NewPipe's privacy policy explains in detail what data is sent and stored when you send a crash report, or comment in our blog. You can find the document [here](https://newpipe.schabi.org/legal/privacy/).
+Therefore, the app does not collect any data without your consent. NewPipe's privacy policy explains in detail what data is sent and stored when you send a crash report, or comment in our blog. You can find the document [here](https://newpipe.net/legal/privacy/).
## License
[![GNU GPLv3 Image](https://www.gnu.org/graphics/gplv3-127x51.png)](http://www.gnu.org/licenses/gpl-3.0.en.html)
From e4aa7a90c7351bd5479557ba09b82a89d7979e97 Mon Sep 17 00:00:00 2001
From: TiA4f8R <74829229+TiA4f8R@users.noreply.github.com>
Date: Sun, 20 Dec 2020 18:36:01 +0100
Subject: [PATCH 44/57] Change NewPipe's domain in Korean ReadMe
---
README.ko.md | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/README.ko.md b/README.ko.md
index bb6bd653b..a86eae8d9 100644
--- a/README.ko.md
+++ b/README.ko.md
@@ -1,4 +1,4 @@
-
+
NewPipe
A libre lightweight streaming frontend for Android.
*Read this in other languages: [English](README.md), [한국어](README.ko.md).*
@@ -86,7 +86,7 @@ NewPipe 코드의 변경이 있을 때(기능 추가 또는 버그 수정으로
1. 직접 디버그 APK를 생성할 수 있습니다. 이 방법은 당신의 기기에서 새로운 기능을 얻을 수 있는 가장 빠른 방법이지만, 꽤 많이 복잡합니다.
따라서 우리는 다른 방법들 중 하나를 사용하는 것을 추천합니다.
2. 우리의 커스텀 저장소를 F-Droid에 추가하고 우리가 릴리즈를 게시하는 대로 저곳에서 릴리즈를 설치할 수 있습니다.
- 이에 대한 설명서는 이곳에서 확인할 수 있습니다: https://newpipe.schabi.org/FAQ/tutorials/install-add-fdroid-repo/
+ 이에 대한 설명서는 이곳에서 확인할 수 있습니다: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/
3. 우리가 릴리즈를 게시하는 대로 [Github Releases](https://github.com/TeamNewPipe/NewPipe/releases)에서 APK를 다운받고 이것을 설치할 수 있습니다.
4. F-Droid를 통해 업데이트 할 수 있습니다. F-Droid는 변화를 인식하고, 스스로 APK를 생성하고, 이것에 서명하고, 사용자들에서 업데이트를 전달해야만 하기 때문에,
이것은 업데이트를 받는 가장 느린 방법입니다.
@@ -111,7 +111,7 @@ NewPipe 코드의 변경이 있을 때(기능 추가 또는 버그 수정으로
## Donate
-만약 NewPipe가 마음에 들었다면, 우리는 기부에 대해 기꺼이 환영합니다. bitcoin을 보내거나, Bountysource 또는 Liberapay를 통해 기부할 수 있습니다. NewPipe에 기부하는 것에 대한 자세한 정보를 원한다면, 우리의 [웹사이트](https://newpipe.schabi.org/donate)를 방문하여 주십시오.
+만약 NewPipe가 마음에 들었다면, 우리는 기부에 대해 기꺼이 환영합니다. bitcoin을 보내거나, Bountysource 또는 Liberapay를 통해 기부할 수 있습니다. NewPipe에 기부하는 것에 대한 자세한 정보를 원한다면, 우리의 [웹사이트](https://newpipe.net/donate)를 방문하여 주십시오.