From 30e33d59e885195bbc67530c937371cfca41bef0 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Tue, 22 Jul 2025 16:03:37 +0200 Subject: [PATCH 01/43] Use correct fix for nextPage being null while creating error report in SearchFragment.handleNextItems() --- .../newpipe/fragments/list/search/SearchFragment.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java index fc95312ea..6916ca826 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 @@ -1089,8 +1089,9 @@ public class SearchFragment extends BaseListFragment result) { showListFooter(false); infoListAdapter.addInfoItemList(result.getItems()); - nextPage = result.getNextPage(); + // nextPage should not be null here because it refers to the page + // which results are handled here, but we check it anyway if (!result.getErrors().isEmpty() && nextPage != null) { showSnackBarError(new ErrorInfo(result.getErrors(), UserAction.SEARCHED, "\"" + searchString + "\" → pageUrl: " + nextPage.getUrl() + ", " @@ -1098,6 +1099,10 @@ public class SearchFragment extends BaseListFragment Date: Thu, 17 Jul 2025 10:32:31 +0200 Subject: [PATCH 02/43] Release v0.28.0 (1005) --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a629f65eb..54bd86a72 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -23,9 +23,9 @@ android { if (System.properties.containsKey('versionCodeOverride')) { versionCode System.getProperty('versionCodeOverride') as Integer } else { - versionCode 1004 + versionCode 1005 } - versionName "0.27.7" + versionName "0.28.0" if (System.properties.containsKey('versionNameSuffix')) { versionNameSuffix System.getProperty('versionNameSuffix') } From 9f526e8e8f649482292ee766d3d3988f4ddb7ebe Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Thu, 24 Jul 2025 07:56:08 +0530 Subject: [PATCH 03/43] Fix short count formatting for Android versions below 7.0 --- .../org/schabi/newpipe/util/Localization.java | 18 +++++++++++------- app/src/main/res/values-ar-rLY/strings.xml | 3 --- app/src/main/res/values-ar/strings.xml | 3 --- app/src/main/res/values-az/strings.xml | 3 --- app/src/main/res/values-b+ast/strings.xml | 3 --- app/src/main/res/values-b+uz+Latn/strings.xml | 3 --- app/src/main/res/values-be/strings.xml | 3 --- app/src/main/res/values-ber/strings.xml | 3 --- app/src/main/res/values-bg/strings.xml | 3 --- app/src/main/res/values-bn-rBD/strings.xml | 3 --- app/src/main/res/values-bn/strings.xml | 3 --- app/src/main/res/values-ca/strings.xml | 3 --- app/src/main/res/values-ckb/strings.xml | 3 --- app/src/main/res/values-cs/strings.xml | 3 --- app/src/main/res/values-da/strings.xml | 3 --- app/src/main/res/values-de/strings.xml | 3 --- app/src/main/res/values-el/strings.xml | 3 --- app/src/main/res/values-eo/strings.xml | 3 --- app/src/main/res/values-es/strings.xml | 3 --- app/src/main/res/values-et/strings.xml | 3 --- app/src/main/res/values-eu/strings.xml | 3 --- app/src/main/res/values-fa/strings.xml | 3 --- app/src/main/res/values-fi/strings.xml | 3 --- app/src/main/res/values-fr/strings.xml | 3 --- app/src/main/res/values-gl/strings.xml | 3 --- app/src/main/res/values-he/strings.xml | 3 --- app/src/main/res/values-hi/strings.xml | 3 --- app/src/main/res/values-hr/strings.xml | 3 --- app/src/main/res/values-hu/strings.xml | 3 --- app/src/main/res/values-in/strings.xml | 3 --- app/src/main/res/values-is/strings.xml | 3 --- app/src/main/res/values-it/strings.xml | 3 --- app/src/main/res/values-ja/strings.xml | 3 --- app/src/main/res/values-ka/strings.xml | 3 --- app/src/main/res/values-kab/strings.xml | 2 -- app/src/main/res/values-kmr/strings.xml | 3 --- app/src/main/res/values-ko/strings.xml | 3 --- app/src/main/res/values-ku/strings.xml | 3 --- app/src/main/res/values-lt/strings.xml | 3 --- app/src/main/res/values-lv/strings.xml | 3 --- app/src/main/res/values-mk/strings.xml | 3 --- app/src/main/res/values-ml/strings.xml | 3 --- app/src/main/res/values-mr/strings.xml | 3 --- app/src/main/res/values-ms/strings.xml | 3 --- app/src/main/res/values-nb-rNO/strings.xml | 3 --- app/src/main/res/values-ne/strings.xml | 3 --- app/src/main/res/values-nl-rBE/strings.xml | 3 --- app/src/main/res/values-nl/strings.xml | 3 --- app/src/main/res/values-nqo/strings.xml | 3 --- app/src/main/res/values-or/strings.xml | 3 --- app/src/main/res/values-pa/strings.xml | 3 --- app/src/main/res/values-pl/strings.xml | 5 +---- app/src/main/res/values-pt-rBR/strings.xml | 3 --- app/src/main/res/values-pt-rPT/strings.xml | 3 --- app/src/main/res/values-pt/strings.xml | 3 --- app/src/main/res/values-ro/strings.xml | 3 --- app/src/main/res/values-ru/strings.xml | 3 --- app/src/main/res/values-ryu/strings.xml | 3 --- app/src/main/res/values-sat/strings.xml | 3 --- app/src/main/res/values-sc/strings.xml | 3 --- app/src/main/res/values-sk/strings.xml | 3 --- app/src/main/res/values-sl/strings.xml | 3 --- app/src/main/res/values-so/strings.xml | 3 --- app/src/main/res/values-sq/strings.xml | 3 --- app/src/main/res/values-sr/strings.xml | 3 --- app/src/main/res/values-sv/strings.xml | 3 --- app/src/main/res/values-ta/strings.xml | 3 --- app/src/main/res/values-te/strings.xml | 3 --- app/src/main/res/values-th/strings.xml | 3 --- app/src/main/res/values-tr/strings.xml | 3 --- app/src/main/res/values-tzm/strings.xml | 1 - app/src/main/res/values-uk/strings.xml | 3 --- app/src/main/res/values-und/strings.xml | 1 - app/src/main/res/values-ur/strings.xml | 3 --- app/src/main/res/values-vi/strings.xml | 3 --- app/src/main/res/values-zh-rCN/strings.xml | 3 --- app/src/main/res/values-zh-rHK/strings.xml | 3 --- app/src/main/res/values-zh-rTW/strings.xml | 3 --- app/src/main/res/values/strings.xml | 6 +++--- 79 files changed, 15 insertions(+), 237 deletions(-) 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 2bd4664ae..d47cb918e 100644 --- a/app/src/main/java/org/schabi/newpipe/util/Localization.java +++ b/app/src/main/java/org/schabi/newpipe/util/Localization.java @@ -191,14 +191,14 @@ public final class Localization { final double value = (double) count; if (count >= 1000000000) { - return localizeNumber(round(value / 1000000000)) - + context.getString(R.string.short_billion); + return context.getString(R.string.short_billion, + localizeNumber(round(value / 1000000000))); } else if (count >= 1000000) { - return localizeNumber(round(value / 1000000)) - + context.getString(R.string.short_million); + return context.getString(R.string.short_million, + localizeNumber(round(value / 1000000))); } else if (count >= 1000) { - return localizeNumber(round(value / 1000)) - + context.getString(R.string.short_thousand); + return context.getString(R.string.short_thousand, + localizeNumber(round(value / 1000, 0))); } else { return localizeNumber(value); } @@ -417,7 +417,11 @@ public final class Localization { } private static double round(final double value) { - return new BigDecimal(value).setScale(1, RoundingMode.HALF_UP).doubleValue(); + return round(value, 1); + } + + private static double round(final double value, final int scale) { + return new BigDecimal(value).setScale(scale, RoundingMode.HALF_UP).doubleValue(); } private static String getQuantity(@NonNull final Context context, diff --git a/app/src/main/res/values-ar-rLY/strings.xml b/app/src/main/res/values-ar-rLY/strings.xml index 0ab5fe741..7f881a9c2 100644 --- a/app/src/main/res/values-ar-rLY/strings.xml +++ b/app/src/main/res/values-ar-rLY/strings.xml @@ -75,13 +75,11 @@ الملفات المحملة لا يوجد مثل هذا الملف/مصدر المحتوى الأكثر إعجابًا - بليون تعذر تحميل موجز \'%s\'. ؟ التحقق من وجود تحديثات مثيلات خوادم پيرتيوب +100 فيديو - ألف مثيل الخادم موجود بالفعل طلب تأكيد قبل مسح قائمة الانتظار المشتركون @@ -649,7 +647,6 @@ تسريع إلى الأمام/-ترجيع وقت البحث تم رفضها من قبل النظام ليس هناك تعليقات - مليون جاري التحقق من وجود تحديثات… المحتوى اسأل عن مكان التنزيل diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index fff1dd3a9..9b6c1a414 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -116,9 +116,6 @@ لا شيء هنا سوى الصراصير الصوت إعادة المحاولة - ألف - مليون - بليون ليس هناك مشترِكون %s مشارك diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index 682dda98f..78cb6c013 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -297,9 +297,6 @@ Bəyən Bəyənmə Yenidən sıralamaq üçün sürüklə - min - Mln - Mlrd Xidməti dəyiş, hazırda seçilmiş: Abunəçi yoxdur Baxış yoxdur diff --git a/app/src/main/res/values-b+ast/strings.xml b/app/src/main/res/values-b+ast/strings.xml index 51b4fdec0..81b212f80 100644 --- a/app/src/main/res/values-b+ast/strings.xml +++ b/app/src/main/res/values-b+ast/strings.xml @@ -43,9 +43,6 @@ Tarrezmes Formatu de videu predetermináu Prietu - mil - mill. - mil mill. Precísase esti permisu p\'abrir \nnel mou ventanu Retu de reCAPTCHA diff --git a/app/src/main/res/values-b+uz+Latn/strings.xml b/app/src/main/res/values-b+uz+Latn/strings.xml index b556da756..2be37ea7c 100644 --- a/app/src/main/res/values-b+uz+Latn/strings.xml +++ b/app/src/main/res/values-b+uz+Latn/strings.xml @@ -267,9 +267,6 @@ Obunachilar yo\'q Hozirda tanlangan xizmatni yoqish: - B - M - k Qayta Audio Video diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 22f963def..968aafaba 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -159,9 +159,6 @@ Відэа Аўдыя Паспрабаваць зноў - тыс. - млн - млрд Няма падпісчыкаў %s падпісчык diff --git a/app/src/main/res/values-ber/strings.xml b/app/src/main/res/values-ber/strings.xml index 3912381fc..39247f49b 100644 --- a/app/src/main/res/values-ber/strings.xml +++ b/app/src/main/res/values-ber/strings.xml @@ -45,9 +45,6 @@ ∞ ⵉⴼⵉⴷⵢⵓⵜⵏ 100+ ⵉⴼⵉⴷⵢⵓⵜⵏ - - - ⴰⵎⵙⵍⴰⵢ ⴰⴼⵉⴷⵢⵓ ⵉⵔⵉⵜⵏ diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index c6d4d76ce..e57413b9d 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -183,9 +183,6 @@ Името на файла не може да бъде празно Възникна грешка: %1$s Не са налични източници за изтегляне - хил. - млн. - млрд. Няма абонати Създай Откажи diff --git a/app/src/main/res/values-bn-rBD/strings.xml b/app/src/main/res/values-bn-rBD/strings.xml index ddc32e418..2b0ffe918 100644 --- a/app/src/main/res/values-bn-rBD/strings.xml +++ b/app/src/main/res/values-bn-rBD/strings.xml @@ -82,9 +82,6 @@ ভিডিও অডিও পুনরায় চেষ্টা করো - হা - M - বি শুরু বিরতি diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index 715c9146e..5721f12ee 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -104,9 +104,6 @@ কোন ভিডিও নেই কোন ভিউ নেই কোন সাবস্ক্রাইবার নেই - B - M - K পুনরায় চেষ্টা করো অডিও ভিডিও diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 123a5ef67..819c9ff0b 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -231,9 +231,6 @@ S\'està recuperant el reproductor després de l\'error Bé, és lamentable. Arrossegueu per reordenar la llista - mil - milions - mil milions Inicia Feu un toc aquí per a més detalls Defineix una carpeta de baixades més endavant als paràmetres diff --git a/app/src/main/res/values-ckb/strings.xml b/app/src/main/res/values-ckb/strings.xml index 649e6e73c..7c23d1d1d 100644 --- a/app/src/main/res/values-ckb/strings.xml +++ b/app/src/main/res/values-ckb/strings.xml @@ -25,7 +25,6 @@ ژمارەی بەژداری نادیارە ناتوانرێت لەسەر ئەو فایله‌وه‌ جێگیر بکرێت په‌ڕه‌ هەڵبژێرە - ملیۆن +١٠٠ ڤیدیۆیان لێده‌ر هاوردە @@ -46,7 +45,6 @@ ئەمە لەسەر ڕێکخستنەکانی ئێستات جێگیر دەبێت. پەیامەکانی نیوپایپ نیوپایپ لەلایەن چەند خۆبەخشێکەوە دروستکراوە کە کاته‌كانی خۆیان پێ بەخشیووە تاکو باشترین خزمەتگوزاریت پێشکەش بکەن. هیچ نەبێت بە کڕینی کوپێک قاوە یارمەتی گەشەپێدەرەکانمان بدە بۆ ئەوەی کاتی زیاتر تەرخان بکەین بۆ بەرەوپێشبردنی نیوپایپ. - ملیار گەڕانی پێشنیارکراوەکان خێرا فایل سڕایەوە @@ -373,7 +371,6 @@ ناتوانرێت داببه‌زێنرێت ناتوانرێت بە ڕاژەكه‌وە پەیوەست ببیت لێدانی ڤیدیۆ، مه‌ودا: - هەزار زۆرترین بەدڵ سڕینەوە جۆری بنەڕەتی ڤیدیۆ diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index ea531408f..6ff8296e6 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -83,9 +83,7 @@ Určete prosím složku pro stahování později v nastavení Co:\\nŽádost:\\nJazyk obsahu:\\nZemě obsahu:\\nJazyk aplikace:\\nSlužba:\\nČas GMT:\\nBalíček:\\nVerze:\\nVerze OS: Vše - tis. Otevřít ve vyskakovacím okně - mil. Toto oprávnění je vyžadováno \npro otevření ve vyskakovacím okně Odstraňuje zvuk v některých rozlišeních @@ -124,7 +122,6 @@ Oznámení pro NewPipe přehrávač Žádné výsledky Je tu sranda jak v márnici - mld. Žádní odběratelé %s odběratel diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index cecdcc4fe..db464ca61 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -305,9 +305,6 @@ Stop Hændelser Ikke andet end fårekyllinger her - t - mio. - mia. %s abonnent %s abonnenter diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 309709f47..a741d743a 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -69,9 +69,6 @@ Fehlerbericht Löschen Prüfsumme - Tsd. - Mio. - Mrd. Dateiname Fehler Bitte warten … diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 67a24bd4f..f66f24d46 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -41,7 +41,6 @@ Μικρογραφία εικόνας προφίλ του χρήστη Like Dislike - δισ/ρια Άνοιγμα σε αναδυόμενο παράθυρο Εγγραφή Εγγεγραμμένος @@ -169,8 +168,6 @@ Δεν υπάρχει τίποτα εδώ Σύρετε για ταξινόμηση Προσπάθεια εκ νέου - χιλ. - εκ/ρια Κανένας συνδρομητής %s συνδρομητής diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index 1da4d536c..408035e00 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -261,9 +261,6 @@ %s spekto %s spektoj - k - M - Mrd Pri NewPipe Eksteraj permesiloj © %1$s de %2$s sub %3$s diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 610d900ec..a1ee4f092 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -81,9 +81,6 @@ Qué:\\nSolicitud:\\nIdioma del contenido:\\nPaís del contenido:\\nIdioma de la aplicación:\\nServicio:\\nMarca de tiempo:\\nPaquete:\\nVersión:\\nVersión del SO: Negro Todo - k - M - MM Abrir en modo emergente Se necesita este permiso \npara abrir en modo emergente diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index 9f9c7207c..170c54060 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -154,9 +154,6 @@ Video Audio Proovi uuesti - tuh - mln - mld Tellijaid pole %s tellija diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 16054d9ae..20a7148eb 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -84,9 +84,6 @@ Bideoa Audioa Saiatu berriro - k - M - MM Hasi Pausatu Ezabatu diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index 3bba8efb8..8b8fdd281 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -148,9 +148,6 @@ خطایی رخ داد: %1$s جریانی برای بارگیری در دسترس نیست بدون نتیجه - K - M - B %s مشترک %s مشترک diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 20734dd26..0c092284c 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -102,9 +102,6 @@ Video Ääni Toista uudelleen - t. - milj. - bilj. Ei tilaajia %s tilaaja diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index c3fe5cf58..934a5a877 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -87,8 +87,6 @@ Lecture en mode flottant Désactivés Quoi :\\nRequest :\\nContent Language :\\nContent Country :\\nApp Language :\\nService :\\nGMT Time :\\nPackage :\\nVersion :\\nOS version : - k - M Cette autorisation est nécessaire pour \nutiliser le mode flottant Arrière-plan @@ -100,7 +98,6 @@ Mémoriser les propriétés de la fenêtre flottante Mémoriser les dernières taille et position de la fenêtre flottante Effacer - G Le son peut être absent à certaines définitions Suggestions de recherche Sélectionner les suggestions à afficher lors d’une recherche diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index d345b9385..3d98682be 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -158,9 +158,6 @@ Vídeo Audio Tentar de novo - k - M - B Ningún subscrito %s subscrito diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index bd560f07b..f17abc60d 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -112,9 +112,6 @@ סרטון שמע ניסיון חוזר - אלפ. - מיל. - מיליארד אין מנויים מנוי אחד diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 37282a0da..7fff20f52 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -126,9 +126,6 @@ वीडियो ऑडियो फिर से कोशिश करें - हज़ार - मिलियन - अरब कोई सब्सक्राइबर नहीं %s सब्सक्राइबर diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index c4cd60c0b..414fdf185 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -97,9 +97,6 @@ Video Audio Pokušaj ponovo - tis. - mil - mlrd. Počni Pauziraj Izbriši diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 14c55b772..d2b84fd2f 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -166,9 +166,6 @@ Nincs letölthető adatfolyam Nincs itt semmi pár tücskön kívül Húzza az átrendezéshez - e - m - M Nincs feliratkozó %s feliratkozó diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 19f867d7c..dba4b2daf 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -82,9 +82,6 @@ Meminta kode reCAPTCHA Hitam Semua - r - J - T Buka pada mode sembulan Izin ini dibutuhkan untuk \nmembuka di mode sembul diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index e7ce69e41..5a97af1ac 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -97,7 +97,6 @@ Hljóðstillingar Spila í bakgrunni Þegar hlekkur er opnaður — %s - þús. Líkar ekki við Reyna aftur Lýsing @@ -217,7 +216,6 @@ Athugasemd þín (á ensku): Engar niðurstöður Myndskeið - ma. Engin áhorf %s áhorf @@ -352,7 +350,6 @@ Flokkur Merki NewPipe er þróað af sjálfboðaliðum sem eyða frítíma sínum í að færa þér bestu notendaupplifunina. Gefðu til baka til að hjálpa forriturum að gera NewPipe enn betri á meðan þeir njóta kaffibolla. - millj. Slökktu á til að fela lýsingu og viðbótarupplýsingar myndskeiðs Villa kom upp: %1$s Þraut reCAPTCHA diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 4c087f4de..383017ba9 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -82,9 +82,6 @@ Risoluzione reCAPTCHA Nero Tutto - k - M - Mrd È richiesta la risoluzione del reCAPTCHA Apri in modalità popup Riproduzione in modalità popup diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 25c1d9fe9..9e8ec1c88 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -83,9 +83,6 @@ reCAPTCHA を要求しました ブラック すべて - k - M - B ポップアップモードで開く ポップアップモードで開くには \n権限の許可が必要です diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index 4fc00c0b3..45804fcfa 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -237,9 +237,6 @@ ვიდეო აუდიო ხელახლა სცადეთ - ათასი - მლნ - ბლნ სერვისის გადართვა, ამჟამად არჩეულია: გამოწერები არ არის diff --git a/app/src/main/res/values-kab/strings.xml b/app/src/main/res/values-kab/strings.xml index 97476fc46..0ded7974c 100644 --- a/app/src/main/res/values-kab/strings.xml +++ b/app/src/main/res/values-kab/strings.xml @@ -82,7 +82,6 @@ Sider Asfaylu udhim Ttu - A Kter Ih Amazray @@ -128,7 +127,6 @@ Snifel isem Asider ur yeddi ara Tamwalit - o Aɣawas n deffir Amazray yesteɛfay diff --git a/app/src/main/res/values-kmr/strings.xml b/app/src/main/res/values-kmr/strings.xml index b5e5235d5..24bc5574e 100644 --- a/app/src/main/res/values-kmr/strings.xml +++ b/app/src/main/res/values-kmr/strings.xml @@ -49,9 +49,6 @@ Ne abone Karûbarê veguheztinê, niha hatî hilbijartin: - B - M - k Dîsa biceribîne Deng Vîdyo diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index cfc328a20..016be8743 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -116,9 +116,6 @@ 무엇:\\n요청:\\n콘텐츠 언어:\\n콘텐츠 국가:\\n앱 언어:\\n서비스:\\nGMT 시간:\\n패키지:\\n버전:\\nOS 버전: 결과 없음 구독할 항목을 추가하세요 - - 백만 - 십억 구독자 없음 구독자 %s명 diff --git a/app/src/main/res/values-ku/strings.xml b/app/src/main/res/values-ku/strings.xml index 2f3934fff..3dc51fcc8 100644 --- a/app/src/main/res/values-ku/strings.xml +++ b/app/src/main/res/values-ku/strings.xml @@ -133,9 +133,6 @@ ڤیدیۆ دەنگ هەوڵدانەوە - هەزار - ملیۆن - بلیۆن هیچ بەشداربوویەک نییە %s بەشداربوو diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index feb11a01c..3324b423c 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -139,9 +139,6 @@ Atstatoma po grotuvo klaidos Nėra rezultatų Čia nieko nėra išskyrus svirplius - Tūkst. - Mln. - Mlrd. Nėra prenumeratorių Nėra peržiūrų diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index 2d1c60256..13e163f72 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -136,9 +136,6 @@ Nav abonamentu Izvēlaties pakalpojumu, šobrīd izvēlēts: - B - M - k Atkārtot Audio Video diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index 1d3183b10..c131e1fd7 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -146,9 +146,6 @@ Видео Звук Пробај повторно - илјади - M - милијарди Нема зачленети %s зачленет diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index 39ce5e57f..adba80891 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -183,9 +183,6 @@ സബ്ക്രൈബേഴ്സ് ഇല്ല സേവനം മാറ്റുക, ഇപ്പോൾ തിരഞ്ഞെടുത്തത്: - B - k - M വീണ്ടും ശ്രമിക്കുക ഓഡിയോ വീഡിയോ diff --git a/app/src/main/res/values-mr/strings.xml b/app/src/main/res/values-mr/strings.xml index 304858d84..7a6b2eda4 100644 --- a/app/src/main/res/values-mr/strings.xml +++ b/app/src/main/res/values-mr/strings.xml @@ -138,11 +138,8 @@ डेबग अपडेट थेट - प्लेलिस्ट - फाईल - के परवाना चेकसम इतिहास diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml index bb0527655..e70e61a74 100644 --- a/app/src/main/res/values-ms/strings.xml +++ b/app/src/main/res/values-ms/strings.xml @@ -171,9 +171,6 @@ Video Audio Cuba semula - K - J - B Tiada pelanggan %s pelanggan diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index c2311585a..027e6fe39 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -89,9 +89,6 @@ Spiller av i oppsprettsmodus Alle Avskrudd - k - M - Mrd. Denne tilgangen trengs for \nåpning i oppsprettsmodus reCAPTCHA-oppgave forespurt diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index dd570b82e..b40145aa6 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -176,9 +176,6 @@ भिडियो अडियो पुन: प्रयास - हजार - करोड - अर्ब कुनै सदस्यहरू छैनन् %s सदस्य diff --git a/app/src/main/res/values-nl-rBE/strings.xml b/app/src/main/res/values-nl-rBE/strings.xml index a78b96585..3b3277307 100644 --- a/app/src/main/res/values-nl-rBE/strings.xml +++ b/app/src/main/res/values-nl-rBE/strings.xml @@ -147,9 +147,6 @@ Video Geluid Opnieuw proberen - k - M - mld. Geen abonnees %s abonnee diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 0c16a5c9b..75822036b 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -84,9 +84,6 @@ reCAPTCHA-uitdaging gevraagd Openen in pop-upmodus Alles - dznd. - mln. - mld. Deze machtiging is vereist om te \nopenen in pop-upmodus Speelt af in pop-upmodus diff --git a/app/src/main/res/values-nqo/strings.xml b/app/src/main/res/values-nqo/strings.xml index 016ce1ba2..739193302 100644 --- a/app/src/main/res/values-nqo/strings.xml +++ b/app/src/main/res/values-nqo/strings.xml @@ -178,9 +178,6 @@ ߞߐߝߟߌ߫ ߕߍ߫ ߦߋ߲߬ ߡߍ߲ߕߊ ߞߵߊ߬ ߡߊߛߊ߬ߦߌ߬ - ߥߊ߯ - ߞߋ߲߬ - ߥߟߡ ߞߊ߬ ߥߏ߬ߦߏ߫ ߣߊ߬ߕߊ ߝߙߊ߬ ߕߎ߲߰ߠߌ߲ ߠߊ߫ ߞߍ߲ߖߘߍߡߊߓߟߏ ߡߊ߬ ߞߊ߬ ߕߎ߲߰ߠߌ߲ ߘߐߞߊ߬ߙߊ߲ ߓߟߏߕߎ߰ (ߞߊߣߊ߬ ߡߊߛߊ߬ߦߌ߬) ߥߏ߬ߦߏ߫ ߢߐ߲߰ߘߐ ߟߎ߫ ߟߊ߫ ߕߏߟߏ߲ߟߊ߲߫ ߥߊ߲߬ߥߊ߲ ߣߎߡߊ߲߫ ߕߟߊ ߖߍ߰ߙߍ ߛߎߥߊ߲ߘߌ߫ diff --git a/app/src/main/res/values-or/strings.xml b/app/src/main/res/values-or/strings.xml index cf9ebdb97..519c8aa22 100644 --- a/app/src/main/res/values-or/strings.xml +++ b/app/src/main/res/values-or/strings.xml @@ -438,7 +438,6 @@ ନାପସନ୍ଦ ମନ୍ତବ୍ୟ ଗୁଡିକ ବର୍ଣ୍ଣନା - ନିୟୁତ ସମାଧାନ ପ୍ଲେବେକ୍ ସ୍ପିଡ୍ ନିୟନ୍ତ୍ରଣ ଟେମ୍ପୋ @@ -528,7 +527,6 @@ ସମ୍ବନ୍ଧୀୟ ଆଇଟମ୍ ଗୁଡ଼ିକ ପୁନଃ ସଯାଇବାକୁ ଡ୍ରାଗ୍ କରନ୍ତୁ ବିରାମ - ଵୃନ୍ଦ କୌଣସି ଗ୍ରାହକ ନାହାଁନ୍ତି ସୃଷ୍ଟି କରନ୍ତୁ ବିବରଣୀ ପାଇଁ ଟ୍ୟାପ୍ କରନ୍ତୁ @@ -609,7 +607,6 @@ ବହିଃ-ଚାଳକ ପାଇଁ ଗୁଣବତ୍ତା ଚୟନ କରନ୍ତୁ ପିନ୍ ହୋଇଥିବା ମନ୍ତବ୍ୟ ୱେବସାଇଟ୍ ଖୋଲନ୍ତୁ - ହଜାର ସୂଚନା ପାଇବା… %s ଗ୍ରାହକ diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index ad14e7d05..a1d144cb2 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -153,9 +153,6 @@ ਵੀਡੀਓ ਆਡੀਓ ਦੋਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ - ਹਜ਼ਾਰ - ਮਿਲੀਅਨ - ਅਰਬ ਕੋਈ ਸਬਸਕ੍ਰਾਈਬਰ ਨਹੀਂ %s ਸਬਸਕ੍ਰਾਈਬਰ diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index dc3f88cec..f56ee344d 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -96,10 +96,7 @@ Wszystkie Wyłączone Wyczyść - tys. - mln - mld - To pozwolenie jest wymagane, aby + To pozwolenie jest wymagane, aby \notworzyć w trybie okienkowym Otwórz w trybie okienkowym Tryb okienkowy diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index d13cbcfe3..3c7bc9498 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -90,9 +90,6 @@ Reproduzindo em modo Popup Todos Desativado - mil - mi - bi Essa permissão é necessária \npara abrir em modo Popup Limpar diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 6ceec006e..0d78bd3db 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -229,7 +229,6 @@ OK Não foi possível atualizar a subscrição Sim e também os vídeos parcialmente vistos - M Ainda não há listas de reprodução favoritas %s ouvinte @@ -423,8 +422,6 @@ Importado Automático Substitui o seu histórico, subscrições, listas de reprodução e (opcionalmente) definições - k - MM Remover marcador Útil ao trocar para dados móveis, mas algumas transferências não podem ser suspensas Toque longo para colocar na fila diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 13a536895..b44cd7a21 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -82,9 +82,6 @@ Abrir no modo popup Preto Tudo - K - M - MM Esta permissão é necessária \npara o modo popup Desafio reCAPTCHA diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index eb4e75c28..628e75f16 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -92,9 +92,6 @@ Dezactivat Aplicația/UI s-a oprit Ce:\\nSolicitare:\\nLimba conținutului:\\nȚara conținutului:\\nLimba aplicației:\\nServiciu:\\nOra GMT:\\nPachet:\\nVersiune:\\nVersiune SO: - k - mil. - mld. Elimină sunetul audio la anumite rezoluții Fundal Pop-up diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index a512b6fa8..d32375a97 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -94,9 +94,6 @@ Выберите отображаемые предложения поиска Отключено Убирает звук в некоторых разрешениях - млн - млрд - тыс. Разрешение всплывающего окна Помнить последние размер и позицию всплывающего окна Предложения поиска diff --git a/app/src/main/res/values-ryu/strings.xml b/app/src/main/res/values-ryu/strings.xml index 1bc89420c..9041fc462 100644 --- a/app/src/main/res/values-ryu/strings.xml +++ b/app/src/main/res/values-ryu/strings.xml @@ -83,9 +83,6 @@ reCAPTCHAようきゅうさびたん ブラック まじり - k - M - B ポップアップモードっしふぃらちゅん ポップアップモードっしふぃらちゅんがー \nきんぎんぬきょかがふぃちようでぃす diff --git a/app/src/main/res/values-sat/strings.xml b/app/src/main/res/values-sat/strings.xml index a3ed7c405..6e6615a84 100644 --- a/app/src/main/res/values-sat/strings.xml +++ b/app/src/main/res/values-sat/strings.xml @@ -216,8 +216,6 @@ ᱡᱟᱦᱟᱱ ᱡᱤᱱᱤᱥ ᱱᱚᱣᱟ ᱨᱮᱫᱚ ᱡᱟᱹᱥᱛᱤ ᱡᱟᱹᱥᱛᱤ ᱠᱨᱤᱠᱮᱴ ᱢᱮᱱᱟᱜᱼᱟ ᱾ ᱵᱷᱤᱰᱤᱭᱳ - k - M ᱥᱮᱞᱮᱫᱤᱭᱟᱹ ᱠᱚᱣᱟᱜ ᱞᱮᱠᱷᱟ ᱵᱟᱭ ᱦᱟᱹᱴᱤᱧ ᱟᱠᱟᱱᱟ ᱵᱟᱱᱩᱜ ᱧᱮᱞ ᱵᱷᱤᱰᱤᱭᱳ ᱵᱟᱹᱱᱩᱜᱼᱟ @@ -478,7 +476,6 @@ ᱱᱟᱣᱟ ᱟᱹᱨᱡᱤ ᱞᱟᱹᱜᱤᱫ ᱟᱹᱪᱩᱨ ᱢᱮ ᱚᱰᱤᱭᱳ ᱟᱨᱦᱚᱸ ᱯᱟᱲᱦᱟᱣ ᱢᱮ - ᱵᱤ ᱱᱤᱛᱚᱜ ᱵᱟᱪᱷᱟᱣ ᱟᱠᱟᱱ ᱴᱳᱜᱞ ᱥᱮᱵᱟ: ᱚᱵᱷᱤᱱᱮᱛᱟᱨ ᱵᱟᱹᱱᱩᱜᱼᱟ ᱚᱠᱚᱭ ᱦᱚᱸ ᱵᱟᱝ ᱧᱮᱞᱚᱜ ᱠᱟᱱᱟ diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index 0c42f1ef0..cb51c3f4d 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -165,9 +165,6 @@ Perunu iscritu Allughe/istuda su servìtziu. Ischertadu como: - Mrd - Mlln - mìg Torra a proare Àudio Vìdeu diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index ad2dacfd6..d4ac57e1e 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -82,9 +82,6 @@ Výzva reCAPTCHA Čierna Všetko - k - M - B Požiadavka reCAPTCHA Otvoriť vo vyskakovacom okne Tieto práva sú potrebné pre diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index cd41b43ba..3705554bb 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -83,9 +83,6 @@ Predmet:\\nZahteva:\\nJezik vsebine:\\nDržava vsebine:\\nJezik aplikacije:\\nStoritev:\\nČas v GMT:\\nPaket:\\nRazličica:\\nRazličica OS: Črna Vse - k - mio - mrd Odpri v pojavnem načinu To dovoljenje je potrebno za odpiranje \nv pojavnem načinu diff --git a/app/src/main/res/values-so/strings.xml b/app/src/main/res/values-so/strings.xml index 6b4de7353..772e03b41 100644 --- a/app/src/main/res/values-so/strings.xml +++ b/app/src/main/res/values-so/strings.xml @@ -242,9 +242,6 @@ Dad rukuntay ma jiraan Furo adeega, hada waxaa dooran: - B - K - M ku celi Dhagaysi Muuqaal diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml index 162ba5ada..9aac66de7 100644 --- a/app/src/main/res/values-sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -295,9 +295,6 @@ Nuk ka abonues Aktivizoje shërbimin, momentalisht e zgjedhur: - B - M - k Riprovo Audio Video diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 99b9e971f..3c82e5612 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -83,9 +83,6 @@ Решите „reCAPTCHA“ задатак Црна Све - хиљ. - мил. - млрд. Отвори у искачућем облику Ова дозвола је потребна за \nотварање у искачућем режиму diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 3beab4181..8aab4a67f 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -112,9 +112,6 @@ Video Ljud Försök igen - t - mn - md Inga prenumeranter %s prenumerant diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index 906249376..7221ab74d 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -245,7 +245,6 @@ உம் அபிமான பியர்டியூப் நிகழ்வுகளைத் தேர்ந்தெடு உள்ளடக்க இயல்பிருப்பு மொழி இயக்குதலைத் மறுதொடர் - நி நிகழ்வு ஏற்கனவே உள்ளது யூடியூபின் \"கட்டுப்பாடு பயன்முறை\"ஐ இயக்கு பாடல்கள் @@ -260,8 +259,6 @@ என்ன:\\nகோரிக்கை:\\nஉள்ளடக்க மொழி:\\nஉள்ளடக்க நாடு:\\nசெயலி மொழி:\\nசேவை:\\nGMT நேரம்:\\nசிப்பம்:\\nபதிப்பு:\\nOS பதிப்பு: காணொளியை இயக்கு, காலவளவு: கருத்தளிப்புகள் - - ப.ல இயக்கியைச் சிதை பட்டியல்களில் இயக்கக குறியட நிலைகாட்டிகளைக் காட்டு துணையியக்கியில் காணொளிகளை துவக்காதே, ஆனால் தானாக சுழற்றல் பூட்டப்பட்டிருந்தால் நேரடியாக முழுதிரைக்குத் திரும்பு. முழுதிரையை வெளியேறி நீங்கள் இன்னும் துணையியக்கியை அணுகலாம் diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index c537495ba..b95e04c0c 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -77,9 +77,6 @@ వీడియో ఆడియో మళ్ళీ ప్రయత్నించు - కి - ఎం - బిలియన్ సభ్యులు లేరు %s సభ్యుడు diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index bcbbca0a4..c2cb4669e 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -165,9 +165,6 @@ วิดีโอ เสียง ลองอีกครั้ง - พัน - ล้าน - พันล้าน ไม่มีสมาชิกที่สมัครรับ %s บอกรับ diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index a26016f1a..79bbea486 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -88,9 +88,6 @@ Devre dışı Yorumunuz (İngilizce): Ayrıntılar: - b - M - M Bu izin, açılır pencere kipinde \naçmak için gereklidir reCAPTCHA formu diff --git a/app/src/main/res/values-tzm/strings.xml b/app/src/main/res/values-tzm/strings.xml index 31d89bdd5..b6539d568 100644 --- a/app/src/main/res/values-tzm/strings.xml +++ b/app/src/main/res/values-tzm/strings.xml @@ -113,7 +113,6 @@ Kkes Senulfu Senti - ifḍ Als-arem Imesli Avidyu diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 32e03bea0..c47d2f1fd 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -65,9 +65,6 @@ Відео Аудіо Повторити спробу - тис - млн - млрд Почати Пауза Видалити diff --git a/app/src/main/res/values-und/strings.xml b/app/src/main/res/values-und/strings.xml index 94e4f9dd6..0bd3bf442 100644 --- a/app/src/main/res/values-und/strings.xml +++ b/app/src/main/res/values-und/strings.xml @@ -70,7 +70,6 @@ ویڈیو آڈیو فیر کرو - ہزار بݨاؤ بارے لائیسنس diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index 1a434ab63..bb95e2811 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -146,9 +146,6 @@ ویڈیو آڈیو دوبارہ کوشش کریں - ہزار - دہ لاکھ - ارب کوئی صارفین نہیں %s صارف diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index e1073e7af..e8f4ec3f9 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -82,9 +82,6 @@ Video Âm thanh Thử lại - nghìn - triệu - tỉ Bắt đầu Dừng Xóa diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 3c9c79457..9c6c8a9b9 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -71,8 +71,6 @@ %s 次观看 - - 百万 开始 暂停 删除 @@ -153,7 +151,6 @@ 详细信息: 播放视频,时长: 视频上传者的头像缩略图 - 十亿 NewPipe 正在下载 请稍后在设置中设定下载目录 使用悬浮窗模式 diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 6b5529992..1f258c1db 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -87,8 +87,6 @@ 全部嘢 App/界面閃退 經過:\\n請求:\\n內容語言:\\n內容國家:\\nApp 語言:\\n服務:\\nGMT 時間:\\n封裝:\\n版本:\\nOS 版本: - - 百萬 reCAPTCHA 考驗 以浮面模式開啟 \n有呢個權限至得 @@ -103,7 +101,6 @@ 不適用 抹走 最佳解像度 - 十億 關於 NewPipe 第三方版權協議 © %1$s %2$s 版權所有,根據 %3$s 嘅條款授權 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index b9ca2d3ce..be46b83a1 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -82,9 +82,6 @@ 影片 音訊 重試 - - 百萬 - 十億 開始 暫停 刪除 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6ab2fc7a5..ff23f1c2b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -287,9 +287,9 @@ Video Audio Retry - k - M - B + %sK + %sM + %sB Toggle service, currently selected: No subscribers From 59db955493370f685281f4e09a068afd7d2eb6ef Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Sun, 27 Jul 2025 11:29:58 +0530 Subject: [PATCH 04/43] Fix new streams notification issue --- app/src/main/AndroidManifest.xml | 8 +++++++- .../local/feed/notifications/NotificationWorker.kt | 5 ++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e21bb518c..efb667b22 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -98,9 +98,15 @@ - + + = Build.VERSION_CODES.Q) ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC else 0 + setForegroundAsync(ForegroundInfo(FeedLoadService.NOTIFICATION_ID, notification, serviceType)) } companion object { From b9b47fc5203a6b2cb08bb70ba51b3eb368ea579e Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Sun, 27 Jul 2025 11:58:01 +0530 Subject: [PATCH 05/43] Update manifest, startForeground call --- app/src/main/AndroidManifest.xml | 11 +++++++++-- .../newpipe/player/notification/NotificationUtil.java | 8 ++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index efb667b22..8a6b22ab3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -96,8 +96,14 @@ android:exported="false" android:label="@string/title_activity_about" /> - - + + + + @@ -431,6 +437,7 @@ diff --git a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java index 30420b0c7..e5e2544b2 100644 --- a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java +++ b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java @@ -174,12 +174,8 @@ public final class NotificationUtil { } updateNotification(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - player.getService().startForeground(NOTIFICATION_ID, notificationBuilder.build(), - ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK); - } else { - player.getService().startForeground(NOTIFICATION_ID, notificationBuilder.build()); - } + ServiceCompat.startForeground(player.getService(), NOTIFICATION_ID, + notificationBuilder.build(), ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK); } public void cancelNotificationAndStopForeground() { From a9ce2e960561ca0687ebf54d21a1c904a8ed3bca Mon Sep 17 00:00:00 2001 From: TobiGr Date: Sun, 27 Jul 2025 09:39:53 +0200 Subject: [PATCH 06/43] Update USER_AGENT to Firefox 140 ESR --- app/src/main/java/org/schabi/newpipe/DownloaderImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java b/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java index 5159fbfdc..6ccc2437a 100644 --- a/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java +++ b/app/src/main/java/org/schabi/newpipe/DownloaderImpl.java @@ -29,7 +29,7 @@ import okhttp3.ResponseBody; public final class DownloaderImpl extends Downloader { public static final String USER_AGENT = - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"; + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0"; public static final String YOUTUBE_RESTRICTED_MODE_COOKIE_KEY = "youtube_restricted_mode_key"; public static final String YOUTUBE_RESTRICTED_MODE_COOKIE = "PREF=f2=8000000"; From fece0741e5a1cf562e0bcfedae3aac327d7d5739 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Sun, 27 Jul 2025 12:17:44 +0530 Subject: [PATCH 07/43] Suppress NewApi --- .../newpipe/local/feed/notifications/NotificationWorker.kt | 4 ++-- .../schabi/newpipe/player/notification/NotificationUtil.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt index ad2f1055c..ca48a4243 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt @@ -2,7 +2,6 @@ package org.schabi.newpipe.local.feed.notifications import android.content.Context import android.content.pm.ServiceInfo -import android.os.Build import android.util.Log import androidx.core.app.NotificationCompat import androidx.work.Constraints @@ -85,7 +84,8 @@ class NotificationWorker( .setPriority(NotificationCompat.PRIORITY_LOW) .setContentTitle(applicationContext.getString(R.string.feed_notification_loading)) .build() - val serviceType = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC else 0 + @Suppress("NewApi") // ServiceInfo constant is inlined + val serviceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC setForegroundAsync(ForegroundInfo(FeedLoadService.NOTIFICATION_ID, notification, serviceType)) } diff --git a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java index e5e2544b2..f314f713a 100644 --- a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java +++ b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java @@ -167,7 +167,7 @@ public final class NotificationUtil { && notificationBuilder.mActions.get(2).actionIntent != null); } - + @SuppressLint("NewApi") // ServiceInfo constant is inlined public void createNotificationAndStartForeground() { if (notificationBuilder == null) { notificationBuilder = createNotification(); From 9f11db8e06385a726105bc63032320e80954a2fe Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Mon, 28 Jul 2025 09:02:52 +0530 Subject: [PATCH 08/43] Improve scale display --- .../org/schabi/newpipe/util/Localization.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) 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 d47cb918e..da4edeca6 100644 --- a/app/src/main/java/org/schabi/newpipe/util/Localization.java +++ b/app/src/main/java/org/schabi/newpipe/util/Localization.java @@ -191,14 +191,20 @@ public final class Localization { final double value = (double) count; if (count >= 1000000000) { + final double shortenedValue = value / 1000000000; + final int scale = shortenedValue >= 100 ? 0 : 1; return context.getString(R.string.short_billion, - localizeNumber(round(value / 1000000000))); + localizeNumber(round(shortenedValue, scale))); } else if (count >= 1000000) { + final double shortenedValue = value / 1000000; + final int scale = shortenedValue >= 100 ? 0 : 1; return context.getString(R.string.short_million, - localizeNumber(round(value / 1000000))); + localizeNumber(round(shortenedValue, scale))); } else if (count >= 1000) { + final double shortenedValue = value / 1000; + final int scale = shortenedValue >= 100 ? 0 : 1; return context.getString(R.string.short_thousand, - localizeNumber(round(value / 1000, 0))); + localizeNumber(round(shortenedValue, scale))); } else { return localizeNumber(value); } @@ -416,10 +422,6 @@ public final class Localization { } } - private static double round(final double value) { - return round(value, 1); - } - private static double round(final double value, final int scale) { return new BigDecimal(value).setScale(scale, RoundingMode.HALF_UP).doubleValue(); } From 9ba30887f9f58f8cd545996a14e0117b815b68fc Mon Sep 17 00:00:00 2001 From: Stypox Date: Mon, 28 Jul 2025 14:43:46 +0200 Subject: [PATCH 09/43] Improve null checking further in SearchFragment.handleNextItems --- .../fragments/list/search/SearchFragment.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java index 6916ca826..cea06b942 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 @@ -1090,14 +1090,19 @@ public class SearchFragment extends BaseListFragment Date: Sat, 26 Jul 2025 15:43:36 +0200 Subject: [PATCH 10/43] Use regions --- .../newpipe/player/helper/PlayerHelper.java | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java index a110a80d6..791346d66 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java @@ -89,9 +89,7 @@ public final class PlayerHelper { private PlayerHelper() { } - //////////////////////////////////////////////////////////////////////////// - // Exposed helpers - //////////////////////////////////////////////////////////////////////////// + // region Exposed helpers @NonNull public static String getTimeString(final int milliSeconds) { @@ -219,9 +217,8 @@ public final class PlayerHelper { ? null : getAutoQueuedSinglePlayQueue(autoQueueItems.get(0)); } - //////////////////////////////////////////////////////////////////////////// - // Settings Resolution - //////////////////////////////////////////////////////////////////////////// + // endregion + // region Resolution public static boolean isResumeAfterAudioFocusGain(@NonNull final Context context) { return getPreferences(context) @@ -405,9 +402,8 @@ public final class PlayerHelper { return Integer.parseInt(preferredIntervalBytes) * 1024; } - //////////////////////////////////////////////////////////////////////////// - // Private helpers - //////////////////////////////////////////////////////////////////////////// + // endregion + // region Private helpers @NonNull private static SharedPreferences getPreferences(@NonNull final Context context) { @@ -427,9 +423,8 @@ public final class PlayerHelper { } - //////////////////////////////////////////////////////////////////////////// - // Utils used by player - //////////////////////////////////////////////////////////////////////////// + // endregion + // region Utils used by player @RepeatMode public static int nextRepeatMode(@RepeatMode final int repeatMode) { @@ -503,4 +498,6 @@ public final class PlayerHelper { player.getContext().getString(R.string.seek_duration_key), player.getContext().getString(R.string.seek_duration_default_value)))); } + + // endregion } From 70841db92ff1d8208acdd687973c40c9a76b01d6 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sat, 26 Jul 2025 15:43:46 +0200 Subject: [PATCH 11/43] Cleanup ``Localization`` formatting --- .../main/java/org/schabi/newpipe/util/Localization.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) 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 2bd4664ae..bd5463088 100644 --- a/app/src/main/java/org/schabi/newpipe/util/Localization.java +++ b/app/src/main/java/org/schabi/newpipe/util/Localization.java @@ -127,14 +127,13 @@ public final class Localization { } public static String localizeNumber(final double number) { - final NumberFormat nf = NumberFormat.getInstance(getAppLocale()); - return nf.format(number); + return NumberFormat.getInstance(getAppLocale()).format(number); } public static String formatDate(@NonNull final OffsetDateTime offsetDateTime) { return DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM) - .withLocale(getAppLocale()).format(offsetDateTime - .atZoneSameInstant(ZoneId.systemDefault())); + .withLocale(getAppLocale()) + .format(offsetDateTime.atZoneSameInstant(ZoneId.systemDefault())); } @SuppressLint("StringFormatInvalid") From ebd5e1a3180671ec0c5b2e3b72a67dbf28d8e543 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sat, 26 Jul 2025 16:01:25 +0200 Subject: [PATCH 12/43] Remove unused method --- .../schabi/newpipe/player/helper/PlayerHelper.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java index 791346d66..d3e10da5d 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java @@ -117,18 +117,6 @@ public final class PlayerHelper { return PITCH_FORMATTER.format(pitch); } - @NonNull - public static String subtitleMimeTypesOf(@NonNull final MediaFormat format) { - switch (format) { - case VTT: - return MimeTypes.TEXT_VTT; - case TTML: - return MimeTypes.APPLICATION_TTML; - default: - throw new IllegalArgumentException("Unrecognized mime type: " + format.name()); - } - } - @NonNull public static String captionLanguageOf(@NonNull final Context context, @NonNull final SubtitlesStream subtitles) { From 893a1cb699f2e74af85ab70a57da82111b7b64b8 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Sat, 26 Jul 2025 16:06:44 +0200 Subject: [PATCH 13/43] Encapsulate Formatters in PlayerHelper and reset them when the language is changed/changing. This way they will be re-initialized on the next call. Also Remove a bunch of outdated/non-thread safe code (STRING_FORMATTER) --- .../newpipe/player/helper/PlayerHelper.java | 71 ++++++++++++++----- .../settings/ContentSettingsFragment.java | 3 + 2 files changed, 57 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java index d3e10da5d..266d65f36 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java @@ -33,11 +33,9 @@ import com.google.android.exoplayer2.trackselection.ExoTrackSelection; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode; import com.google.android.exoplayer2.ui.CaptionStyleCompat; -import com.google.android.exoplayer2.util.MimeTypes; import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.InfoItem; -import org.schabi.newpipe.extractor.MediaFormat; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.SubtitlesStream; @@ -47,13 +45,14 @@ import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.PlayQueueItem; import org.schabi.newpipe.player.playqueue.SinglePlayQueue; import org.schabi.newpipe.util.ListHelper; +import org.schabi.newpipe.util.Localization; import java.lang.annotation.Retention; import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collections; -import java.util.Formatter; import java.util.HashSet; import java.util.List; import java.util.Locale; @@ -62,11 +61,7 @@ import java.util.Set; import java.util.concurrent.TimeUnit; public final class PlayerHelper { - private static final StringBuilder STRING_BUILDER = new StringBuilder(); - private static final Formatter STRING_FORMATTER = - new Formatter(STRING_BUILDER, Locale.getDefault()); - private static final NumberFormat SPEED_FORMATTER = new DecimalFormat("0.##x"); - private static final NumberFormat PITCH_FORMATTER = new DecimalFormat("##%"); + private static final FormattersProvider FORMATTERS_PROVIDER = new FormattersProvider(); @Retention(SOURCE) @IntDef({AUTOPLAY_TYPE_ALWAYS, AUTOPLAY_TYPE_WIFI, @@ -91,6 +86,10 @@ public final class PlayerHelper { // region Exposed helpers + public static void resetFormat() { + FORMATTERS_PROVIDER.reset(); + } + @NonNull public static String getTimeString(final int milliSeconds) { final int seconds = (milliSeconds % 60000) / 1000; @@ -98,23 +97,24 @@ public final class PlayerHelper { final int hours = (milliSeconds % 86400000) / 3600000; final int days = (milliSeconds % (86400000 * 7)) / 86400000; - STRING_BUILDER.setLength(0); - return (days > 0 - ? STRING_FORMATTER.format("%d:%02d:%02d:%02d", days, hours, minutes, seconds) - : hours > 0 - ? STRING_FORMATTER.format("%d:%02d:%02d", hours, minutes, seconds) - : STRING_FORMATTER.format("%02d:%02d", minutes, seconds) - ).toString(); + final Formatters formatters = FORMATTERS_PROVIDER.formatters(); + if (days > 0) { + return formatters.stringFormat("%d:%02d:%02d:%02d", days, hours, minutes, seconds); + } + + return hours > 0 + ? formatters.stringFormat("%d:%02d:%02d", hours, minutes, seconds) + : formatters.stringFormat("%02d:%02d", minutes, seconds); } @NonNull public static String formatSpeed(final double speed) { - return SPEED_FORMATTER.format(speed); + return FORMATTERS_PROVIDER.formatters().speed().format(speed); } @NonNull public static String formatPitch(final double pitch) { - return PITCH_FORMATTER.format(pitch); + return FORMATTERS_PROVIDER.formatters().pitch().format(pitch); } @NonNull @@ -487,5 +487,42 @@ public final class PlayerHelper { player.getContext().getString(R.string.seek_duration_default_value)))); } + // endregion + // region Format + + static class FormattersProvider { + private Formatters formatters; + + public Formatters formatters() { + if (formatters == null) { + formatters = Formatters.create(); + } + return formatters; + } + + public void reset() { + formatters = null; + } + } + + record Formatters( + Locale locale, + NumberFormat speed, + NumberFormat pitch) { + + static Formatters create() { + final Locale locale = Localization.getAppLocale(); + final DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale); + return new Formatters( + locale, + new DecimalFormat("0.##x", dfs), + new DecimalFormat("##%", dfs)); + } + + String stringFormat(final String format, final Object... args) { + return String.format(locale, format, args); + } + } + // endregion } 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 ffc80e30e..e1d0e7be3 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java @@ -16,6 +16,7 @@ import androidx.preference.Preference; import org.schabi.newpipe.DownloaderImpl; import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.NewPipe; +import org.schabi.newpipe.player.helper.PlayerHelper; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.image.ImageStrategy; import org.schabi.newpipe.util.image.PicassoHelper; @@ -53,6 +54,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment { final Intent intent = new Intent(Settings.ACTION_APP_LOCALE_SETTINGS) .setData(Uri.fromParts("package", requireContext().getPackageName(), null)); startActivity(intent); + PlayerHelper.resetFormat(); return true; }); newAppLanguagePref.setVisible(true); @@ -64,6 +66,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment { final String systemLang = getString(R.string.default_localization_key); final String tag = systemLang.equals(language) ? null : language; AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(tag)); + PlayerHelper.resetFormat(); return true; }); } From eea2b7417efa09d04b6c88aae9d76266d6852297 Mon Sep 17 00:00:00 2001 From: Stypox Date: Mon, 28 Jul 2025 15:29:06 +0200 Subject: [PATCH 14/43] Fix player formatters resetting too early on language change formatters() is called again by the player before the user has a chance to click on the language in the language chooser. So the correct solution would probably be to attach to https://developer.android.com/reference/android/content/Intent#ACTION_LOCALE_CHANGED, but let's keep it simple. I added `PlayerHelper.resetFormat();` in `ContentSettingsFragment.onDestroy()` and it works. It will mean the player formatters will be reset every time the user exits content settings, but whatever. --- .../org/schabi/newpipe/settings/ContentSettingsFragment.java | 3 +-- 1 file changed, 1 insertion(+), 2 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 e1d0e7be3..b855f7c38 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java @@ -54,7 +54,6 @@ public class ContentSettingsFragment extends BasePreferenceFragment { final Intent intent = new Intent(Settings.ACTION_APP_LOCALE_SETTINGS) .setData(Uri.fromParts("package", requireContext().getPackageName(), null)); startActivity(intent); - PlayerHelper.resetFormat(); return true; }); newAppLanguagePref.setVisible(true); @@ -66,7 +65,6 @@ public class ContentSettingsFragment extends BasePreferenceFragment { final String systemLang = getString(R.string.default_localization_key); final String tag = systemLang.equals(language) ? null : language; AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(tag)); - PlayerHelper.resetFormat(); return true; }); } @@ -110,5 +108,6 @@ public class ContentSettingsFragment extends BasePreferenceFragment { NewPipe.setupLocalization( Localization.getPreferredLocalization(context), Localization.getPreferredContentCountry(context)); + PlayerHelper.resetFormat(); } } From 6516fb96fd345076d6a1ce21759b61323c96eb98 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 28 Jul 2025 20:39:59 +0200 Subject: [PATCH 15/43] Translated using Weblate (Romanian) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (748 of 748 strings) Translated using Weblate (Arabic) Currently translated at 100.0% (86 of 86 strings) Translated using Weblate (Russian) Currently translated at 100.0% (86 of 86 strings) Translated using Weblate (Arabic) Currently translated at 100.0% (748 of 748 strings) Translated using Weblate (Arabic) Currently translated at 100.0% (748 of 748 strings) Translated using Weblate (Russian) Currently translated at 100.0% (748 of 748 strings) Translated using Weblate (Turkish) Currently translated at 100.0% (748 of 748 strings) Translated using Weblate (Indonesian) Currently translated at 100.0% (748 of 748 strings) Translated using Weblate (French) Currently translated at 100.0% (748 of 748 strings) Translated using Weblate (Icelandic) Currently translated at 99.4% (745 of 749 strings) Translated using Weblate (Estonian) Currently translated at 18.6% (16 of 86 strings) Translated using Weblate (Slovak) Currently translated at 100.0% (86 of 86 strings) Translated using Weblate (Portuguese (Portugal)) Currently translated at 99.5% (746 of 749 strings) Translated using Weblate (Belarusian) Currently translated at 99.7% (747 of 749 strings) Translated using Weblate (Estonian) Currently translated at 100.0% (749 of 749 strings) Translated using Weblate (Bulgarian) Currently translated at 100.0% (749 of 749 strings) Translated using Weblate (Hebrew) Currently translated at 99.7% (747 of 749 strings) Translated using Weblate (Chinese (Traditional Han script)) Currently translated at 100.0% (749 of 749 strings) Translated using Weblate (Chinese (Simplified Han script)) Currently translated at 100.0% (749 of 749 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (749 of 749 strings) Translated using Weblate (Polish) Currently translated at 100.0% (749 of 749 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (749 of 749 strings) Translated using Weblate (Czech) Currently translated at 100.0% (749 of 749 strings) Translated using Weblate (Slovak) Currently translated at 99.7% (747 of 749 strings) Translated using Weblate (Greek) Currently translated at 100.0% (749 of 749 strings) Translated using Weblate (Portuguese) Currently translated at 99.5% (746 of 749 strings) Translated using Weblate (Italian) Currently translated at 100.0% (749 of 749 strings) Translated using Weblate (Hungarian) Currently translated at 100.0% (749 of 749 strings) Translated using Weblate (German) Currently translated at 100.0% (749 of 749 strings) Translated using Weblate (German) Currently translated at 100.0% (749 of 749 strings) Translated using Weblate (Tamazight (Central Atlas)) Currently translated at 19.2% (144 of 749 strings) Translated using Weblate (Macedonian) Currently translated at 79.3% (594 of 749 strings) Translated using Weblate (Slovenian) Currently translated at 54.6% (409 of 749 strings) Translated using Weblate (Tigrinya) Currently translated at 12.7% (95 of 747 strings) Translated using Weblate (Tigrinya) Currently translated at 3.4% (3 of 86 strings) Translated using Weblate (Icelandic) Currently translated at 99.4% (743 of 747 strings) Translated using Weblate (Chinese (Simplified Han script)) Currently translated at 90.6% (78 of 86 strings) Translated using Weblate (Slovak) Currently translated at 100.0% (86 of 86 strings) Translated using Weblate (French) Currently translated at 100.0% (86 of 86 strings) Translated using Weblate (Italian) Currently translated at 100.0% (86 of 86 strings) Translated using Weblate (Italian) Currently translated at 100.0% (86 of 86 strings) Translated using Weblate (Polish) Currently translated at 58.1% (50 of 86 strings) Translated using Weblate (Hindi) Currently translated at 100.0% (86 of 86 strings) Translated using Weblate (Hungarian) Currently translated at 100.0% (86 of 86 strings) Translated using Weblate (Punjabi) Currently translated at 100.0% (86 of 86 strings) Translated using Weblate (Czech) Currently translated at 100.0% (86 of 86 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (86 of 86 strings) Translated using Weblate (German) Currently translated at 100.0% (86 of 86 strings) Translated using Weblate (Belarusian) Currently translated at 100.0% (747 of 747 strings) Translated using Weblate (Punjabi) Currently translated at 100.0% (747 of 747 strings) Translated using Weblate (Hindi) Currently translated at 100.0% (747 of 747 strings) Translated using Weblate (Czech) Currently translated at 100.0% (747 of 747 strings) Translated using Weblate (Slovak) Currently translated at 100.0% (747 of 747 strings) Translated using Weblate (Slovak) Currently translated at 100.0% (747 of 747 strings) Translated using Weblate (German) Currently translated at 100.0% (747 of 747 strings) Co-authored-by: 439JBYL80IGQTF25UXNR0X1BG <439JBYL80IGQTF25UXNR0X1BG@users.noreply.hosted.weblate.org> Co-authored-by: Agnieszka C Co-authored-by: Drugi Sapog Co-authored-by: Dual Natan Co-authored-by: Emin Tufan Çetin Co-authored-by: Fjuro Co-authored-by: Ghost of Sparta Co-authored-by: Hakim Oubouali Co-authored-by: Hosted Weblate Co-authored-by: Igor Rückert Co-authored-by: Igor Sorocean Co-authored-by: Jeff Huang Co-authored-by: Marian Hanzel Co-authored-by: Matej U Co-authored-by: Michael Moroni Co-authored-by: Mickaël Binos Co-authored-by: Milan Co-authored-by: NTFSynergy Co-authored-by: Priit Jõerüüt Co-authored-by: Random Co-authored-by: Rex_sa Co-authored-by: Stypox Co-authored-by: Sveinn í Felli Co-authored-by: Trunars Co-authored-by: Vasilis K Co-authored-by: VfBFan Co-authored-by: Yaron Shahrabani Co-authored-by: Yassin Amir Co-authored-by: erti Co-authored-by: ikanakova Co-authored-by: nautilusx Co-authored-by: ssantos Co-authored-by: whistlingwoods <72640314+whistlingwoods@users.noreply.github.com> Co-authored-by: zmni Co-authored-by: Максим Горпиніч Co-authored-by: 大王叫我来巡山 Co-authored-by: 赖诚俊 Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ar/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/cs/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/de/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/et/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/fr/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/hi/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/hu/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/it/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pa/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pl/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ru/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/sk/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ti/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/uk/ Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/zh_Hans/ Translation: NewPipe/Metadata --- app/src/main/res/values-ar/strings.xml | 5 ++ app/src/main/res/values-be/strings.xml | 71 ++++++++++--------- app/src/main/res/values-bg/strings.xml | 4 +- app/src/main/res/values-cs/strings.xml | 22 +++--- app/src/main/res/values-de/strings.xml | 5 ++ app/src/main/res/values-el/strings.xml | 5 ++ app/src/main/res/values-et/strings.xml | 4 +- app/src/main/res/values-fr/strings.xml | 4 +- app/src/main/res/values-he/strings.xml | 6 +- app/src/main/res/values-hi/strings.xml | 8 +++ app/src/main/res/values-hu/strings.xml | 2 + app/src/main/res/values-in/strings.xml | 9 ++- app/src/main/res/values-is/strings.xml | 8 +++ app/src/main/res/values-it/strings.xml | 2 + app/src/main/res/values-mk/strings.xml | 2 +- app/src/main/res/values-pa/strings.xml | 10 ++- app/src/main/res/values-pl/strings.xml | 2 + app/src/main/res/values-pt-rBR/strings.xml | 5 ++ app/src/main/res/values-pt-rPT/strings.xml | 2 + app/src/main/res/values-pt/strings.xml | 2 + app/src/main/res/values-ro/strings.xml | 11 ++- app/src/main/res/values-ru/strings.xml | 5 ++ app/src/main/res/values-sk/strings.xml | 53 +++++++------- app/src/main/res/values-sl/strings.xml | 2 +- app/src/main/res/values-ti/strings.xml | 12 ++-- app/src/main/res/values-tr/strings.xml | 10 ++- app/src/main/res/values-tzm/strings.xml | 2 +- app/src/main/res/values-uk/strings.xml | 8 ++- app/src/main/res/values-zh-rCN/strings.xml | 6 +- app/src/main/res/values-zh-rTW/strings.xml | 4 ++ .../metadata/android/ar/changelogs/1005.txt | 17 +++++ .../metadata/android/cs/changelogs/1005.txt | 17 +++++ .../metadata/android/de/changelogs/1005.txt | 17 +++++ .../metadata/android/et/changelogs/1005.txt | 17 +++++ .../metadata/android/fr/changelogs/1005.txt | 17 +++++ .../metadata/android/hi/changelogs/1005.txt | 17 +++++ .../metadata/android/hu/changelogs/1005.txt | 17 +++++ .../metadata/android/it/changelogs/1005.txt | 17 +++++ .../metadata/android/pa/changelogs/1005.txt | 17 +++++ .../metadata/android/pl/changelogs/1005.txt | 17 +++++ .../metadata/android/ru/changelogs/1005.txt | 17 +++++ .../metadata/android/sk/changelogs/1000.txt | 20 +++--- .../metadata/android/sk/changelogs/1005.txt | 18 +++++ .../metadata/android/sk/full_description.txt | 2 +- .../metadata/android/ti/full_description.txt | 2 +- .../metadata/android/ti/short_description.txt | 2 +- .../metadata/android/uk/changelogs/1002.txt | 5 +- .../metadata/android/uk/changelogs/1003.txt | 7 +- .../metadata/android/uk/changelogs/1004.txt | 4 +- .../metadata/android/uk/changelogs/1005.txt | 17 +++++ .../android/zh-Hans/changelogs/1001.txt | 6 ++ 51 files changed, 448 insertions(+), 113 deletions(-) create mode 100644 fastlane/metadata/android/ar/changelogs/1005.txt create mode 100644 fastlane/metadata/android/cs/changelogs/1005.txt create mode 100644 fastlane/metadata/android/de/changelogs/1005.txt create mode 100644 fastlane/metadata/android/et/changelogs/1005.txt create mode 100644 fastlane/metadata/android/fr/changelogs/1005.txt create mode 100644 fastlane/metadata/android/hi/changelogs/1005.txt create mode 100644 fastlane/metadata/android/hu/changelogs/1005.txt create mode 100644 fastlane/metadata/android/it/changelogs/1005.txt create mode 100644 fastlane/metadata/android/pa/changelogs/1005.txt create mode 100644 fastlane/metadata/android/pl/changelogs/1005.txt create mode 100644 fastlane/metadata/android/ru/changelogs/1005.txt create mode 100644 fastlane/metadata/android/sk/changelogs/1005.txt create mode 100644 fastlane/metadata/android/uk/changelogs/1005.txt create mode 100644 fastlane/metadata/android/zh-Hans/changelogs/1001.txt diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index fff1dd3a9..7e002d88a 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -885,4 +885,9 @@ صفحة مجموعة القناة حدد مجموعة المحتوى لم تنشئ مجموعة محتوى + الإعجابات + البحث %1$s + البحث %1$s (%2$s) + تمت إزالة صفحة أفضل 50 من SoundCloud + أوقفت SoundCloud صفحة أفضل 50 الأصلية. تمت إزالة علامة التبويب المقابلة من صفحتك الرئيسية. diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 22f963def..9f40ae48f 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -55,7 +55,7 @@ Памятаць апошнія памер і пазіцыю ўсплывальнага акна Хуткі пошук пазіцыі Недакладны пошук дазваляе плэеру знаходзіць пазіцыі хутчэй са зніжанай дакладнасцю. Пошук цягам 5, 15 ці 25 секунд пры гэтым немажлівы - Кэш малюнкаў ачышчаны + Кэш відарысаў ачышчаны Ачысціць кэш метаданых Выдаліць усе даныя вэб-старонак у кэшы Кэш метаданых ачышчаны @@ -71,8 +71,8 @@ Працягваць прайграванне пасля перапынкаў (напрыклад, тэлефонных званкоў) Спампаваць «Наступнае» і «Прапанаванае» відэа - Паказваць падказку «Зацісніце, каб дадаць» - Паказваць падказку пры націсканні «У акне» або «У фоне» на старонцы звестак аб відэа + Паказваць падказку «Утрымлівайце, каб дадаць у чаргу» + Паказваць падказку пры націсканні кнопкі «У акне» або «У фоне» на старонцы відэа URL не падтрымліваецца Прадвызначаная краіна кантэнту Прадвызначаная мова кантэнту @@ -137,7 +137,7 @@ Такой папкі не існуе Такога файла або крыніцы кантэнту не існуе Файл не існуе або няма дазволу на яго чытанне ці запіс - Імя файла не можа быць пустым + Назва файла не можа быць пустой Адбылася памылка: %1$s Няма трансляцый, даступных для спампоўвання Прабачце, гэта не павінна было адбыцца. @@ -154,7 +154,7 @@ Спадабалася Не спадабалася Няма вынікаў - Нічога няма, акрамя цвыркуноў + Нічога няма, хоць сабак ганяй Перацягніце, каб змяніць парадак Відэа Аўдыя @@ -191,7 +191,7 @@ Адхіліць Перайменаваць ОК - Імя файла + Назва файла Патокі Памылка NewPipe спампоўвае @@ -204,7 +204,7 @@ Запыт reCAPTCHA Запытаны ўвод reCAPTCHA Спампоўванне - Дапушчальныя ў назвах файлаў сімвалы + Сімвалы, дапушчальныя ў назвах файлаў Недапушчальныя сімвалы замяняюцца на гэты Сімвал для замены Літары і лічбы @@ -253,7 +253,7 @@ Выдаліць Падрабязнасці Налады аўдыя - Зацісніце, каб дадаць у чаргу + Утрымлівайце, каб дадаць у чаргу Пачаць прайграванне ў фоне Пачаць прайграванне ў акне Адкрыць бакавую панэль @@ -268,7 +268,7 @@ Загрузка запытанага кантэнту Стварыць плэй-ліст Перайменаваць - Імя + Назва Дадаць у плэй-ліст Зрабіць мініяцюрай плэй-ліста Дадаць плэй-ліст у закладкі @@ -327,7 +327,7 @@ Апавяшчэнні пра новыя версіі NewPipe Знешняе сховішча недаступна Спампоўванне на знешнюю SD-карту немагчыма. Скінуць размяшчэнне папкі спампоўвання? - Памылка чытання захаваных укладак. Выкарыстоўваюцца ўкладкі па змаўчанні + Не ўдалося прачытаць захаваныя ўкладкі, таму выкарыстоўваюцца прадвызначаныя Аднавіць прадвызначаныя значэнні Аднавіць прадвызначаныя значэнні? Колькасць падпісчыкаў недаступна @@ -347,9 +347,9 @@ Дадаць у чаргу Дзеянне забаронена сістэмай Памылка спампоўвання - Стварыць унікальнае імя + Стварыць унікальную назву Перазапісаць - Файл з такім імем ужо спампоўваецца + Файл з такой назвай ўжо спампоўваецца Паказаць тэкст памылкі Немагчыма стварыць папку прызначэння Немагчыма стварыць файл @@ -376,14 +376,14 @@ Працягваць прайграванне Аднаўляць апошнюю пазіцыю Пазіцыі ў спісах - Адлюстроўваць індыкатары пазіцый прагляду ў спісах + Паказваць у спісах пазіцыю прайгравання Ачыстка даных Пазіцыі прайгравання выдалены Файл перамешчаны або выдалены - Файл з такім імем ужо існуе - Файл з такім імем ужо існуе + Файл з такой назвай ужо існуе + Спампаваны файл з такой назвай ужо існуе немагчыма перазапісаць файл - Файл з такім імем ужо дададзены ў чаргу спампоўвання + Файл з такой назвай ужо ў чарзе спампоўвання Праграма NewPipe была закрыта падчас працы з файлам На прыладзе скончылася вольнае месца Прагрэс страчаны, бо файл быў выдалены @@ -542,11 +542,11 @@ Апавяшчэнні пра ход відэахэшавання Стварыць паведамленне пра памылку Выберыце падпіскі - Імпарт ці экспарт падпісак з 3-кропкавага меню + Імпартуйце або экспартуйце падпіскі праз меню з трыма кропкамі ⁝ Забарона вылучэння тэксту ў апісанні Хуткі рэжым Калі ў вас узніклі праблемы з выкарыстаннем праграмы, абавязкова азнаёмцеся з адказамі на частыя пытанні! - Адключыць тунэляванне медыя + Адключыць тунэляванне мультымедыя Мініяцюра з перадпраглядам у паласе перамотвання Высокая якасць (больш) Не паказваць @@ -607,15 +607,15 @@ Дублікат дададзены %d раз(ы) LeakCanary недаступны Паказаць уцечкі памяці - Адключыце мультымедыйнае тунэляванне, калі ў вас з\'яўляецца чорны экран або заіканне падчас прайгравання відэа. + Адключыце тунэляванне мультымедыя, калі відэа прайграецца перарывіста або паказваецца чорны экран. Не ўдалося скапіяваць у буфер абмену Папка спампоўвання яшчэ не зададзена, выберыце папку спампоўвання цяпер Частыя пытанні Перайсці на вэб-сайт - Правядзіце пальцам па элементах, каб выдаліць іх + Каб выдаліць элемент, змахніце яго ўбок Прыбраць пастаянную мініяцюру - Паказваць індыкатары выяў - Паказваць каляровыя стужкі Пікаса на выявах, якія пазначаюць іх крыніцу: чырвоная для сеткі, сіняя для дыска і зялёная для памяці + Паказваць на відарысах указальнікі + Паказваць на відарысах каляровыя меткі Picasso, якія абазначаюць яго крыніцу: чырвоная — сетка, сіняя — дыск, зялёная — памяць Апрацоўка стужкі… Пры кожным спампоўванні вам будзе прапанавана выбраць месца захавання Загрузка канала… @@ -641,10 +641,10 @@ %d выбраных %d выбраных - Пустая назва групы - Выдаліць гэту групу? + Назва групы пустая + Выдаліць групу? Новая - Паказаць толькі разгрупаваныя падпіскі + Паказваць толькі не згрупаваныя падпіскі Запланаваныя Паказваць «Збой плэера» Запусціце праверку новых патокаў @@ -715,7 +715,7 @@ Даступна для некаторых сэрвісаў, звычайна значна хутчэй, але можа перадаваць абмежаваную колькасць элементаў і не ўсю інфармацыю (можа адсутнічаць працягласць, тып элемента, паказчык трансляцыі) Узроставае абмежаванне Для гэтага дзеяння не знойдзены прыдатны файлавы менеджар. \nУсталюйце файлавы менеджар, сумяшчальны з Storage Access Framework - Ніякая праграма на вашай прыладзе не можа адкрыць гэта + На прыладзе няма праграмы, каб адкрыць гэты файл Стандартнае значэнне ExoPlayer Прагледжаныя часткова Лічыце, што загрузка каналаў адбываецца занадта павольна? Калі так, паспрабуйце ўключыць хуткую загрузку (можна змяніць у наладах або націснуўшы кнопку ніжэй). \n \nNewPipe прапануе два спосабы загрузкі каналаў: \n• Атрыманне ўсяго канала падпіскі. Павольны, але інфармацыя поўная). \n• Выкарыстанне спецыяльнай канчатковай кропкі абслугоўвання. Хуткі, але звычайна інфармацыя няпоўная). \n \nРозніца паміж імі ў тым, што ў хуткім звычайна адсутнічае частка інфармацыі, напрыклад, працягласць або тып (немагчыма адрозніць трансляцыі ад звычайных відэа), і ён можа вяртаць менш элементаў. \n \nYouTube з\'яўляецца прыкладам сэрвісу, які прапануе гэты хуткі метад праз RSS-канал. \n \nТакім чынам, выбар залежыць ад таго, чаму вы аддаяце перавагу: хуткасці або дакладнасці інфармацыя. @@ -747,8 +747,8 @@ У гэтым патоку ўжо павінна быць гукавая дарожка Уключыце гэту опцыю, калі ў вас ёсць праблемы з ініцыялізацыяй дэкодэра, якая вяртаецца да дэкодэраў з больш нізкім прыярытэтам, калі ініцыялізацыя асноўных дэкодэраў не ўдаецца. Гэта можа прывесці да нізкай прадукцыйнасці прайгравання, чым пры выкарыстанні асноўных дэкодэраў Кіраванне некаторымі наладамі ExoPlayer. Каб гэтыя змены ўступілі ў сілу, патрабуецца перазапуск прайгравальніка - Гэты абыходны шлях вызваляе і паўторна стварае відэакодэкі, калі адбываецца змяненне паверхні, замест таго, каб зажаваць паверхню непасрэдна для кодэка. Ужо выкарыстоўваецца ExoPlayer на некаторых прыладах з такой праблемай, гэты параметр ужываецца толькі на прыладах з Android 6 і вышэй\n\nУключэнне параметра можа прадухіліць памылкі прайгравання пры пераключэнні бягучага відэаплэера або пераключэнні ў поўнаэкранны рэжым - Якасць выяў + Гэты абыходны шлях вызваляе і паўторна стварае відэакодэкі, калі адбываецца змяненне паверхні, замест таго, каб задаваць паверхню непасрэдна для кодэка. Ужо выкарыстоўваецца ExoPlayer на некаторых прыладах з такой праблемай, гэты параметр ужываецца толькі на прыладах з Android 6 і вышэй\n\nУключэнне параметра можа прадухіліць памылкі прайгравання пры пераключэнні бягучага відэаплэера або пераключэнні ў поўнаэкранны рэжым + Якасць відарысаў Відэа \? Падпісчыкі @@ -767,12 +767,12 @@ Атрыманне ўкладак канала Аватары Наступны паток - Прадвызначана на вашай прыладзе адключана медыятунэляванне, бо гэтая мадэль прылады яго не падтрымлівае. + Прадвызначана на вашай прыладзе адключана тунэляванне мультымедыя, бо вядома, што гэта мадэль яго не падтрымлівае. Аватары падканалаў Адкрыць чаргу прайгравання - Не загружаць выявы + Не загружаць відарысы Высокая якасць - Аб канале + Пра канал Абагуліць плэй-ліст Пераматаць наперад Альбомы @@ -786,9 +786,9 @@ - %1$s: %2$s Перамясціць панэль укладак уніз Няма жывых трансляцый - Выберыце якасць выяў і ці трэба спампоўваць выявы ўвогуле, каб паменшыць выкарыстанне даных і памяці. Змены ачышчаюць кэш выяў як у памяці, так і на дыску - %s + Выберыце якасць відарысаў ці ўвогуле не загружаць відарысы, каб паменшыць выкарыстанне даных і памяці. Змены ачышчаюць кэш відарысаў у памяці і на дыску (%s) Прайграць - Іншыя опцыі + Іншыя параметры Мініяцюры Трэкі Працягласць @@ -807,7 +807,7 @@ Каб адрэдагаваць кожнае з дзеянняў у апавяшчэнні, націсніце на яго. Першыя тры дзеянні (прайграванне/паўза, папярэдні і наступны) зададзены сістэмай, іх змяніць немагчыма. Недастаткова вольнага месца на прыладзе Так - NewPipe можа аўтаматычна правяраць наяўнасць абнаўленняў і паведаміць вам, калі яны будуць даступны. \nУключыць гэту функцыю? + NewPipe можа час ад часу аўтаматычна правяраць наяўнасць новай версіі і апавяшчаць, калі яна будзе даступна. \nУключыць гэту функцыю? Налады ў імпартаваным экспарце выкарыстоўваюць уразлівы фармат, які састарэў з версіі NewPipe 0.27.0. Пераканайцеся, што імпартаваны экспарт атрыманы з надзейнай крыніцы, і ў будучыні пераважней выкарыстоўваць толькі экспарт, атрыманы з NewPipe 0.27.0 ці навей. Падтрымка імпарту налад у гэтым уразлівым фармаце хутка будзе цалкам выдаленая, і тады старыя версіі NewPipe больш не змогуць імпартаваць наладкі з экспарту з новых версій. Не Рэзервовае капіяванне і аднаўленне @@ -820,4 +820,7 @@ Выберыце групу каналаў Група каналаў яшчэ не створана Старонка групы каналаў + Пошук %1$s + Пошук %1$s (%2$s) + Спадабалася diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index c6d4d76ce..0d83f6c0c 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -229,7 +229,7 @@ Съдържание на главната страница Празна страница Страница-павилион - Страница на определен канал + Страница на канал Изберете канал За момента нямате абонаменти Изберете павилион @@ -817,4 +817,6 @@ Търсене %1$s Търсене %1$s (%2$s) Харесвания + Страница SoundCloud Top 50 е премахната + SoundCloud преустанови оригиналните класации Топ 50. Съответният раздел е премахнат от главната ви страница. diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index ea531408f..c1f23457d 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -57,7 +57,7 @@ Jméno souboru Vlákna Zastavit - Smazat + Odstranit Start Zkusit znovu Video @@ -234,8 +234,8 @@ Přidat do playlistu Nastavit jako náhled playlistu Přidat playlist do záložek - Smazat záložku - Smazat tento playlist\? + Odstranit záložku + Odstranit tento playlist? Playlist vytvořen V playlistu Náhled playlistu změněn. @@ -411,9 +411,9 @@ Zobrazit pozici přehrávání v seznamech Pozice playbacku smazány Timeout spojení - Smazat pozice playbacku - Smazat všechny pozice playbacku - Smazat všechny pozice playbacku\? + Vymazat pozice přehrávání + Vymaže všechny pozice přehrávání + Vymazat všechny pozice přehrávání? Přepnout službu, právě vybráno: Nikdo nesleduje @@ -444,8 +444,8 @@ obnovuji Toto stahování nelze obnovit Vyberte instanci - Smazat historii stahování - Smazat stažené soubory + Vymazat historii stahování + Odstranit stažené soubory Souhlasit se zobrazením přes jiné aplikace Jazyk aplikace Jazyk systému @@ -488,7 +488,7 @@ %d vybráno Prázdné jméno skupiny - Přejete si smazat tuto skupinu\? + Přejete si odstranit tuto skupinu? Nová Novinky Limit aktualizace novinek @@ -689,7 +689,7 @@ Frekvence kontroly Jakákoli síť Požadované síťové připojení - Smazat všechny stažené soubory z disku\? + Odstranit všechny stažené soubory z disku? Objednali jste si nyní tento kanál Všechny přepnout Nové streamy @@ -846,4 +846,6 @@ Hledat %1$s Hledat %1$s (%2$s) Líbí se + Stránka SoundCloud Top 50 odstraněna + SoundCloud zrušil původní žebříčky Top 50. Příslušná karta byla odstraněna z vaší hlavní stránky. diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 309709f47..1f06121a8 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -829,4 +829,9 @@ Eine Feed-Gruppe auswählen Kanalgruppen-Seite Es wurde noch keine Feed-Gruppe erstellt + Suche %1$s + Suche %1$s (%2$s) + Gefällt mir + SoundCloud-Top-50-Seite entfernt + SoundCloud hat die ursprünglichen Top-50-Charts abgeschafft. Der entsprechende Tab wurde von deiner Hauptseite entfernt. diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 67a24bd4f..84da93a0f 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -829,4 +829,9 @@ Επιλογή ομάδας τροφοδοσίας Δεν δημιουργήθηκε ομάδα τροφοδοσίας ακόμα Σελίδα καναλιού ομάδας + Αναζήτηση %1$s + Αναζήτηση %1$s (%2$s) + Likes + Η σελίδα των SoundCloud Top 50 αφαιρέθηκε + Το SoundCloud έχει καταργήσει τα αρχικά charts με τα Top 50. Η αντίστοιχη καρτέλα έχει αφαιρεθεί από την κύρια σελίδα σας. diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index 9f9c7207c..af8cfde88 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -217,7 +217,7 @@ Enim esitatud Avalehe sisu Tühi leht - Kioski leht + Kioskivaade Kanali leht Vali kanal Kanaleid pole veel tellitud @@ -817,4 +817,6 @@ Otsi: %1$s Otsi: %1$s (%2$s) Meeldimisi + SoundCloudi „Top 50“ leht on eemaldatud + SoundCloud on lõpetanud oma algse „Top 50“ edetabeli pidamise. Seega on ka vastav vahekaart meie rakenduse põhivaatest eemaldatud. diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index c3fe5cf58..9a9590a07 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -164,7 +164,7 @@ Caractères spéciaux Voulez-vous supprimer cet élément de l’historique de recherche \? Contenu de la page principale - Page vide + Page blanche Chaîne Sélectionner une chaîne Tendances @@ -848,4 +848,6 @@ Rechercher %1$s Rechercher %1$s (%2$s) Likes + Page SoundCloud Top 50 supprimée + SoundCloud a abandonné le classement original du Top 50. L\'onglet correspondant a été supprimé de votre page d\'accueil. diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index bd560f07b..a09c0da03 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -179,9 +179,9 @@ היסטוריה למחוק את הפריט הזה מהיסטוריית החיפושים\? תוכן הדף הראשי - דף ריק - דף גישה מזדמנת - דף ערוצים + עמוד ריק + עמוד גישה מזדמנת + עמוד הערוץ נא לבחור ערוץ אין עדיין מינויים לערוצים נא לבחור סוג גישה מזדמנת diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 37282a0da..7d405bcef 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -824,4 +824,12 @@ बैकअप और रिस्टोर आयात किए जा रहे निर्यात में सेटिंग्स एक कमजोर प्रारूप का उपयोग करती हैं जिसे न्यूपाइप 0.27.0 के बाद से हटा दिया गया था। सुनिश्चित करें कि आयात किया जा रहा निर्यात किसी विश्वसनीय स्रोत से है, और भविष्य में केवल न्यूपाइप 0.27.0 या नए से प्राप्त निर्यात का उपयोग करना पसंद करें। इस असुरक्षित प्रारूप में सेटिंग्स आयात करने के लिए समर्थन जल्द ही पूरी तरह से हटा दिया जाएगा, और फिर न्यूपाइप के पुराने संस्करण अब नए संस्करणों से निर्यात की सेटिंग्स आयात नहीं कर पाएंगे। सेकेंडरी + %1$s खोजें + %1$s (%2$s) खोजें + प्लेलिस्ट + कृपया एक फ़ीड समूह चुनें + अभी तक कोई फ़ीड समूह नहीं बनाया गया है + चैनल समूह पेज + पसंद + यूट्यूब अस्थायी प्लेलिस्ट के रूप में साझा करें diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 14c55b772..eb60e377f 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -803,4 +803,6 @@ Keresés %1$s Keresés %1$s (%2$s) Kedvelések + SoundCloud Top 50 oldal eltávolítva + A SoundCloud megszüntette az eredeti Top 50-es listákat. A megfelelő lap el lett távolítva a főoldalról. diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 19f867d7c..b640a1232 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -193,8 +193,8 @@ Terakhir Diputar Sering Diputar Konten halaman utama - Halaman Kosong - Halaman Kedai + Halaman kosong + Halaman kiosk Halaman saluran Pilih saluran Belum ada saluran langganan @@ -815,4 +815,9 @@ Halaman grup saluran Belum ada grup umpan yang dibuat Pilih grup umpan + Cari %1$s + Cari %1$s (%2$s) + Suka + Halaman Top 50 SoundCloud dihapus + SoundCloud telah menghentikan dukungan tangga lagu Top 50. Tab terkait telah dihapus dari halaman utama Anda. diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index e7ce69e41..bc85f0e06 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -805,4 +805,12 @@ auka Deila sem YouTube-bráðabirgðaspilunarlista Spilunarlistar + Leita í %1$s + Leita í %1$s (%2$s) + Veldu hóp streyma + Enginn hópur streyma útbúinn ennþá + Síða rásahóps + Líkar við + Topp 50 síða SoundCloud fjarlægð + SoundCloud er hætt með Topp 50 vinsældalistann. Viðkomandi flipi hefur verið fjarlægður af aðalsíðunni þinni. diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 4c087f4de..d98875630 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -846,4 +846,6 @@ Cerca %1$s (%2$s) Cerca su %1$s Mi piace + Pagina Top 50 di SoundCloud rimossa + SoundCloud ha dismesso i grafici Top 50 originali. La scheda relativa è stata rimossa dalla pagina principale. diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index 1d3183b10..ff3f9b687 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -721,4 +721,4 @@ Изберете гестикулација за десната половина од екранот на плеерот Видеата нема да започнат со емитување во миниплеерот, туку директно ќе се вклучат на цел екран, доколку автоматското ротирање е заклучено. Сѐ уште можете да добиете пристап до миниплеерот, кога ќе излезете од целиот екран URL адресата не може да биде распознаена. Да се отвори со друга апликација? - \ No newline at end of file + diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index ad14e7d05..757632994 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -84,7 +84,7 @@ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲ ਰਿਹਾ ਹੈ ਪੌਪ-ਅਪ ਮੋਡ ਵਿੱਚ ਚੱਲ ਰਿਹਾ ਹੈ ਸਮੱਗਰੀ - ਉਮਰ-ਮੁਤਾਬਕ-ਪਾਬੰਦੀਸ਼ੁਦਾ ਸਮੱਗਰੀ ਵਿਖਾਓ + ਉਮਰ ਮੁਤਾਬਕ ਪਾਬੰਦੀਸ਼ੁਦਾ ਸਮੱਗਰੀ ਵਿਖਾਓ ਲਾਈਵ ਡਾਊਨਲੋਡਸ ਡਾਊਨਲੋਡਸ @@ -824,6 +824,12 @@ ਨਹੀਂ ਇੰਪੋਰਟ ਕੀਤੇ ਜਾ ਰਹੇ ਐਕਸਪੋਰਟ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਇੱਕ ਕਮਜ਼ੋਰ ਫਾਰਮੈਟ ਦੀ ਵਰਤੋਂ ਕਰਦੀਆਂ ਹਨ ਜੋ ਨਿਊਪਾਈਪ 0.27.0 ਤੋਂ ਬਰਤਰਫ਼ ਕੀਤਾ ਗਿਆ ਸੀ। ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਇੰਪੋਰਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਨਿਰਯਾਤ ਇੱਕ ਭਰੋਸੇਯੋਗ ਸਰੋਤ ਤੋਂ ਹੈ, ਅਤੇ ਸਿਰਫ਼ ਨਿਊਪਾਈਪ 0.27.0 ਜਾਂ ਇਸਤੋਂ ਨਵੇਂ ਤੋਂ ਪ੍ਰਾਪਤ ਕੀਤੇ ਐਕਸਪੋਰਟ ਦੀ ਵਰਤੋਂ ਕਰਨ ਨੂੰ ਤਰਜੀਹ ਦਿਓ। ਇਸ ਕਮਜ਼ੋਰ ਫਾਰਮੈਟ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਨੂੰ ਆਯਾਤ ਕਰਨ ਲਈ ਸਮਰਥਨ ਜਲਦੀ ਹੀ ਪੂਰੀ ਤਰ੍ਹਾਂ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ ਅਤੇ ਫਿਰ ਨਿਊਪਾਈਪ ਦੇ ਪੁਰਾਣੇ ਸੰਸਕਰਣ ਹੁਣ ਨਵੇਂ ਸੰਸਕਰਣਾਂ ਤੋਂ ਐਕਸਪੋਰਟ ਦੀਆਂ ਸੈਟਿੰਗਾਂ ਨੂੰ ਇੰਪੋਰਟ ਕਰਨ ਦੇ ਯੋਗ ਨਹੀਂ ਹੋਣਗੇ। ਸੈਕੰਡਰੀ - ਟੈਂਪਰੇਰੀ ਯੂਟਿਊਬ ਪਲੇਲਿਸਟ ਵੱਜੋਂ ਸ਼ੇਅਰ ਕਰੋ + ਅਸਥਾਈ ਯੂਟਿਊਬ ਪਲੇਲਿਸਟ ਵਜੋਂ ਸਾਂਝਾ ਕਰੋ ਪਲੇਲਿਸਟਾਂ + %1$s ਦੀ ਖੋਜ ਕਰੋ + %1$s (%2$s) ٪1$s ਦੀ ਖੋਜ ਕਰੋ + ਫੀਡ ਗਰੁੱਪ ਚੁਣੋ + ਅਜੇ ਤੱਕ ਕੋਈ ਫੀਡ ਗਰੁੱਪ ਨਹੀਂ ਬਣਾਇਆ ਗਿਆ + ਚੈਨਲ ਗਰੁੱਪ ਪੰਨਾ + ਪਸੰਦ diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index dc3f88cec..a0c68f942 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -855,4 +855,6 @@ Szukaj %1$s Szukaj %1$s (%2$s) Polubienia + Usunięto stronę SoundCloud 50 najlepszych + SoundCloud wycofał oryginalną listę 50 najlepszych. Odpowiadająca karta została usunięta ze strony głównej. diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index d13cbcfe3..56731cb06 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -843,4 +843,9 @@ Selecione um grupo de feeds Nenhum grupo de feeds criado ainda Página do grupo do canal + Pesquisar %1$s + Pesquisar %1$s (%2$s) + Curtidas + Página Top 50 do SoundCloud removida + O SoundCloud descontinuou as paradas originais do Top 50. A aba correspondente foi removida da sua página principal. diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 6ceec006e..f670aa52e 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -843,4 +843,6 @@ Selecione um grupo de feeds Ainda nenhum grupo de feeds criado Página do grupo do canal + Pesquisar %1$s + Pesquisar %1$s (%2$s) diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 13a536895..72c6b62da 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -843,4 +843,6 @@ Selecione um grupo de feeds Ainda nenhum grupo de feeds criado Página do grupo do canal + Pesquisar %1$s + Pesquisar %1$s (%2$s) diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index eb4e75c28..cda82bd25 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -164,9 +164,9 @@ Istoric Doriți să ștergeți acest element din istoricul de căutare? Conținutul pagini principale - Pagină Goală + Pagină goală Pagina de chioșc - Pagină Canale + Pagină canale Alegeți un canal Nu v-ați abonat la niciun canal deocamdată Alegeți un chioșc @@ -841,4 +841,11 @@ Distribuie ca listă de redare temporară YouTube Liste de redare Pagina grupului de canale + Caută: %1$s + Caută %1$s (%2$s) + Selectează un grup de fluxuri + Încă nu a fost creat niciun grup de fluxuri + Aprecieri + Pagina SoundCloud Top 50 a fost eliminată + SoundCloud a eliminat Top 50. Fila corespunzătoare a fost eliminată din pagina principală. diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index a512b6fa8..8b54adaad 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -848,4 +848,9 @@ Страница группы каналов Выберите группу кормов Группа кормов еще не создана + Поиск %1$s + Поиск %1$s (%2$s) + Лайки + Страница SoundCloud Top 50 удалена + SoundCloud прекратил поддерживать оригинальные чарты Top 50. Соответствующая вкладка была удалена с вашей главной страницы. diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index ad2dacfd6..3bae642c7 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -13,12 +13,12 @@ Zdieľať s Použiť externý prehrávač videa Použiť externý prehrávač zvuku - Prevzaté video ukladať do - Prevzaté video súbory sú uložené tu + Adresár stiahnutých videí + Stiahnuté video súbory sú uložené tu Vyberte priečinok pre stiahnuté video Priečinok pre stiahnuté audio Vyberte priečinok pre audio súbory - Prevzaté zvukové súbory sú uložené tu + Stiahnuté zvukové súbory sú uložené tu Štandardné rozlíšenie Prehrať cez Kodi Nainštalovať chýbajúcu aplikáciu Kore\? @@ -74,8 +74,8 @@ Čakajte prosím… Skopírované do schránky Priečinok na sťahovanie zadefinujte prosím neskôr v nastaveniach - Prevzaté - Prevzaté + Sťahované súbory + Stiahnuté Hlásenie o chybe Aplikácia/UP zlyhalo Čo:\\nPožiadavka:\\nJazyk obsahu:\\nKrajina Obsahu:\\nJazyk Aplikácie:\\nSlužba:\\nČas v GMT:\\nBalík:\\nVerzia:\\nOS: @@ -165,7 +165,7 @@ Nebol nájdený žiadny prehrávač pre stream (môžete si nainštalovať napr. VLC). Stiahnuť súbor streamu Zobraziť info - Uložené zoznamy + Uložené playlisty Pridať do Zobrazovať tip \"Pridať podržaním\" Zobrazí tip pri stlačení tlačidiel pozadia alebo vyskakovacieho okna videa \"Podrobnosti:\" @@ -179,8 +179,8 @@ Prepnúť na Video Importovať databázu Exportovať databázu - Prepíše aktuálnu históriu, odbery, zoznamy skladieb a (voliteľne) nastavenia - Exportuje históriu, odbery, zoznamy skladieb a nastavenia + Prepíše aktuálnu históriu, odbery, playlisty a (voliteľne) nastavenia + Exportuje históriu, odbery, playlisty a nastavenia Nepodarilo sa prehrať tento stream Pri prehrávaní došlo k chybe a nemožno pokračovať Zotavovanie po chybe v prehrávaní @@ -200,7 +200,7 @@ Naposledy prehrávané Najprehrávanejšie Obsah na hlavnej stránke - Prázdna strana + Prázdna stránka Kiosk Kanál Vyberte si kanál @@ -228,17 +228,17 @@ Vždy sa opýtať Získavajú sa informácie… Načítanie požadované obsahu - Nový zoznam skladieb + Nový playlist Premenovať Názov - Pridať do zoznamu skladieb - Nastaviť ako miniatúru zoznamu skladieb - Záložka zoznamu skladieb - Odstrániť Záložku - Odstrániť tento zoznam skladieb\? - Zoznam skladieb vytvorený + Pridať do playlistu + Nastaviť ako miniatúru playlistu + Pridať playlist medzi záložky + Odstrániť záložku + Odstrániť tento playlist? + Playlist bol vytvorený V playliste - Miniatúra zoznamu skladieb bola zmenená. + Miniatúra playlistu bola zmenená. Bez titulkov Prispôsobiť Vyplniť @@ -321,7 +321,7 @@ Bez limitu Limitovať rozlíšenie pri použití mobilných dát Kanály - Zoznamy skladieb + Playlisty Skladby Používatelia Pretáčať tiché pasáže @@ -513,8 +513,7 @@ \n \nMožno v budúcnosti sa to zmení. Áno aj čiastočne pozreté videá - Pozreté videá, ktoré ste pozreli pred a po ich pridaní do zoznamu, budú odstránené. -\nSte si istí ich odstránením zo zoznamu\? Táto operácia je nezvratná! + Pozreté videá, ktoré ste pozreli pred a po ich pridaní do playlistu, budú odstránené. \nSte si istí ich odstránením z playlistu? Táto operácia je nezvratná! Odstrániť pozreté videá\? Odstrániť pozreté Pôvodné texty zo služieb budú viditeľné v položkách streamu @@ -534,14 +533,14 @@ Nahlásiť na GitHub-e Kopírovať formátované hlásenie Zobrazujú sa výsledky pre: %s - Zoznamy skladieb + Zoznam playlistov Zobraziť iba nezoskupené odbery Nikdy Iba na WiFi Spustí automatické prehrávanie - %s Prehrať zoznam - Zatiaľ bez záložiek zoznamu - Vyberte zoznam skladieb + Žiadne záložky playlistov + Vyberte playlist Skontrolujte prosím, či rovnaká chyba už nie je nahlásená. Vytváranie duplicitných hlásení komplikuje prácu vývojárov. Nemožno rozpoznať URL. Otvoriť pomocou inej aplikácie\? Automatický rad @@ -722,7 +721,7 @@ Ak máte problémy s používaním aplikácie, určite si prečítajte tieto odpovede na časté otázky! Vypnutie trvalého náhľadu Kopírovanie do schránky zlyhalo - Zoznamy zobrazené šedou farbou už obsahujú danú položku. + Playlisty zobrazené šedou farbou už obsahujú danú položku. Karta Dotykom stiahnite %s Duplikát bol pridaný %d-krát @@ -749,7 +748,7 @@ Preferovať prehrávanie popisu Zvuk: %s Zvuková stopa - Chcete odstrániť všetky duplikátne streamy z tohoto zoznamu\? + Chcete odstrániť všetky duplikátne streamy z tohoto playlistu? Zobrazovať nasledovné streamy V tomto streame by už mala byť prítomná zvuková stopa Výber zvukovej stopy pre externé prehrávače @@ -788,7 +787,7 @@ Dozadu Opäť prehrať Karty, ktoré sa majú načítať pri aktualizácii informačného kanála. Táto možnosť nemá žiadny účinok, ak je kanál aktualizovaný pomocou rýchleho režimu. - Zoznamy skladieb + Playlisty Presunie výber hlavnej karty do spodnej časti Žiadne živé prenosy Prehrať @@ -846,4 +845,6 @@ Hľadať %1$s (%2$s) Hľadať %1$s Páči sa + SoundCloud Top 50 stránka odstránená + SoundCloud prestal používať pôvodnú Top 50. Daná stránka bola odstránená z hlavnej stránky. diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index cd41b43ba..68875fe23 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -459,4 +459,4 @@ Označi kot že ogledano Uporabite hitro nenatančno iskanje Sesuj predvajalnik - \ No newline at end of file + diff --git a/app/src/main/res/values-ti/strings.xml b/app/src/main/res/values-ti/strings.xml index c6edbe4c3..e1f61b7d1 100644 --- a/app/src/main/res/values-ti/strings.xml +++ b/app/src/main/res/values-ti/strings.xml @@ -4,7 +4,7 @@ ኣብ መርበብ-ሓበሬታ ክፉት ውጽኢት ናይ፦ %s ንኽትጅምር ነቲ ምድላይ ምልክት ጠውቆ። - ኣብ %1$s ዝተሓትመ + ዝተሓትመሉ ዕለት %1$s ናይ ዥረት ተጻዋታይ ኣይተረኽበን። VLC ኣውርድ፧ ሐራይ ቅጥዕታት @@ -26,7 +26,7 @@ ሰዓበ ናይ ደገ ቪድዮ ተጠቐም መጻወቲ ምውራድ - ኣይትጽንበሩ + ምስዓብ ኣቋርጽ ነቲ ኣብ\'ቲ ምልክታ ዝተርኣየ ናይ ቪድዮ ምስሊ ካብ 16:9 ናብ 1:1 ርሕቐት ኣቀራርባ ቅረጽ ምስ Kodi ተጻወት ድምር ምስ @@ -43,7 +43,7 @@ ናይ ደገ ድምጺ መጻወቲ ተጠቐም Android ሕብሪ ናይቲ መተሓሳሰቢ ብመሰረት እቲ ኣብቲ ንእሽቶ ስእሊ ዘሎ ቀንዲ ሕብሪ ከም ዝጥዕሞ ግበር (እዚ ኣብ ኩሉ መሳርሒታት ከምዘይርከብ ኣስተውዕል) ትሑዝ ፖፕኣፕ ድንቀት - ነፍሲ ወከፍ መፍለጢ ተግባር ኣብ ታሕቲ ብምጥዋቕ ኣርትዖ። ኣብቲ ውህሉል መተሓሳሰቢ ንኽርአ ክሳብ ሰለስተ ካብኣቶም ምረጽ፡ ኣብ የማናይ ሸነኽ ዘሎ ሳጹናት ብምጥቃም + ነፍሲ ወከፍ መፍለጢ ተግባር ኣብ ታሕቲ ብምጥዋቕ ኣርትዖ። ኣብቲ ውህሉል መተሓሳሰቢ ንኽርአ ክሳብ ሰለስተ ካብኣቶም ምረጽ፡ ኣብ የማናይ ሸነኽ ዘሎ ሳጹናት ብምጥቃም። ፖፕኣፕ ትሑዝ ድንቀት ዝወረዱ ናይ ተንቃሳቀሴ-ምስሌ ፋይላት ኣብዚ ይኽዘኑ @@ -56,7 +56,7 @@ ናይ ድምጺ ፋይል ኣራግፍ ምረጽ ዝጎደለ ኮረ ኣፕፕ ኣውራድ፧ ነባሪ ቅርጺ ድምጺ - ምዝገባ + እትስዕቦም Kodi ሚድያ ማእኸል ቪድዮ ንምጽዋት ዝሕግዝ ኣማራጺ ኣብቲ ውሱን መፍለጢ ንምርኣይ እንተበዝሐ ሰለስተ ተግባራት ክትመርጽ ትኽእል ኢኻ! ተንቃሳቀሴ-ምስሌ ፋይል ኣራግፍ @@ -70,7 +70,7 @@ እወ ኣይፋልን ጸሊም - ቆርበት + ቆርበት ኣርእስቲ ለይታው ቆርበት ናይ ፖፕኣፕ ባህርያት ዘክር ናይ ፖፕኣፕ ዝነበሮ ቦታ ዘክር @@ -88,7 +88,7 @@ ኵሉ መስመርት ዝርዝር-ጸወታ - ቅዳሒት + ቪዶ ተጠቀምቲ ፍጻመታት ደርፍታት diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index a26016f1a..e2774ad39 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -164,9 +164,9 @@ Kurtarılamayan oynatıcı hatası oluştu Oynatıcı hatasından kurtarılıyor Ana sayfanın içeriği - Boş Sayfa - Kiosk Sayfası - Kanal Sayfası + Boş sayfa + Kiosk sayfası + Kanal sayfası Kanal seçin Henüz kanal aboneliği yok Kiosk seçin @@ -830,4 +830,8 @@ Kanal küme sayfası Besleme kümesi oluşturulmadı Beğeni + %1$s İle Ara + %1$s İle Ara (%2$s) + SoundCloud Top 50 sayfası kaldırıldı + SoundCloud, özgün Top 50 listesini artık yayınlamıyor. İlgili sekme ana sayfanızdan kaldırıldı. diff --git a/app/src/main/res/values-tzm/strings.xml b/app/src/main/res/values-tzm/strings.xml index 31d89bdd5..8ef077a9f 100644 --- a/app/src/main/res/values-tzm/strings.xml +++ b/app/src/main/res/values-tzm/strings.xml @@ -178,4 +178,4 @@ Ilbumen Tilgamin n tɣuri Taɣuri tawurmant - \ No newline at end of file + diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 32e03bea0..d548dac3c 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -218,8 +218,8 @@ Відтворювалося найбільше Вміст на головній сторінці Порожня сторінка - Кіоск-сторінка - Канал + Сторінка кіоску + Сторінка каналу Обрати канал Немає підписок на канали Обрати кіоск @@ -849,4 +849,8 @@ Виберіть групу каналів Групу каналів ще не створено Вподобання + Пошук %1$s + Пошук %1$s (%2$s) + Сторінку SoundCloud Top 50 видалено + SoundCloud припинив підтримку оригінальних чартів Топ-50. Відповідну вкладку видалено з вашої головної сторінки. diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 3c9c79457..c63e952f0 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -198,7 +198,7 @@ 是否删除此条搜索历史记录? 主页面的显示内容 空白页 - 『时下流行』页-自定义 + Kiosk 页面 频道页 选择一个频道 尚未订阅频道 @@ -816,4 +816,8 @@ 选择一个订阅源组 尚未创建订阅源组 + 搜索%1$s + 搜索 %1$s (%2$s) + 移除了 SoundCloud Top 50 页面 + SoundCloud 已停止发布原创 Top 50 榜单。相应的标签页已从你的主页移除。 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index b9ca2d3ce..1427ce483 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -816,4 +816,8 @@ 選取 feed 群組 尚未建立 feed 群組 喜歡 + 搜尋 %1$s + 搜尋 %1$s (%2$s) + 已移除 SoundCloud Top 50 頁面 + SoundCloud 已停止原有的 Top 50 排行榜。對應的標籤已從您的首頁移除。 diff --git a/fastlane/metadata/android/ar/changelogs/1005.txt b/fastlane/metadata/android/ar/changelogs/1005.txt new file mode 100644 index 000000000..933c7286a --- /dev/null +++ b/fastlane/metadata/android/ar/changelogs/1005.txt @@ -0,0 +1,17 @@ +جديد +• أضف دعمًا لنظام Android Auto +• السماح لإعداد مجموعات التغذية كعلامات شاشة رئيسية +• [يوتيوب] شارك كقائمة تشغيل مؤقتة +• [SoundCloud] Leges Table Tab + +تحسن +• تلميحات شريط بحث أفضل +• عرض تاريخ التنزيل في التنزيلات +• استخدام Android 13 لكل لغة + +مُثَبَّت +• إصلاح ألوان النص المكسورة في الوضع المظلم +• [youtube] إصلاح قوائم التشغيل لا تحميل أكثر من 100 عنصر +• [youtube] إصلاح مقاطع الفيديو الموصى بها مفقودة +• إصلاح حوادث في عرض قائمة التاريخ +• إصلاح الطوابع الزمنية في ردود التعليقات diff --git a/fastlane/metadata/android/cs/changelogs/1005.txt b/fastlane/metadata/android/cs/changelogs/1005.txt new file mode 100644 index 000000000..2059e43de --- /dev/null +++ b/fastlane/metadata/android/cs/changelogs/1005.txt @@ -0,0 +1,17 @@ +Novinky +• Přidána podpora pro Android Auto. +• Možnost nastavit skupiny kanálů jako záložky na hlavní obrazovce. +• [YouTube] Sdílení jako dočasný seznam skladeb. +• [SoundCloud] Záložka Oblíbené kanály + +Vylepšeno +• Lepší nápověda pro vyhledávací lištu +• Zobrazení data stažení v sekci Stažené soubory +• Použití jazyka Android 13 pro jednotlivé aplikace + +Opraveno +• Oprava chybných barev textu v tmavém režimu +• [YouTube] Oprava seznamů skladeb, které nenačtou více než 100 položek +• [YouTube] Oprava chybějících doporučených videí +• Oprava pádů v zobrazení seznamu historie +• Oprava časových značek v odpovědích na komentáře diff --git a/fastlane/metadata/android/de/changelogs/1005.txt b/fastlane/metadata/android/de/changelogs/1005.txt new file mode 100644 index 000000000..ac9000b65 --- /dev/null +++ b/fastlane/metadata/android/de/changelogs/1005.txt @@ -0,0 +1,17 @@ +Neu +• Android Auto +• Feed-Gruppen als Hauptbildschirm-Tabs +• [YouTube] Teilen als temporäre Wiedergabeliste +• [SoundCloud] Gefällt-Kanal-Tab + +Verbessert +• Bessere Suchleisten-Hinweise +• Anzeige des Downloaddatums +• App-spezifische Spracheinstellungen (Android 13) + +Behoben +• Fehlerhafte Textfarben im dunklen Modus +• [YouTube] Wiedergabelisten laden nicht mehr als 100 Einträge +• [YouTube] Fehlende empfohlene Videos +• Abstürze in der Verlaufslisten-Ansicht +• Zeitstempel in Kommentarantworten diff --git a/fastlane/metadata/android/et/changelogs/1005.txt b/fastlane/metadata/android/et/changelogs/1005.txt new file mode 100644 index 000000000..685803416 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/1005.txt @@ -0,0 +1,17 @@ +Uus +• Android Auto tugi +• Meedivoogude grupid põhivaates +• [YouTube] Jagamine ajutise esitusloendina +• [SoundCloud] Meeldimiste kanali vahekaart + +Täiendatud +• Paremad otsinguvihjed +• Allalaadimise kuupäev vastavas vaates +• Android 13 puhul rakendusekohane keel + +Parandatud +• Tekstivärvid tumedas kujundused +• [YouTube] Esitusloend ei laadinud üle 100 kirje +• [YouTube] Puuduvad videosoovitused +• Ajaloovaate kookujooksmine +• Ajatemplid kommentaaride vastustes diff --git a/fastlane/metadata/android/fr/changelogs/1005.txt b/fastlane/metadata/android/fr/changelogs/1005.txt new file mode 100644 index 000000000..b7e5ff49f --- /dev/null +++ b/fastlane/metadata/android/fr/changelogs/1005.txt @@ -0,0 +1,17 @@ +Nouveau +• Prise en charge d'Android Auto +• Possibilité de définir des groupes de flux comme onglets de l'écran principal +• [YouTube] Partager comme playlist temporaire +• [SoundCloud] Onglet « J'aime » + +Amélioration +• Amélioration des astuces de la barre de recherche +• Affichage de la date de téléchargement dans Téléchargements +• Utilisation de la langue par application d'Android 13 + +Corrigé +• Correction des couleurs de texte défectueuses en mode sombre +• [YouTube] Correction des playlists ne chargeant pas plus de 100 éléments +• [YouTube] Correction des vidéos recommandées manquantes +• Correction des plantages dans la vue Historique +• Correction des horodatages dans les réponses aux commentaires diff --git a/fastlane/metadata/android/hi/changelogs/1005.txt b/fastlane/metadata/android/hi/changelogs/1005.txt new file mode 100644 index 000000000..495894e76 --- /dev/null +++ b/fastlane/metadata/android/hi/changelogs/1005.txt @@ -0,0 +1,17 @@ +नया ++ • Android Auto के लिए समर्थन जोड़ें ++ • फ़ीड समूहों को मुख्य स्क्रीन टैब के रूप में सेट करने की अनुमति दें ++ • [YouTube] अस्थायी प्लेलिस्ट के रूप में साझा करें ++ • [SoundCloud] "पसंद" चैनल टैब जोङी गई + +बेहतर किए ++ • खोज बार संकेत ++ • डाउनलोडस स्क्रीन में डाउनलोड की तारीख दिखाएं ++ • Android 13+ पर प्रति-ऐप भाषा का उपयोग करें + +फिक्स किए ++ • डार्क मोड में पाठ के रंग ठीक करें ++ • [YouTube] 100 से अधिक आइटम लोड नहीं करने वाली प्लेलिस्ट को ठीक करें ++ • [YouTube] अनुपलब्ध अनुशंसित वीडियो को ठीक करें ++ • इतिहास सूची दृश्य में क्रैश ठीक करें ++ • टिप्पणी के उत्तरों में टाइमस्टैम्प को ठीक करें diff --git a/fastlane/metadata/android/hu/changelogs/1005.txt b/fastlane/metadata/android/hu/changelogs/1005.txt new file mode 100644 index 000000000..6d6974391 --- /dev/null +++ b/fastlane/metadata/android/hu/changelogs/1005.txt @@ -0,0 +1,17 @@ +Újdonság +- Android Auto támogatás hozzáadása +- A hírfolyamcsoportok főképernyőfülekként való beállítása +- [YouTube] Megosztás ideiglenes lejátszási listaként +- [SoundCloud] „Kedvelések” csatorna lap + +Továbbfejlesztve +- Jobb keresősáv-súgók +- Letöltési dátum megjelenítése a letöltések között +- Android 13 alkalmazásonkénti nyelv használata + +Javítva +- Törött szövegszínek javítása sötét módban +- [YouTube] A lejátszási listák 100-nál több elemet nem töltöttek be. +- [YouTube] Az ajánlott videók hiányának javítása +- Az előzmények listanézetben bekövetkező összeomlások javítása +- A hozzászólásválaszok időbélyegeinek javítása diff --git a/fastlane/metadata/android/it/changelogs/1005.txt b/fastlane/metadata/android/it/changelogs/1005.txt new file mode 100644 index 000000000..e70610077 --- /dev/null +++ b/fastlane/metadata/android/it/changelogs/1005.txt @@ -0,0 +1,17 @@ +Novità +• Ora NewPipe funziona su Android Auto +• Aggiungi feed di gruppi di canali nella schermata principale +• [YouTube] Condividi come playlist temporanea +• [SoundCloud] Mi piace nei canali + +Migliorie +• Indizi nella barra di ricerca +• Mostrata la data di scaricamento nella relativa sezione +• Uso della possibilità di scegliere la lingua dell'app, funzione nativa di Android 13 + +Correzioni +• Sistemati i colori del testo col tema scuro +• [YouTube] Ora si caricano più di 100 video nelle playlist +• [YouTube] Ripristinati i video consigliati +• Sistemati i crash nella cronologia +* Sistemato un errore nell'orario di inserimento di una risposta nei commenti diff --git a/fastlane/metadata/android/pa/changelogs/1005.txt b/fastlane/metadata/android/pa/changelogs/1005.txt new file mode 100644 index 000000000..f1492a1ac --- /dev/null +++ b/fastlane/metadata/android/pa/changelogs/1005.txt @@ -0,0 +1,17 @@ +ਨਵਾਂ ++ • Android Auto ਲਈ ਸਮਰਥਨ ਸ਼ਾਮਿਲ ਕਰੋ ++ • ਫੀਡ ਗਰੁੱਪਾਂ ਨੂੰ ਮੁੱਖ ਸਕ੍ਰੀਨ ਟੈਬਾਂ ਵਜੋਂ ਸੈੱਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ ++ • [YouTube] ਅਸਥਾਈ ਪਲੇਲਿਸਟ ਦੇ ਵਜੋਂ ਸਾਂਝਾ ਕਰੋ ++ • [SoundCloud] "ਪਸੰਦ" ਚੈਨਲ ਟੈਬ ਜੋੜੀ ਗਈ + +ਬਿਹਤਰ ਕੀਤੇ ++ • ਖੋਜ ਬਾਰ ਸੰਕੇਤ ++ • ਡਾਊਨਲੋਡਸ ਸੂਚੀ ਵਿੱਚ ਡਾਊਨਲੋਡ ਤਾਰੀਖ ਦਿਖਾਓ ++ • ਐਂਡਰਾਇਡ 13+ 'ਤੇ ਪ੍ਰਤੀ ਐਪ ਭਾਸ਼ਾ ਦੀ ਵਰਤੋਂ ਕਰੋ + +ਦਰੁਸਤ ਕੀਤੇ ++ • ਡਾਰਕ ਥੀਮਾਂ 'ਤੇ ਟੈਕਸਟ ਰੰਗਾਂ ਨੂੰ ਠੀਕ ਕਰੋ ++ • [YouTube] ਪਲੇਲਿਸਟਾਂ ਨੂੰ ਠੀਕ ਕਰੋ ਜੋ 100 ਤੋਂ ਵੱਧ ਆਈਟਮਾਂ ਲੋਡ ਨਹੀਂ ਕਰਦੀਆਂ ++ • [YouTube] ਸਿਫਾਰਸ਼ ਕੀਤੀਆਂ ਵੀਡੀਓਜ਼ ਦੀ ਅਣਉਪਲੱਬਧਤਾ ਨੂੰ ਠੀਕ ਕਰੋ ++ • ਇਤਿਹਾਸ ਸੂਚੀ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਕ੍ਰੈਸ਼ ਨੂੰ ਠੀਕ ਕਰੋ ++ • ਟਿੱਪਣੀਆਂ ਦੇ ਜਵਾਬ ਵਿੱਚ ਟਾਈਮਸਟੈਂਪਾਂ ਨੂੰ ਠੀਕ ਕਰੋ diff --git a/fastlane/metadata/android/pl/changelogs/1005.txt b/fastlane/metadata/android/pl/changelogs/1005.txt new file mode 100644 index 000000000..336aa1fa6 --- /dev/null +++ b/fastlane/metadata/android/pl/changelogs/1005.txt @@ -0,0 +1,17 @@ +Nowe +- Obsł. Android Auto +- Opcja ustawiania grup kanałów jako kart ekranu głównego +- [YouTube] Udostęp. jako tymczasowa playlista +- [SoundCloud] Karta kanału polubień + +Ulepszone +- Lepsze podpow. paska wysz. +- Wyśw. daty pobrania w Pobranych +- Używanie języka aplikacji w Androidzie 13 + +Naprawione +- Uszkodzone kolory tekstu w trybie ciemnym +- [YouTube] Playlisty ładujące maks. 100 pozycji +- [YouTube] Brakujące polecane wideo +- Awarie w widoku listy Historii +- Znaczniki czasu w odp. na komentarze diff --git a/fastlane/metadata/android/ru/changelogs/1005.txt b/fastlane/metadata/android/ru/changelogs/1005.txt new file mode 100644 index 000000000..3dead0f05 --- /dev/null +++ b/fastlane/metadata/android/ru/changelogs/1005.txt @@ -0,0 +1,17 @@ +Новое +• Поддержка Android Auto +• Использование групп лент как вкладок главного экрана +• [YouTube] Возможность поделиться временным плейлистом +• [SoundCloud] Вкладка канала "Лайки" + +Улучшено +• Поисковые подсказки +• Показ даты загрузки в Загрузках +• Установка языка для каждого приложения + +Исправлено +• Цвета текста в тёмном режиме +• [YouTube] Плейлисты не загружали более чем 100 элементов +• [YouTube] Отсутствующие рекомендованные видео +• Вылеты в Истории +• Временные метки в ответах на комментарии diff --git a/fastlane/metadata/android/sk/changelogs/1000.txt b/fastlane/metadata/android/sk/changelogs/1000.txt index 61cabd89d..29e2182f4 100644 --- a/fastlane/metadata/android/sk/changelogs/1000.txt +++ b/fastlane/metadata/android/sk/changelogs/1000.txt @@ -1,13 +1,13 @@ Vylepšené -- Umožnené kliknutie na popis playlistu, aby sa zobrazilo viac/menej obsahu -- [PeerTube] Automatické spracovanie odkazov inštancie `subscribeto.me` -- Spustenie prehrávania iba jednej položky v histórii +- Kliknutím na playlist sa zobrazí viac/menej obsahu +- [PeerTube] Automatické spracovanie odkazov z `subscribeto.me` +- Spustiť prehrávanie iba jednej položky v histórii Opravené -- Oprava viditeľnosti tlačidla RSS -- Oprava pádov náhľadu na paneli vyhľadávania -- Oprava pridania položky bez miniatúry do playlistu -- Oprava ukončenia okna sťahovania pred jeho zobrazením -- Oprava vyskakovacieho okna zoznamu súvisiacich položiek -- Oprava poradia v okne pridania do playlistu -- Úprava rozloženia položiek záložiek playlistu +- Viditeľnosť tlačidla RSS +- Pády pri náhľadoch +- Pridanie položky bez miniatúry do playlistu +- Zatváranie okna sťahovania pred jeho zobrazením +- Vyskakovacie okno zoznamu súvisiacich položiek +- Poradie v okne pridania do playlistu +- Rozloženie položiek záložiek playlistu diff --git a/fastlane/metadata/android/sk/changelogs/1005.txt b/fastlane/metadata/android/sk/changelogs/1005.txt new file mode 100644 index 000000000..8f2bfbfab --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/1005.txt @@ -0,0 +1,18 @@ +Novinky +• Pridaná podpora pre Android Auto +• Možnosť nastaviť skupiny kanálov ako hlavné karty na obrazovke +• [YouTube] Zdieľanie ako dočasný playlist + +• [SoundCloud] Karta „Páči sa“ kanál. + +Vylepšenia +• Lepšia nápoveda v paneli vyhľadávania +• Zobrazenie dátumu stiahnutia v sekcii „Stiahnuté” +• Použitie jazyka Android 13 pre jednotlivé aplikácie + +Opravy +• Oprava chybných farieb textu v tmavom režime +• [YouTube] Oprava playlistov, ktoré nenačítavajú viac ako 100 položiek +• [YouTube] Oprava chýbajúcich odporúčaných videí +• Oprava pádov v zobrazení zoznamu histórie +• Oprava časových značiek v odpovediach na komentáre. diff --git a/fastlane/metadata/android/sk/full_description.txt b/fastlane/metadata/android/sk/full_description.txt index 9de86c677..e1483d4fd 100644 --- a/fastlane/metadata/android/sk/full_description.txt +++ b/fastlane/metadata/android/sk/full_description.txt @@ -1 +1 @@ -NewPipe nepoužíva žiadne Google framework knižnice, ani YouTube API rozhranie. Len analyzuje web, aby získal potrebné informácie. Preto je možné túto aplikáciu používať na zariadeniach bez nainštalovaných Google služieb. Taktiež nepotrebujete účet na YouTube. Appka je FLOSS. +NewPipe nepoužíva Google framework knižnice, ani YouTube API rozhranie. Iba spracováva YouTube stránku aby získal potrebné informácie. Túto aplikáciu je teda možné používať na zariadeniach bez nainštalovaných Google služieb. Taktiež nepotrebujete účet na YouTube. Aplikácia je FLOSS. diff --git a/fastlane/metadata/android/ti/full_description.txt b/fastlane/metadata/android/ti/full_description.txt index f0afa90ab..f58ede5da 100644 --- a/fastlane/metadata/android/ti/full_description.txt +++ b/fastlane/metadata/android/ti/full_description.txt @@ -1 +1 @@ -ኒውፓይፕ ዝዀነ ይኹን ናይ ጎልጋል ቤተ-መጻሕፍቲ ወይ ናይ ዩቱብ ኤፒኢ ኣይጥቀምን ኢዩ። ነቲ ወብ ሳይት ዜድልዮ ሓበሬታ ንምርካብ ጥራይ እዩ ዚምርምሮ ። ስለዚ እዚ ኣፕሊኬሽን እዚ ብዘይ ናይ ጎልጋል ሰርቪስ ኣብ ኤለክትሮኒካዊ መሳርሒታት ክትጥቀመሉ ትኽእል ኢኻ ። ኒውፓይፕ ንምጥቃም እውን ናይ ዩቱብ ሕሳብ ኣየድልየካን ኢዩ እዚ ኸኣ FLOSS ኢዩ። +ኒውፓይፕ ዝዀነ ናይ ጉግል ቤተ-ምስሊታት ወይ ናይ ዩቱብ ኤፒኢይ ኣይጥቀምን ኢዩ። ነቲ መርበብ- ስፍራ ዜድልዮ ሓበሬታ ንምርካብ ጥራይ እዩ ዚምርምሮ። ስለዚ እዚ ኣፕሊኬሽን እዚ ብዘይ ናይ ጉግል ኣገልግሎት ኣብ ኤለክትሮኒካዊ-መሳርሒታት ክትጥቀመሉ ትኽእል ኢኻ። ኒውፓይፕ ንምጥቃም ናይ ዩቱብ ሕሳብ ኣየድልየካን ኢዩ፣ ኒውፓይፕ FLOSS ኢዩ። diff --git a/fastlane/metadata/android/ti/short_description.txt b/fastlane/metadata/android/ti/short_description.txt index f7f2099a1..107cabea0 100644 --- a/fastlane/metadata/android/ti/short_description.txt +++ b/fastlane/metadata/android/ti/short_description.txt @@ -1 +1 @@ -ብናጻ ፈኲስ ናይ ዩቱብ ግንባር ንኣንድሮይድ ። +ነጻ ናይ ዩቱብ ግንባር ንኣንድሮይድ። diff --git a/fastlane/metadata/android/uk/changelogs/1002.txt b/fastlane/metadata/android/uk/changelogs/1002.txt index a90cfff6b..f52bf43af 100644 --- a/fastlane/metadata/android/uk/changelogs/1002.txt +++ b/fastlane/metadata/android/uk/changelogs/1002.txt @@ -1 +1,4 @@ -Виправлено проблему невідтворюваності трансляцій YouTube +Виправлено помилку, через яку YouTube не відтворював жодної трансляції. + +У цьому випуску вирішено лише найактуальнішу помилку, яка перешкоджала завантаженню деталей відео YouTube. +Ми знаємо про інші проблеми, і незабаром випустимо окремий випуск для їх вирішення. diff --git a/fastlane/metadata/android/uk/changelogs/1003.txt b/fastlane/metadata/android/uk/changelogs/1003.txt index a90cfff6b..b969e091c 100644 --- a/fastlane/metadata/android/uk/changelogs/1003.txt +++ b/fastlane/metadata/android/uk/changelogs/1003.txt @@ -1 +1,6 @@ -Виправлено проблему невідтворюваності трансляцій YouTube +Це виправлення, яке виправляє помилки YouTube: +• [YouTube] Виправлено не завантаження інформації про відео, виправлено помилки HTTP 403 під час відтворення відео та відновлено відтворення деяких відео з віковими обмеженнями +• Виправлено незмінні розміри субтитрів +• Виправлено подвійне завантаження інформації під час відкриття потоку +• [Soundcloud] Видалено невідтворювані потоки, захищені DRM +• Оновлені переклади diff --git a/fastlane/metadata/android/uk/changelogs/1004.txt b/fastlane/metadata/android/uk/changelogs/1004.txt index a90cfff6b..1c2ec5d7f 100644 --- a/fastlane/metadata/android/uk/changelogs/1004.txt +++ b/fastlane/metadata/android/uk/changelogs/1004.txt @@ -1 +1,3 @@ -Виправлено проблему невідтворюваності трансляцій YouTube +У цьому випуску виправлено помилку, через яку YouTube відтворював лише 360p-потік. + +Зверніть увагу, що рішення, що використовується в цій версії, ймовірно, тимчасове, і в довгостроковій перспективі потрібно буде впровадити відеопротокол SABR, але учасники TeamNewPipe зараз зайняті, тому будь-яка допомога буде дуже вдячна! https://github.com/TeamNewPipe/NewPipe/issues/12248 diff --git a/fastlane/metadata/android/uk/changelogs/1005.txt b/fastlane/metadata/android/uk/changelogs/1005.txt new file mode 100644 index 000000000..474127f95 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/1005.txt @@ -0,0 +1,17 @@ +Нове +• Додано підтримку Android Auto +• Дозволено налаштування груп стрічок як вкладок головного екрана +• [YouTube] Поділитися як тимчасовий список відтворення +• [SoundCloud] Вкладка каналу «Вподобання» + +Покращено +• Кращі підказки в рядку пошуку +• Показувати дату завантаження в розділі «Завантаження» +• Використовувати мову Android 13 для кожної програми + +Виправлено +• Виправлено пошкоджені кольори тексту в темному режимі +• [YouTube] Виправлено списки відтворення, які не завантажували більше 100 елементів +• [YouTube] Виправлено відсутні рекомендовані відео +• Виправлено збої в перегляді історії +• Виправлено позначки часу у відповідях на коментарі diff --git a/fastlane/metadata/android/zh-Hans/changelogs/1001.txt b/fastlane/metadata/android/zh-Hans/changelogs/1001.txt new file mode 100644 index 000000000..cdebebf55 --- /dev/null +++ b/fastlane/metadata/android/zh-Hans/changelogs/1001.txt @@ -0,0 +1,6 @@ +改进 +- 始终允许在 Android 13以上系统上更改播放器通知首选项 + +修复 +- 修复了导出数据库/订阅时不会截断已存在的文件,从而可能导致导出损坏的问题 +- 修复了点击时间戳时,播放器从头开始恢复的问题 From ef29c318b06e5875aacf765c1c1b2adbb5d49b1f Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Tue, 29 Jul 2025 06:18:27 +0530 Subject: [PATCH 16/43] Remove NewApi suppression --- .../newpipe/local/feed/notifications/NotificationWorker.kt | 4 ++-- .../schabi/newpipe/player/notification/NotificationUtil.java | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt index ca48a4243..ad2f1055c 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt @@ -2,6 +2,7 @@ package org.schabi.newpipe.local.feed.notifications import android.content.Context import android.content.pm.ServiceInfo +import android.os.Build import android.util.Log import androidx.core.app.NotificationCompat import androidx.work.Constraints @@ -84,8 +85,7 @@ class NotificationWorker( .setPriority(NotificationCompat.PRIORITY_LOW) .setContentTitle(applicationContext.getString(R.string.feed_notification_loading)) .build() - @Suppress("NewApi") // ServiceInfo constant is inlined - val serviceType = ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC + val serviceType = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC else 0 setForegroundAsync(ForegroundInfo(FeedLoadService.NOTIFICATION_ID, notification, serviceType)) } diff --git a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java index f314f713a..8b7287f56 100644 --- a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java +++ b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java @@ -167,15 +167,16 @@ public final class NotificationUtil { && notificationBuilder.mActions.get(2).actionIntent != null); } - @SuppressLint("NewApi") // ServiceInfo constant is inlined public void createNotificationAndStartForeground() { if (notificationBuilder == null) { notificationBuilder = createNotification(); } updateNotification(); + final int serviceType = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q + ? ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK : 0; ServiceCompat.startForeground(player.getService(), NOTIFICATION_ID, - notificationBuilder.build(), ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK); + notificationBuilder.build(), serviceType); } public void cancelNotificationAndStopForeground() { From e08d2d8726d6eadca78dc7ef06d537598daad6ca Mon Sep 17 00:00:00 2001 From: tobigr Date: Mon, 28 Jul 2025 22:02:16 +0200 Subject: [PATCH 17/43] Add new locals to the in-app language chooser --- app/src/main/res/values/settings_keys.xml | 32 +++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index f98639e04..01a812532 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -1192,6 +1192,8 @@ bn bn-bd bn-in + br + bs ca ckb cs @@ -1207,7 +1209,9 @@ fi fil fr + frc gl + gu he hi hr @@ -1219,23 +1223,31 @@ it ja jv + ka kab kmr + kn ko ku + la lt lv mk ml + mn + mr ms nb-no + nn ne nl nl-be + nqo oc or pa + pa-pk pl pt pt-br @@ -1254,7 +1266,11 @@ ta te th + ti + tl + tok tr + tt tzm uk ur @@ -1277,6 +1293,8 @@ বাংলা বাংলা (বাংলাদেশ) বাংলা (भारत) + Brezhoneg + Босански Català کوردیی سۆرانی Čeština @@ -1292,7 +1310,9 @@ Suomen kieli Wikang Filipino Français + Français (Louisiana) Galego + ગુજરાતી עברית हिन्दी Hrvatski @@ -1304,23 +1324,31 @@ Italiano 日本語 ꦧꦱꦗꦮ + ქართული Taqbaylit Kurmancî + ಕನ್ನಡ 한국어 کوردی + Latina Lietuvių kalba latviski македонски јазик മലയാളം + Монгол хэл + मराठी Bahasa Melayu Norsk bokmål + Norsk Nynorsk Nनेपाली Nederlands (NL) Nederlands (BE) + ߒߞߏ Occitan ଓଡ଼ିଆ ਪੰਜਾਬੀ + ਪੰਜਾਬੀ (PK) Polski Português Português (BR) @@ -1339,7 +1367,11 @@ தமிழ் తెలుగు ไทย + ትግርኛ + Wikang Tagalog + Toki Pona Türkçe + Татар теле Tamaziɣt українська мова اردو From 7130adb4eceaa43d60775190010a81db53ffb264 Mon Sep 17 00:00:00 2001 From: tobigr Date: Mon, 28 Jul 2025 22:02:29 +0200 Subject: [PATCH 18/43] Clean strings --- app/src/main/res/values-tl/strings.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/res/values-tl/strings.xml b/app/src/main/res/values-tl/strings.xml index 02794a620..d41b317e8 100644 --- a/app/src/main/res/values-tl/strings.xml +++ b/app/src/main/res/values-tl/strings.xml @@ -66,5 +66,4 @@ \nBuksan ang \"%1$s\" sa ayos ng app kung gusto mong makita ito. Mga Artista Nakalutang - \ No newline at end of file From ca9fc14c2aab2a49a4cd052136a0009a5a51a19b Mon Sep 17 00:00:00 2001 From: Stypox Date: Tue, 29 Jul 2025 20:18:31 +0200 Subject: [PATCH 19/43] Fix name of nepali language (there was a leftover N) --- app/src/main/res/values/settings_keys.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 01a812532..352e4cec1 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -1340,7 +1340,7 @@ Bahasa Melayu Norsk bokmål Norsk Nynorsk - Nनेपाली + नेपाली Nederlands (NL) Nederlands (BE) From ed93603815df0e58dcff19c72d412abd52444741 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Tue, 22 Jul 2025 00:01:40 +0200 Subject: [PATCH 20/43] WIP: Add SettingsMigration to change YouTube trending kiosk tab --- .../java/org/schabi/newpipe/MainActivity.java | 4 +- .../newpipe/settings/NewPipeSettings.java | 3 +- .../settings/migration/MigrationManager.java | 103 ++++++++++++++ .../{ => migration}/SettingMigrations.java | 128 ++++++++++++------ app/src/main/res/values/strings.xml | 2 + 5 files changed, 192 insertions(+), 48 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/settings/migration/MigrationManager.java rename app/src/main/java/org/schabi/newpipe/settings/{ => migration}/SettingMigrations.java (69%) diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 21f4f97a1..1aae7fa86 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -78,8 +78,8 @@ import org.schabi.newpipe.player.Player; import org.schabi.newpipe.player.event.OnKeyDownListener; import org.schabi.newpipe.player.helper.PlayerHolder; import org.schabi.newpipe.player.playqueue.PlayQueue; -import org.schabi.newpipe.settings.SettingMigrations; import org.schabi.newpipe.settings.UpdateSettingsFragment; +import org.schabi.newpipe.settings.migration.MigrationManager; import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.KioskTranslator; @@ -195,7 +195,7 @@ public class MainActivity extends AppCompatActivity { UpdateSettingsFragment.askForConsentToUpdateChecks(this); } - SettingMigrations.showUserInfoIfPresent(this); + MigrationManager.showUserInfoIfPresent(this); } @Override diff --git a/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java b/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java index 421440ea7..0a5512c69 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java +++ b/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java @@ -13,6 +13,7 @@ import androidx.preference.PreferenceManager; import org.schabi.newpipe.App; import org.schabi.newpipe.R; +import org.schabi.newpipe.settings.migration.MigrationManager; import org.schabi.newpipe.util.DeviceUtils; import java.io.File; @@ -46,7 +47,7 @@ public final class NewPipeSettings { public static void initSettings(final Context context) { // first run migrations, then setDefaultValues, since the latter requires the correct types - SettingMigrations.runMigrationsIfNeeded(context); + MigrationManager.runMigrationsIfNeeded(context); // readAgain is true so that if new settings are added their default value is set PreferenceManager.setDefaultValues(context, R.xml.main_settings, true); diff --git a/app/src/main/java/org/schabi/newpipe/settings/migration/MigrationManager.java b/app/src/main/java/org/schabi/newpipe/settings/migration/MigrationManager.java new file mode 100644 index 000000000..d5b0e783d --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/migration/MigrationManager.java @@ -0,0 +1,103 @@ +package org.schabi.newpipe.settings.migration; + +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.core.util.Consumer; + +import org.schabi.newpipe.R; +import org.schabi.newpipe.error.ErrorUtil; + +import java.util.ArrayList; +import java.util.List; + +/** + * MigrationManager is responsible for running migrations and showing the user information about + * the migrations that were applied. + */ +public final class MigrationManager { + + private static final String TAG = MigrationManager.class.getSimpleName(); + /** + * List of UI actions that are performed after the UI is initialized (e.g. showing alert + * dialogs) to inform the user about changes that were applied by migrations. + */ + private static final List> MIGRATION_INFO = new ArrayList<>(); + + private MigrationManager() { + // MigrationManager is a utility class that is completely static + } + + /** + * Run all migrations that are needed for the current version of NewPipe. + * This method should be called at the start of the application, before any other operations + * that depend on the settings. + * + * @param context Context that can be used to run migrations + */ + public static void runMigrationsIfNeeded(@NonNull final Context context) { + SettingMigrations.runMigrationsIfNeeded(context); + } + + /** + * Perform UI actions informing about migrations that took place if they are present. + * @param context Context that can be used to show dialogs/snackbars/toasts + */ + public static void showUserInfoIfPresent(@NonNull final Context context) { + if (MIGRATION_INFO.isEmpty()) { + return; + } + + try { + MIGRATION_INFO.get(0).accept(context); + } catch (final Exception e) { + ErrorUtil.showUiErrorSnackbar(context, "Showing migration info to the user", e); + // Remove the migration that caused the error and continue with the next one + MIGRATION_INFO.remove(0); + showUserInfoIfPresent(context); + } + } + + /** + * Add a migration info action that will be executed after the UI is initialized. + * This can be used to show dialogs/snackbars/toasts to inform the user about changes that + * were applied by migrations. + * + * @param info the action to be executed + */ + public static void addMigrationInfo(final Consumer info) { + MIGRATION_INFO.add(info); + } + + /** + * This method should be called when the user dismisses the migration info + * to check if there are any more migration info actions to be shown. + * @param context Context that can be used to show dialogs/snackbars/toasts + */ + public static void onMigrationInfoDismissed(@NonNull final Context context) { + MIGRATION_INFO.remove(0); + showUserInfoIfPresent(context); + } + + /** + * Creates a dialog to inform the user about the migration. + * @param uiContext Context that can be used to show dialogs/snackbars/toasts + * @param title the title of the dialog + * @param message the message of the dialog + * @return the dialog that can be shown to the user with a custom dismiss listener + */ + static AlertDialog createMigrationInfoDialog(@NonNull final Context uiContext, + @NonNull final String title, + @NonNull final String message) { + return new AlertDialog.Builder(uiContext) + .setTitle(title) + .setMessage(message) + .setPositiveButton(R.string.ok, null) + .setOnDismissListener(dialog -> + MigrationManager.onMigrationInfoDismissed(uiContext)) + .setCancelable(false) // prevents the dialog from being dismissed accidentally + .create(); + } + +} diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java b/app/src/main/java/org/schabi/newpipe/settings/migration/SettingMigrations.java similarity index 69% rename from app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java rename to app/src/main/java/org/schabi/newpipe/settings/migration/SettingMigrations.java index d13e73090..99af27766 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java +++ b/app/src/main/java/org/schabi/newpipe/settings/migration/SettingMigrations.java @@ -1,11 +1,14 @@ -package org.schabi.newpipe.settings; +package org.schabi.newpipe.settings.migration; + +import static org.schabi.newpipe.MainActivity.DEBUG; +import static org.schabi.newpipe.extractor.ServiceList.SoundCloud; +import static org.schabi.newpipe.extractor.ServiceList.YouTube; import android.content.Context; import android.content.SharedPreferences; import android.util.Log; import androidx.annotation.NonNull; -import androidx.appcompat.app.AlertDialog; import androidx.core.util.Consumer; import androidx.preference.PreferenceManager; @@ -25,27 +28,28 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; -import static org.schabi.newpipe.MainActivity.DEBUG; -import static org.schabi.newpipe.extractor.ServiceList.SoundCloud; - /** - * In order to add a migration, follow these steps, given P is the previous version:
- * - in the class body add a new {@code MIGRATION_P_P+1 = new Migration(P, P+1) { ... }} and put in - * the {@code migrate()} method the code that need to be run when migrating from P to P+1
- * - add {@code MIGRATION_P_P+1} at the end of {@link SettingMigrations#SETTING_MIGRATIONS}
- * - increment {@link SettingMigrations#VERSION}'s value by 1 (so it should become P+1) + * This class contains the code to migrate the settings from one version to another. + * Migrations are run automatically when the app is started and the settings version changed. + *
+ * In order to add a migration, follow these steps, given {@code P} is the previous version: + *
    + *
  • in the class body add a new {@code MIGRATION_P_P+1 = new Migration(P, P+1) { ... }} and put + * in the {@code migrate()} method the code that need to be run + * when migrating from {@code P} to {@code P+1}
  • + *
  • add {@code MIGRATION_P_P+1} at the end of {@link SettingMigrations#SETTING_MIGRATIONS}
  • + *
  • increment {@link SettingMigrations#VERSION}'s value by 1 + * (so it becomes {@code P+1})
  • + *
+ * Migrations can register UI actions using {@link MigrationManager#addMigrationInfo(Consumer)} + * that will be performed after the UI is initialized to inform the user about changes + * that were applied by migrations. */ public final class SettingMigrations { private static final String TAG = SettingMigrations.class.toString(); private static SharedPreferences sp; - /** - * List of UI actions that are performed after the UI is initialized (e.g. showing alert - * dialogs) to inform the user about changes that were applied by migrations. - */ - private static final List> MIGRATION_INFO = new ArrayList<>(); - private static final Migration MIGRATION_0_1 = new Migration(0, 1) { @Override public void migrate(@NonNull final Context context) { @@ -169,16 +173,63 @@ public final class SettingMigrations { && kioskTab.getKioskServiceId() == SoundCloud.getServiceId() && kioskTab.getKioskId().equals("Top 50"))) .collect(Collectors.toUnmodifiableList()); - if (tabs.size() != cleanedTabs.size()) { + if (tabs.size() != cleanedTabs.size() || DEBUG) { // TODO: remove debug condition tabsManager.saveTabs(cleanedTabs); // create an AlertDialog to inform the user about the change - MIGRATION_INFO.add((Context uiContext) -> new AlertDialog.Builder(uiContext) - .setTitle(R.string.migration_info_6_7_title) - .setMessage(R.string.migration_info_6_7_message) - .setPositiveButton(R.string.ok, null) - .setCancelable(false) - .create() - .show()); + MigrationManager.addMigrationInfo(uiContext -> + MigrationManager.createMigrationInfoDialog( + uiContext, + uiContext.getString(R.string.migration_info_6_7_title), + uiContext.getString(R.string.migration_info_6_7_message)) + .show()); + } + } + }; + + private static final Migration MIGRATION_7_8 = new Migration(7, 8) { + @Override + protected void migrate(@NonNull final Context context) { + // YouTube remove the combined Trending kiosk, see + // https://github.com/TeamNewPipe/NewPipe/discussions/12445 for more information. + // If the user has a dedicated YouTube/Trending kiosk tab, + // it is removed and replaced with the new live kiosk tab. + // The default trending kiosk tab is not touched + // because it uses the default kiosk provided by the extractor + // and is thus updated automatically. + final TabsManager tabsManager = TabsManager.getManager(context); + final List tabs = tabsManager.getTabs(); + final boolean hadYtTrendingTab = tabs.stream() + .anyMatch(tab -> !(tab instanceof Tab.KioskTab kioskTab + && kioskTab.getKioskServiceId() == YouTube.getServiceId() + && kioskTab.getKioskId().equals("Trending"))); + if (hadYtTrendingTab) { + final List cleanedTabs = new ArrayList<>(); + for (final Tab tab : tabs) { + if (tab instanceof Tab.KioskTab kioskTab + && kioskTab.getKioskServiceId() == YouTube.getServiceId() + && kioskTab.getKioskId().equals("Trending")) { + // replace the YouTube Trending tab with the new live kiosk tab + // TODO: use the correct kiosk ID for the live kiosk tab + cleanedTabs.add(new Tab.KioskTab(YouTube.getServiceId(), "Live")); + } else { + cleanedTabs.add(tab); + } + } + tabsManager.saveTabs(cleanedTabs); + } + + final boolean hasDefaultTrendingTab = tabs.stream() + .anyMatch(tab -> tab instanceof Tab.DefaultKioskTab); + + // TODO: remove debugging code + if (hadYtTrendingTab || hasDefaultTrendingTab || newVersion == VERSION) { + // User is informed about the change + MigrationManager.addMigrationInfo(uiContext -> + MigrationManager.createMigrationInfoDialog( + uiContext, + uiContext.getString(R.string.migration_info_7_8_title), + uiContext.getString(R.string.migration_info_7_8_message)) + .show()); } } }; @@ -196,26 +247,28 @@ public final class SettingMigrations { MIGRATION_3_4, MIGRATION_4_5, MIGRATION_5_6, - MIGRATION_6_7 + MIGRATION_6_7, + MIGRATION_7_8, }; /** * Version number for preferences. Must be incremented every time a migration is necessary. */ - private static final int VERSION = 7; + private static final int VERSION = 8; - public static void runMigrationsIfNeeded(@NonNull final Context context) { + static void runMigrationsIfNeeded(@NonNull final Context context) { // setup migrations and check if there is something to do sp = PreferenceManager.getDefaultSharedPreferences(context); final String lastPrefVersionKey = context.getString(R.string.last_used_preferences_version); - final int lastPrefVersion = sp.getInt(lastPrefVersionKey, 0); + //final int lastPrefVersion = sp.getInt(lastPrefVersionKey, 0); + final int lastPrefVersion = 6; // TODO: remove this line after testing // no migration to run, already up to date if (App.getApp().isFirstRun()) { sp.edit().putInt(lastPrefVersionKey, VERSION).apply(); return; - } else if (lastPrefVersion == VERSION) { + } else if (lastPrefVersion == VERSION && !DEBUG) { // TODO: remove DEBUG check return; } @@ -249,21 +302,6 @@ public final class SettingMigrations { sp.edit().putInt(lastPrefVersionKey, currentVersion).apply(); } - /** - * Perform UI actions informing about migrations that took place if they are present. - * @param context Context that can be used to show dialogs/snackbars/toasts - */ - public static void showUserInfoIfPresent(@NonNull final Context context) { - for (final Consumer consumer : MIGRATION_INFO) { - try { - consumer.accept(context); - } catch (final Exception e) { - ErrorUtil.showUiErrorSnackbar(context, "Showing migration info to the user", e); - } - } - MIGRATION_INFO.clear(); - } - private SettingMigrations() { } abstract static class Migration { @@ -282,7 +320,7 @@ public final class SettingMigrations { * the current settings version. */ private boolean shouldMigrate(final int currentVersion) { - return oldVersion >= currentVersion; + return oldVersion >= currentVersion || newVersion == VERSION; } protected abstract void migrate(@NonNull Context context); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6ab2fc7a5..cfc51f4e9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -866,4 +866,6 @@ The settings in the export being imported use a vulnerable format that was deprecated since NewPipe 0.27.0. Make sure the export being imported is from a trusted source, and prefer using only exports obtained from NewPipe 0.27.0 or newer in the future. Support for importing settings in this vulnerable format will soon be removed completely, and then old versions of NewPipe will not be able to import settings of exports from new versions anymore. SoundCloud Top 50 page removed SoundCloud has discontinued the original Top 50 charts. The corresponding tab has been removed from your main page. + YouTube combined trending removed + YouTube has discontinued the combined trending page as of 21st July 2025. NewPipe replaced the default trending page with the trending livestreams.\n\nYou can also select different ones in the content settings. From 7cecd11f721d49c8da357a63ef193dc19a42b3b0 Mon Sep 17 00:00:00 2001 From: Stypox Date: Mon, 28 Jul 2025 19:24:18 +0200 Subject: [PATCH 21/43] [YouTube] Add icons and strings for new trending pages --- .../org/schabi/newpipe/util/KioskTranslator.java | 16 ++++++++++++++++ app/src/main/res/drawable/ic_podcasts.xml | 5 +++++ app/src/main/res/values/strings.xml | 4 ++++ 3 files changed, 25 insertions(+) create mode 100644 app/src/main/res/drawable/ic_podcasts.xml diff --git a/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.java b/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.java index b8c2ff236..69cf17639 100644 --- a/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.java +++ b/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.java @@ -52,6 +52,14 @@ public final class KioskTranslator { return c.getString(R.string.featured); case "Radio": return c.getString(R.string.radio); + case "trending_gaming": + return c.getString(R.string.gaming); + case "trending_music": + return c.getString(R.string.music); + case "trending_movies_and_shows": + return c.getString(R.string.movies); + case "trending_podcasts_episodes": + return c.getString(R.string.podcasts); default: return kioskId; } @@ -77,6 +85,14 @@ public final class KioskTranslator { return R.drawable.ic_stars; case "Radio": return R.drawable.ic_radio; + case "trending_gaming": + return R.drawable.ic_videogame_asset; + case "trending_music": + return R.drawable.ic_music_note; + case "trending_movies_and_shows": + return R.drawable.ic_movie; + case "trending_podcasts_episodes": + return R.drawable.ic_podcasts; default: return 0; } diff --git a/app/src/main/res/drawable/ic_podcasts.xml b/app/src/main/res/drawable/ic_podcasts.xml new file mode 100644 index 000000000..c297e8fd3 --- /dev/null +++ b/app/src/main/res/drawable/ic_podcasts.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cfc51f4e9..a8c8694ca 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -868,4 +868,8 @@ SoundCloud has discontinued the original Top 50 charts. The corresponding tab has been removed from your main page. YouTube combined trending removed YouTube has discontinued the combined trending page as of 21st July 2025. NewPipe replaced the default trending page with the trending livestreams.\n\nYou can also select different ones in the content settings. + Gaming + Music + Movies + Podcasts From 8400a9ae8ec7a4361b9398f7e20177531d751119 Mon Sep 17 00:00:00 2001 From: Stypox Date: Mon, 28 Jul 2025 21:47:26 +0200 Subject: [PATCH 22/43] Remove DEBUG statements and don't replace yt trending with live You can use this command to test instead: adb shell run-as org.schabi.newpipe.debug.pr12450 'sed -i '"'"'s###'"'"' shared_prefs/org.schabi.newpipe.debug.pr12450_preferences.xml' && adb shell run-as org.schabi.newpipe.debug.pr12450 'sed -i '"'"'s#\]}#,{\"tab_id\":5,\"service_id\":0,\"kiosk_id\":\"Trending\"},{\"tab_id\":5,\"service_id\":1,\"kiosk_id\":\"Top 50\"}]}#'"'"' shared_prefs/org.schabi.newpipe.debug.pr12450_preferences.xml' --- .../settings/migration/SettingMigrations.java | 34 ++++++------------- app/src/main/res/values/strings.xml | 2 +- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/migration/SettingMigrations.java b/app/src/main/java/org/schabi/newpipe/settings/migration/SettingMigrations.java index 99af27766..67944075d 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/migration/SettingMigrations.java +++ b/app/src/main/java/org/schabi/newpipe/settings/migration/SettingMigrations.java @@ -21,7 +21,6 @@ import org.schabi.newpipe.settings.tabs.Tab; import org.schabi.newpipe.settings.tabs.TabsManager; import org.schabi.newpipe.util.DeviceUtils; -import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -173,7 +172,7 @@ public final class SettingMigrations { && kioskTab.getKioskServiceId() == SoundCloud.getServiceId() && kioskTab.getKioskId().equals("Top 50"))) .collect(Collectors.toUnmodifiableList()); - if (tabs.size() != cleanedTabs.size() || DEBUG) { // TODO: remove debug condition + if (tabs.size() != cleanedTabs.size()) { tabsManager.saveTabs(cleanedTabs); // create an AlertDialog to inform the user about the change MigrationManager.addMigrationInfo(uiContext -> @@ -198,31 +197,19 @@ public final class SettingMigrations { // and is thus updated automatically. final TabsManager tabsManager = TabsManager.getManager(context); final List tabs = tabsManager.getTabs(); - final boolean hadYtTrendingTab = tabs.stream() - .anyMatch(tab -> !(tab instanceof Tab.KioskTab kioskTab + final List cleanedTabs = tabs.stream() + .filter(tab -> !(tab instanceof Tab.KioskTab kioskTab && kioskTab.getKioskServiceId() == YouTube.getServiceId() - && kioskTab.getKioskId().equals("Trending"))); - if (hadYtTrendingTab) { - final List cleanedTabs = new ArrayList<>(); - for (final Tab tab : tabs) { - if (tab instanceof Tab.KioskTab kioskTab - && kioskTab.getKioskServiceId() == YouTube.getServiceId() - && kioskTab.getKioskId().equals("Trending")) { - // replace the YouTube Trending tab with the new live kiosk tab - // TODO: use the correct kiosk ID for the live kiosk tab - cleanedTabs.add(new Tab.KioskTab(YouTube.getServiceId(), "Live")); - } else { - cleanedTabs.add(tab); - } - } + && kioskTab.getKioskId().equals("Trending"))) + .collect(Collectors.toUnmodifiableList()); + if (tabs.size() != cleanedTabs.size()) { tabsManager.saveTabs(cleanedTabs); } final boolean hasDefaultTrendingTab = tabs.stream() .anyMatch(tab -> tab instanceof Tab.DefaultKioskTab); - // TODO: remove debugging code - if (hadYtTrendingTab || hasDefaultTrendingTab || newVersion == VERSION) { + if (tabs.size() != cleanedTabs.size() || hasDefaultTrendingTab) { // User is informed about the change MigrationManager.addMigrationInfo(uiContext -> MigrationManager.createMigrationInfoDialog( @@ -261,14 +248,13 @@ public final class SettingMigrations { // setup migrations and check if there is something to do sp = PreferenceManager.getDefaultSharedPreferences(context); final String lastPrefVersionKey = context.getString(R.string.last_used_preferences_version); - //final int lastPrefVersion = sp.getInt(lastPrefVersionKey, 0); - final int lastPrefVersion = 6; // TODO: remove this line after testing + final int lastPrefVersion = sp.getInt(lastPrefVersionKey, 0); // no migration to run, already up to date if (App.getApp().isFirstRun()) { sp.edit().putInt(lastPrefVersionKey, VERSION).apply(); return; - } else if (lastPrefVersion == VERSION && !DEBUG) { // TODO: remove DEBUG check + } else if (lastPrefVersion == VERSION) { return; } @@ -320,7 +306,7 @@ public final class SettingMigrations { * the current settings version. */ private boolean shouldMigrate(final int currentVersion) { - return oldVersion >= currentVersion || newVersion == VERSION; + return oldVersion >= currentVersion; } protected abstract void migrate(@NonNull Context context); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a8c8694ca..c78845472 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -867,7 +867,7 @@ SoundCloud Top 50 page removed SoundCloud has discontinued the original Top 50 charts. The corresponding tab has been removed from your main page. YouTube combined trending removed - YouTube has discontinued the combined trending page as of 21st July 2025. NewPipe replaced the default trending page with the trending livestreams.\n\nYou can also select different ones in the content settings. + YouTube has discontinued the combined trending page as of 21st July 2025. NewPipe replaced the default trending page with the trending livestreams.\n\nYou can also select different trending pages in \"Settings > Content > Content of main page\". Gaming Music Movies From d96c0aebb1c2a893fb28e6cf40aa9af772ecb002 Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 31 Jul 2025 22:48:13 +0200 Subject: [PATCH 23/43] Show tabs above kiosks in drawer --- .../java/org/schabi/newpipe/MainActivity.java | 60 ++++++++++--------- app/src/main/res/menu/drawer_items.xml | 1 + 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 1aae7fa86..4fbd562b4 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -263,19 +263,6 @@ public class MainActivity extends AppCompatActivity { */ private void addDrawerMenuForCurrentService() throws ExtractionException { //Tabs - final int currentServiceId = ServiceHelper.getSelectedServiceId(this); - final StreamingService service = NewPipe.getService(currentServiceId); - - int kioskMenuItemId = 0; - - for (final String ks : service.getKioskList().getAvailableKiosks()) { - drawerLayoutBinding.navigation.getMenu() - .add(R.id.menu_tabs_group, kioskMenuItemId, 0, KioskTranslator - .getTranslatedKioskName(ks, this)) - .setIcon(KioskTranslator.getKioskIcon(ks)); - kioskMenuItemId++; - } - drawerLayoutBinding.navigation.getMenu() .add(R.id.menu_tabs_group, ITEM_ID_SUBSCRIPTIONS, ORDER, R.string.tab_subscriptions) @@ -293,6 +280,20 @@ public class MainActivity extends AppCompatActivity { .add(R.id.menu_tabs_group, ITEM_ID_HISTORY, ORDER, R.string.action_history) .setIcon(R.drawable.ic_history); + //Kiosks + final int currentServiceId = ServiceHelper.getSelectedServiceId(this); + final StreamingService service = NewPipe.getService(currentServiceId); + + int kioskMenuItemId = 0; + + for (final String ks : service.getKioskList().getAvailableKiosks()) { + drawerLayoutBinding.navigation.getMenu() + .add(R.id.menu_kiosks_group, kioskMenuItemId, 0, KioskTranslator + .getTranslatedKioskName(ks, this)) + .setIcon(KioskTranslator.getKioskIcon(ks)); + kioskMenuItemId++; + } + //Settings and About drawerLayoutBinding.navigation.getMenu() .add(R.id.menu_options_about_group, ITEM_ID_SETTINGS, ORDER, R.string.settings) @@ -312,10 +313,13 @@ public class MainActivity extends AppCompatActivity { changeService(item); break; case R.id.menu_tabs_group: + tabSelected(item); + break; + case R.id.menu_kiosks_group: try { - tabSelected(item); + kioskSelected(item); } catch (final Exception e) { - ErrorUtil.showUiErrorSnackbar(this, "Selecting main page tab", e); + ErrorUtil.showUiErrorSnackbar(this, "Selecting drawer kiosk", e); } break; case R.id.menu_options_about_group: @@ -339,7 +343,7 @@ public class MainActivity extends AppCompatActivity { .setChecked(true); } - private void tabSelected(final MenuItem item) throws ExtractionException { + private void tabSelected(final MenuItem item) { switch (item.getItemId()) { case ITEM_ID_SUBSCRIPTIONS: NavigationHelper.openSubscriptionFragment(getSupportFragmentManager()); @@ -356,18 +360,19 @@ public class MainActivity extends AppCompatActivity { case ITEM_ID_HISTORY: NavigationHelper.openStatisticFragment(getSupportFragmentManager()); break; - default: - final StreamingService currentService = ServiceHelper.getSelectedService(this); - int kioskMenuItemId = 0; - for (final String kioskId : currentService.getKioskList().getAvailableKiosks()) { - if (kioskMenuItemId == item.getItemId()) { - NavigationHelper.openKioskFragment(getSupportFragmentManager(), - currentService.getServiceId(), kioskId); - break; - } - kioskMenuItemId++; - } + } + } + + private void kioskSelected(final MenuItem item) throws ExtractionException { + final StreamingService currentService = ServiceHelper.getSelectedService(this); + int kioskMenuItemId = 0; + for (final String kioskId : currentService.getKioskList().getAvailableKiosks()) { + if (kioskMenuItemId == item.getItemId()) { + NavigationHelper.openKioskFragment(getSupportFragmentManager(), + currentService.getServiceId(), kioskId); break; + } + kioskMenuItemId++; } } @@ -408,6 +413,7 @@ public class MainActivity extends AppCompatActivity { 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_kiosks_group); drawerLayoutBinding.navigation.getMenu().removeGroup(R.id.menu_options_about_group); // Show up or down arrow diff --git a/app/src/main/res/menu/drawer_items.xml b/app/src/main/res/menu/drawer_items.xml index 24c321b8a..8214f3f02 100644 --- a/app/src/main/res/menu/drawer_items.xml +++ b/app/src/main/res/menu/drawer_items.xml @@ -2,5 +2,6 @@ + From b7b836e941a87a44a149775dc33c23a4f001055c Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 31 Jul 2025 23:10:47 +0200 Subject: [PATCH 24/43] Update the names of YT kiosks --- .../java/org/schabi/newpipe/util/KioskTranslator.java | 8 ++++---- .../main/java/org/schabi/newpipe/util/Localization.java | 3 ++- app/src/main/res/values/strings.xml | 8 ++++---- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.java b/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.java index 69cf17639..5aa332159 100644 --- a/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.java +++ b/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.java @@ -53,13 +53,13 @@ public final class KioskTranslator { case "Radio": return c.getString(R.string.radio); case "trending_gaming": - return c.getString(R.string.gaming); + return c.getString(R.string.trending_gaming); case "trending_music": - return c.getString(R.string.music); + return c.getString(R.string.trending_music); case "trending_movies_and_shows": - return c.getString(R.string.movies); + return c.getString(R.string.trending_movies); case "trending_podcasts_episodes": - return c.getString(R.string.podcasts); + return c.getString(R.string.trending_podcasts); default: return kioskId; } 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 bd5463088..1073afffd 100644 --- a/app/src/main/java/org/schabi/newpipe/util/Localization.java +++ b/app/src/main/java/org/schabi/newpipe/util/Localization.java @@ -388,9 +388,10 @@ public final class Localization { * {@code parsed != null} and the relevant setting is enabled, {@code textual} will * be appended to the returned string for debugging purposes. */ + @Nullable public static String relativeTimeOrTextual(@Nullable final Context context, @Nullable final DateWrapper parsed, - final String textual) { + @Nullable final String textual) { if (parsed == null) { return textual; } else if (DEBUG && context != null && PreferenceManager diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c78845472..57f78c221 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -868,8 +868,8 @@ SoundCloud has discontinued the original Top 50 charts. The corresponding tab has been removed from your main page. YouTube combined trending removed YouTube has discontinued the combined trending page as of 21st July 2025. NewPipe replaced the default trending page with the trending livestreams.\n\nYou can also select different trending pages in \"Settings > Content > Content of main page\". - Gaming - Music - Movies - Podcasts + Gaming trends + Trending podcasts + Trending movies and shows + Trending music From b846746119fb037b39425775acbea53d92472673 Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 31 Jul 2025 23:32:04 +0200 Subject: [PATCH 25/43] Update NewPipeExtractor to v0.24.8 --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 54bd86a72..d6c93c1f7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -214,7 +214,7 @@ dependencies { // the corresponding commit hash, since JitPack sometimes deletes artifacts. // If there’s already a git hash, just add more of it to the end (or remove a letter) // to cause jitpack to regenerate the artifact. - implementation 'com.github.TeamNewPipe:NewPipeExtractor:7adbc48a0aa872c016b8ec089e278d5e12772054' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.24.8' implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0' /** Checkstyle **/ From 5aefa4aff258487df72343ea5edcfbe43e1b3f2e Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Thu, 31 Jul 2025 23:42:34 +0200 Subject: [PATCH 26/43] Translated using Weblate (Tigrinya) Currently translated at 12.7% (95 of 748 strings) Co-authored-by: fool --- app/src/main/res/values-ti/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-ti/strings.xml b/app/src/main/res/values-ti/strings.xml index e1f61b7d1..f25b86cc1 100644 --- a/app/src/main/res/values-ti/strings.xml +++ b/app/src/main/res/values-ti/strings.xml @@ -5,7 +5,7 @@ ውጽኢት ናይ፦ %s ንኽትጅምር ነቲ ምድላይ ምልክት ጠውቆ። ዝተሓትመሉ ዕለት %1$s - ናይ ዥረት ተጻዋታይ ኣይተረኽበን። VLC ኣውርድ፧ + ናይ ዥረት ተጻዋታይ ኣይተረኽበን። VLC ይውርድ፧ ሐራይ ቅጥዕታት \"%1$s\" ማለቱ ድዩ፧ From d6c0dc32d1aea7d48405577db352488d7b633ff1 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Fri, 1 Aug 2025 10:50:54 +0200 Subject: [PATCH 27/43] Correctly ignore new version check for picasso --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 35846c551..dbffc2bf6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -280,7 +280,7 @@ dependencies { implementation "com.github.lisawray.groupie:groupie-viewbinding:${groupieVersion}" // Image loading - //noinspection GradleDependency --> 2.8 is the last version, not 2.71828! + //noinspection NewerVersionAvailable,GradleDependency --> 2.8 is the last version, not 2.71828! implementation "com.squareup.picasso:picasso:2.8" // Markdown library for Android From 7644066c5a3707a28eadbc93cf061c01b428b21f Mon Sep 17 00:00:00 2001 From: Stypox Date: Sat, 16 Aug 2025 16:50:01 +0200 Subject: [PATCH 28/43] Add option to delete a download without also deleting file --- .../giga/service/DownloadManager.java | 6 ++- .../giga/ui/adapter/MissionAdapter.java | 13 +++++-- .../us/shandian/giga/ui/common/Deleter.java | 37 +++++++++++++++---- app/src/main/res/menu/mission.xml | 6 ++- app/src/main/res/values/strings.xml | 3 ++ 5 files changed, 51 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/us/shandian/giga/service/DownloadManager.java b/app/src/main/java/us/shandian/giga/service/DownloadManager.java index 9b90fa14b..d02f77bc1 100644 --- a/app/src/main/java/us/shandian/giga/service/DownloadManager.java +++ b/app/src/main/java/us/shandian/giga/service/DownloadManager.java @@ -265,7 +265,7 @@ public class DownloadManager { } } - public void deleteMission(Mission mission) { + public void deleteMission(Mission mission, boolean alsoDeleteFile) { synchronized (this) { if (mission instanceof DownloadMission) { mMissionsPending.remove(mission); @@ -274,7 +274,9 @@ public class DownloadManager { mFinishedMissionStore.deleteMission(mission); } - mission.delete(); + if (alsoDeleteFile) { + mission.delete(); + } } } 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 9722a9a1f..79dda9011 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 @@ -614,7 +614,7 @@ public class MissionAdapter extends Adapter implements Handler.Callb while (i.hasNext()) { Mission mission = i.next(); if (mission != null) { - mDownloadManager.deleteMission(mission); + mDownloadManager.deleteMission(mission, true); mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, mission.storage.getUri())); } i.remove(); @@ -667,7 +667,14 @@ public class MissionAdapter extends Adapter implements Handler.Callb shareFile(h.item.mission); return true; case R.id.delete: - mDeleter.append(h.item.mission); + // delete the entry and the file + mDeleter.append(h.item.mission, true); + applyChanges(); + checkMasterButtonsVisibility(); + return true; + case R.id.delete_entry: + // just delete the entry + mDeleter.append(h.item.mission, false); applyChanges(); checkMasterButtonsVisibility(); return true; @@ -676,7 +683,7 @@ public class MissionAdapter extends Adapter implements Handler.Callb final StoredFileHelper storage = h.item.mission.storage; if (!storage.existsAsFile()) { Toast.makeText(mContext, R.string.missing_file, Toast.LENGTH_SHORT).show(); - mDeleter.append(h.item.mission); + mDeleter.append(h.item.mission, true); applyChanges(); return true; } diff --git a/app/src/main/java/us/shandian/giga/ui/common/Deleter.java b/app/src/main/java/us/shandian/giga/ui/common/Deleter.java index 1902076d6..0f285fd74 100644 --- a/app/src/main/java/us/shandian/giga/ui/common/Deleter.java +++ b/app/src/main/java/us/shandian/giga/ui/common/Deleter.java @@ -13,7 +13,9 @@ import com.google.android.material.snackbar.Snackbar; import org.schabi.newpipe.R; import java.util.ArrayList; +import java.util.Optional; +import kotlin.Pair; import us.shandian.giga.get.FinishedMission; import us.shandian.giga.get.Mission; import us.shandian.giga.service.DownloadManager; @@ -30,7 +32,8 @@ public class Deleter { private static final int DELAY_RESUME = 400;// ms private Snackbar snackbar; - private ArrayList items; + // list of missions to be deleted, and whether to also delete the corresponding file + private ArrayList> items; private boolean running = true; private final Context mContext; @@ -51,7 +54,7 @@ public class Deleter { items = new ArrayList<>(2); } - public void append(Mission item) { + public void append(Mission item, boolean alsoDeleteFile) { /* If a mission is removed from the list while the Snackbar for a previously * removed item is still showing, commit the action for the previous item * immediately. This prevents Snackbars from stacking up in reverse order. @@ -60,13 +63,13 @@ public class Deleter { commit(); mIterator.hide(item); - items.add(0, item); + items.add(0, new Pair<>(item, alsoDeleteFile)); show(); } private void forget() { - mIterator.unHide(items.remove(0)); + mIterator.unHide(items.remove(0).getFirst()); mAdapter.applyChanges(); show(); @@ -84,7 +87,19 @@ public class Deleter { private void next() { if (items.size() < 1) return; - String msg = mContext.getString(R.string.file_deleted).concat(":\n").concat(items.get(0).storage.getName()); + final Optional fileToBeDeleted = items.stream() + .filter(Pair::getSecond) + .map(p -> p.getFirst().storage.getName()) + .findFirst(); + + String msg; + if (fileToBeDeleted.isPresent()) { + msg = mContext.getString(R.string.file_deleted) + .concat(":\n") + .concat(fileToBeDeleted.get()); + } else { + msg = mContext.getString(R.string.entry_deleted); + } snackbar = Snackbar.make(mView, msg, Snackbar.LENGTH_INDEFINITE); snackbar.setAction(R.string.undo, s -> forget()); @@ -98,11 +113,13 @@ public class Deleter { if (items.size() < 1) return; while (items.size() > 0) { - Mission mission = items.remove(0); + Pair missionAndAlsoDeleteFile = items.remove(0); + Mission mission = missionAndAlsoDeleteFile.getFirst(); + boolean alsoDeleteFile = missionAndAlsoDeleteFile.getSecond(); if (mission.deleted) continue; mIterator.unHide(mission); - mDownloadManager.deleteMission(mission); + mDownloadManager.deleteMission(mission, alsoDeleteFile); if (mission instanceof FinishedMission) { mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, mission.storage.getUri())); @@ -137,7 +154,11 @@ public class Deleter { pause(); - for (Mission mission : items) mDownloadManager.deleteMission(mission); + for (Pair missionAndAlsoDeleteFile : items) { + Mission mission = missionAndAlsoDeleteFile.getFirst(); + boolean alsoDeleteFile = missionAndAlsoDeleteFile.getSecond(); + mDownloadManager.deleteMission(mission, alsoDeleteFile); + } items = null; } } diff --git a/app/src/main/res/menu/mission.xml b/app/src/main/res/menu/mission.xml index 4273c1ed6..6566252e8 100644 --- a/app/src/main/res/menu/mission.xml +++ b/app/src/main/res/menu/mission.xml @@ -27,7 +27,11 @@ + android:title="@string/delete_file" /> + + Pause Create Delete + Delete file + Delete entry Checksum Dismiss Rename @@ -872,4 +874,5 @@ Trending podcasts Trending movies and shows Trending music + Entry deleted From cf4b5e17c510c0b4f3b8ad7a1c2ccbdd4f85f2f5 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Mon, 25 Aug 2025 14:32:19 +0530 Subject: [PATCH 29/43] Fix database import --- .../BackupRestoreSettingsFragment.java | 4 +--- .../settings/export/BackupFileLocator.kt | 12 ++++++------ .../settings/export/ImportExportManager.kt | 4 ++-- .../settings/ImportExportManagerTest.kt | 19 ++++++++++--------- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/BackupRestoreSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/BackupRestoreSettingsFragment.java index 031f0d36c..e794ace72 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/BackupRestoreSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/BackupRestoreSettingsFragment.java @@ -57,9 +57,7 @@ public class BackupRestoreSettingsFragment extends BasePreferenceFragment { @Override public void onCreatePreferences(@Nullable final Bundle savedInstanceState, @Nullable final String rootKey) { - final var dbDir = requireContext().getDatabasePath(BackupFileLocator.FILE_NAME_DB).toPath() - .getParent(); - manager = new ImportExportManager(new BackupFileLocator(dbDir)); + manager = new ImportExportManager(new BackupFileLocator(requireContext())); importExportDataPathKey = getString(R.string.import_export_data_path); diff --git a/app/src/main/java/org/schabi/newpipe/settings/export/BackupFileLocator.kt b/app/src/main/java/org/schabi/newpipe/settings/export/BackupFileLocator.kt index 0ce2d5f4d..38227e10e 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/export/BackupFileLocator.kt +++ b/app/src/main/java/org/schabi/newpipe/settings/export/BackupFileLocator.kt @@ -1,12 +1,13 @@ package org.schabi.newpipe.settings.export +import android.content.Context import java.nio.file.Path import kotlin.io.path.div /** * Locates specific files of NewPipe based on the home directory of the app. */ -class BackupFileLocator(homeDir: Path) { +class BackupFileLocator(context: Context) { companion object { const val FILE_NAME_DB = "newpipe.db" @Deprecated( @@ -17,9 +18,8 @@ class BackupFileLocator(homeDir: Path) { const val FILE_NAME_JSON_PREFS = "preferences.json" } - val dbDir = homeDir / "databases" - val db = homeDir / FILE_NAME_DB - val dbJournal = homeDir / "$FILE_NAME_DB-journal" - val dbShm = dbDir / "$FILE_NAME_DB-shm" - val dbWal = dbDir / "$FILE_NAME_DB-wal" + val db: Path = context.getDatabasePath(FILE_NAME_DB).toPath() + val dbJournal: Path = db.resolveSibling("$FILE_NAME_DB-journal") + val dbShm: Path = db.resolveSibling("$FILE_NAME_DB-shm") + val dbWal: Path = db.resolveSibling("$FILE_NAME_DB-wal") } diff --git a/app/src/main/java/org/schabi/newpipe/settings/export/ImportExportManager.kt b/app/src/main/java/org/schabi/newpipe/settings/export/ImportExportManager.kt index 6b0eb7eb9..cbf860d2c 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/export/ImportExportManager.kt +++ b/app/src/main/java/org/schabi/newpipe/settings/export/ImportExportManager.kt @@ -12,7 +12,7 @@ import java.io.FileNotFoundException import java.io.IOException import java.io.ObjectOutputStream import java.util.zip.ZipOutputStream -import kotlin.io.path.createDirectories +import kotlin.io.path.createParentDirectories import kotlin.io.path.deleteIfExists class ImportExportManager(private val fileLocator: BackupFileLocator) { @@ -63,7 +63,7 @@ class ImportExportManager(private val fileLocator: BackupFileLocator) { */ @Throws(IOException::class) fun ensureDbDirectoryExists() { - fileLocator.dbDir.createDirectories() + fileLocator.db.createParentDirectories() } /** diff --git a/app/src/test/java/org/schabi/newpipe/settings/ImportExportManagerTest.kt b/app/src/test/java/org/schabi/newpipe/settings/ImportExportManagerTest.kt index f362963db..6f6ba671e 100644 --- a/app/src/test/java/org/schabi/newpipe/settings/ImportExportManagerTest.kt +++ b/app/src/test/java/org/schabi/newpipe/settings/ImportExportManagerTest.kt @@ -25,11 +25,12 @@ import org.schabi.newpipe.streams.io.StoredFileHelper import us.shandian.giga.io.FileStream import java.io.File import java.io.ObjectInputStream +import java.nio.file.Paths import java.util.zip.ZipFile -import kotlin.io.path.Path import kotlin.io.path.createTempDirectory import kotlin.io.path.createTempFile import kotlin.io.path.deleteIfExists +import kotlin.io.path.div import kotlin.io.path.exists import kotlin.io.path.fileSize import kotlin.io.path.inputStream @@ -52,7 +53,7 @@ class ImportExportManagerTest { @Test fun `The settings must be exported successfully in the correct format`() { - val db = Path(classloader.getResource("settings/newpipe.db")!!.file) + val db = Paths.get(classloader.getResource("settings/newpipe.db")!!.toURI()) `when`(fileLocator.db).thenReturn(db) val expectedPreferences = mapOf("such pref" to "much wow") @@ -87,21 +88,21 @@ class ImportExportManagerTest { @Test fun `Ensuring db directory existence must work`() { - val dir = createTempDirectory("newpipe_") - Assume.assumeTrue(dir.deleteIfExists()) - `when`(fileLocator.dbDir).thenReturn(dir) + val path = createTempDirectory("newpipe_") / BackupFileLocator.FILE_NAME_DB + Assume.assumeTrue(path.parent.deleteIfExists()) + `when`(fileLocator.db).thenReturn(path) ImportExportManager(fileLocator).ensureDbDirectoryExists() - assertTrue(dir.exists()) + assertTrue(path.parent.exists()) } @Test fun `Ensuring db directory existence must work when the directory already exists`() { - val dir = createTempDirectory("newpipe_") - `when`(fileLocator.dbDir).thenReturn(dir) + val path = createTempDirectory("newpipe_") / BackupFileLocator.FILE_NAME_DB + `when`(fileLocator.db).thenReturn(path) ImportExportManager(fileLocator).ensureDbDirectoryExists() - assertTrue(dir.exists()) + assertTrue(path.parent.exists()) } @Test From 386d5197d888433fa340b6bdf8ddd30ac1819622 Mon Sep 17 00:00:00 2001 From: Profpatsch Date: Mon, 5 May 2025 19:21:14 +0200 Subject: [PATCH 30/43] Permission: display explanatory dialog for Android > R MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Android > R, ACTION_MANAGE_OVERLAY_PERMISSION always brings the user to the app selection screen. https://developer.android.com/about/versions/11/privacy/permissions#manage_overlay This is highly confusing behaviour from the system, so let’s add an instruction before navigating to the settings menu. --- .../schabi/newpipe/util/PermissionHelper.java | 49 ++++++++++++++++--- app/src/main/res/values/strings.xml | 2 + 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java b/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java index 55193599e..c690e5bd9 100644 --- a/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java @@ -2,6 +2,7 @@ package org.schabi.newpipe.util; import android.Manifest; import android.app.Activity; +import android.app.AlertDialog; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; @@ -9,6 +10,7 @@ import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.provider.Settings; +import android.text.Html; import android.widget.Toast; import androidx.annotation.RequiresApi; @@ -113,14 +115,47 @@ public final class PermissionHelper { @RequiresApi(api = Build.VERSION_CODES.M) public static boolean checkSystemAlertWindowPermission(final Context context) { if (!Settings.canDrawOverlays(context)) { - final Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, - Uri.parse("package:" + context.getPackageName())); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - try { - context.startActivity(i); - } catch (final ActivityNotFoundException ignored) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { + final Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, + Uri.parse("package:" + context.getPackageName())); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + try { + context.startActivity(i); + } catch (final ActivityNotFoundException ignored) { + } + return false; + // from Android R the ACTION_MANAGE_OVERLAY_PERMISSION will only point to the menu, + // so let’s add a dialog that points the user to the right setting. + } else { + final String appName = context.getApplicationInfo() + .loadLabel(context.getPackageManager()).toString(); + final String title = context.getString(R.string.permission_display_over_apps); + final String permissionName = + context.getString(R.string.permission_display_over_apps_permission_name); + final String appNameItalic = "" + appName + ""; + final String permissionNameItalic = "" + permissionName + ""; + final String message = + context.getString(R.string.permission_display_over_apps_message, + appNameItalic, + permissionNameItalic + ); + new AlertDialog.Builder(context) + .setTitle(title) + .setMessage(Html.fromHtml(message, Html.FROM_HTML_MODE_COMPACT)) + .setPositiveButton("OK", (dialog, which) -> { + // we don’t need the package name here, since it won’t do anything on >R + final Intent intent = + new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); + try { + context.startActivity(intent); + } catch (final ActivityNotFoundException ignored) { + } + }) + .setCancelable(true) + .show(); + return false; } - return false; + } else { return true; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6b7082ef3..922b7bd3f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -257,6 +257,8 @@ Restore defaults Do you want to restore defaults? Give permission to display over other apps + In order to use the Popup Player, please select %1$s in the following Android settings menu and enable %2$s. + “Allow display over other apps” NewPipe encountered an error, tap to report An error occurred, see the notification From 74562db9659086c3f417775ffe0df6ed008b45e2 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Wed, 27 Aug 2025 11:45:31 +0200 Subject: [PATCH 31/43] Use androidx compat alert dialog --- app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java b/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java index c690e5bd9..2785afab0 100644 --- a/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/PermissionHelper.java @@ -2,7 +2,6 @@ package org.schabi.newpipe.util; import android.Manifest; import android.app.Activity; -import android.app.AlertDialog; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; @@ -14,6 +13,7 @@ import android.text.Html; import android.widget.Toast; import androidx.annotation.RequiresApi; +import androidx.appcompat.app.AlertDialog; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; From 38064be702a9418864a7675bb44f3d213053e032 Mon Sep 17 00:00:00 2001 From: Stypox Date: Mon, 28 Jul 2025 23:54:47 +0200 Subject: [PATCH 32/43] Add more specific error messages and deduplicate their handling --- app/build.gradle | 2 +- .../org/schabi/newpipe/RouterActivity.java | 34 +++---------------- .../org/schabi/newpipe/error/ErrorInfo.kt | 34 +++++++++++++++++-- .../schabi/newpipe/error/ErrorPanelHelper.kt | 31 +---------------- .../org/schabi/newpipe/error/ErrorUtil.kt | 2 +- .../org/schabi/newpipe/error/UserAction.java | 3 +- .../util/text/InternalUrlsHandler.java | 23 +++++-------- app/src/main/res/values/strings.xml | 2 ++ 8 files changed, 52 insertions(+), 79 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index dbffc2bf6..7f4166a57 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -214,7 +214,7 @@ dependencies { // the corresponding commit hash, since JitPack sometimes deletes artifacts. // If there’s already a git hash, just add more of it to the end (or remove a letter) // to cause jitpack to regenerate the artifact. - implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.24.8' + implementation 'com.github.Stypox:NewPipeExtractor:b8bd4cda8cca00a14940933e3d3635d5aafec222' implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0' /** Checkstyle **/ diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index 3294cae0b..dac2d29a1 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -58,20 +58,13 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.StreamingService.LinkType; import org.schabi.newpipe.extractor.channel.ChannelInfo; -import org.schabi.newpipe.extractor.exceptions.AgeRestrictedContentException; import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException; import org.schabi.newpipe.extractor.exceptions.ExtractionException; -import org.schabi.newpipe.extractor.exceptions.GeographicRestrictionException; -import org.schabi.newpipe.extractor.exceptions.PaidContentException; -import org.schabi.newpipe.extractor.exceptions.PrivateContentException; import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; -import org.schabi.newpipe.extractor.exceptions.SoundCloudGoPlusContentException; -import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.stream.StreamInfo; -import org.schabi.newpipe.ktx.ExceptionUtils; import org.schabi.newpipe.local.dialog.PlaylistDialog; import org.schabi.newpipe.player.PlayerType; import org.schabi.newpipe.player.helper.PlayerHelper; @@ -279,28 +272,11 @@ public class RouterActivity extends AppCompatActivity { final Intent intent = new Intent(context, ReCaptchaActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); - } else if (errorInfo.getThrowable() != null - && ExceptionUtils.isNetworkRelated(errorInfo.getThrowable())) { - Toast.makeText(context, R.string.network_error, Toast.LENGTH_LONG).show(); - } else if (errorInfo.getThrowable() instanceof AgeRestrictedContentException) { - Toast.makeText(context, R.string.restricted_video_no_stream, - Toast.LENGTH_LONG).show(); - } else if (errorInfo.getThrowable() instanceof GeographicRestrictionException) { - Toast.makeText(context, R.string.georestricted_content, Toast.LENGTH_LONG).show(); - } else if (errorInfo.getThrowable() instanceof PaidContentException) { - Toast.makeText(context, R.string.paid_content, Toast.LENGTH_LONG).show(); - } else if (errorInfo.getThrowable() instanceof PrivateContentException) { - Toast.makeText(context, R.string.private_content, Toast.LENGTH_LONG).show(); - } else if (errorInfo.getThrowable() instanceof SoundCloudGoPlusContentException) { - Toast.makeText(context, R.string.soundcloud_go_plus_content, - Toast.LENGTH_LONG).show(); - } else if (errorInfo.getThrowable() instanceof YoutubeMusicPremiumContentException) { - Toast.makeText(context, R.string.youtube_music_premium_content, - Toast.LENGTH_LONG).show(); - } else if (errorInfo.getThrowable() instanceof ContentNotAvailableException) { - Toast.makeText(context, R.string.content_not_available, Toast.LENGTH_LONG).show(); - } else if (errorInfo.getThrowable() instanceof ContentNotSupportedException) { - Toast.makeText(context, R.string.content_not_supported, Toast.LENGTH_LONG).show(); + } else if (errorInfo.getThrowable() instanceof ContentNotAvailableException + || errorInfo.getThrowable() instanceof ContentNotSupportedException) { + // this exception does not usually indicate a problem that should be reported, + // so just show a toast instead of the notification + Toast.makeText(context, errorInfo.getMessageStringId(), Toast.LENGTH_LONG).show(); } else { ErrorUtil.createNotification(context, errorInfo); } diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt index 6d8c1bd63..014be540f 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt @@ -3,14 +3,25 @@ package org.schabi.newpipe.error import android.os.Parcelable import androidx.annotation.StringRes import com.google.android.exoplayer2.ExoPlaybackException +import com.google.android.exoplayer2.upstream.HttpDataSource +import com.google.android.exoplayer2.upstream.Loader import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize import org.schabi.newpipe.R import org.schabi.newpipe.extractor.Info import org.schabi.newpipe.extractor.exceptions.AccountTerminatedException +import org.schabi.newpipe.extractor.exceptions.AgeRestrictedContentException import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException import org.schabi.newpipe.extractor.exceptions.ExtractionException +import org.schabi.newpipe.extractor.exceptions.GeographicRestrictionException +import org.schabi.newpipe.extractor.exceptions.PaidContentException +import org.schabi.newpipe.extractor.exceptions.PrivateContentException +import org.schabi.newpipe.extractor.exceptions.ReCaptchaException +import org.schabi.newpipe.extractor.exceptions.SoundCloudGoPlusContentException +import org.schabi.newpipe.extractor.exceptions.UnsupportedContentInCountryException +import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentException +import org.schabi.newpipe.extractor.exceptions.YoutubeSignInConfirmNotBotException import org.schabi.newpipe.ktx.isNetworkRelated import org.schabi.newpipe.util.ServiceHelper @@ -91,11 +102,28 @@ class ErrorInfo( action: UserAction ): Int { return when { + // content not available exceptions throwable is AccountTerminatedException -> R.string.account_terminated + throwable is AgeRestrictedContentException -> R.string.restricted_video_no_stream + throwable is GeographicRestrictionException -> R.string.georestricted_content + throwable is PaidContentException -> R.string.paid_content + throwable is PrivateContentException -> R.string.private_content + throwable is SoundCloudGoPlusContentException -> R.string.soundcloud_go_plus_content + throwable is UnsupportedContentInCountryException -> R.string.unsupported_content_in_country + throwable is YoutubeMusicPremiumContentException -> R.string.youtube_music_premium_content + throwable is YoutubeSignInConfirmNotBotException -> R.string.youtube_sign_in_confirm_not_bot_error throwable is ContentNotAvailableException -> R.string.content_not_available - throwable != null && throwable.isNetworkRelated -> R.string.network_error + + // ReCaptchas should have already been handled elsewhere, + // but return an error message here just in case + throwable is ReCaptchaException -> R.string.recaptcha_request_toast + + // other extractor exceptions throwable is ContentNotSupportedException -> R.string.content_not_supported + throwable != null && throwable.isNetworkRelated -> R.string.network_error throwable is ExtractionException -> R.string.parsing_error + + // ExoPlayer exceptions throwable is ExoPlaybackException -> { when (throwable.type) { ExoPlaybackException.TYPE_SOURCE -> R.string.player_stream_failure @@ -103,13 +131,15 @@ class ErrorInfo( else -> R.string.player_unrecoverable_failure } } + + // user actions (in case the exception is unrecognizable) action == UserAction.UI_ERROR -> R.string.app_ui_crash action == UserAction.REQUESTED_COMMENTS -> R.string.error_unable_to_load_comments action == UserAction.SUBSCRIPTION_CHANGE -> R.string.subscription_change_failed action == UserAction.SUBSCRIPTION_UPDATE -> R.string.subscription_update_failed action == UserAction.LOAD_IMAGE -> R.string.could_not_load_thumbnails action == UserAction.DOWNLOAD_OPEN_DIALOG -> R.string.could_not_setup_download_menu - else -> R.string.general_error + else -> R.string.error_snackbar_message } } } diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt index 14ec41148..66d4d9fae 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt @@ -15,19 +15,12 @@ import io.reactivex.rxjava3.disposables.Disposable import org.schabi.newpipe.MainActivity import org.schabi.newpipe.R import org.schabi.newpipe.extractor.exceptions.AccountTerminatedException -import org.schabi.newpipe.extractor.exceptions.AgeRestrictedContentException import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException -import org.schabi.newpipe.extractor.exceptions.GeographicRestrictionException -import org.schabi.newpipe.extractor.exceptions.PaidContentException -import org.schabi.newpipe.extractor.exceptions.PrivateContentException import org.schabi.newpipe.extractor.exceptions.ReCaptchaException -import org.schabi.newpipe.extractor.exceptions.SoundCloudGoPlusContentException -import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentException import org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty import org.schabi.newpipe.ktx.animate import org.schabi.newpipe.ktx.isInterruptedCaused -import org.schabi.newpipe.ktx.isNetworkRelated import org.schabi.newpipe.util.ServiceHelper import org.schabi.newpipe.util.external_communication.ShareUtils import java.util.concurrent.TimeUnit @@ -127,7 +120,7 @@ class ErrorPanelHelper( ErrorUtil.openActivity(context, errorInfo) } - errorTextView.setText(getExceptionDescription(errorInfo.throwable)) + errorTextView.setText(errorInfo.messageStringId) if (errorInfo.throwable !is ContentNotAvailableException && errorInfo.throwable !is ContentNotSupportedException @@ -192,27 +185,5 @@ class ErrorPanelHelper( companion object { val TAG: String = ErrorPanelHelper::class.simpleName!! val DEBUG: Boolean = MainActivity.DEBUG - - @StringRes - fun getExceptionDescription(throwable: Throwable?): Int { - return when (throwable) { - is AgeRestrictedContentException -> R.string.restricted_video_no_stream - is GeographicRestrictionException -> R.string.georestricted_content - is PaidContentException -> R.string.paid_content - is PrivateContentException -> R.string.private_content - is SoundCloudGoPlusContentException -> R.string.soundcloud_go_plus_content - is YoutubeMusicPremiumContentException -> R.string.youtube_music_premium_content - is ContentNotAvailableException -> R.string.content_not_available - is ContentNotSupportedException -> R.string.content_not_supported - else -> { - // show retry button only for content which is not unavailable or unsupported - if (throwable != null && throwable.isNetworkRelated) { - R.string.network_error - } else { - R.string.error_snackbar_message - } - } - } - } } } diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt index e74711b88..958188b6a 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt @@ -156,7 +156,7 @@ class ErrorUtil { // fallback to showing a notification if no root view is available createNotification(context, errorInfo) } else { - Snackbar.make(rootView, R.string.error_snackbar_message, Snackbar.LENGTH_LONG) + Snackbar.make(rootView, errorInfo.messageStringId, Snackbar.LENGTH_LONG) .setActionTextColor(Color.YELLOW) .setAction(context.getString(R.string.error_snackbar_action).uppercase()) { openActivity(context, errorInfo) diff --git a/app/src/main/java/org/schabi/newpipe/error/UserAction.java b/app/src/main/java/org/schabi/newpipe/error/UserAction.java index afb880a29..997bff996 100644 --- a/app/src/main/java/org/schabi/newpipe/error/UserAction.java +++ b/app/src/main/java/org/schabi/newpipe/error/UserAction.java @@ -33,7 +33,8 @@ public enum UserAction { SHARE_TO_NEWPIPE("share to newpipe"), CHECK_FOR_NEW_APP_VERSION("check for new app version"), OPEN_INFO_ITEM_DIALOG("open info item dialog"), - GETTING_MAIN_SCREEN_TAB("getting main screen tab"); + GETTING_MAIN_SCREEN_TAB("getting main screen tab"), + PLAY_ON_POPUP("play on popup"); private final String message; diff --git a/app/src/main/java/org/schabi/newpipe/util/text/InternalUrlsHandler.java b/app/src/main/java/org/schabi/newpipe/util/text/InternalUrlsHandler.java index 066515d6b..a2743141b 100644 --- a/app/src/main/java/org/schabi/newpipe/util/text/InternalUrlsHandler.java +++ b/app/src/main/java/org/schabi/newpipe/util/text/InternalUrlsHandler.java @@ -1,14 +1,13 @@ package org.schabi.newpipe.util.text; import android.content.Context; -import android.util.Log; import androidx.annotation.NonNull; -import androidx.appcompat.app.AlertDialog; import org.schabi.newpipe.MainActivity; -import org.schabi.newpipe.R; -import org.schabi.newpipe.error.ErrorPanelHelper; +import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; +import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; @@ -158,19 +157,13 @@ public final class InternalUrlsHandler { disposables.add(single.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(info -> { - final PlayQueue playQueue = - new SinglePlayQueue(info, seconds * 1000L); + final PlayQueue playQueue = new SinglePlayQueue(info, seconds * 1000L); NavigationHelper.playOnPopupPlayer(context, playQueue, false); }, throwable -> { - if (DEBUG) { - Log.e(TAG, "Could not play on popup: " + url, throwable); - } - new AlertDialog.Builder(context) - .setTitle(R.string.player_stream_failure) - .setMessage( - ErrorPanelHelper.Companion.getExceptionDescription(throwable)) - .setPositiveButton(R.string.ok, null) - .show(); + final var errorInfo = new ErrorInfo(throwable, UserAction.PLAY_ON_POPUP, url); + // This will only show a snackbar if the passed context has a root view: + // otherwise it will resort to showing a notification, so we are safe here. + ErrorUtil.showSnackbar(context, errorInfo); })); return true; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 922b7bd3f..21593674d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -877,4 +877,6 @@ Trending movies and shows Trending music Entry deleted + YouTube refused to provide data, asking for a login.\n\nYour IP might have been temporarily banned by YouTube, you can wait some time or switch to a different IP (for example by turning on/off a VPN, or by switching from WiFi to mobile data). + This content is not available for the currently selected content country.\n\nChange your selection from \"Settings > Content > Default content country\". From 29a3ca83b5b9c18c00a72a0dbfb2582a24f11f14 Mon Sep 17 00:00:00 2001 From: Stypox Date: Mon, 28 Jul 2025 23:57:55 +0200 Subject: [PATCH 33/43] Show better information about player errors --- .../org/schabi/newpipe/error/ErrorInfo.kt | 19 +++++++++++++------ .../MediaBrowserPlaybackPreparer.kt | 7 ++++--- app/src/main/res/values/strings.xml | 1 + 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt index 014be540f..f4af65bbc 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt @@ -23,6 +23,8 @@ import org.schabi.newpipe.extractor.exceptions.UnsupportedContentInCountryExcept import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentException import org.schabi.newpipe.extractor.exceptions.YoutubeSignInConfirmNotBotException import org.schabi.newpipe.ktx.isNetworkRelated +import org.schabi.newpipe.player.mediasource.FailedMediaSource +import org.schabi.newpipe.player.resolver.PlaybackResolver import org.schabi.newpipe.util.ServiceHelper @Parcelize @@ -97,9 +99,9 @@ class ErrorInfo( if (info == null) SERVICE_NONE else ServiceHelper.getNameOfServiceById(info.serviceId) @StringRes - private fun getMessageStringId( + fun getMessageStringId( throwable: Throwable?, - action: UserAction + action: UserAction? ): Int { return when { // content not available exceptions @@ -123,14 +125,19 @@ class ErrorInfo( throwable != null && throwable.isNetworkRelated -> R.string.network_error throwable is ExtractionException -> R.string.parsing_error - // ExoPlayer exceptions + // player exceptions throwable is ExoPlaybackException -> { - when (throwable.type) { - ExoPlaybackException.TYPE_SOURCE -> R.string.player_stream_failure - ExoPlaybackException.TYPE_UNEXPECTED -> R.string.player_recoverable_failure + val cause = throwable.cause + when { + cause is HttpDataSource.InvalidResponseCodeException && cause.responseCode == 403 -> R.string.player_error_403 + cause is Loader.UnexpectedLoaderException && cause.cause is ExtractionException -> getMessageStringId(throwable, action) + throwable.type == ExoPlaybackException.TYPE_SOURCE -> R.string.player_stream_failure + throwable.type == ExoPlaybackException.TYPE_UNEXPECTED -> R.string.player_recoverable_failure else -> R.string.player_unrecoverable_failure } } + throwable is FailedMediaSource.FailedMediaSourceException -> getMessageStringId(throwable.cause, action) + throwable is PlaybackResolver.ResolverException -> R.string.player_stream_failure // user actions (in case the exception is unrecognizable) action == UserAction.UI_ERROR -> R.string.app_ui_crash diff --git a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserPlaybackPreparer.kt b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserPlaybackPreparer.kt index 2948eeaf8..7f0f9f8b6 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserPlaybackPreparer.kt +++ b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserPlaybackPreparer.kt @@ -17,6 +17,7 @@ import io.reactivex.rxjava3.schedulers.Schedulers import org.schabi.newpipe.MainActivity import org.schabi.newpipe.NewPipeDatabase import org.schabi.newpipe.R +import org.schabi.newpipe.error.ErrorInfo import org.schabi.newpipe.extractor.InfoItem.InfoType import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler @@ -84,7 +85,7 @@ class MediaBrowserPlaybackPreparer( }, { throwable -> Log.e(TAG, "Failed to start playback of media ID [$mediaId]", throwable) - onPrepareError() + onPrepareError(throwable) } ) } @@ -115,9 +116,9 @@ class MediaBrowserPlaybackPreparer( ) } - private fun onPrepareError() { + private fun onPrepareError(throwable: Throwable) { setMediaSessionError.accept( - ContextCompat.getString(context, R.string.error_snackbar_message), + ContextCompat.getString(context, ErrorInfo.getMessageStringId(throwable, null)), PlaybackStateCompat.ERROR_CODE_APP_ERROR ) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 21593674d..a54ddb9ee 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -877,6 +877,7 @@ Trending movies and shows Trending music Entry deleted + HTTP error 403 occurred while playing, likely caused by an IP ban or streaming URL deobfuscation issues YouTube refused to provide data, asking for a login.\n\nYour IP might have been temporarily banned by YouTube, you can wait some time or switch to a different IP (for example by turning on/off a VPN, or by switching from WiFi to mobile data). This content is not available for the currently selected content country.\n\nChange your selection from \"Settings > Content > Default content country\". From 1bde2dcd9fbcb3402e1b5c9b9c297816d102cb80 Mon Sep 17 00:00:00 2001 From: Stypox Date: Tue, 29 Jul 2025 00:31:54 +0200 Subject: [PATCH 34/43] Fix ordering of error messages conditions --- .../org/schabi/newpipe/error/ErrorInfo.kt | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt index f4af65bbc..77f818b00 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt @@ -104,28 +104,8 @@ class ErrorInfo( action: UserAction? ): Int { return when { - // content not available exceptions - throwable is AccountTerminatedException -> R.string.account_terminated - throwable is AgeRestrictedContentException -> R.string.restricted_video_no_stream - throwable is GeographicRestrictionException -> R.string.georestricted_content - throwable is PaidContentException -> R.string.paid_content - throwable is PrivateContentException -> R.string.private_content - throwable is SoundCloudGoPlusContentException -> R.string.soundcloud_go_plus_content - throwable is UnsupportedContentInCountryException -> R.string.unsupported_content_in_country - throwable is YoutubeMusicPremiumContentException -> R.string.youtube_music_premium_content - throwable is YoutubeSignInConfirmNotBotException -> R.string.youtube_sign_in_confirm_not_bot_error - throwable is ContentNotAvailableException -> R.string.content_not_available - - // ReCaptchas should have already been handled elsewhere, - // but return an error message here just in case - throwable is ReCaptchaException -> R.string.recaptcha_request_toast - - // other extractor exceptions - throwable is ContentNotSupportedException -> R.string.content_not_supported - throwable != null && throwable.isNetworkRelated -> R.string.network_error - throwable is ExtractionException -> R.string.parsing_error - // player exceptions + // some may be IOException, so do these checks before isNetworkRelated! throwable is ExoPlaybackException -> { val cause = throwable.cause when { @@ -139,7 +119,30 @@ class ErrorInfo( throwable is FailedMediaSource.FailedMediaSourceException -> getMessageStringId(throwable.cause, action) throwable is PlaybackResolver.ResolverException -> R.string.player_stream_failure - // user actions (in case the exception is unrecognizable) + // content not available exceptions + throwable is AccountTerminatedException -> R.string.account_terminated + throwable is AgeRestrictedContentException -> R.string.restricted_video_no_stream + throwable is GeographicRestrictionException -> R.string.georestricted_content + throwable is PaidContentException -> R.string.paid_content + throwable is PrivateContentException -> R.string.private_content + throwable is SoundCloudGoPlusContentException -> R.string.soundcloud_go_plus_content + throwable is UnsupportedContentInCountryException -> R.string.unsupported_content_in_country + throwable is YoutubeMusicPremiumContentException -> R.string.youtube_music_premium_content + throwable is YoutubeSignInConfirmNotBotException -> R.string.youtube_sign_in_confirm_not_bot_error + throwable is ContentNotAvailableException -> R.string.content_not_available + + // other extractor exceptions + throwable is ContentNotSupportedException -> R.string.content_not_supported + // ReCaptchas should have already been handled elsewhere, + // but return an error message here just in case + throwable is ReCaptchaException -> R.string.recaptcha_request_toast + // test this at the end as many exceptions could be a subclass of IOException + throwable != null && throwable.isNetworkRelated -> R.string.network_error + // an extraction exception unrelated to the network + // is likely an issue with parsing the website + throwable is ExtractionException -> R.string.parsing_error + + // user actions (in case the exception is null or unrecognizable) action == UserAction.UI_ERROR -> R.string.app_ui_crash action == UserAction.REQUESTED_COMMENTS -> R.string.error_unable_to_load_comments action == UserAction.SUBSCRIPTION_CHANGE -> R.string.subscription_change_failed From a369deeef45b740e3dc4aca34ab23299fbe313e8 Mon Sep 17 00:00:00 2001 From: Stypox Date: Sat, 30 Aug 2025 14:33:04 +0200 Subject: [PATCH 35/43] Allow ErrorInfo messages with formatArgs - ErrorInfo.getMessage() now returns an ErrorMessage instance that can be formatted into a string using a context (this allows the construction of an ErrorInfo to remain independent of a Context) - now the service ID is used in ErrorInfo.getMessage() to customize some messages based on the currently selected service - player HTTP invalid statuses are now included in the message - building a custom error message for AccountTerminatedException was moved from ErrorPanelHelper to ErrorInfo --- app/build.gradle | 2 +- .../org/schabi/newpipe/RouterActivity.java | 2 +- .../newpipe/error/AcraReportSender.java | 2 +- .../schabi/newpipe/error/ErrorActivity.java | 2 +- .../org/schabi/newpipe/error/ErrorInfo.kt | 188 +++++++++++++----- .../schabi/newpipe/error/ErrorPanelHelper.kt | 19 +- .../org/schabi/newpipe/error/ErrorUtil.kt | 4 +- .../org/schabi/newpipe/error/UserAction.java | 3 +- .../SubscriptionsImportFragment.java | 2 +- .../MediaBrowserPlaybackPreparer.kt | 2 +- .../giga/ui/adapter/MissionAdapter.java | 6 +- app/src/main/res/values-ar-rLY/strings.xml | 1 - app/src/main/res/values-ar/strings.xml | 1 - app/src/main/res/values-az/strings.xml | 1 - app/src/main/res/values-be/strings.xml | 1 - app/src/main/res/values-bg/strings.xml | 1 - app/src/main/res/values-bn/strings.xml | 1 - app/src/main/res/values-ca/strings.xml | 1 - app/src/main/res/values-ckb/strings.xml | 1 - app/src/main/res/values-cs/strings.xml | 1 - app/src/main/res/values-da/strings.xml | 1 - app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-el/strings.xml | 1 - app/src/main/res/values-eo/strings.xml | 1 - app/src/main/res/values-es/strings.xml | 1 - app/src/main/res/values-et/strings.xml | 1 - app/src/main/res/values-eu/strings.xml | 1 - app/src/main/res/values-fa/strings.xml | 1 - app/src/main/res/values-fi/strings.xml | 1 - app/src/main/res/values-fr/strings.xml | 1 - app/src/main/res/values-gl/strings.xml | 1 - app/src/main/res/values-he/strings.xml | 1 - app/src/main/res/values-hi/strings.xml | 1 - app/src/main/res/values-hr/strings.xml | 1 - app/src/main/res/values-hu/strings.xml | 1 - app/src/main/res/values-in/strings.xml | 1 - app/src/main/res/values-is/strings.xml | 1 - app/src/main/res/values-it/strings.xml | 1 - app/src/main/res/values-ja/strings.xml | 1 - app/src/main/res/values-ka/strings.xml | 1 - app/src/main/res/values-ko/strings.xml | 1 - app/src/main/res/values-lt/strings.xml | 1 - app/src/main/res/values-lv/strings.xml | 1 - app/src/main/res/values-mk/strings.xml | 1 - app/src/main/res/values-ml/strings.xml | 1 - app/src/main/res/values-nb-rNO/strings.xml | 1 - app/src/main/res/values-nl/strings.xml | 1 - app/src/main/res/values-nqo/strings.xml | 1 - app/src/main/res/values-or/strings.xml | 1 - app/src/main/res/values-pa/strings.xml | 1 - app/src/main/res/values-pl/strings.xml | 1 - app/src/main/res/values-pt-rBR/strings.xml | 1 - app/src/main/res/values-pt-rPT/strings.xml | 1 - app/src/main/res/values-pt/strings.xml | 1 - app/src/main/res/values-ro/strings.xml | 1 - app/src/main/res/values-ru/strings.xml | 1 - app/src/main/res/values-ryu/strings.xml | 1 - app/src/main/res/values-sat/strings.xml | 1 - app/src/main/res/values-sc/strings.xml | 1 - app/src/main/res/values-sk/strings.xml | 1 - app/src/main/res/values-so/strings.xml | 1 - app/src/main/res/values-sq/strings.xml | 1 - app/src/main/res/values-sr/strings.xml | 1 - app/src/main/res/values-sv/strings.xml | 1 - app/src/main/res/values-ta/strings.xml | 1 - app/src/main/res/values-tr/strings.xml | 1 - app/src/main/res/values-uk/strings.xml | 1 - app/src/main/res/values-vi/strings.xml | 1 - app/src/main/res/values-zh-rCN/strings.xml | 1 - app/src/main/res/values-zh-rHK/strings.xml | 1 - app/src/main/res/values-zh-rTW/strings.xml | 1 - app/src/main/res/values/strings.xml | 8 +- 72 files changed, 154 insertions(+), 146 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 7f4166a57..38765476a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -214,7 +214,7 @@ dependencies { // the corresponding commit hash, since JitPack sometimes deletes artifacts. // If there’s already a git hash, just add more of it to the end (or remove a letter) // to cause jitpack to regenerate the artifact. - implementation 'com.github.Stypox:NewPipeExtractor:b8bd4cda8cca00a14940933e3d3635d5aafec222' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:0023b22095a2d62a60cdfc87f4b5cd85c8b266c3' implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0' /** Checkstyle **/ diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index dac2d29a1..cb7ea3dd7 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -276,7 +276,7 @@ public class RouterActivity extends AppCompatActivity { || errorInfo.getThrowable() instanceof ContentNotSupportedException) { // this exception does not usually indicate a problem that should be reported, // so just show a toast instead of the notification - Toast.makeText(context, errorInfo.getMessageStringId(), Toast.LENGTH_LONG).show(); + Toast.makeText(context, errorInfo.getMessage(context), Toast.LENGTH_LONG).show(); } else { ErrorUtil.createNotification(context, errorInfo); } diff --git a/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java b/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java index 4d9966364..8876a66e4 100644 --- a/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java +++ b/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java @@ -36,7 +36,7 @@ public class AcraReportSender implements ReportSender { ErrorUtil.openActivity(context, new ErrorInfo( new String[]{report.getString(ReportField.STACK_TRACE)}, UserAction.UI_ERROR, - ErrorInfo.SERVICE_NONE, + null, "ACRA report", R.string.app_ui_crash)); } diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java index a07b9b0b5..160dcca4d 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorActivity.java @@ -115,7 +115,7 @@ public class ErrorActivity extends AppCompatActivity { // normal bugreport buildInfo(errorInfo); - activityErrorBinding.errorMessageView.setText(errorInfo.getMessageStringId()); + activityErrorBinding.errorMessageView.setText(errorInfo.getMessage(this)); activityErrorBinding.errorView.setText(formErrorText(errorInfo.getStackTraces())); // print stack trace once again for debugging: diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt index 77f818b00..bac294d0f 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt @@ -1,7 +1,9 @@ package org.schabi.newpipe.error +import android.content.Context import android.os.Parcelable import androidx.annotation.StringRes +import androidx.core.content.ContextCompat import com.google.android.exoplayer2.ExoPlaybackException import com.google.android.exoplayer2.upstream.HttpDataSource import com.google.android.exoplayer2.upstream.Loader @@ -9,6 +11,8 @@ import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize import org.schabi.newpipe.R import org.schabi.newpipe.extractor.Info +import org.schabi.newpipe.extractor.ServiceList +import org.schabi.newpipe.extractor.ServiceList.YouTube import org.schabi.newpipe.extractor.exceptions.AccountTerminatedException import org.schabi.newpipe.extractor.exceptions.AgeRestrictedContentException import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException @@ -18,22 +22,21 @@ import org.schabi.newpipe.extractor.exceptions.GeographicRestrictionException import org.schabi.newpipe.extractor.exceptions.PaidContentException import org.schabi.newpipe.extractor.exceptions.PrivateContentException import org.schabi.newpipe.extractor.exceptions.ReCaptchaException +import org.schabi.newpipe.extractor.exceptions.SignInConfirmNotBotException import org.schabi.newpipe.extractor.exceptions.SoundCloudGoPlusContentException import org.schabi.newpipe.extractor.exceptions.UnsupportedContentInCountryException import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentException -import org.schabi.newpipe.extractor.exceptions.YoutubeSignInConfirmNotBotException import org.schabi.newpipe.ktx.isNetworkRelated import org.schabi.newpipe.player.mediasource.FailedMediaSource import org.schabi.newpipe.player.resolver.PlaybackResolver -import org.schabi.newpipe.util.ServiceHelper @Parcelize -class ErrorInfo( +class ErrorInfo private constructor( val stackTraces: Array, val userAction: UserAction, - val serviceName: String, + val serviceId: Int?, val request: String, - val messageStringId: Int + private val message: ErrorMessage, ) : Parcelable { // no need to store throwable, all data for report is in other variables @@ -44,14 +47,14 @@ class ErrorInfo( private constructor( throwable: Throwable, userAction: UserAction, - serviceName: String, + serviceId: Int?, request: String ) : this( throwableToStringList(throwable), userAction, - serviceName, + serviceId, request, - getMessageStringId(throwable, userAction) + getMessage(throwable, userAction, serviceId) ) { this.throwable = throwable } @@ -59,97 +62,176 @@ class ErrorInfo( private constructor( throwable: List, userAction: UserAction, - serviceName: String, + serviceId: Int?, request: String ) : this( throwableListToStringList(throwable), userAction, - serviceName, + serviceId, request, - getMessageStringId(throwable.firstOrNull(), userAction) + getMessage(throwable.firstOrNull(), userAction, serviceId) ) { this.throwable = throwable.firstOrNull() } + // constructor to manually build ErrorInfo + constructor(stackTraces: Array, userAction: UserAction, serviceId: Int?, request: String, @StringRes message: Int) : + this(stackTraces, userAction, serviceId, request, ErrorMessage(message)) + // constructors with single throwable constructor(throwable: Throwable, userAction: UserAction, request: String) : - this(throwable, userAction, SERVICE_NONE, request) + this(throwable, userAction, null, request) constructor(throwable: Throwable, userAction: UserAction, request: String, serviceId: Int) : - this(throwable, userAction, ServiceHelper.getNameOfServiceById(serviceId), request) + this(throwable, userAction, serviceId, request) constructor(throwable: Throwable, userAction: UserAction, request: String, info: Info?) : - this(throwable, userAction, getInfoServiceName(info), request) + this(throwable, userAction, info?.serviceId, request) // constructors with list of throwables constructor(throwable: List, userAction: UserAction, request: String) : - this(throwable, userAction, SERVICE_NONE, request) + this(throwable, userAction, null, request) constructor(throwable: List, userAction: UserAction, request: String, serviceId: Int) : - this(throwable, userAction, ServiceHelper.getNameOfServiceById(serviceId), request) + this(throwable, userAction, serviceId, request) constructor(throwable: List, userAction: UserAction, request: String, info: Info?) : - this(throwable, userAction, getInfoServiceName(info), request) + this(throwable, userAction, info?.serviceId, request) + + fun getServiceName(): String { + return getServiceName(serviceId) + } + + fun getMessage(context: Context): String { + return message.getString(context) + } companion object { - const val SERVICE_NONE = "none" + @Parcelize + class ErrorMessage( + @StringRes + private val stringRes: Int, + private vararg val formatArgs: String, + ) : Parcelable { + fun getString(context: Context): String { + return if (formatArgs.isEmpty()) { + // use ContextCompat.getString() just in case context is not AppCompatActivity + ContextCompat.getString(context, stringRes) + } else { + // ContextCompat.getString() with formatArgs does not exist, so we just + // replicate its source code but with formatArgs + ContextCompat.getContextForLanguage(context).getString(stringRes, *formatArgs) + } + } + } + + const val SERVICE_NONE = "" + + private fun getServiceName(serviceId: Int?) = + // not using getNameOfServiceById since we want to accept a nullable serviceId and we + // want to default to SERVICE_NONE + ServiceList.all()?.firstOrNull { it.serviceId == serviceId }?.serviceInfo?.name + ?: SERVICE_NONE fun throwableToStringList(throwable: Throwable) = arrayOf(throwable.stackTraceToString()) fun throwableListToStringList(throwableList: List) = throwableList.map { it.stackTraceToString() }.toTypedArray() - private fun getInfoServiceName(info: Info?) = - if (info == null) SERVICE_NONE else ServiceHelper.getNameOfServiceById(info.serviceId) - - @StringRes - fun getMessageStringId( + fun getMessage( throwable: Throwable?, - action: UserAction? - ): Int { + action: UserAction?, + serviceId: Int?, + ): ErrorMessage { return when { // player exceptions // some may be IOException, so do these checks before isNetworkRelated! throwable is ExoPlaybackException -> { val cause = throwable.cause when { - cause is HttpDataSource.InvalidResponseCodeException && cause.responseCode == 403 -> R.string.player_error_403 - cause is Loader.UnexpectedLoaderException && cause.cause is ExtractionException -> getMessageStringId(throwable, action) - throwable.type == ExoPlaybackException.TYPE_SOURCE -> R.string.player_stream_failure - throwable.type == ExoPlaybackException.TYPE_UNEXPECTED -> R.string.player_recoverable_failure - else -> R.string.player_unrecoverable_failure + cause is HttpDataSource.InvalidResponseCodeException -> { + if (cause.responseCode == 403) { + if (serviceId == YouTube.serviceId) { + ErrorMessage(R.string.youtube_player_http_403) + } else { + ErrorMessage(R.string.player_http_403) + } + } else { + ErrorMessage(R.string.player_http_invalid_status, cause.responseCode.toString()) + } + } + cause is Loader.UnexpectedLoaderException && cause.cause is ExtractionException -> + getMessage(throwable, action, serviceId) + throwable.type == ExoPlaybackException.TYPE_SOURCE -> + ErrorMessage(R.string.player_stream_failure) + throwable.type == ExoPlaybackException.TYPE_UNEXPECTED -> + ErrorMessage(R.string.player_recoverable_failure) + else -> + ErrorMessage(R.string.player_unrecoverable_failure) } } - throwable is FailedMediaSource.FailedMediaSourceException -> getMessageStringId(throwable.cause, action) - throwable is PlaybackResolver.ResolverException -> R.string.player_stream_failure + throwable is FailedMediaSource.FailedMediaSourceException -> + getMessage(throwable.cause, action, serviceId) + throwable is PlaybackResolver.ResolverException -> + ErrorMessage(R.string.player_stream_failure) // content not available exceptions - throwable is AccountTerminatedException -> R.string.account_terminated - throwable is AgeRestrictedContentException -> R.string.restricted_video_no_stream - throwable is GeographicRestrictionException -> R.string.georestricted_content - throwable is PaidContentException -> R.string.paid_content - throwable is PrivateContentException -> R.string.private_content - throwable is SoundCloudGoPlusContentException -> R.string.soundcloud_go_plus_content - throwable is UnsupportedContentInCountryException -> R.string.unsupported_content_in_country - throwable is YoutubeMusicPremiumContentException -> R.string.youtube_music_premium_content - throwable is YoutubeSignInConfirmNotBotException -> R.string.youtube_sign_in_confirm_not_bot_error - throwable is ContentNotAvailableException -> R.string.content_not_available + throwable is AccountTerminatedException -> + throwable.message + ?.takeIf { reason -> !reason.isEmpty() } + ?.let { reason -> + ErrorMessage( + R.string.account_terminated_service_provides_reason, + getServiceName(serviceId), + reason + ) + } + ?: ErrorMessage(R.string.account_terminated) + throwable is AgeRestrictedContentException -> + ErrorMessage(R.string.restricted_video_no_stream) + throwable is GeographicRestrictionException -> + ErrorMessage(R.string.georestricted_content) + throwable is PaidContentException -> + ErrorMessage(R.string.paid_content) + throwable is PrivateContentException -> + ErrorMessage(R.string.private_content) + throwable is SoundCloudGoPlusContentException -> + ErrorMessage(R.string.soundcloud_go_plus_content) + throwable is UnsupportedContentInCountryException -> + ErrorMessage(R.string.unsupported_content_in_country) + throwable is YoutubeMusicPremiumContentException -> + ErrorMessage(R.string.youtube_music_premium_content) + throwable is SignInConfirmNotBotException -> + ErrorMessage(R.string.sign_in_confirm_not_bot_error, getServiceName(serviceId)) + throwable is ContentNotAvailableException -> + ErrorMessage(R.string.content_not_available) // other extractor exceptions - throwable is ContentNotSupportedException -> R.string.content_not_supported + throwable is ContentNotSupportedException -> + ErrorMessage(R.string.content_not_supported) // ReCaptchas should have already been handled elsewhere, // but return an error message here just in case - throwable is ReCaptchaException -> R.string.recaptcha_request_toast + throwable is ReCaptchaException -> + ErrorMessage(R.string.recaptcha_request_toast) // test this at the end as many exceptions could be a subclass of IOException - throwable != null && throwable.isNetworkRelated -> R.string.network_error + throwable != null && throwable.isNetworkRelated -> + ErrorMessage(R.string.network_error) // an extraction exception unrelated to the network // is likely an issue with parsing the website - throwable is ExtractionException -> R.string.parsing_error + throwable is ExtractionException -> + ErrorMessage(R.string.parsing_error) // user actions (in case the exception is null or unrecognizable) - action == UserAction.UI_ERROR -> R.string.app_ui_crash - action == UserAction.REQUESTED_COMMENTS -> R.string.error_unable_to_load_comments - action == UserAction.SUBSCRIPTION_CHANGE -> R.string.subscription_change_failed - action == UserAction.SUBSCRIPTION_UPDATE -> R.string.subscription_update_failed - action == UserAction.LOAD_IMAGE -> R.string.could_not_load_thumbnails - action == UserAction.DOWNLOAD_OPEN_DIALOG -> R.string.could_not_setup_download_menu - else -> R.string.error_snackbar_message + action == UserAction.UI_ERROR -> + ErrorMessage(R.string.app_ui_crash) + action == UserAction.REQUESTED_COMMENTS -> + ErrorMessage(R.string.error_unable_to_load_comments) + action == UserAction.SUBSCRIPTION_CHANGE -> + ErrorMessage(R.string.subscription_change_failed) + action == UserAction.SUBSCRIPTION_UPDATE -> + ErrorMessage(R.string.subscription_update_failed) + action == UserAction.LOAD_IMAGE -> + ErrorMessage(R.string.could_not_load_thumbnails) + action == UserAction.DOWNLOAD_OPEN_DIALOG -> + ErrorMessage(R.string.could_not_setup_download_menu) + else -> + ErrorMessage(R.string.error_snackbar_message) } } } diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt index 66d4d9fae..959759127 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt @@ -14,14 +14,11 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.disposables.Disposable import org.schabi.newpipe.MainActivity import org.schabi.newpipe.R -import org.schabi.newpipe.extractor.exceptions.AccountTerminatedException import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException import org.schabi.newpipe.extractor.exceptions.ReCaptchaException -import org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty import org.schabi.newpipe.ktx.animate import org.schabi.newpipe.ktx.isInterruptedCaused -import org.schabi.newpipe.util.ServiceHelper import org.schabi.newpipe.util.external_communication.ShareUtils import java.util.concurrent.TimeUnit @@ -99,20 +96,6 @@ class ErrorPanelHelper( errorRetryButton.isVisible = retryShouldBeShown showAndSetOpenInBrowserButtonAction(errorInfo) - } else if (errorInfo.throwable is AccountTerminatedException) { - errorTextView.setText(R.string.account_terminated) - - if (!isNullOrEmpty((errorInfo.throwable as AccountTerminatedException).message)) { - errorServiceInfoTextView.text = context.resources.getString( - R.string.service_provides_reason, - ServiceHelper.getSelectedService(context)?.serviceInfo?.name ?: "" - ) - errorServiceInfoTextView.isVisible = true - - errorServiceExplanationTextView.text = - (errorInfo.throwable as AccountTerminatedException).message - errorServiceExplanationTextView.isVisible = true - } } else { showAndSetErrorButtonAction( R.string.error_snackbar_action @@ -120,7 +103,7 @@ class ErrorPanelHelper( ErrorUtil.openActivity(context, errorInfo) } - errorTextView.setText(errorInfo.messageStringId) + errorTextView.text = errorInfo.getMessage(context) if (errorInfo.throwable !is ContentNotAvailableException && errorInfo.throwable !is ContentNotSupportedException diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt index 958188b6a..520d02b3b 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt @@ -122,7 +122,7 @@ class ErrorUtil { ) .setSmallIcon(R.drawable.ic_bug_report) .setContentTitle(context.getString(R.string.error_report_notification_title)) - .setContentText(context.getString(errorInfo.messageStringId)) + .setContentText(errorInfo.getMessage(context)) .setAutoCancel(true) .setContentIntent( PendingIntentCompat.getActivity( @@ -156,7 +156,7 @@ class ErrorUtil { // fallback to showing a notification if no root view is available createNotification(context, errorInfo) } else { - Snackbar.make(rootView, errorInfo.messageStringId, Snackbar.LENGTH_LONG) + Snackbar.make(rootView, errorInfo.getMessage(context), Snackbar.LENGTH_LONG) .setActionTextColor(Color.YELLOW) .setAction(context.getString(R.string.error_snackbar_action).uppercase()) { openActivity(context, errorInfo) diff --git a/app/src/main/java/org/schabi/newpipe/error/UserAction.java b/app/src/main/java/org/schabi/newpipe/error/UserAction.java index 997bff996..64829523a 100644 --- a/app/src/main/java/org/schabi/newpipe/error/UserAction.java +++ b/app/src/main/java/org/schabi/newpipe/error/UserAction.java @@ -34,7 +34,8 @@ public enum UserAction { CHECK_FOR_NEW_APP_VERSION("check for new app version"), OPEN_INFO_ITEM_DIALOG("open info item dialog"), GETTING_MAIN_SCREEN_TAB("getting main screen tab"), - PLAY_ON_POPUP("play on popup"); + PLAY_ON_POPUP("play on popup"), + SUBSCRIPTIONS("loading subscriptions"),; private final String message; diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java index 77a70afa9..501639ff8 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java @@ -89,7 +89,7 @@ public class SubscriptionsImportFragment extends BaseFragment { if (supportedSources.isEmpty() && currentServiceId != Constants.NO_SERVICE_ID) { ErrorUtil.showSnackbar(activity, new ErrorInfo(new String[]{}, UserAction.SUBSCRIPTION_IMPORT_EXPORT, - ServiceHelper.getNameOfServiceById(currentServiceId), + currentServiceId, "Service does not support importing subscriptions", R.string.general_error)); activity.finish(); diff --git a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserPlaybackPreparer.kt b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserPlaybackPreparer.kt index 7f0f9f8b6..4815965a3 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserPlaybackPreparer.kt +++ b/app/src/main/java/org/schabi/newpipe/player/mediabrowser/MediaBrowserPlaybackPreparer.kt @@ -118,7 +118,7 @@ class MediaBrowserPlaybackPreparer( private fun onPrepareError(throwable: Throwable) { setMediaSessionError.accept( - ContextCompat.getString(context, ErrorInfo.getMessageStringId(throwable, null)), + ErrorInfo.getMessage(throwable, null, null).getString(context), PlaybackStateCompat.ERROR_CODE_APP_ERROR ) } 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 79dda9011..31065d57c 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 @@ -563,11 +563,11 @@ public class MissionAdapter extends Adapter implements Handler.Callb } request.append("]"); - String service; + Integer service; try { - service = NewPipe.getServiceByUrl(mission.source).getServiceInfo().getName(); + service = NewPipe.getServiceByUrl(mission.source).getServiceId(); } catch (Exception e) { - service = ErrorInfo.SERVICE_NONE; + service = null; } ErrorUtil.createNotification(mContext, diff --git a/app/src/main/res/values-ar-rLY/strings.xml b/app/src/main/res/values-ar-rLY/strings.xml index 7f881a9c2..35e6cb5e7 100644 --- a/app/src/main/res/values-ar-rLY/strings.xml +++ b/app/src/main/res/values-ar-rLY/strings.xml @@ -641,7 +641,6 @@ الصوت : %s خطوة حل - %s يقدم هذا السبب: الدفق المحدد غير مدعوم من قبل المشغلون الخارجيون عن تطبيق نيوپايپ تسريع إلى الأمام/-ترجيع وقت البحث diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 7865b1f9d..f5c8efb0d 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -649,7 +649,6 @@ تمكين تحديد نص في الوصف يمكنك الآن تحديد نص داخل الوصف. لاحظ أن الصفحة قد تومض وقد لا تكون الروابط قابلة للنقر أثناء وضع التحديد. فتح الموقع - %s يقدم هذا السبب: تم إنهاء الحساب لا يوفر وضع التغذية السريعة مزيدًا من المعلومات حول هذا الموضوع. حساب منشئ المحتوى قد تم إنهائه. diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index 78cb6c013..0e0135c71 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -501,7 +501,6 @@ Endirmə növbəsini məhdudlaşdır Eyni vaxtda ancaq bir endirmə həyata keçiriləcək Hesab ləğv edildi - %s bu səbəbi təmin edir: Yükləmə başladı Açıqlamadakı mətni seçməyi qeyri-aktiv et Kateqoriya diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index a0930a9f8..72b08414e 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -704,7 +704,6 @@ Гэта змесціва з\'яўляецца прыватным, таму NewPipe не можа яго трансляваць або спампоўваць. Гэта відэа даступна толькі для падпісчыкаў YouTube Music Premium, таму NewPipe не можа яго трансляваць або спампоўваць. Уліковы запіс спынены - %s дае наступную прычыну: Вартае ўвагі Унутраная Прагледжаныя цалкам diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 7ecab17c6..870b6be79 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -416,7 +416,6 @@ Страница на плейлиста Глави Лиценз - %s посочва следната причина: Маркери Поверителност Език diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index 5721f12ee..682b59fe3 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -540,7 +540,6 @@ \'%s\' এর জন্য ফিড প্রক্রিয়া করা যাচ্ছে না। বর্ণনার লেখা নির্বাচন করা নিষ্ক্রিয় করো বর্ণনার লেখা নির্বাচন করা সক্ষম করো - %s এই কারণ বলছে: প্রক্রিয়াকরণ ফিডে ত্রুটি ওয়েবসাইট খুলুন অ্যাকাউন্ট ধ্বংসকৃত diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 819c9ff0b..dadac3c3f 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -612,7 +612,6 @@ Pot seleccionar el seu tema fosc favorit aqui sota Selecciona el teu tema fosc favorit — %s Automàtic (tema del dispositiu) - %s dóna aquesta raó: Usuari suspes El compte de l\'autor ha estat esborrat. \nNewPipe no serà capaç de carregar aquest fil en el futur. diff --git a/app/src/main/res/values-ckb/strings.xml b/app/src/main/res/values-ckb/strings.xml index 7c23d1d1d..f0ddfb6e9 100644 --- a/app/src/main/res/values-ckb/strings.xml +++ b/app/src/main/res/values-ckb/strings.xml @@ -596,7 +596,6 @@ ڕادیۆ تایبەتکراو ئه‌م بابه‌ته‌ ته‌نیا بۆ ئه‌و كه‌سانه‌ به‌رده‌سته‌ كه‌ پاره‌یان داوه‌ ، بۆیه‌ ناتوانرێت له‌ نیوپایپه‌وه‌ داببه‌زێنرێت. - %s ئه‌م هۆكاره‌ دابین ده‌كات: هه‌ژمار له‌ناوبراوه‌ ئه‌م ڤیدیۆیه‌ ته‌نیا له‌ وه‌شانی نایابی یوتوب میوزیك به‌رده‌سته‌ ، بۆیه‌ ناتوانرێت له‌ نیوپایپه‌وه‌ داببه‌زێنرێت. ئه‌مه‌ تراكی SoundCloud Go+ ه‌ ، لانی كه‌م له‌ وڵاته‌كه‌ی تۆدا، ناتوانرێت له‌لایه‌ن نیوپایپه‌وه‌ داببه‌زێنرێت. diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 2eabe57b0..756cf17cf 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -619,7 +619,6 @@ Vypnout výběr textu v popisu Zapnout výběr textu v popisu Nyní můžete vybrat v popisu text. Pamatujte, že v režimu výběru může stránka blikat a odkazy nemusí reagovat na kliknutí. - %s udává teno důvod: Účet uzavřen Režim rychlého feedu o tom neposkytuje více informací. Autorův účet byl uzavřen. diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index db464ca61..5354bb7ad 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -554,7 +554,6 @@ Dette indhold er privat, så det kan ikke streames eller hentes af NewPipe. Nyligt tilføjede Fremhævede - %s giver denne grund: %s lytter %s lyttere diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 3e7adfcd9..b99209f0f 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -627,7 +627,6 @@ Du wirst jedes Mal gefragt werden, wohin der Download gespeichert werden soll Fehler beim Laden des Feeds Konnte Feed für \'%s\' nicht laden. - %s gibt diesen Grund an: An Tablet-Modus Aus diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 0781776d7..5cb645bfa 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -608,7 +608,6 @@ Ενεργοποίηση επιλογής κειμένου στην περιγραφή Τώρα μπορείτε να επιλέξετε κείμενο εντός της περιγραφής. Σημειώστε ότι, η σελίδα μπορεί να παρουσιάζει αστάθεια κατά τη διάρκεια της κατάστασης επιλογής κειμένου. Ανοικτή ιστοσελίδα - Το %s παρέχει αυτή την αιτία: Ο λογαριασμός διαγράφηκε Η κατάσταση γρήγορης τροφοδοσίας δεν παρέχει περισσότερες πληροφορίες. Ο λογαριασμός του δημιουργού έχει διαγραφεί. diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index 408035e00..3dde69618 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -504,7 +504,6 @@ Ŝaltita Etikedoj Elŝutado komenciĝis - %s donas tiun kialon: Tiu enaĵo ne disponeblas en via lando. Freŝaj De %s diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index a1ee4f092..c88da0a2f 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -611,7 +611,6 @@ Deshabilitar la selección de texto de la descripción Habilitar la selección de texto de la descripción Ahora puede seleccionar el texto dentro de la descripción. Note que la página puede parpadear y los links no serán cliqueables mientras está en el modo de selección. - %s da esta razón: No fue posible cargar el feed por \'%s\'. Cuenta cancelada El modo de muro rápido no arroja más información sobre esto. diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index d25229cd0..dc9643678 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -562,7 +562,6 @@ Näita pisipilte Kasuta pisipilti nii lukustusvaate kui teavituste taustana Kasutajakonto on suletud - %s toob põhjuseks: Võimalda valida kirjelduse teksti Ära võimalda valida kirjelduse teksti Kategooria diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 20a7148eb..5c963d6b7 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -615,7 +615,6 @@ Non gorde galdetuko zaizu deskarga bakoitzean Ez da deskargatzeko karpetarik ezarri oraindik, aukeratu lehenetsitako deskargatzeko karpeta orain Pribatutasuna - %s arrazoi hau ematen du: Kontua ezabatu da Jario azkarrak ez du honi buruz informazio gehiagorik ematen. Adin muga diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index 8b8fdd281..403fb4c11 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -626,7 +626,6 @@ \nنیوپایپ قادر به بار کردن این خوراک در آینده نیست. \nمی‌خواهید اشتراک این کانال را لغو کنید؟ حالت خوراک سریع، اطَلاعات بیش‌تری در این باره نمی‌دهد. - %s این دلیل را آورد: پیش‌نمایش بندانگشتی نوار جویش قلب‌شده به دست ایجادگر پیشنهادهای جست‌وجوی محلّی diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 0c092284c..22c1fab12 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -592,7 +592,6 @@ Yöteema Poista käytöstä tekstinvalinta kuvauskentän sisältä Voit nyt valita tekstin kuvauskentän sisältä. Huomioithan, että valintatilan aikana sivu voi vilkkua ja linkit eivät ehkä ole klikattavia. - %s tuo tämän syyn: Säätövivun kuvakkeen esikatselu Poista median tunnelointi käytöstä, jos havaitset mustan näyttöruudun tai änkytystä videon toistossa. Poista median tunnelointi käytöstä diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 9cf8c6b2b..ffb78e19f 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -620,7 +620,6 @@ Étiquettes Catégorie Vous pouvez maintenant sélectionner du texte à l’intérieur de la description. Notez que la page peut scintiller et que les liens peuvent ne pas être cliquables en mode sélection. - %s indique le motif : Aucun dossier de téléchargement n’est défini pour le moment, sélectionnez le dossier de téléchargement par défaut Ouvrir le site web Compte résilié diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 3d98682be..aacaf9288 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -554,7 +554,6 @@ Agora pode seleccionar o texto na descrición. Teña en conta que a páxina pode cintilar e as ligazóns poden non ser clicábeis no modo selección. Automático (Tema do dispositivo) Radio - %s dá este motivo: Este contido non está dispoñíbel no seu país. Capítulos Recentes diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index 4553679ac..2131dc9c0 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -632,7 +632,6 @@ \nל־NewPipe לא תהיה אפשרות להוריד את ההזנה הזאת בעתיד. \nלהסיר את המינוי מהערוץ הזה\? פתיחת האתר - %s מספק את הסיבה הבאה: החשבון הושמד מצב ההזנה המהירה לא מספק מידע נוסף על כך. לא ניתן לטעון את ההזנה עבור ‚%s’. diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index e4484742b..dd23cfc08 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -655,7 +655,6 @@ मीडिया टनलिंग अक्षम करें \"क्रैश द प्लेयर\" दिखाएं लोड नहीं हुआ: %d - %s इसका कारण प्रदान करता है: टैग लाइसेंस यदि आपको ऐप का उपयोग करने में परेशानी हो रही है, तो सामान्य प्रश्नों के इन उत्तरों को देखना सुनिश्चित करें! diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 414fdf185..77a256ba4 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -639,7 +639,6 @@ Interno Privatnost Sada možeš odabrati tekst u opisu. Napomena: stranica će možda treperiti i možda nećeš moći kliknuti poveznice u načinu rada za odabir teksta. - %s pruža ovaj razlog: Obrada u tijeku … Može malo potrajati Za ukljanjanje stavki povuci ih Prikaži indikatore slike diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index d196268e2..cf0e9da04 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -537,7 +537,6 @@ Kapcsolódó elemek Ellenőrizze, hogy létezik-e már olyan jegy, amely az összeomlásával foglalkozik. Ha duplikált jegyet ad fel, akkor olyan időt vesz el tőlünk, amelyet a hiba javítására tudnánk fordítani. Minimalizálás alkalmazásváltáskor - A(z) %s ezt az okot adta meg: Helyi keresési javaslatok Távoli keresési javaslatok A fő lejátszó teljes képernyős indítása diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 72316eff9..3c3f03192 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -599,7 +599,6 @@ Aktifkan dapat memilih teks pada deskripsi Anda sekarang dapat memilih teks di dalam deskripsi. Perhatikan bahwa halaman mungkin berkedip dan tautan tidak dapat diklik saat dalam mode pemilihan. Buka situs web - %s menyediakan alasan ini: Akun dinonaktifkan Mode langganan cepat tidak menyediakan lebih banyak info tentang ini. Akun kreator telah dinonaktifkan. diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index 936705ccf..9daa67dbf 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -573,7 +573,6 @@ Enginn viðeigandi skráarstjóri fannst fyrir þessa aðgerð. \nVinsamlegast settu upp skráarstjóra sem styður Geymsluaðgangsramma (SAF) Þetta efni er ekki fáanlegt í þínu landi. - %s gefur þessa ástæðu: Þetta efni er aðeins í boði fyrir notendur sem hafa greitt — það er ekki hægt að streyma því eða sækja með NewPipe. Sjálfvirk (þema tækis) Veldu uppáhalds næturþemu þína — %s diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index b743f750d..459bab3d3 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -619,7 +619,6 @@ Attiva la selezione del testo nella descrizione È possibile selezionare il testo all\'interno della descrizione. In modalità selezione la pagina potrebbe sfarfallare e i collegamenti potrebbero non essere cliccabili. Visita il sito - %s fornisce questa motivazione: Account chiuso Il recupero veloce dei feed non fornisce ulteriori informazioni al riguardo. L\'account dell\'autore è stato chiuso. diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 9e8ec1c88..3274062b5 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -612,7 +612,6 @@ オフ オン タブレットモード - %s がこの理由を提示: 表示しない 低品質 (小) 高品質 (大) diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index 45804fcfa..b27443344 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -545,7 +545,6 @@ ეს ხელმიუწვდომელია თქვენი ქვეყნიდან. ეს მასალა პირადულია, ამიტომაც NewPipe-ს მისი არც მთლიანად და არც თანდათანობით ჩამოწერა არ შეუძლია. ანგარიში შეწყვეტილია - %s იძლევა ამ მიზეზს: ეს მასალა ხელმისაწვდომია მხოლოდ გადამხდელებისთვის, ამიტომაც NewPipe-ს მისი არც მთლიანად და არც თანდათანობით ჩამოწერა არ შეუძლია. გამორჩეული რადიო diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 016be8743..6a7e463a1 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -645,7 +645,6 @@ 챕터 최근 계정이 해지됨 - %s은(는) 다음과 같은 이유를 제공: 이것은 적어도 귀하의 국가에서 SoundCloud Go+ 트랙이므로 NewPipe에서 스트리밍하거나 다운로드할 수 없습니다. 자동 (장치 테마) 고정된 댓글 diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 3324b423c..91c8005ce 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -623,7 +623,6 @@ Įgalinti teksto pasirinkimą apraše Neleisti pasirinkti teksto apraše Dabar apraše galite pasirinkti tekstą aprašyme. Atminkite, kad puslapis gali mirgėti, o nuorodos gali būti nespustelėjamos, kai veikia pasirinkimo režimas. - %s pateikia šią priežastį: Paskyra anuliuota Greito srauto režimas nesuteikia daugiau informacijos apie tai. Autoriaus paskyra anuliuota. diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index 13e163f72..c769392cf 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -631,7 +631,6 @@ \nNewPipe turpmāk nevarēs ielādēt šo plūsmu. \nVai vēlaties atteikties no šī kanāla abonēšanas\? Ātrās straumes režīms nesniedz vairāk informācijas par šo. - %s dod šādu pamatojumu: Izslēgt teksta atlasīšanu video aprakstā Iekšeji Autors piekrīt diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index 8b493ba08..3a8fa2f07 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -431,7 +431,6 @@ Неуспешно вчитување на новинска лента за „%s“. Прикажи / скриј стримови Оваа содржина е приватна, така што не може да биде емитувана или преземена од страна на NewPipe. - %s ја посочува следната причина: Истакнато Радио Автоматски (режим на уредот) diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index adba80891..5a449025e 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -613,7 +613,6 @@ ടാഗുക്കൾ വിഭാഗം താക്കൾക് ഇപ്പോൾ ഡിസ്ക്രിപ്ഷൻ ബോക്സിലെ ടെക്സ്റ്റ്‌ തിരഞ്ഞെടുക്കാൻ സാധിക്കും. ശ്രെദ്ധിക്കുക സെലെക്ഷൻ മോഡിൽ പേജ് ചിലപ്പോൾ മിന്നുകയും ലിങ്കുകൾ ക്ലിക്ക് ചെയ്യാനാകാതെയും വന്നേക്കാം. - ഇതിന്റെ കാരണം %s നൽകും: അക്കൗണ്ട് ഇല്ലാതായിരിക്കുന്നു ഫാസ്റ്റ് ഫീഡ് മോഡ് കൂടുതൽ വിവരങ്ങൾ നൽകില്ല. സൃഷ്ടാവിന്റെ അക്കൗണ്ട് ഇല്ലാതായിരിക്കുന്നു. diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 027e6fe39..d5edc2060 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -600,7 +600,6 @@ \nØnsker du å oppheve ditt abonnement på denne kanalen\? Skru av merking av tekst i beskrivelsen Skru på merking av tekst i beskrivelsen - %s oppgav denne grunnen: Konto terminert Kunne ikke laste inn informasjonskanal for «%s». Kunne ikke laste inn informasjonskanal diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 75822036b..9f99e3a70 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -612,7 +612,6 @@ Aan Tablet-modus Website openen - %s geeft de volgende reden: Account getermineerd De snelle feed mode levert hierover niet meer informatie. De account van de auteur is getermineerd. diff --git a/app/src/main/res/values-nqo/strings.xml b/app/src/main/res/values-nqo/strings.xml index 739193302..caf8509e3 100644 --- a/app/src/main/res/values-nqo/strings.xml +++ b/app/src/main/res/values-nqo/strings.xml @@ -627,7 +627,6 @@ ߞߐߕߐ߯ ߡߊߡߙߊߟߊ߲߫ ߛߌ߫ ߡߊ߫ ߛߐ߬ߘߐ߲߬ ߞߋߥߊߟߌ ߣߌ߲߬ ߞߊ߲ߡߊ߬. \nߘߌ߬ߢߍ߬ ߦߋ߫ ߞߐߕߐ߯ ߡߊߡߙߊߟߊ߲ ߘߏ߫ ߡߊߞߍ߫ ߡߍ߲ ߣߌ߫ ߡߙߊ߬ߘߐ߬ߦߊ ߟߊߛߐ߬ߘߐ߲ ߡߎ߬ߙߊ߲߬ߞߊ߲ߞߋ ߘߌ߫ ߓߍ߲߬ ߦߋߡߍ߲ߕߊ ߘߌ߫ ߡߊߛߐ߬ߘߐ߲߬ YouTube Music Premium ߛߌ߲߬ߝߏ߲ ߠߎ߬ ߟߋ߬ ߘߐߙߐ߲߫ ߓߟߏ߫߸ ߏ߬ ߘߐ߫ ߊ߬ ߕߍ߫ ߛߋ߫ ߘߐߛߊߙߌ߫ ߟߊ߫ ߥߟߊ߫ ߞߵߊ߬ ߟߊߖߌ߰ ߣߌߎߔߌߔ ߓߟߏ. - %s ߦߋ߫ ߞߎ߲߭ ߣߌ߲߬ ߠߋ߬ ߝߐ߫ ߟߊ߫: ߛߊ߲ߞߊߥߟߌ ߥߎߢߊ߲ߓߍ߲ ߖߘߍ߬ߢߍ߫ (ߕߙߏߞߏ߫ ߛߊߛߊ) diff --git a/app/src/main/res/values-or/strings.xml b/app/src/main/res/values-or/strings.xml index 519c8aa22..81184d526 100644 --- a/app/src/main/res/values-or/strings.xml +++ b/app/src/main/res/values-or/strings.xml @@ -486,7 +486,6 @@ ସଦସ୍ୟତା ଚୟନ କରନ୍ତୁ କୌଣସି ସଦସ୍ୟତା ଚୟନ ହୋଇନାହିଁ ଦ୍ରୁତ ମୋଡ୍ ସକ୍ଷମ କରନ୍ତୁ - %s ଏହି କାରଣ ପ୍ରଦାନ କରେ: ଚ୍ୟାନେଲର ଅବତାର ଥମ୍ୱନେଲ୍ ବୈଶିଷ୍ଟ୍ୟ ରେଡିଓ diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index 93ea7923c..8b5969c0c 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -455,7 +455,6 @@ ਰੇਡੀਓ ਫੀਚਰਡ ਇਹ ਸਮੱਗਰੀ ਸਿਰਫ਼ ਉਹਨਾਂ ਵਰਤੋਂਕਾਰਾਂ ਲਈ ਉਪਲਬਧ ਹੈ ਜਿੰਨ੍ਹਾਂ ਨੇ ਇਸਦੇ ਲਈ ਕੀਮਤ ਦਿੱਤੀ ਹੈ, ਇਸ ਕਰਕੇ ਨਿਊ-ਪਾਈਪ ਦੁਆਰਾ ਚਲਾਈ ਜਾਂ ਡਾਊਨਲੋਡ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ। - %s ਇਸਦਾ ਕਾਰਨ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ: ਖਾਤਾ ਬੰਦ ਕੀਤਾ ਗਿਆ ਇਹ ਵੀਡੀਓ ਸਿਰਫ਼ ਯੂਟਿਊਬ ਮਿਊਜ਼ਿਕ ਦੇ ਪ੍ਰੀਮੀਅਮ ਮੈਂਬਰਾਂ ਲਈ ਉਪਲਬਧ ਹੈ, ਇਸ ਕਰਕੇ ਨਿਊ-ਪਾਈਪ ਦੁਆਰਾ ਚਲਾਈ ਜਾਂ ਡਾਊਨਲੋਡ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ। ਇਹ ਸਮੱਗਰੀ ਨਿੱਜੀ (ਪ੍ਰਾਈਵੇਟ) ਹੈ, ਇਸ ਕਰਕੇ ਨਿਊ-ਪਾਈਪ ਦੁਆਰਾ ਚਲਾਈ ਜਾਂ ਡਾਊਨਲੋਡ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ। diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 0f1ea119d..0a95609cd 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -623,7 +623,6 @@ Kategoria Otwórz stronę Teraz możesz zaznaczyć tekst wewnątrz opisu. Pamiętaj, że w trybie zaznaczania strona może migotać i linki nie będą klikalne. - %s podaje ten powód: Konto zamknięte Tryb szybki dla ładowania kanału nie dostarcza więcej informacji na ten temat. Konto autora zostało zawieszone. diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 839c23c2a..30fc565c6 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -619,7 +619,6 @@ Ativar seleção de texto na descrição Agora você pode selecionar o texto dentro da descrição. Note que a página pode piscar e os URL podem não ser clicáveis no modo de seleção. Abrir site - %s fornece este motivo: Conta encerrada O modo feed rápido não fornece mais informações sobre isso. A conta do autor foi encerrada. diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 3c1fe989b..6783327ec 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -623,7 +623,6 @@ Desativar seleção de texto na descrição Ativar seleção de texto na descrição Agora pode selecionar o texto na descrição. Note que a página pode cintilar e as ligações podem não ser clicáveis enquanto estiver no modo de seleção. - %s fornece este motivo: Conta encerrada O modo de feed rápido não fornece mais informações sobre isto. A conta do autor foi encerrada. diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index ef14944e7..d4b35fa55 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -605,7 +605,6 @@ Desativar túnel multimédia Sempre que descarregar um ficheiro, terá que indicar o local para o guardar Ainda não definiu uma pasta para as descargas. Escolha agora a pasta a utilizar - %s fornece este motivo: Conta encerrada O modo de fonte rápida não fornece mais informações sobre isto. A conta do autor foi encerrada. diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 0a7711d15..17106ed45 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -624,7 +624,6 @@ Dezactivați selectarea textului în descriere Activați selectarea textului în descriere Acum puteți selecta text în interiorul descrierii. Rețineți că este posibil ca pagina să pâlpâie, iar linkurile să nu poată fi accesate în modul de selecție. - %s oferă acest motiv: Contul a fost închis Modul rapid nu furnizează mai multe informații în acest sens. Contul autorului a fost închis. diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 96d28290b..4e7428b3c 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -633,7 +633,6 @@ Не удалось загрузить подписку \'%s\'. Ошибка загрузки подписки Открыть веб-сайт - %s указывает следующую причину: Аккаунт отключён Начиная с Android 10 поддерживается только «Storage Access Framework» Спрашивать, куда сохранять каждую загрузку diff --git a/app/src/main/res/values-ryu/strings.xml b/app/src/main/res/values-ryu/strings.xml index 9041fc462..e9baa11da 100644 --- a/app/src/main/res/values-ryu/strings.xml +++ b/app/src/main/res/values-ryu/strings.xml @@ -622,7 +622,6 @@ オフ オン タブレットモード - %sやしがくぬりゆうていじ: ひょうじさん ていふぃんしち(しょう) かんふぃんしち(だい) diff --git a/app/src/main/res/values-sat/strings.xml b/app/src/main/res/values-sat/strings.xml index 6e6615a84..717283e83 100644 --- a/app/src/main/res/values-sat/strings.xml +++ b/app/src/main/res/values-sat/strings.xml @@ -331,7 +331,6 @@ ᱪᱮᱯᱴᱟᱨᱥ ᱞᱟᱹᱠᱛᱤ ᱠᱟᱱᱟ ᱟᱢ ᱢᱤᱫ ᱯᱷᱤᱞ ᱢᱟᱱᱮᱡᱚᱨ ᱤᱱᱥᱴᱚᱞ ᱢᱮ ᱟᱨᱵᱟᱝ ᱰᱟᱩᱱᱞᱚᱰ ᱥᱤᱴᱤᱝ ᱨᱮ ᱵᱚᱫᱚᱞ ᱦᱚᱪᱚ ᱞᱟᱹᱜᱤᱫ ᱯᱨᱚᱵᱷᱟᱣ ᱢᱮ\" ᱱᱚᱶᱟ ᱵᱷᱤᱰᱤᱭᱳ ᱫᱚ ᱭᱩᱴᱭᱩᱵᱽ ᱢᱤᱣᱡᱤᱠ ᱯᱨᱤᱢᱤᱭᱟᱢ ᱥᱮᱞᱮᱫᱤᱭᱟᱹ ᱠᱚ ᱞᱟᱹᱜᱤᱫ ᱜᱮ ᱧᱟᱢᱚᱜᱼᱟ, ᱚᱱᱟᱛᱮ ᱱᱚᱶᱟ ᱫᱚ ᱱᱤᱭᱩ ᱯᱟᱭᱤᱯ ᱦᱚᱛᱮᱛᱮ ᱵᱟᱝ ᱥᱴᱨᱤᱢ ᱟᱨ ᱵᱟᱝ ᱰᱟᱩᱱᱞᱳᱰ ᱦᱩᱭ ᱫᱟᱲᱮᱭᱟᱜᱼᱟ ᱾ - %s ᱫᱚ ᱱᱚᱶᱟ ᱞᱟᱹᱠᱛᱤ ᱠᱟᱱᱟ: ᱚᱴᱚᱢᱟᱴᱤᱠ (ᱰᱤᱵᱟᱤᱥ ᱛᱷᱮᱢ) ᱟᱢᱟᱜ ᱯᱩᱭᱞᱩ ᱧᱤᱫᱟᱹ ᱛᱷᱤᱢ ᱵᱟᱪᱷᱟᱣ ᱢᱮ ⁇ %s ᱟᱢ ᱞᱟᱛᱟᱨ ᱨᱮ ᱟᱢᱟᱜ ᱧᱤᱫᱟᱹ ᱪᱮᱛᱟᱱ ᱵᱟᱪᱷᱟᱣ ᱫᱟᱲᱮᱭᱟᱜ ᱟ diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index cb51c3f4d..ac694bba9 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -610,7 +610,6 @@ Como podes ischertare su testu in intro de sa descritzione. Ammenta·ti chi sa pàgina diat pòdere trèmere e sos ligàmenes si diant pòdere no abèrrere cando ses in modalidade de ischerta. Incumintzende dae Android 10 petzi sa \'Storage Access Framework\' (Istrutura de Atzessu a s\'Archiviatzione) est suportada Aberi su situ web - %s frunit custa resone: Contu serradu Su recùperu lestru de sos flussos non frunit àteras informatziones in subra de custu. Su contu de s\'autore l\'ant serradu. diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index c8f2d9744..f725965e2 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -618,7 +618,6 @@ Povolenie výberu textu v popise Teraz môžete vybrať text vo vnútri popisu. Upozorňujeme, že stránka môže blikať a odkazy nemusia byť klikateľné, keď je v režime výberu. Otvoriť webstránku - %s uvádza tento dôvod: Účet bol zrušený Tento rýchly režim neposkytuje viac informácií. Účet autora bol zrušený. diff --git a/app/src/main/res/values-so/strings.xml b/app/src/main/res/values-so/strings.xml index 772e03b41..860a607f5 100644 --- a/app/src/main/res/values-so/strings.xml +++ b/app/src/main/res/values-so/strings.xml @@ -608,7 +608,6 @@ Xidh caalamadinta qoraalka Fur caalamadinta qoraalka Hadda waad dooran kartaa qoraalka ku dhexjira faahfaahinta. Ogow markaad caalamdinayso qoraalka boggu wuu boodboodi karaa tixraacyadana waxay noqon karaan kuwo aan lagu dhufan karin. - %s wuxuu sheegayaa sababtan: Akoonka waa lajoojiyay Nidaamka dagdaga ah faahfaahin dheeraad ah uma hayo shaygan. Akoonka soosaaraha waa la joojiyay. diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml index 9aac66de7..4b9c2ac36 100644 --- a/app/src/main/res/values-sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -598,7 +598,6 @@ Zgjidhni temën tuaj të preferuar të natës - %s Automatike (tema e pajisjes) Radio - %s e jep këtë arsye: Llogaria është mbyllur Kjo përmbajtje është private, kështu që nuk mund të luhet apo shkarkohet nga NewPipe. Kjo përmbajtje nuk është e disponueshme në shtetin tuaj. diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 3c82e5612..722ce6855 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -619,7 +619,6 @@ Омогући бирање текста унутар описа Онемогући бирање текста унутар описа Сада можете изабрати текст унутар описа. Имајте на уму да страница може треперети и да се на линкове можда неће моћи кликнути док сте у режиму избора. - %s даје овај разлог: Налог укинут Режим брзог фида не пружа више информација о овоме. Налог аутора је укинут. diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 8aab4a67f..f3703ea87 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -586,7 +586,6 @@ Hämtningen har startat Radio Detta innehåll är endast tillgängligt för användare som har betalat för det, så det kan inte strömmas eller hämtas av NewPipe. - %s anger detta skäl: Kontot avslutat Denna video är endast tillgänglig för YouTube Music Premium-medlemmar, så den kan inte strömmas eller hämtas av NewPipe. Detta innehåll är privat, så det kan inte strömmas eller hämtas av NewPipe. diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index 7221ab74d..f1d388393 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -428,7 +428,6 @@ பதிவிறக்க வரிசையை கட்டுப்படுத்துங்கள் ஒரு பதிவிறக்கம் ஒரே நேரத்தில் இயங்கும் உங்கள் சாதனத்தில் எந்த பயன்பாடும் இதைத் திறக்க முடியாது - %s இந்த காரணத்தை வழங்குகிறது: துணை சேனல் அவதாரங்கள் அவதாரங்கள் எக்சோப்ளேயர் இயல்புநிலை diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 9a93d8177..c1d364226 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -608,7 +608,6 @@ Açıklamadaki metni seçmeyi etkinleştir Artık, açıklamadaki metni seçebilirsiniz. Seçim kipindeyken sayfanın titreyebileceğini ve bağlantıların tıklanamayacağını unutmayın. Web sitesini aç - %s şu nedeni sağlıyor: Hesap sonlandırıldı Hızlı besleme kipi bununla ilgili daha çok bilgi sağlamıyor. Yazarın hesabı sonlandırılmış. diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index d7917db64..c0bc903a0 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -624,7 +624,6 @@ Заборонити виділення тексту в описі Дозволити виділяти текст в описі Тепер можна виділяти текст в описі. Зауважте, що сторінка може мигати і посилання можуть не працювати в режимі виділення. - %s подає таку причину: Неможливо завантажити стрічку для «%s». Помилка завантаження стрічки Обліковий запис автора припинено. diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index e8f4ec3f9..d145991bc 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -602,7 +602,6 @@ Tắt chọn văn bản trong mô tả Bật chọn văn bản trong mô tả Bây giờ bạn có thể chọn văn bản trong mô tả. Lưu ý rằng trang có thể nhấp nháy và các liên kết có thể không nhấn vào được trong khi ở chế độ chọn. - %s cung cấp lý do này: Tài khoản đã bị chấm dứt Chế độ nạp nhanh không cung cấp thêm thông tin về điều này. Tài khoản của tác giả đã bị chấm dứt. diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index cfd2030c6..c6e1538ec 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -599,7 +599,6 @@ 启用简介中的文本选择功能 你现在可以选择简介中的文本,注意,在选择模式下,页面可能会闪烁,链接可能无法点击。 打开网站 - %s 提供这个原因: 账号被终止 快速 Feed 模式不提供关于这个的更多信息。 作者账号已被终止。 diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 1f258c1db..24f457c25 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -486,7 +486,6 @@ NewPipe 仲未支援到呢樣。 \n \n希望未來會喺日後嘅版本支援啦。 - %s 話理由如下: 搵唔到合適嘅檔案總管進行呢個動作。 \n請安裝一個檔案管理程式,又或者試下喺下載設定度停用「%s」 搵唔到合適嘅檔案總管進行呢個動作。 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 4e1fbd18e..22dd24a33 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -599,7 +599,6 @@ 啟用選取描述中的文字 您現在可以選取描述中的文字了。請注意,在選取模式下,頁面可能會閃爍,連結也可能無法點擊。 開啟網站 - %s 提供了這個理由: 帳號已終止 快速 feed 模式不會提供更多資訊。 作者的帳號已被終止。 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a54ddb9ee..fc111e15a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -757,7 +757,7 @@ This content is private, so it cannot be streamed or downloaded by NewPipe. This video is available only to YouTube Music Premium members, so it cannot be streamed or downloaded by NewPipe. Account terminated - %s provides this reason: + Account terminated\n\n%1$s provides this reason: %2$s This content is only available to users who have paid, so it cannot be streamed or downloaded by NewPipe. Featured Radio @@ -877,7 +877,9 @@ Trending movies and shows Trending music Entry deleted - HTTP error 403 occurred while playing, likely caused by an IP ban or streaming URL deobfuscation issues - YouTube refused to provide data, asking for a login.\n\nYour IP might have been temporarily banned by YouTube, you can wait some time or switch to a different IP (for example by turning on/off a VPN, or by switching from WiFi to mobile data). + HTTP error 403 received from server while playing, likely caused by an IP ban or by streaming URL expiration + HTTP error %1$s received from server while playing + HTTP error 403 received from server while playing, likely caused by an IP ban or streaming URL deobfuscation issues + %1$s refused to provide data, asking for a login to confirm the requester is not a bot.\n\nYour IP might have been temporarily banned by %1$s, you can wait some time or switch to a different IP (for example by turning on/off a VPN, or by switching from WiFi to mobile data). This content is not available for the currently selected content country.\n\nChange your selection from \"Settings > Content > Default content country\". From 989c0cfd284351c71bf1af314a7af4cd2741a901 Mon Sep 17 00:00:00 2001 From: Stypox Date: Sat, 30 Aug 2025 14:39:23 +0200 Subject: [PATCH 36/43] Fix REPORT in snackbar not opening ErrorActivity if MainActivity not shown Bug caused by https://github.com/TeamNewPipe/NewPipe/pull/11789 --- app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt index 520d02b3b..b358a5fd2 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt @@ -159,7 +159,7 @@ class ErrorUtil { Snackbar.make(rootView, errorInfo.getMessage(context), Snackbar.LENGTH_LONG) .setActionTextColor(Color.YELLOW) .setAction(context.getString(R.string.error_snackbar_action).uppercase()) { - openActivity(context, errorInfo) + context.startActivity(getErrorActivityIntent(context, errorInfo)) }.show() } } From 204df4c45a4a02e37428ce67974896811ccd7d04 Mon Sep 17 00:00:00 2001 From: Stypox Date: Sat, 30 Aug 2025 14:58:08 +0200 Subject: [PATCH 37/43] Fix test --- .../schabi/newpipe/error/ErrorInfoTest.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/java/org/schabi/newpipe/error/ErrorInfoTest.java b/app/src/androidTest/java/org/schabi/newpipe/error/ErrorInfoTest.java index 891824a55..892d1df0f 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/error/ErrorInfoTest.java +++ b/app/src/androidTest/java/org/schabi/newpipe/error/ErrorInfoTest.java @@ -12,6 +12,7 @@ import org.schabi.newpipe.extractor.ServiceList; import org.schabi.newpipe.extractor.exceptions.ParsingException; import java.util.Arrays; +import java.util.Objects; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -23,8 +24,23 @@ import static org.junit.Assert.assertTrue; @LargeTest public class ErrorInfoTest { + /** + * @param errorInfo the error info to access + * @return the private field errorInfo.message.stringRes using reflection + */ + private int getMessageFromErrorInfo(final ErrorInfo errorInfo) + throws NoSuchFieldException, IllegalAccessException { + final var message = ErrorInfo.class.getDeclaredField("message"); + message.setAccessible(true); + final var messageValue = (ErrorInfo.Companion.ErrorMessage) message.get(errorInfo); + + final var stringRes = ErrorInfo.Companion.ErrorMessage.class.getDeclaredField("stringRes"); + stringRes.setAccessible(true); + return (int) Objects.requireNonNull(stringRes.get(messageValue)); + } + @Test - public void errorInfoTestParcelable() { + public void errorInfoTestParcelable() throws NoSuchFieldException, IllegalAccessException { final ErrorInfo info = new ErrorInfo(new ParsingException("Hello"), UserAction.USER_REPORT, "request", ServiceList.YouTube.getServiceId()); // Obtain a Parcel object and write the parcelable object to it: @@ -39,7 +55,7 @@ public class ErrorInfoTest { assertEquals(ServiceList.YouTube.getServiceInfo().getName(), infoFromParcel.getServiceName()); assertEquals("request", infoFromParcel.getRequest()); - assertEquals(R.string.parsing_error, infoFromParcel.getMessageStringId()); + assertEquals(R.string.parsing_error, getMessageFromErrorInfo(infoFromParcel)); parcel.recycle(); } From 08f51abefbe40ebe49d2bf203cc489de1ab3411b Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Sun, 31 Aug 2025 22:25:12 +0530 Subject: [PATCH 38/43] Added comments --- .../newpipe/local/feed/notifications/NotificationWorker.kt | 1 + .../org/schabi/newpipe/player/notification/NotificationUtil.java | 1 + 2 files changed, 2 insertions(+) diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt index ad2f1055c..6fe311fb0 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationWorker.kt @@ -85,6 +85,7 @@ class NotificationWorker( .setPriority(NotificationCompat.PRIORITY_LOW) .setContentTitle(applicationContext.getString(R.string.feed_notification_loading)) .build() + // ServiceInfo constants are not used below Android Q, so 0 is set here val serviceType = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC else 0 setForegroundAsync(ForegroundInfo(FeedLoadService.NOTIFICATION_ID, notification, serviceType)) } diff --git a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java index 8b7287f56..cfd91a0ae 100644 --- a/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java +++ b/app/src/main/java/org/schabi/newpipe/player/notification/NotificationUtil.java @@ -173,6 +173,7 @@ public final class NotificationUtil { } updateNotification(); + // ServiceInfo constants are not used below Android Q, so 0 is set here final int serviceType = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q ? ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK : 0; ServiceCompat.startForeground(player.getService(), NOTIFICATION_ID, From 79980e20781dde95478012894c366ae25739c80b Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 4 Sep 2025 13:17:45 +0200 Subject: [PATCH 39/43] Address PR reviews --- app/src/main/java/org/schabi/newpipe/error/UserAction.java | 2 +- app/src/main/res/values/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/error/UserAction.java b/app/src/main/java/org/schabi/newpipe/error/UserAction.java index 64829523a..d3af9d32e 100644 --- a/app/src/main/java/org/schabi/newpipe/error/UserAction.java +++ b/app/src/main/java/org/schabi/newpipe/error/UserAction.java @@ -35,7 +35,7 @@ public enum UserAction { OPEN_INFO_ITEM_DIALOG("open info item dialog"), GETTING_MAIN_SCREEN_TAB("getting main screen tab"), PLAY_ON_POPUP("play on popup"), - SUBSCRIPTIONS("loading subscriptions"),; + SUBSCRIPTIONS("loading subscriptions"); private final String message; diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fc111e15a..147c88938 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -877,7 +877,7 @@ Trending movies and shows Trending music Entry deleted - HTTP error 403 received from server while playing, likely caused by an IP ban or by streaming URL expiration + HTTP error 403 received from server while playing, likely caused by streaming URL expiration or an IP ban HTTP error %1$s received from server while playing HTTP error 403 received from server while playing, likely caused by an IP ban or streaming URL deobfuscation issues %1$s refused to provide data, asking for a login to confirm the requester is not a bot.\n\nYour IP might have been temporarily banned by %1$s, you can wait some time or switch to a different IP (for example by turning on/off a VPN, or by switching from WiFi to mobile data). From f27ec53c088010e87dc36f2c9688e1f3821a572a Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 4 Sep 2025 22:31:24 +0200 Subject: [PATCH 40/43] Even more centralized error handling in ErrorInfo --- .../org/schabi/newpipe/RouterActivity.java | 31 ++-- .../newpipe/download/DownloadDialog.java | 9 +- .../newpipe/error/AcraReportSender.java | 2 +- .../org/schabi/newpipe/error/ErrorInfo.kt | 155 +++++++++++++----- .../schabi/newpipe/error/ErrorPanelHelper.kt | 60 ++----- .../fragments/detail/VideoDetailFragment.java | 6 +- .../fragments/list/BaseListInfoFragment.java | 8 +- .../list/channel/ChannelFragment.java | 2 +- .../fragments/list/search/SearchFragment.java | 24 ++- .../SubscriptionsImportFragment.java | 2 +- .../org/schabi/newpipe/player/Player.java | 5 +- .../schabi/newpipe/util/SparseItemUtil.java | 2 +- .../util/text/InternalUrlsHandler.java | 4 +- .../giga/ui/adapter/MissionAdapter.java | 2 +- 14 files changed, 178 insertions(+), 134 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index cb7ea3dd7..50639c5ae 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -58,10 +58,7 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.StreamingService.LinkType; import org.schabi.newpipe.extractor.channel.ChannelInfo; -import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; -import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException; import org.schabi.newpipe.extractor.exceptions.ExtractionException; -import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.stream.StreamInfo; @@ -253,7 +250,8 @@ public class RouterActivity extends AppCompatActivity { showUnsupportedUrlDialog(url); } }, throwable -> handleError(this, new ErrorInfo(throwable, - UserAction.SHARE_TO_NEWPIPE, "Getting service from url: " + url)))); + UserAction.SHARE_TO_NEWPIPE, "Getting service from url: " + url, + null, url)))); } /** @@ -262,23 +260,19 @@ public class RouterActivity extends AppCompatActivity { * @param errorInfo the error information */ private static void handleError(final Context context, final ErrorInfo errorInfo) { - if (errorInfo.getThrowable() != null) { - errorInfo.getThrowable().printStackTrace(); - } - - if (errorInfo.getThrowable() instanceof ReCaptchaException) { + if (errorInfo.getRecaptchaUrl() != null) { Toast.makeText(context, R.string.recaptcha_request_toast, Toast.LENGTH_LONG).show(); // Starting ReCaptcha Challenge Activity final Intent intent = new Intent(context, ReCaptchaActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(ReCaptchaActivity.RECAPTCHA_URL_EXTRA, errorInfo.getRecaptchaUrl()); context.startActivity(intent); - } else if (errorInfo.getThrowable() instanceof ContentNotAvailableException - || errorInfo.getThrowable() instanceof ContentNotSupportedException) { + } else if (errorInfo.isReportable()) { + ErrorUtil.createNotification(context, errorInfo); + } else { // this exception does not usually indicate a problem that should be reported, // so just show a toast instead of the notification Toast.makeText(context, errorInfo.getMessage(context), Toast.LENGTH_LONG).show(); - } else { - ErrorUtil.createNotification(context, errorInfo); } if (context instanceof RouterActivity) { @@ -641,7 +635,8 @@ public class RouterActivity extends AppCompatActivity { startActivity(intent); finish(); }, throwable -> handleError(this, new ErrorInfo(throwable, - UserAction.SHARE_TO_NEWPIPE, "Starting info activity: " + currentUrl))) + UserAction.SHARE_TO_NEWPIPE, "Starting info activity: " + currentUrl, + null, currentUrl))) ); return; } @@ -828,10 +823,10 @@ public class RouterActivity extends AppCompatActivity { }) )), throwable -> runOnVisible(ctx -> handleError(ctx, new ErrorInfo( - throwable, - UserAction.REQUESTED_STREAM, + throwable, UserAction.REQUESTED_STREAM, "Tried to add " + currentUrl + " to a playlist", - ((RouterActivity) ctx).currentService.getServiceId()) + ((RouterActivity) ctx).currentService.getServiceId(), + currentUrl) )) ) ); @@ -971,7 +966,7 @@ public class RouterActivity extends AppCompatActivity { } }, throwable -> handleError(this, new ErrorInfo(throwable, finalUserAction, choice.url + " opened with " + choice.playerChoice, - choice.serviceId))); + choice.serviceId, choice.url))); } } diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java index 003aa5893..0857fa339 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -389,8 +389,7 @@ public class DownloadDialog extends DialogFragment } }, throwable -> ErrorUtil.showSnackbar(context, new ErrorInfo(throwable, UserAction.DOWNLOAD_OPEN_DIALOG, - "Downloading video stream size", - currentInfo.getServiceId())))); + "Downloading video stream size", currentInfo)))); disposables.add(StreamInfoWrapper.fetchMoreInfoForWrapper(getWrappedAudioStreams()) .subscribe(result -> { if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId() @@ -399,8 +398,7 @@ public class DownloadDialog extends DialogFragment } }, throwable -> ErrorUtil.showSnackbar(context, new ErrorInfo(throwable, UserAction.DOWNLOAD_OPEN_DIALOG, - "Downloading audio stream size", - currentInfo.getServiceId())))); + "Downloading audio stream size", currentInfo)))); disposables.add(StreamInfoWrapper.fetchMoreInfoForWrapper(wrappedSubtitleStreams) .subscribe(result -> { if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId() @@ -409,8 +407,7 @@ public class DownloadDialog extends DialogFragment } }, throwable -> ErrorUtil.showSnackbar(context, new ErrorInfo(throwable, UserAction.DOWNLOAD_OPEN_DIALOG, - "Downloading subtitle stream size", - currentInfo.getServiceId())))); + "Downloading subtitle stream size", currentInfo)))); } private void setupAudioTrackSpinner() { diff --git a/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java b/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java index 8876a66e4..90d8f4797 100644 --- a/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java +++ b/app/src/main/java/org/schabi/newpipe/error/AcraReportSender.java @@ -36,8 +36,8 @@ public class AcraReportSender implements ReportSender { ErrorUtil.openActivity(context, new ErrorInfo( new String[]{report.getString(ReportField.STACK_TRACE)}, UserAction.UI_ERROR, - null, "ACRA report", + null, R.string.app_ui_crash)); } } diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt index bac294d0f..609fbb336 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorInfo.kt @@ -7,7 +7,6 @@ import androidx.core.content.ContextCompat import com.google.android.exoplayer2.ExoPlaybackException import com.google.android.exoplayer2.upstream.HttpDataSource import com.google.android.exoplayer2.upstream.Loader -import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize import org.schabi.newpipe.R import org.schabi.newpipe.extractor.Info @@ -29,70 +28,108 @@ import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentExcepti import org.schabi.newpipe.ktx.isNetworkRelated import org.schabi.newpipe.player.mediasource.FailedMediaSource import org.schabi.newpipe.player.resolver.PlaybackResolver +import java.net.UnknownHostException +/** + * An error has occurred in the app. This class contains plain old parcelable data that can be used + * to report the error and to show it to the user along with correct action buttons. + */ @Parcelize class ErrorInfo private constructor( val stackTraces: Array, val userAction: UserAction, - val serviceId: Int?, val request: String, + val serviceId: Int?, private val message: ErrorMessage, + /** + * If `true`, a report button will be shown for this error. Otherwise the error is not something + * that can really be reported (e.g. a network issue, or content not being available at all). + */ + val isReportable: Boolean, + /** + * If `true`, the process causing this error can be retried, otherwise not. + */ + val isRetryable: Boolean, + /** + * If present, indicates that the exception was a ReCaptchaException, and this is the URL + * provided by the service that can be used to solve the ReCaptcha challenge. + */ + val recaptchaUrl: String?, + /** + * If present, this resource can alternatively be opened in browser (useful if NewPipe is + * badly broken). + */ + val openInBrowserUrl: String?, ) : Parcelable { - // no need to store throwable, all data for report is in other variables - // also, the throwable might not be serializable, see TeamNewPipe/NewPipe#7302 - @IgnoredOnParcel - var throwable: Throwable? = null - - private constructor( + @JvmOverloads + constructor( throwable: Throwable, userAction: UserAction, - serviceId: Int?, - request: String + request: String, + serviceId: Int? = null, + openInBrowserUrl: String? = null, ) : this( throwableToStringList(throwable), userAction, - serviceId, request, - getMessage(throwable, userAction, serviceId) - ) { - this.throwable = throwable - } + serviceId, + getMessage(throwable, userAction, serviceId), + isReportable(throwable), + isRetryable(throwable), + (throwable as? ReCaptchaException)?.url, + openInBrowserUrl, + ) - private constructor( - throwable: List, + @JvmOverloads + constructor( + throwables: List, userAction: UserAction, - serviceId: Int?, - request: String + request: String, + serviceId: Int? = null, + openInBrowserUrl: String? = null, ) : this( - throwableListToStringList(throwable), + throwableListToStringList(throwables), userAction, - serviceId, request, - getMessage(throwable.firstOrNull(), userAction, serviceId) - ) { - this.throwable = throwable.firstOrNull() - } + serviceId, + getMessage(throwables.firstOrNull(), userAction, serviceId), + throwables.any(::isReportable), + throwables.isEmpty() || throwables.any(::isRetryable), + throwables.firstNotNullOfOrNull { it as? ReCaptchaException }?.url, + openInBrowserUrl, + ) - // constructor to manually build ErrorInfo - constructor(stackTraces: Array, userAction: UserAction, serviceId: Int?, request: String, @StringRes message: Int) : - this(stackTraces, userAction, serviceId, request, ErrorMessage(message)) + // constructor to manually build ErrorInfo when no throwable is available + constructor( + stackTraces: Array, + userAction: UserAction, + request: String, + serviceId: Int?, + @StringRes message: Int + ) : + this( + stackTraces, userAction, request, serviceId, ErrorMessage(message), + true, false, null, null + ) - // constructors with single throwable - constructor(throwable: Throwable, userAction: UserAction, request: String) : - this(throwable, userAction, null, request) - constructor(throwable: Throwable, userAction: UserAction, request: String, serviceId: Int) : - this(throwable, userAction, serviceId, request) - constructor(throwable: Throwable, userAction: UserAction, request: String, info: Info?) : - this(throwable, userAction, info?.serviceId, request) + // constructor with only one throwable to extract service id and openInBrowserUrl from an Info + constructor( + throwable: Throwable, + userAction: UserAction, + request: String, + info: Info?, + ) : + this(throwable, userAction, request, info?.serviceId, info?.url) - // constructors with list of throwables - constructor(throwable: List, userAction: UserAction, request: String) : - this(throwable, userAction, null, request) - constructor(throwable: List, userAction: UserAction, request: String, serviceId: Int) : - this(throwable, userAction, serviceId, request) - constructor(throwable: List, userAction: UserAction, request: String, info: Info?) : - this(throwable, userAction, info?.serviceId, request) + // constructor with multiple throwables to extract service id and openInBrowserUrl from an Info + constructor( + throwables: List, + userAction: UserAction, + request: String, + info: Info?, + ) : + this(throwables, userAction, request, info?.serviceId, info?.url) fun getServiceName(): String { return getServiceName(serviceId) @@ -205,8 +242,7 @@ class ErrorInfo private constructor( // other extractor exceptions throwable is ContentNotSupportedException -> ErrorMessage(R.string.content_not_supported) - // ReCaptchas should have already been handled elsewhere, - // but return an error message here just in case + // ReCaptchas will be handled in a special way anyway throwable is ReCaptchaException -> ErrorMessage(R.string.recaptcha_request_toast) // test this at the end as many exceptions could be a subclass of IOException @@ -234,5 +270,36 @@ class ErrorInfo private constructor( ErrorMessage(R.string.error_snackbar_message) } } + + fun isReportable(throwable: Throwable?): Boolean { + return when (throwable) { + // we don't have an exception, so this is a manually built error, which likely + // indicates that it's important and is thus reportable + null -> true + // the service explicitly said that content is not available (e.g. age restrictions, + // video deleted, etc.), there is no use in letting users report it + is ContentNotAvailableException -> false + // we know the content is not supported, no need to let the user report it + is ContentNotSupportedException -> false + // happens often when there is no internet connection; we don't use + // `throwable.isNetworkRelated` since any `IOException` would make that function + // return true, but not all `IOException`s are network related + is UnknownHostException -> false + // by default, this is an unexpected exception, which the user could report + else -> true + } + } + + fun isRetryable(throwable: Throwable?): Boolean { + return when (throwable) { + // we know the content is not available, retrying won't help + is ContentNotAvailableException -> false + // we know the content is not supported, retrying won't help + is ContentNotSupportedException -> false + // by default (including if throwable is null), enable retrying (though the retry + // button will be shown only if a way to perform the retry is implemented) + else -> true + } + } } } diff --git a/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt b/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt index 959759127..4ec5f58c3 100644 --- a/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt +++ b/app/src/main/java/org/schabi/newpipe/error/ErrorPanelHelper.kt @@ -2,7 +2,6 @@ package org.schabi.newpipe.error import android.content.Context import android.content.Intent -import android.util.Log import android.view.View import android.widget.Button import android.widget.TextView @@ -14,11 +13,7 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.disposables.Disposable import org.schabi.newpipe.MainActivity import org.schabi.newpipe.R -import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException -import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException -import org.schabi.newpipe.extractor.exceptions.ReCaptchaException import org.schabi.newpipe.ktx.animate -import org.schabi.newpipe.ktx.isInterruptedCaused import org.schabi.newpipe.util.external_communication.ShareUtils import java.util.concurrent.TimeUnit @@ -68,50 +63,32 @@ class ErrorPanelHelper( } fun showError(errorInfo: ErrorInfo) { - - if (errorInfo.throwable != null && errorInfo.throwable!!.isInterruptedCaused) { - if (DEBUG) { - Log.w(TAG, "onError() isInterruptedCaused! = [$errorInfo.throwable]") - } - return - } - ensureDefaultVisibility() + errorTextView.text = errorInfo.getMessage(context) - if (errorInfo.throwable is ReCaptchaException) { - errorTextView.setText(R.string.recaptcha_request_toast) - - showAndSetErrorButtonAction( - R.string.recaptcha_solve - ) { + if (errorInfo.recaptchaUrl != null) { + showAndSetErrorButtonAction(R.string.recaptcha_solve) { // Starting ReCaptcha Challenge Activity val intent = Intent(context, ReCaptchaActivity::class.java) - intent.putExtra( - ReCaptchaActivity.RECAPTCHA_URL_EXTRA, - (errorInfo.throwable as ReCaptchaException).url - ) + intent.putExtra(ReCaptchaActivity.RECAPTCHA_URL_EXTRA, errorInfo.recaptchaUrl) fragment.startActivityForResult(intent, ReCaptchaActivity.RECAPTCHA_REQUEST) errorActionButton.setOnClickListener(null) } - - errorRetryButton.isVisible = retryShouldBeShown - showAndSetOpenInBrowserButtonAction(errorInfo) - } else { - showAndSetErrorButtonAction( - R.string.error_snackbar_action - ) { + } else if (errorInfo.isReportable) { + showAndSetErrorButtonAction(R.string.error_snackbar_action) { ErrorUtil.openActivity(context, errorInfo) } + } - errorTextView.text = errorInfo.getMessage(context) + if (errorInfo.isRetryable) { + errorRetryButton.isVisible = retryShouldBeShown + } - if (errorInfo.throwable !is ContentNotAvailableException && - errorInfo.throwable !is ContentNotSupportedException - ) { - // show retry button only for content which is not unavailable or unsupported - errorRetryButton.isVisible = retryShouldBeShown + if (errorInfo.openInBrowserUrl != null) { + errorOpenInBrowserButton.isVisible = true + errorOpenInBrowserButton.setOnClickListener { + ShareUtils.openUrlInBrowser(context, errorInfo.openInBrowserUrl) } - showAndSetOpenInBrowserButtonAction(errorInfo) } setRootVisible() @@ -129,15 +106,6 @@ class ErrorPanelHelper( errorActionButton.setOnClickListener(listener) } - fun showAndSetOpenInBrowserButtonAction( - errorInfo: ErrorInfo - ) { - errorOpenInBrowserButton.isVisible = true - errorOpenInBrowserButton.setOnClickListener { - ShareUtils.openUrlInBrowser(context, errorInfo.request) - } - } - fun showTextError(errorString: String) { ensureDefaultVisibility() 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 b46b0c708..342333aa5 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 @@ -876,7 +876,7 @@ public final class VideoDetailFragment } } }, throwable -> showError(new ErrorInfo(throwable, UserAction.REQUESTED_STREAM, - url == null ? "no url" : url, serviceId))); + url == null ? "no url" : url, serviceId, url))); } /*////////////////////////////////////////////////////////////////////////// @@ -1593,8 +1593,8 @@ public final class VideoDetailFragment } if (!info.getErrors().isEmpty()) { - showSnackBarError(new ErrorInfo(info.getErrors(), - UserAction.REQUESTED_STREAM, info.getUrl(), info)); + showSnackBarError(new ErrorInfo(info.getErrors(), UserAction.REQUESTED_STREAM, + "Some info not extracted: " + info.getUrl(), info)); } } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java index 7f594734a..848dfe6f5 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java @@ -153,7 +153,7 @@ public abstract class BaseListInfoFragment showError(new ErrorInfo(throwable, errorUserAction, - "Start loading: " + url, serviceId))); + "Start loading: " + url, serviceId, url))); } /** @@ -184,7 +184,7 @@ public abstract class BaseListInfoFragment dynamicallyShowErrorPanelOrSnackbar(new ErrorInfo(throwable, - errorUserAction, "Loading more items: " + url, serviceId))); + errorUserAction, "Loading more items: " + url, serviceId, url))); } private void forbidDownwardFocusScroll() { @@ -210,7 +210,7 @@ public abstract class BaseListInfoFragment isLoading.set(false); handleResult(result); }, throwable -> showError(new ErrorInfo(throwable, UserAction.REQUESTED_CHANNEL, - url == null ? "No URL" : url, serviceId))); + url == null ? "No URL" : url, serviceId, url))); } @Override 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 cea06b942..8cb5f6497 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 @@ -54,6 +54,7 @@ import org.schabi.newpipe.extractor.MetaInfo; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.Page; import org.schabi.newpipe.extractor.StreamingService; +import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.search.SearchInfo; import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubeSearchQueryHandlerFactory; @@ -934,7 +935,21 @@ public class SearchFragment extends BaseListFragment ErrorUtil.createNotification(context, new ErrorInfo(throwable, UserAction.REQUESTED_STREAM, - "Loading stream info: " + url, serviceId) + "Loading stream info: " + url, serviceId, url) )); } } diff --git a/app/src/main/java/org/schabi/newpipe/util/text/InternalUrlsHandler.java b/app/src/main/java/org/schabi/newpipe/util/text/InternalUrlsHandler.java index a2743141b..2e4aa320f 100644 --- a/app/src/main/java/org/schabi/newpipe/util/text/InternalUrlsHandler.java +++ b/app/src/main/java/org/schabi/newpipe/util/text/InternalUrlsHandler.java @@ -160,10 +160,10 @@ public final class InternalUrlsHandler { final PlayQueue playQueue = new SinglePlayQueue(info, seconds * 1000L); NavigationHelper.playOnPopupPlayer(context, playQueue, false); }, throwable -> { - final var errorInfo = new ErrorInfo(throwable, UserAction.PLAY_ON_POPUP, url); // This will only show a snackbar if the passed context has a root view: // otherwise it will resort to showing a notification, so we are safe here. - ErrorUtil.showSnackbar(context, errorInfo); + ErrorUtil.showSnackbar(context, + new ErrorInfo(throwable, UserAction.PLAY_ON_POPUP, url, null, url)); })); return true; } 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 31065d57c..f245b3dd9 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 @@ -572,7 +572,7 @@ public class MissionAdapter extends Adapter implements Handler.Callb ErrorUtil.createNotification(mContext, new ErrorInfo(ErrorInfo.Companion.throwableToStringList(mission.errObject), action, - service, request.toString(), reason)); + request.toString(), service, reason)); } public void clearFinishedDownloads(boolean delete) { From 01a8c4e584a61d49608a41f3d472cda7058baf47 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Fri, 5 Sep 2025 18:14:29 +0530 Subject: [PATCH 41/43] Clean up EmptyStateComposable code --- .../list/channel/ChannelFragment.java | 7 +- .../fragments/list/search/SearchFragment.java | 6 +- .../local/bookmark/BookmarkFragment.java | 7 +- .../settings/SelectChannelFragment.java | 3 +- .../settings/SelectPlaylistFragment.java | 3 +- .../PreferenceSearchFragment.java | 7 +- .../video/comment/CommentRepliesDialog.kt | 38 +++--- .../video/comment/CommentSection.kt | 16 +-- .../ui/emptystate/EmptyStateComposable.kt | 122 +++++++----------- 9 files changed, 77 insertions(+), 132 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java index a09cd5912..f0bcc5eae 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java @@ -3,6 +3,7 @@ package org.schabi.newpipe.fragments.list.channel; import static org.schabi.newpipe.ktx.TextViewUtils.animateTextColor; import static org.schabi.newpipe.ktx.ViewUtils.animate; import static org.schabi.newpipe.ktx.ViewUtils.animateBackgroundColor; +import static org.schabi.newpipe.ui.emptystate.EmptyStateUtil.setEmptyStateComposable; import android.content.Context; import android.content.SharedPreferences; @@ -45,7 +46,6 @@ import org.schabi.newpipe.ktx.AnimationType; import org.schabi.newpipe.local.feed.notifications.NotificationHelper; import org.schabi.newpipe.local.subscription.SubscriptionManager; import org.schabi.newpipe.ui.emptystate.EmptyStateSpec; -import org.schabi.newpipe.ui.emptystate.EmptyStateUtil; import org.schabi.newpipe.util.ChannelTabHelper; import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.ExtractorHelper; @@ -200,10 +200,7 @@ public class ChannelFragment extends BaseStateFragment protected void initViews(final View rootView, final Bundle savedInstanceState) { super.initViews(rootView, savedInstanceState); - EmptyStateUtil.setEmptyStateComposable( - binding.emptyStateView, - EmptyStateSpec.Companion.getContentNotSupported() - ); + setEmptyStateComposable(binding.emptyStateView, EmptyStateSpec.ContentNotSupported); tabAdapter = new TabAdapter(getChildFragmentManager()); binding.viewPager.setAdapter(tabAdapter); 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 9f85be1e0..4ddebeb92 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 @@ -3,6 +3,7 @@ package org.schabi.newpipe.fragments.list.search; import static androidx.recyclerview.widget.ItemTouchHelper.Callback.makeMovementFlags; import static org.schabi.newpipe.extractor.utils.Utils.isBlank; import static org.schabi.newpipe.ktx.ViewUtils.animate; +import static org.schabi.newpipe.ui.emptystate.EmptyStateUtil.setEmptyStateComposable; import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView; import static java.util.Arrays.asList; @@ -65,7 +66,6 @@ import org.schabi.newpipe.ktx.ExceptionUtils; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.settings.NewPipeSettings; import org.schabi.newpipe.ui.emptystate.EmptyStateSpec; -import org.schabi.newpipe.ui.emptystate.EmptyStateUtil; import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.ExtractorHelper; @@ -356,9 +356,7 @@ public class SearchFragment extends BaseListFragment { + LoadingIndicator(modifier = Modifier.padding(top = 8.dp)) + } + else -> { + // TODO use error panel instead + EmptyStateComposable( + spec = if (refresh is LoadState.Error) { + EmptyStateSpec.ErrorLoadingComments + } else { + EmptyStateSpec.NoComments }, - ), - modifier = Modifier - .fillMaxWidth() - .heightIn(min = 128.dp) - ) - } else { - EmptyStateComposable( - spec = EmptyStateSpec.NoComments, - modifier = Modifier - .fillMaxWidth() - .heightIn(min = 128.dp) - ) + modifier = Modifier + .fillMaxWidth() + .heightIn(min = 128.dp) + ) + } } } } else { diff --git a/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentSection.kt b/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentSection.kt index b2c9f6b85..a33ffc0ca 100644 --- a/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentSection.kt +++ b/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentSection.kt @@ -15,7 +15,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.rememberNestedScrollInteropConnection import androidx.compose.ui.res.pluralStringResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -75,7 +74,6 @@ private fun CommentSection( modifier = Modifier .fillMaxWidth() .heightIn(min = 128.dp) - ) } } else if (count == 0) { @@ -111,13 +109,7 @@ private fun CommentSection( is LoadState.Error -> { item { // TODO use error panel instead - EmptyStateComposable( - EmptyStateSpec.DisabledComments.copy( - descriptionText = { - stringResource(R.string.error_unable_to_load_comments) - } - ) - ) + EmptyStateComposable(EmptyStateSpec.ErrorLoadingComments) } } @@ -134,11 +126,7 @@ private fun CommentSection( item { // TODO use error panel instead EmptyStateComposable( - spec = EmptyStateSpec.DisabledComments.copy( - descriptionText = { - stringResource(R.string.error_unable_to_load_comments) - } - ), + spec = EmptyStateSpec.ErrorLoadingComments, modifier = Modifier .fillMaxWidth() .heightIn(min = 128.dp) diff --git a/app/src/main/java/org/schabi/newpipe/ui/emptystate/EmptyStateComposable.kt b/app/src/main/java/org/schabi/newpipe/ui/emptystate/EmptyStateComposable.kt index 3917c4203..77fa02082 100644 --- a/app/src/main/java/org/schabi/newpipe/ui/emptystate/EmptyStateComposable.kt +++ b/app/src/main/java/org/schabi/newpipe/ui/emptystate/EmptyStateComposable.kt @@ -1,6 +1,7 @@ package org.schabi.newpipe.ui.emptystate import android.graphics.Color +import androidx.annotation.StringRes import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth @@ -22,25 +23,14 @@ import org.schabi.newpipe.ui.theme.AppTheme fun EmptyStateComposable( spec: EmptyStateSpec, modifier: Modifier = Modifier, -) = EmptyStateComposable( - emojiText = spec.emojiText(), - descriptionText = spec.descriptionText(), - modifier = modifier -) - -@Composable -private fun EmptyStateComposable( - emojiText: String, - descriptionText: String, - modifier: Modifier = Modifier, ) { Column( modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center + verticalArrangement = Arrangement.Center, ) { Text( - text = emojiText, + text = spec.emojiText, style = MaterialTheme.typography.titleLarge, textAlign = TextAlign.Center, ) @@ -49,7 +39,7 @@ private fun EmptyStateComposable( modifier = Modifier .padding(top = 6.dp) .padding(horizontal = 16.dp), - text = descriptionText, + text = stringResource(spec.descriptionText), style = MaterialTheme.typography.bodyMedium, textAlign = TextAlign.Center, ) @@ -82,66 +72,48 @@ fun EmptyStateComposableNoCommentPreview() { } } -data class EmptyStateSpec( - val emojiText: @Composable () -> String, - val descriptionText: @Composable () -> String, +enum class EmptyStateSpec( + val emojiText: String, + @field:StringRes val descriptionText: Int, ) { - companion object { - - val GenericError = - EmptyStateSpec( - emojiText = { "¯\\_(ツ)_/¯" }, - descriptionText = { stringResource(id = R.string.empty_list_subtitle) }, - ) - - val NoVideos = - EmptyStateSpec( - emojiText = { "(╯°-°)╯" }, - descriptionText = { stringResource(id = R.string.no_videos) }, - ) - - val NoComments = - EmptyStateSpec( - - emojiText = { "¯\\_(╹x╹)_/¯" }, - descriptionText = { stringResource(id = R.string.no_comments) }, - ) - - val DisabledComments = - NoComments.copy( - descriptionText = { stringResource(id = R.string.comments_are_disabled) }, - ) - - val NoSearchResult = - NoComments.copy( - emojiText = { "╰(°●°╰)" }, - descriptionText = { stringResource(id = R.string.search_no_results) } - ) - - val NoSearchMaxSizeResult = - NoSearchResult - - val ContentNotSupported = - NoComments.copy( - emojiText = { "(︶︹︺)" }, - descriptionText = { stringResource(id = R.string.content_not_supported) }, - ) - - val NoBookmarkedPlaylist = - EmptyStateSpec( - emojiText = { "(╥﹏╥)" }, - descriptionText = { stringResource(id = R.string.no_playlist_bookmarked_yet) }, - ) - - val NoSubscriptionsHint = - EmptyStateSpec( - emojiText = { "(꩜ᯅ꩜)" }, - descriptionText = { stringResource(id = R.string.import_subscriptions_hint) }, - ) - - val NoSubscriptions = - NoSubscriptionsHint.copy( - descriptionText = { stringResource(id = R.string.no_channel_subscribed_yet) }, - ) - } + GenericError( + emojiText = "¯\\_(ツ)_/¯", + descriptionText = R.string.empty_list_subtitle, + ), + NoVideos( + emojiText = "(╯°-°)╯", + descriptionText = R.string.no_videos, + ), + NoComments( + emojiText = "¯\\_(╹x╹)_/¯", + descriptionText = R.string.no_comments, + ), + DisabledComments( + emojiText = "¯\\_(╹x╹)_/¯", + descriptionText = R.string.comments_are_disabled, + ), + ErrorLoadingComments( + emojiText = "¯\\_(╹x╹)_/¯", + descriptionText = R.string.error_unable_to_load_comments, + ), + NoSearchResult( + emojiText = "╰(°●°╰)", + descriptionText = R.string.search_no_results, + ), + ContentNotSupported( + emojiText = "(︶︹︺)", + descriptionText = R.string.content_not_supported, + ), + NoBookmarkedPlaylist( + emojiText = "(╥﹏╥)", + descriptionText = R.string.no_playlist_bookmarked_yet, + ), + NoSubscriptionsHint( + emojiText = "(꩜ᯅ꩜)", + descriptionText = R.string.import_subscriptions_hint, + ), + NoSubscriptions( + emojiText = "(꩜ᯅ꩜)", + descriptionText = R.string.no_channel_subscribed_yet, + ), } From 9d3775f132ee4213bec224f7bd2b2b1689aead77 Mon Sep 17 00:00:00 2001 From: Stypox Date: Sat, 6 Sep 2025 17:06:47 +0200 Subject: [PATCH 42/43] Rewrite logo SVGs to make them line-only Also optimize them with svgo --- assets/NP logo v2.svg | 22 +----------- assets/newpipe_squircle.svg | 1 + assets/pure_logo.svg | 68 +------------------------------------ 3 files changed, 3 insertions(+), 88 deletions(-) create mode 100644 assets/newpipe_squircle.svg diff --git a/assets/NP logo v2.svg b/assets/NP logo v2.svg index 51fdf95de..88bf3d33d 100644 --- a/assets/NP logo v2.svg +++ b/assets/NP logo v2.svg @@ -1,21 +1 @@ - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/assets/newpipe_squircle.svg b/assets/newpipe_squircle.svg new file mode 100644 index 000000000..91358d421 --- /dev/null +++ b/assets/newpipe_squircle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/pure_logo.svg b/assets/pure_logo.svg index 4455b19c6..c4473eb9b 100644 --- a/assets/pure_logo.svg +++ b/assets/pure_logo.svg @@ -1,67 +1 @@ - - - -image/svg+xml - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file From b36201442d6f7c2ffa43c7035b14bb9f96bcb924 Mon Sep 17 00:00:00 2001 From: Stypox Date: Sat, 6 Sep 2025 17:22:43 +0200 Subject: [PATCH 43/43] Use ImageVector to render NewPipe squircle app icon --- .../newpipe/ui/components/about/AboutTab.kt | 14 ++- .../newpipe/util/image/NewPipeSquircleIcon.kt | 99 +++++++++++++++++++ 2 files changed, 105 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/util/image/NewPipeSquircleIcon.kt diff --git a/app/src/main/java/org/schabi/newpipe/ui/components/about/AboutTab.kt b/app/src/main/java/org/schabi/newpipe/ui/components/about/AboutTab.kt index 3bba5dba9..dbb10b9a8 100644 --- a/app/src/main/java/org/schabi/newpipe/ui/components/about/AboutTab.kt +++ b/app/src/main/java/org/schabi/newpipe/ui/components/about/AboutTab.kt @@ -1,12 +1,14 @@ package org.schabi.newpipe.ui.components.about import androidx.annotation.StringRes +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.rememberScrollState @@ -16,7 +18,6 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.NonRestartableComposable -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext @@ -26,13 +27,12 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider import androidx.compose.ui.unit.dp -import androidx.core.content.ContextCompat.getDrawable -import coil3.compose.AsyncImage import my.nanihadesuka.compose.ColumnScrollbar import org.schabi.newpipe.BuildConfig import org.schabi.newpipe.R import org.schabi.newpipe.ui.components.common.defaultThemedScrollbarSettings import org.schabi.newpipe.util.external_communication.ShareUtils +import org.schabi.newpipe.util.image.NewPipeSquircleIcon private val ABOUT_ITEMS = listOf( AboutData(R.string.faq_title, R.string.faq_description, R.string.faq, R.string.faq_url), @@ -83,12 +83,10 @@ fun AboutTab() { .wrapContentSize(Alignment.Center), horizontalAlignment = Alignment.CenterHorizontally ) { - // note: the preview - val context = LocalContext.current - val launcherDrawable = remember { getDrawable(context, R.mipmap.ic_launcher) } - AsyncImage( - model = launcherDrawable, + Image( + imageVector = NewPipeSquircleIcon, contentDescription = stringResource(R.string.app_name), + modifier = Modifier.size(64.dp), ) Spacer(Modifier.height(4.dp)) Text( diff --git a/app/src/main/java/org/schabi/newpipe/util/image/NewPipeSquircleIcon.kt b/app/src/main/java/org/schabi/newpipe/util/image/NewPipeSquircleIcon.kt new file mode 100644 index 000000000..a4ff131a1 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/image/NewPipeSquircleIcon.kt @@ -0,0 +1,99 @@ +package org.schabi.newpipe.util.image + +import androidx.compose.foundation.Image +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp + +/** + * Generated with https://github.com/rafaeltonholo/svg-to-compose/ + * based on assets/newpipe_squircle.svg. + */ +val NewPipeSquircleIcon: ImageVector + get() { + val current = _newPipeIcon + if (current != null) return current + + return ImageVector.Builder( + name = "org.schabi.newpipe.ui.theme.AppTheme.NewPipeSquircleIcon", + defaultWidth = 100.0.dp, + defaultHeight = 100.0.dp, + viewportWidth = 100.0f, + viewportHeight = 100.0f, + ).apply { + // M0 50 C0 15 15 0 50 0 s50 15 50 50 -15 50 -50 50 S0 85 0 50 + path( + fill = SolidColor(Color(0xFFCD201F)), + ) { + // M 0 50 + moveTo(x = 0.0f, y = 50.0f) + // C 0 15 15 0 50 0 + curveTo( + x1 = 0.0f, + y1 = 15.0f, + x2 = 15.0f, + y2 = 0.0f, + x3 = 50.0f, + y3 = 0.0f, + ) + // s 50 15 50 50 + reflectiveCurveToRelative( + dx1 = 50.0f, + dy1 = 15.0f, + dx2 = 50.0f, + dy2 = 50.0f, + ) + // s -15 50 -50 50 + reflectiveCurveToRelative( + dx1 = -15.0f, + dy1 = 50.0f, + dx2 = -50.0f, + dy2 = 50.0f, + ) + // S 0 85 0 50 + reflectiveCurveTo( + x1 = 0.0f, + y1 = 85.0f, + x2 = 0.0f, + y2 = 50.0f, + ) + } + // M31.7 19.2 v61.7 l9.7 -5.73 V36 l23.8 14 -17.6 10.35 V71.5 L84 50 + path( + fill = SolidColor(Color(0xFFFFFFFF)), + ) { + // M 31.7 19.2 + moveTo(x = 31.7f, y = 19.2f) + // v 61.7 + verticalLineToRelative(dy = 61.7f) + // l 9.7 -5.73 + lineToRelative(dx = 9.7f, dy = -5.73f) + // V 36 + verticalLineTo(y = 36.0f) + // l 23.8 14 + lineToRelative(dx = 23.8f, dy = 14.0f) + // l -17.6 10.35 + lineToRelative(dx = -17.6f, dy = 10.35f) + // V 71.5 + verticalLineTo(y = 71.5f) + // L 84 50 + lineTo(x = 84.0f, y = 50.0f) + } + }.build().also { _newPipeIcon = it } + } + +@Preview +@Composable +private fun IconPreview() { + Image( + imageVector = NewPipeSquircleIcon, + contentDescription = null, + ) +} + +@Suppress("ObjectPropertyName") +private var _newPipeIcon: ImageVector? = null