From 60ed308caac3fe879629633bdab87e5da2f001ca Mon Sep 17 00:00:00 2001 From: Duppadaadadii Date: Sat, 4 Nov 2017 18:56:11 +0000 Subject: [PATCH 001/159] Translated using Weblate (Finnish) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-fi/strings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index bdaede658..02afa4998 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -268,4 +268,5 @@ Yksityiskohdat Audioasetukset Pidä pohjassa lisätäksesi jonoon - +Näytä vihje soittolistalle + From 17aa44c88b0a32b052c93e2067339fbc389142db Mon Sep 17 00:00:00 2001 From: Omar Date: Mon, 6 Nov 2017 09:34:32 +0000 Subject: [PATCH 002/159] Translated using Weblate (Arabic) Currently translated at 33.4% (78 of 233 strings) --- app/src/main/res/values-ar/strings.xml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 44599b136..1b06d5b17 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -13,12 +13,12 @@ هل تقصد : %1$s ؟ تنزيل تنزيل - أدخل مسار التنزيل للملفات الصوتية. + أدخل مسار لتنزيل الملفات الصوتية. مسار حفظ التنزيلات الصوتية في. مسار الصوتيات المحفوظة أدخل مسار التنزيل لملفات الفيديو مسار حفظ تنزيلات الفيديو في - مسار الفيديوهات المحفوظة + مسار تحميل الفيديو "لا يمكن إنشاء مجلد للتنزيلات في '%1$s'" "تم إنشاء مجلد تنزيلات في '%1$s'" تثبيت @@ -84,4 +84,13 @@ عن التطبيق التأريخ التأريخ + فتح في نوافذ + بعض خيارات الجودة لن يكون الصوت عند تمكين هذا الخيار + NewPipe وضع النافذة + تم إلغاء اشتراك القناة + تعذر تغيير في الاشتراك + تعذر تحديث الاشتراك + + نافذة + From 9dcbcd57cb29e468869a4b689220452169da8c10 Mon Sep 17 00:00:00 2001 From: anonymous <> Date: Mon, 6 Nov 2017 09:36:37 +0000 Subject: [PATCH 003/159] Translated using Weblate (Arabic) Currently translated at 33.4% (78 of 233 strings) --- app/src/main/res/values-ar/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 1b06d5b17..895d1adca 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -14,7 +14,7 @@ تنزيل تنزيل أدخل مسار لتنزيل الملفات الصوتية. - مسار حفظ التنزيلات الصوتية في. + مسار حفظ التنزيلات الصوتية مسار الصوتيات المحفوظة أدخل مسار التنزيل لملفات الفيديو مسار حفظ تنزيلات الفيديو في From e4d6a453b03a5434ec16c0b2a2adb09f67449f57 Mon Sep 17 00:00:00 2001 From: wb9688 Date: Mon, 6 Nov 2017 10:44:08 +0000 Subject: [PATCH 004/159] Translated using Weblate (Dutch) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-nl/strings.xml | 31 +++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 574b3189e..33c6a1df9 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -262,4 +262,33 @@ te openen in pop-upmodus Item verwijderd Wil je dit item uit je geschiedenis verwijderen? Laat vasthouden om te toevoegen zien - + Toon tip wanneer achtergrond- of pop-upknop is ingedrukt op de video-detailpagina + Toegevoegd aan wachtrij voor achtergrondspeler + Toegevoegd aan wachtrij voor pop-upspeler + Speel Alle + + Kon deze stream niet afspelen + Onherstelbare spelerfout opgetreden + Aan het herstellen van spelerfout + + Content van hoofdpagina + Blanke Pagina + Kioskpagina + Abonnementenpagina + Feedpagina + Kanaalpagina + Selecteer een kanaal + Nog niet geabonneerd op een kanaal + Selecteer een kiosk + + Kiosk + Trending + Top 50 + Nieuw en populair + Achtergrondspeler + Pop-upspeler + Verwijder + Details + Audio-instellingen + Houd ingedrukt om toe te voegen aan wachtrij + From 4b775d15a2a13a2322514bdb6549b9bd410a28a8 Mon Sep 17 00:00:00 2001 From: yilun Date: Mon, 6 Nov 2017 12:27:10 +0000 Subject: [PATCH 005/159] Fixes ClassCastException when getting Bitmap from AdaptiveIcon on Android 8+ --- .../us/shandian/giga/service/DownloadManagerService.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java index d60ae86ab..50975728f 100755 --- a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java +++ b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java @@ -6,8 +6,8 @@ import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Binder; import android.os.Handler; @@ -15,7 +15,6 @@ import android.os.HandlerThread; import android.os.IBinder; import android.os.Message; import android.support.v4.app.NotificationCompat.Builder; -import android.support.v4.content.ContextCompat; import android.support.v4.content.PermissionChecker; import android.util.Log; import android.widget.Toast; @@ -96,12 +95,12 @@ public class DownloadManagerService extends Service { openDownloadListIntent, PendingIntent.FLAG_UPDATE_CURRENT); - Drawable icon = ContextCompat.getDrawable(this, R.mipmap.ic_launcher); + Bitmap iconBitmap = BitmapFactory.decodeResource(this.getResources(), R.mipmap.ic_launcher); Builder builder = new Builder(this, getString(R.string.notification_channel_id)) .setContentIntent(pendingIntent) .setSmallIcon(android.R.drawable.stat_sys_download) - .setLargeIcon(((BitmapDrawable) icon).getBitmap()) + .setLargeIcon(iconBitmap) .setContentTitle(getString(R.string.msg_running)) .setContentText(getString(R.string.msg_running_detail)); From 6449d7d4eeadc1df0ca98e04938b0b3c5631c5ff Mon Sep 17 00:00:00 2001 From: anonymous <> Date: Mon, 6 Nov 2017 10:46:10 +0000 Subject: [PATCH 006/159] Translated using Weblate (Dutch) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-nl/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 33c6a1df9..1f2bc2d45 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -164,7 +164,7 @@ te openen in pop-upmodus Verversen Wissen - Onthou grootte en positie van pop-up + Onthoud grootte en positie van pop-up Onthou laatste grootte en positie van pop-up Pop-up From ebdeee8b3c4d00c091d55aca2f5ea0e9bbe0cddc Mon Sep 17 00:00:00 2001 From: wb9688 Date: Mon, 6 Nov 2017 17:20:28 +0000 Subject: [PATCH 007/159] Translated using Weblate (Dutch) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-nl/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 1f2bc2d45..00215278c 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -205,8 +205,8 @@ te openen in pop-upmodus Abonneer Geabonneerd Abonnement opgezegd - Niet in staat abonnement te wijzigen - Niet in staat abbonement te vernieuwen + Kan het abonnement niet veranderen + Kan het abonnement niet vernieuwen Start Abonnementen From 48cb3ed138521b609feab5ca943ecc7a4c5c02c9 Mon Sep 17 00:00:00 2001 From: Nathan Follens Date: Mon, 6 Nov 2017 17:23:49 +0000 Subject: [PATCH 008/159] Translated using Weblate (Dutch) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-nl/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 00215278c..c18e72e3b 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -261,7 +261,7 @@ te openen in pop-upmodus Item verwijderd Wil je dit item uit je geschiedenis verwijderen? -Laat vasthouden om te toevoegen zien +Toon tip voor ingedrukt houden om toe te voegen Toon tip wanneer achtergrond- of pop-upknop is ingedrukt op de video-detailpagina Toegevoegd aan wachtrij voor achtergrondspeler Toegevoegd aan wachtrij voor pop-upspeler From 04e22faf853695a25210d5e4c667cced617ad59e Mon Sep 17 00:00:00 2001 From: r2308145 Date: Mon, 6 Nov 2017 21:37:46 +0000 Subject: [PATCH 009/159] Translated using Weblate (Czech) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-cs/strings.xml | 78 ++++++++++++++++++-------- 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index ed2e8b5f8..6f1e0d24c 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -40,29 +40,29 @@ Stáhnout Následující video - Zobrazit následující a podobná videa + Zobrazovat další a podobná videa URL není podporováno Preferovaný jazyk obsahu - Video a audio + Video a zvuk Vzhled Ostatní - Přehrávám na pozadí + Přehrávání na pozadí Přehrát Chyba Chyba sítě Nebylo možné nahrát všechny náhledy Nebylo možné dekódovat URL videa - Nebylo možné analyzovat webovou stránku + Nebylo možné analyzovat stránku Obsah není k dispozici Obsah blokuje GEMA Náhled videa Náhled videa - Náhled obrázku uploadera + Náhled avataru uploadera To se mi líbí To se mi nelíbí Použít Tor - (Experimentální) Vynutit stahování skrz Tor pro zvýšené soukromí (streaming zatím není podporován). + (Experimentální) Vynutit stahování skrz Tor pro zvýšené soukromí (streamovaná videa zatím nepodporována). Nebylo možné vytvořit složku pro stažené soubory \'%1$s\' Vytvořena složka pro stažené soubory \'%1$s\' @@ -74,7 +74,7 @@ živě Nebylo možné kompletně analyzovat stránku - Pro začátek stiskni hledat + Začni stiskem hledat Zkopírováno do schránky Počkejte prosím… NewPipe se stahuje @@ -91,9 +91,9 @@ Začít Zkusit znovu Video - Audio + Zvuk Nahlásit chybu - Detaily: + Podrobnosti: Co se stalo: @@ -111,9 +111,9 @@ Stažené soubory Stažené soubory Info: - Vaše poznámky (Anglicky): + Vaše poznámky (anglicky): Oprávnění přístupu do úložiště bylo zamítnuto - Shlédnout + Přehrát Nová mise Hotovo @@ -160,9 +160,9 @@ otevření ve vyskakovacím okně Hlavní Odběry - Co je nové + Co je nového - V pozadí + Na pozadí V okně Výchozí rozlišení v okně @@ -187,7 +187,7 @@ otevření ve vyskakovacím okně Obnovit Vyčistit Změna velikosti - Nejlepší rozlošení + Nejlepší rozlišení Vrátit NewPipe notifikace @@ -208,12 +208,12 @@ otevření ve vyskakovacím okně - Žádná shlédnutí + Žádná zhlédnutí - %s shlédnutí - %s shlédnutí - %s shlédnutí - + %s zhlédnutí + %s zhlédnutí + %s zhlédnutí + Žádná videa @@ -234,12 +234,12 @@ otevření ve vyskakovacím okně O NewPipe Nastavení - O + O aplikaci Licence třetích stran © %1$s od %2$s pod %3$s - Nemožné nahrát licenci + Nepodařilo se nahrát licenci Otevřít webstránku - O + O aplikaci Přispěvatelé Licence Bezplatná a nenáročná YouTube aplikace pro Android. @@ -251,10 +251,42 @@ otevření ve vyskakovacím okně Histrorie Vyhledáváno - Sledováno + Zhlédnuto Historie je vypnutá Historie Historie je prázdná Historie byla vymazána Položka byla odstraněna +Zobrazovat nápovědu \"Podrž pro přidání\" + Zobrazí se po stisku tlačítka na pozadí nebo v okně na stránce s podrobnostmi o videu + Ve frontě přehrávače na pozadí + Ve frontě přehrávače v okně + Přehrát vše + + Přehrávání streamu selhalo + Došlo k neobnovitelné chybě přehrávače + Obnovování z chyby přehrávače + + Odstranit tuto položku z historie vyhledávání? + + Obsah úvodní obrazovky + Prázdná stránka + Kiosek + Odběry + Feed + Kanál + Zvolte kanál + Žádný kanál dosud neodebírán + Zvolte kiosek + + Kiosek + Trendy + Top 50 + Nové & hot + Přehrávač na pozadí + Přehrávač v okně + Odebrat + Detaily + Nastavení audia + Podrž pro zařazení do fronty From d5b1bae305dc16a686438d5b3c6770de4ca40578 Mon Sep 17 00:00:00 2001 From: vesp Date: Mon, 6 Nov 2017 21:38:56 +0000 Subject: [PATCH 010/159] Translated using Weblate (Czech) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-cs/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 6f1e0d24c..a39ea2c82 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -139,7 +139,7 @@ k Otevřít ve vyskakovacím okně - M + mil. Toto oprávnění je vyžadováno pro otevření ve vyskakovacím okně @@ -213,7 +213,7 @@ otevření ve vyskakovacím okně %s zhlédnutí %s zhlédnutí %s zhlédnutí - + Žádná videa From cc52d3b0af6fd3ca93c3d4e4562467b307b367cb Mon Sep 17 00:00:00 2001 From: r2308145 Date: Mon, 6 Nov 2017 21:39:49 +0000 Subject: [PATCH 011/159] Translated using Weblate (Czech) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-cs/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index a39ea2c82..7dbe2cbe8 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -198,7 +198,7 @@ otevření ve vyskakovacím okně Starý zabudovaný Mediaframework přehrávač - B + mld. Žádní odběratelé From d37fee346a65214956d9ada16294f3169188f4ff Mon Sep 17 00:00:00 2001 From: vesp Date: Mon, 6 Nov 2017 21:41:12 +0000 Subject: [PATCH 012/159] Translated using Weblate (Czech) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-cs/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 7dbe2cbe8..971dbf652 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -136,7 +136,7 @@ Později - k + tis. Otevřít ve vyskakovacím okně mil. From b242c86869cec3321acb1368201ddc3ef0f4d8cb Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Tue, 7 Nov 2017 11:04:12 +0100 Subject: [PATCH 013/159] add support for indian languages --- app/src/main/res/values-hi/strings.xml | 3 +++ app/src/main/res/values-te/strings.xml | 3 +++ app/src/main/res/values-tl/strings.xml | 3 +++ 3 files changed, 9 insertions(+) create mode 100644 app/src/main/res/values-hi/strings.xml create mode 100644 app/src/main/res/values-te/strings.xml create mode 100644 app/src/main/res/values-tl/strings.xml diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml new file mode 100644 index 000000000..8850a563a --- /dev/null +++ b/app/src/main/res/values-hi/strings.xml @@ -0,0 +1,3 @@ + + + diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml new file mode 100644 index 000000000..8850a563a --- /dev/null +++ b/app/src/main/res/values-te/strings.xml @@ -0,0 +1,3 @@ + + + diff --git a/app/src/main/res/values-tl/strings.xml b/app/src/main/res/values-tl/strings.xml new file mode 100644 index 000000000..8850a563a --- /dev/null +++ b/app/src/main/res/values-tl/strings.xml @@ -0,0 +1,3 @@ + + + From 4e4cabb92931717cb49ec9f64653581d38a0cd81 Mon Sep 17 00:00:00 2001 From: Omar Date: Mon, 6 Nov 2017 09:49:49 +0000 Subject: [PATCH 014/159] Translated using Weblate (Arabic) Currently translated at 40.3% (94 of 233 strings) --- app/src/main/res/values-ar/strings.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 895d1adca..004fe64ec 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -93,4 +93,20 @@ نافذة + تشغيل الفيديو تلقائيا عند استدعاء نيوبيب من تطبيق آخر + جودة النوافذ الافتراضية + إظهار جودة أعلى + فقط بعض الأجهزة تدعم تشغيل فيديوهات 2K / 4K + تنسيق الفيديو الافتراضي + تذكر حجم النافذة و وضعها + تذكر آخر حجم ومكان النافذة + ضوابط إشارة المشغل + استخدم الإشارات للتحكم في سطوع وحجم المشغل + اقتراحات البحث + عرض الاقتراحات عند البحث + سجل البحث + تخزين طلبات البحث محليا + تتبع مقاطع الفيديو التي تمت مشاهدتها + استئناف عند اكساب التركيز + متابعة اللعب بعد المقاطعات (مثل المكالمات الهاتفية) From 64ac631040a0f9470d0a88a8723ebd4bc9f1bcb9 Mon Sep 17 00:00:00 2001 From: r2308145 Date: Mon, 6 Nov 2017 22:18:05 +0000 Subject: [PATCH 015/159] Translated using Weblate (Czech) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-cs/strings.xml | 58 +++++++++++++------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 971dbf652..85dc7357d 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -30,8 +30,8 @@ Zobrazit možnost \"Přehrát pomocí Kodi\" Zobrazit možnost přehrání videa pomocí multimediálního centra Kodi - Audio - Výchozí audio formát + Zvuk + Výchozí formát zvuku WebM — svobodný formát M4A — lepší kvalita Téma @@ -39,7 +39,7 @@ Světlé Stáhnout - Následující video + Další video Zobrazovat další a podobná videa URL není podporováno Preferovaný jazyk obsahu @@ -77,18 +77,18 @@ Začni stiskem hledat Zkopírováno do schránky Počkejte prosím… - NewPipe se stahuje - Stiskněte pro detaily + NewPipe stahuje + Stiskni pro detaily Server není podporován Soubor již existuje - Špatné URL nebo připojení k Internetu není k disposici + Špatné URL nebo bez připojení k internetu Chyba Jméno souboru Vlákna Zastavit Smazat - Začít + Start Zkusit znovu Video Zvuk @@ -115,7 +115,7 @@ Oprávnění přístupu do úložiště bylo zamítnuto Přehrát Nová mise - Hotovo + OK reCAPTCHA Výzva reCAPTCHA @@ -145,14 +145,14 @@ otevření ve vyskakovacím okně Použít starý přehrávač Některé formáty rozlišení NEBUDOU obsahovat zvukovou stopu po zapnutí této funkce - Zobrazit vyšší rozlišení - Pouze některá zařízení podporují přehrávání videí ve 2K/4K - Preferovaný video formát - Zapamatovat si velikost a pozici vyskakovacího okna - Zapamatovat si poslední nastavení velikosti a pozice vyskakovacího okna - Režim NewPipe vyskakovacího okna + Zobrazovat vyšší rozlišení + Pouze některá zařízení podporují přehrávání 2K/4K videí + Výchozí formát videa + Pamatovat si velikost a pozici vyskakovacího okna + Pamatovat si poslední velikost a pozici vyskakovacího okna + NewPipe režim vyskakovacího okna Odebírat - Odebírané + Odebíráno Odběr zrušen Nelze změnit odběr Nelze aktualizovat odběr @@ -165,15 +165,15 @@ otevření ve vyskakovacím okně Na pozadí V okně - Výchozí rozlišení v okně - Nastavení gest přehrávače - Používat gesta pro kontrolu jasu a hlasitosti přehrávače - Vyhledat návrhy - Ukazovat návrhy při vyhledávání - Historie prohlížení - Ukládat hledané výrazy lokálně + Výchozí rozlišení vyskakovacího okna + Ovládání přehrávače gesty + Používat gesta pro nastavení jasu a hlasitosti přehrávače + Návrhy vyhledávání + Zobrazovat návrhy při vyhledávání + Historie vyhledávání + Hledané výrazy lokálně uchovávat Historie - Evidovat sledovaná videa + Evidovat zhlédnutá videa Přehrávat po přechodu do popředí Pokračovat v přehrávání po přerušení (např. hovor) Přehrávač @@ -226,7 +226,7 @@ otevření ve vyskakovacím okně Stahování Povolené znaky v názvech souborů - Neplatné znaky jdou nahrazeny těmito znaky + Neplatné znaky budou nahrazeny těmito Náhradní znak Písmena a číslice @@ -249,15 +249,15 @@ otevření ve vyskakovacím okně Přečíst licenci Příspěvek - Histrorie + Historie Vyhledáváno Zhlédnuto Historie je vypnutá Historie Historie je prázdná - Historie byla vymazána + Historie smazána Položka byla odstraněna -Zobrazovat nápovědu \"Podrž pro přidání\" +Zobrazovat tip \"Podrž pro přidání\" Zobrazí se po stisku tlačítka na pozadí nebo v okně na stránce s podrobnostmi o videu Ve frontě přehrávače na pozadí Ve frontě přehrávače v okně @@ -286,7 +286,7 @@ otevření ve vyskakovacím okně Přehrávač na pozadí Přehrávač v okně Odebrat - Detaily - Nastavení audia + Podrobnosti + Nastavení zvuku Podrž pro zařazení do fronty From 1a4ef06ee98b1608f311208c4bf6a80dfb8b4e42 Mon Sep 17 00:00:00 2001 From: Nathan Follens Date: Mon, 6 Nov 2017 17:27:55 +0000 Subject: [PATCH 016/159] Translated using Weblate (Dutch) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-nl/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index c18e72e3b..2057bb4e2 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -265,7 +265,7 @@ te openen in pop-upmodus Toon tip wanneer achtergrond- of pop-upknop is ingedrukt op de video-detailpagina Toegevoegd aan wachtrij voor achtergrondspeler Toegevoegd aan wachtrij voor pop-upspeler - Speel Alle + Alles afspelen Kon deze stream niet afspelen Onherstelbare spelerfout opgetreden @@ -287,7 +287,7 @@ te openen in pop-upmodus Nieuw en populair Achtergrondspeler Pop-upspeler - Verwijder + Verwijderen Details Audio-instellingen Houd ingedrukt om toe te voegen aan wachtrij From 65205ace952998689cb208cef5b681e7fe5fec13 Mon Sep 17 00:00:00 2001 From: Duppadaadadii Date: Mon, 6 Nov 2017 20:59:46 +0000 Subject: [PATCH 017/159] Translated using Weblate (Finnish) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-fi/strings.xml | 52 +++++++++++++------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 568d25cd9..f375e469b 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -2,13 +2,13 @@ Napauta hakua aloittaaksesi %1$s näyttökertaa Julkaistu %1$s - Ei löytynyt suoratoistosoitinta. Haluatko asentaa VLC:n? + Ei löytynyt soitinta. Haluatko asentaa VLC:n? Asenna Peruuta Avaa selaimessa Avaa ponnahdusikkunassa Jaa - Lataa + Lataus Haku Asetukset Tarkoititko: %1$s ? @@ -33,13 +33,13 @@ Taustatoisto Ikkuna - Videon latauksen sijainti + Videolatausten sijainti Sijainti ladatuille videoille Aseta sijainti minne videot tallennetaan - Audion latauksen sijainti - Sijainti ladatuille audiotiedostoille - Aseta sijainti minne audiotiedostot tallennetaan + Äänilatausten sijainti + Sijainti ladatuille äänitiedostoille + Aseta sijainti minne äänitiedostot tallennetaan Automaattitoisto Toistaa automaattisesti videon, kun NewPipe sovellusta kutsutaan toisesta sovelluksesta @@ -51,9 +51,9 @@ Kore sovellusta ei löytynyt. Asennetaanko se? Näytä \"Toista Kodi:ssa\" vaihtoehto Näyttää painikkeen, jolla voi toistaa videon Kodi media center:llä - Audio - Oletus audioformaatti - Oletus videoformaatti + Ääni + Oletusääniformaatti + Oletusvideoformaatti WebM — vapaa formaatti M4A — parempi laatu Teema @@ -71,14 +71,14 @@ Historia Pidä muistissa katsotut videot Jatka toistoa keskeytysten jälkeen (esim. puhelut) - Lataa + Lataus Seuraava video - Näytä seuraava video ja samankaltaisia videoita + Näytä seuraavia ja samankaltaisia videoita URL ei tueta - Oletus sisällon kieli + Oletus-sisällon kieli Soitin Käyttäytyminen - Video & Audio + Video & Ääni Historia Ponnahdusikkuna Ulkoasu @@ -147,11 +147,11 @@ Luotiin lataushakemisto \'%1$s\' Video - Audio + Ääni Toista uudelleen Oikeus tallennustilan hallintaan evätty Käytä vanhaa soitinta - Käytä vanhaa sisäänrakennettua Mediaframework soitinta + Käytä vanhaa sisäänrakennettua Mediaframework-soitinta t. milj. @@ -218,7 +218,7 @@ Tietoja Hyväntekijät Lisenssit - Vapaa kevyt YouTube frontend Android:lle. + Vapaa kevyt Android YouTube-frontend. Näytä GitHub:ssa NewPipe:n Lisenssi Olkoon sinulla ideoita; käännöksistä, design muutoksista, koodin siivoamisesta tai raskaista koodimuutoksista—apu on aina tervetullutta. Mitä enemmän saadaan tehtyä, sen paremmaksi sovellus tulee! @@ -240,10 +240,10 @@ © %1$s %2$s %3$s alla Pääsivun sisältö Tyhjä sivu - Kioski sivu - Tilaukset sivu - Syötteet sivu - Kanavat sivu + Kioski + Tilaukset + Syötteet + Kanavat Valitse kanava Ei yhtään tilattua kanavaa vielä Valitse kioski @@ -252,20 +252,20 @@ Nousussa Top 50 Uudet & kuumat -Näytä vihje kun taustasoitto tai popup painiketta on painettu +Näytä vihje kun taustasoitto tai popup painiketta painetaan pohjassa Lisätty taustasoittojonoon - Lisätty popup-jonoon + Lisätty ikkunajonoon Toista kaikki - Suoratoisto epäonnistui + Toisto epäonnistui Palautuskelvoton soittimen virhe Palaudutaan soittimen virheestä - Taustasoittosoitin - Popup-soitin + Taustatoisto + Ikkuna Poista Yksityiskohdat - Audioasetukset + Ääniasetukset Pidä pohjassa lisätäksesi jonoon Näytä vihje soittolistalle From 441b510775e2d2b7b335a05a3d1067c40f6ea0be Mon Sep 17 00:00:00 2001 From: TobiGr Date: Tue, 7 Nov 2017 14:48:33 +0100 Subject: [PATCH 018/159] Fix plurals not showing number of views, videos and subscribers Fix typo in pull request template --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- app/src/main/res/values-cs/strings.xml | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0f588e9dd..d0e58680a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1 +1 @@ -- [ ] I carefully reed the [contribution guidelines](https://github.com/TeamNewPipe/NewPipe/blob/HEAD/.github/CONTRIBUTING.md) and agree to them. +- [ ] I carefully read the [contribution guidelines](https://github.com/TeamNewPipe/NewPipe/blob/HEAD/.github/CONTRIBUTING.md) and agree to them. diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 85dc7357d..196c1e517 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -204,24 +204,21 @@ otevření ve vyskakovacím okně %s odběratel %s odběratelů - %s odběratelé - + %s odběratelé Žádná zhlédnutí %s zhlédnutí %s zhlédnutí - %s zhlédnutí - + %s zhlédnutí Žádná videa %s video %s videí - %s videa - + %s videa Stahování From 1c20a4d9eb0e10f3d1b814242a5aeccc21bc1cc4 Mon Sep 17 00:00:00 2001 From: Arjen Singels Date: Wed, 8 Nov 2017 13:58:01 +0200 Subject: [PATCH 019/159] Update CONTRIBUTING.md fixed typo. --- .github/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 4a3cc8254..ae6ea696c 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -32,7 +32,7 @@ Do not report crashes in the GitHub issue tracker. NewPipe has an automated cras * Please test (compile and run) your code before you submit changes! Ideally, provide test feedback in the PR description. Untested code will **not** be merged! * Try to figure out yourself why builds on our CI fail. * Make sure your PR is up-to-date with the rest of the code. Often, a simple click on "Update branch" will do the job, but if not, you are asked to merge the master branch manually and resolve the problems on your own. That will make the maintainers' jobs way easier. -* Please show intention to maintain your features and code after you contributed it. Unmaintained code is a hassle for the core developers, and just adds work. If you do not intend to maintain features you contributed, please think again about sumission, or clearly state that in the description of your PR. +* Please show intention to maintain your features and code after you contributed it. Unmaintained code is a hassle for the core developers, and just adds work. If you do not intend to maintain features you contributed, please think again about submission, or clearly state that in the description of your PR. * Respond yourselves if someone requests changes or otherwise raises issues about your PRs. * Check if your contributions align with the [fdroid inclusion guidelines](https://f-droid.org/en/docs/Inclusion_Policy/). * Check if your submission can be build with the current fdroid build server setup. From 1fbc8a28507f72a5c5537ff6faee456c72ef9870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Freddy=20Mor=C3=A1n=20Jr?= Date: Tue, 7 Nov 2017 18:05:55 +0000 Subject: [PATCH 020/159] Translated using Weblate (Spanish) Currently translated at 98.7% (230 of 233 strings) --- app/src/main/res/values-es/strings.xml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index d39156260..11931b05f 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -273,4 +273,18 @@ abrir en modo popup Kiosco Tendencias Top 50 - +Mostrar sugerencia cuando se presiona el botón de segundo plano o popup en la página de detalles del vídeo + En cola en el reproductor de fondo + En cola en el reproductor popup + Reproducir todo + + Error al reproducir esta transmisión + Se produjo un error irrecuperable del reproductor + Recuperándose del error del reproductor + + Reproductor de fondo + Reproductor popup + Remover + Detalles + Ajustes de audio + From 401960079caecacb6c23d20284cb54be75e64ea5 Mon Sep 17 00:00:00 2001 From: r2308145 Date: Tue, 7 Nov 2017 21:39:31 +0000 Subject: [PATCH 021/159] Translated using Weblate (Czech) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-cs/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 85dc7357d..73b049318 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -258,7 +258,7 @@ otevření ve vyskakovacím okně Historie smazána Položka byla odstraněna Zobrazovat tip \"Podrž pro přidání\" - Zobrazí se po stisku tlačítka na pozadí nebo v okně na stránce s podrobnostmi o videu + Zobrazí se na stránce videa po stisku tlačítek přehrát na pozadí nebo v okně Ve frontě přehrávače na pozadí Ve frontě přehrávače v okně Přehrát vše From 84d21af64499dffaa31e761ffbd255bd429836e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Wed, 8 Nov 2017 20:27:17 +0000 Subject: [PATCH 022/159] =?UTF-8?q?Translated=20using=20Weblate=20(Norwegi?= =?UTF-8?q?an=20Bokm=C3=A5l)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 95.7% (223 of 233 strings) --- app/src/main/res/values-nb-rNO/strings.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index ae4d6e10e..c60bc6fa6 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -254,4 +254,24 @@ Historikk tømt Element slettet Ønsker du å slette dette elementet fra søkehistorikken? +Spill av alle + + Klarte ikke å spille av denne strømmen + Uopprettelig avspillerfeil oppstod + Blank side + Kiosk-side + Abonnementsside + Kanalside + Velg en kanal + Velg en kiosk + + Kiosk + Topp 50 + Nytt og hett + Bakgrunnsavspiller + Oppsprettsavspiller + Fjern + Detaljer + Lydinnstillinger + Hold for å legge i kø From 985bf50f7f79a3bdd1845ab3a5509a912daa5d24 Mon Sep 17 00:00:00 2001 From: Xuacu Saturio Date: Wed, 8 Nov 2017 21:21:39 +0000 Subject: [PATCH 023/159] Translated using Weblate (Asturian) Currently translated at 96.5% (225 of 233 strings) --- app/src/main/res/values-b+ast/strings.xml | 24 ++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-b+ast/strings.xml b/app/src/main/res/values-b+ast/strings.xml index c3bd768df..08d209448 100644 --- a/app/src/main/res/values-b+ast/strings.xml +++ b/app/src/main/res/values-b+ast/strings.xml @@ -253,4 +253,26 @@ Llimpióse l\'historial Desanicióse l\'elementu ¿Quies desaniciar esti elementu del historial de gueta? - +Reproducir too + + Nun pudo reproducise esta tresmisión + Asocedió un error irrecuperable del reproductor + Recuperándose del error del reproductor + + Conteníu de la páxina principal + Páxina en blancu + Páxina del quioscu + Páxina de suscripción + Páxina de fluxu + Páxina de canal + Seleiciona un canal + Entá nun hai canales soscritos + Seleiciona un quioscu + + Quioscu + Tendencies + 50 meyores + Reproductor de fondu + Desaniciar + Detalles + From 5d6320d925b024258be6055d14a9cf0b3f212de3 Mon Sep 17 00:00:00 2001 From: wb9688 Date: Fri, 10 Nov 2017 10:33:59 +0100 Subject: [PATCH 024/159] Upgrade to Studio 3 --- app/build.gradle | 64 +++++++++++++----------- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 3 +- 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f7af72968..187bb5326 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 26 - buildToolsVersion '26.0.1' + compileSdkVersion 27 + buildToolsVersion '27.0.1' defaultConfig { applicationId "org.schabi.newpipe" minSdkVersion 15 - targetSdkVersion 26 + targetSdkVersion 27 versionCode 41 versionName "0.11.0" @@ -27,6 +27,10 @@ android { applicationIdSuffix ".debug" } beta { + minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + applicationIdSuffix ".beta" } } @@ -44,42 +48,42 @@ android { } dependencies { - androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2') { + androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2') { exclude module: 'support-annotations' } - compile 'com.github.TeamNewPipe:NewPipeExtractor:b9d0941' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:b9d0941411' - testCompile 'junit:junit:4.12' - testCompile 'org.mockito:mockito-core:1.10.19' + testImplementation 'junit:junit:4.12' + testImplementation 'org.mockito:mockito-core:1.10.19' - compile 'com.android.support:appcompat-v7:26.0.1' - compile 'com.android.support:support-v4:26.0.1' - compile 'com.android.support:design:26.0.1' - compile 'com.android.support:recyclerview-v7:26.0.1' - compile 'com.android.support:preference-v14:26.0.1' + implementation 'com.android.support:appcompat-v7:27.0.0' + implementation 'com.android.support:support-v4:27.0.0' + implementation 'com.android.support:design:27.0.0' + implementation 'com.android.support:recyclerview-v7:27.0.0' + implementation 'com.android.support:preference-v14:27.0.0' - compile 'com.google.code.gson:gson:2.7' - compile 'ch.acra:acra:4.9.0' + implementation 'com.google.code.gson:gson:2.8.2' + implementation 'ch.acra:acra:4.9.0' - compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' - compile 'de.hdodenhof:circleimageview:2.1.0' - compile 'com.github.nirhart:parallaxscroll:1.0' - compile 'com.nononsenseapps:filepicker:3.0.1' - compile 'com.google.android.exoplayer:exoplayer:r2.5.4' + implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' + implementation 'de.hdodenhof:circleimageview:2.2.0' + implementation 'com.github.nirhart:ParallaxScroll:dd53d1f9d1' + implementation 'com.nononsenseapps:filepicker:3.0.1' + implementation 'com.google.android.exoplayer:exoplayer:r2.5.4' - debugCompile 'com.facebook.stetho:stetho:1.5.0' - debugCompile 'com.facebook.stetho:stetho-urlconnection:1.5.0' - debugCompile 'com.android.support:multidex:1.0.1' + debugImplementation 'com.facebook.stetho:stetho:1.5.0' + debugImplementation 'com.facebook.stetho:stetho-urlconnection:1.5.0' + debugImplementation 'com.android.support:multidex:1.0.2' - compile 'io.reactivex.rxjava2:rxjava:2.1.2' - compile 'io.reactivex.rxjava2:rxandroid:2.0.1' - compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0' + implementation 'io.reactivex.rxjava2:rxjava:2.1.6' + implementation 'io.reactivex.rxjava2:rxandroid:2.0.1' + implementation 'com.jakewharton.rxbinding2:rxbinding:2.0.0' - compile 'android.arch.persistence.room:runtime:1.0.0-alpha8' - compile 'android.arch.persistence.room:rxjava2:1.0.0-alpha8' - annotationProcessor 'android.arch.persistence.room:compiler:1.0.0-alpha8' + implementation 'android.arch.persistence.room:runtime:1.0.0' + implementation 'android.arch.persistence.room:rxjava2:1.0.0' + annotationProcessor 'android.arch.persistence.room:compiler:1.0.0' - compile 'frankiesardo:icepick:3.2.0' - provided 'frankiesardo:icepick-processor:3.2.0' + implementation 'frankiesardo:icepick:3.2.0' + annotationProcessor 'frankiesardo:icepick-processor:3.2.0' } diff --git a/build.gradle b/build.gradle index 5c494fe59..c0c46fdc2 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.0.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 52dd1f044..4c397c615 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Thu Nov 09 12:44:58 CET 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.3.1-all.zip From b4120c39e6d803e51e96c54bfc76b1ec1d5a0609 Mon Sep 17 00:00:00 2001 From: Ephraim Raj Date: Thu, 9 Nov 2017 12:36:18 +0000 Subject: [PATCH 025/159] Translated using Weblate (Hindi) Currently translated at 21.8% (51 of 233 strings) --- app/src/main/res/values-hi/strings.xml | 57 +++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 8850a563a..407011ab1 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -1,3 +1,58 @@ - +%1$s दृश्य + %1$s को प्रकाशित + + इंस्टॉल करें + ब्राउज़र में खोलें + पॉपअप मोड में खोलें + शेयर करें + डाउनलोड + खोज + सेटिंग + ब्राउज़र चुनें + रोटेशन + [NEWPIPE] पॉपअप मोड + सदस्य बनें + सदस्यता ली + सदस्यता निकाली गई + सदस्यता + + पीछे + पॉप अप + + स्वतः चलाएं + ऑडियो + हलका + काली + इतिहास + डाउनलोड + अगला वीडियो + वीडियो और ऑडियो + इतिहास + पीछे चल रहा है + कोई दृश्य नहीं + कोई वीडियो नहीं है + [NewPipe] बारे में + सेटिंग + इसके बारे में + तृतीय पक्ष लाइसेंस + वेबसाइट खोलें + इसके बारे में + लाइसेंस + GitHub में देखें + [NewPipe] का लाइसेंस + लाइसेंस पढ़ें + योगदान + + इतिहास + कोज चुके + देखा वीडियो + इतिहास अक्षम है + इतिहास + इतिहास खाली है + इतिहास स्पष्ट हो चुकी है + मद हटाया गया + चर्चित + ऑडियो सेटिंग + From a09c8934fcc249f3cfa964dc8e48706b27b6d133 Mon Sep 17 00:00:00 2001 From: wb9688 Date: Fri, 10 Nov 2017 15:34:57 +0100 Subject: [PATCH 026/159] Fix Travis --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e0fcfb82b..fe50d1a63 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,10 @@ android: components: # The BuildTools version used by NewPipe - tools - - build-tools-26.0.1 + - build-tools-27.0.1 # The SDK version used to compile NewPipe - - android-26 + - android-27 script: ./gradlew -Dorg.gradle.jvmargs=-Xmx1536m assembleDebug lintDebug testDebugUnitTest From ac53eeb76d8f071d950cbbd5f5379bea31a19818 Mon Sep 17 00:00:00 2001 From: wb9688 Date: Fri, 10 Nov 2017 15:36:13 +0100 Subject: [PATCH 027/159] Upgrade ACRA --- app/build.gradle | 2 +- app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 187bb5326..69504e2f9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -64,7 +64,7 @@ dependencies { implementation 'com.android.support:preference-v14:27.0.0' implementation 'com.google.code.gson:gson:2.8.2' - implementation 'ch.acra:acra:4.9.0' + implementation 'ch.acra:acra:4.9.2' implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' implementation 'de.hdodenhof:circleimageview:2.2.0' diff --git a/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java b/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java index b62b63510..43e240fbb 100644 --- a/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java +++ b/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java @@ -160,7 +160,7 @@ public class ErrorActivity extends AppCompatActivity { key = k; } } - String[] el = new String[]{report.get(key)}; + String[] el = new String[]{report.get(key).toString()}; Intent intent = new Intent(context, ErrorActivity.class); intent.putExtra(ERROR_INFO, errorInfo); From 997381d0c3652e7fe35811c98058abd7da2dbf32 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Fri, 10 Nov 2017 16:57:58 +0100 Subject: [PATCH 028/159] Fix Tamil language code --- app/src/main/res/{values-tl => values-ta}/strings.xml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/main/res/{values-tl => values-ta}/strings.xml (100%) diff --git a/app/src/main/res/values-tl/strings.xml b/app/src/main/res/values-ta/strings.xml similarity index 100% rename from app/src/main/res/values-tl/strings.xml rename to app/src/main/res/values-ta/strings.xml From e6773aac0e9ac3f994fb1975a6aa728ab5fb93a1 Mon Sep 17 00:00:00 2001 From: Nick Undnick Date: Thu, 9 Nov 2017 18:25:56 +0000 Subject: [PATCH 029/159] Translated using Weblate (German) Currently translated at 99.5% (232 of 233 strings) --- app/src/main/res/values-de/strings.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index e6d39d3c9..7efeee6cd 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -284,4 +284,8 @@ Kiosk auswählen Kiosk - + "Tipp anzeigen, wenn der Hintergrundwiedergabe-Button oder der Popup-Button auf der Videodetailseite gedrückt und gehalten wird" + In der Warteschlange bei der Hintergrundwiedergabe + Neu und brandheiß + Halten, um in die Warteschlange einzureihen + From 4f44f263334a4949a29855c5690cb658c8b9ee8b Mon Sep 17 00:00:00 2001 From: Tobias Groza Date: Fri, 10 Nov 2017 19:39:23 +0000 Subject: [PATCH 030/159] Translated using Weblate (German) Currently translated at 99.5% (232 of 233 strings) --- app/src/main/res/values-de/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 7efeee6cd..4e0f45332 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -284,7 +284,7 @@ Kiosk auswählen Kiosk - "Tipp anzeigen, wenn der Hintergrundwiedergabe-Button oder der Popup-Button auf der Videodetailseite gedrückt und gehalten wird" + Tipp anzeigen, wenn der Hintergrundwiedergabe-Button oder der Popup-Button auf der Videodetailseite gedrückt und gehalten wird In der Warteschlange bei der Hintergrundwiedergabe Neu und brandheiß Halten, um in die Warteschlange einzureihen From 80d16ea4074dd412db1173513725d05cebc5dcc4 Mon Sep 17 00:00:00 2001 From: r2308145 Date: Fri, 10 Nov 2017 14:43:49 +0000 Subject: [PATCH 031/159] Translated using Weblate (Czech) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-cs/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 92b25f322..085f06ffa 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -255,7 +255,7 @@ otevření ve vyskakovacím okně Historie smazána Položka byla odstraněna Zobrazovat tip \"Podrž pro přidání\" - Zobrazí se na stránce videa po stisku tlačítek přehrát na pozadí nebo v okně + Zobrazí se po stisku tlačítek přehrát na pozadí nebo v okně na stránce videa Ve frontě přehrávače na pozadí Ve frontě přehrávače v okně Přehrát vše @@ -270,7 +270,7 @@ otevření ve vyskakovacím okně Prázdná stránka Kiosek Odběry - Feed + Novinky Kanál Zvolte kanál Žádný kanál dosud neodebírán From ac01c4966605cc9dea59a8764f4daa87fa80149a Mon Sep 17 00:00:00 2001 From: drgsh Date: Fri, 10 Nov 2017 16:51:05 +0000 Subject: [PATCH 032/159] Translated using Weblate (Hindi) Currently translated at 23.6% (55 of 233 strings) --- app/src/main/res/values-hi/strings.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 407011ab1..e4e248c47 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -2,7 +2,7 @@ %1$s दृश्य %1$s को प्रकाशित - + वीडियो दिखाना के लिए एप्लिकेशन नहीं मिला. क्या आप VLC इंस्टॉल करना चाहते हैं? इंस्टॉल करें ब्राउज़र में खोलें पॉपअप मोड में खोलें @@ -55,4 +55,7 @@ मद हटाया गया चर्चित ऑडियो सेटिंग + खोज चिह्न दबाके आरंम्भ करे + रद्द करें + क्या आप का मतलब %1$s है? From b39366c80a06398266f7822ab3c4936edb663b10 Mon Sep 17 00:00:00 2001 From: Praveen0899 Date: Fri, 10 Nov 2017 10:32:51 +0000 Subject: [PATCH 033/159] Translated using Weblate (Telugu) Currently translated at 72.5% (169 of 233 strings) --- app/src/main/res/values-te/strings.xml | 196 +++++++++++++++++++++++++ 1 file changed, 196 insertions(+) diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index 8850a563a..6ac31bd85 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -1,3 +1,199 @@ +ప్రారంభించడానికి శోధనను క్లిక్ + %1$s వీక్షణలు + %1$\ts ప్రచురించబడింది + ఇన్స్టాల్ + రద్దు చేయి + బ్రౌజర్ తెరవండి + ఈ వీడియోను భాగస్వామ్యం చేయండి + డౌన్లోడ్ + శోధిచు + సెట్టింగ్‌లు + %1$s ? అంటే నువ్వు అనేది + తో పంచు + బ్రౌజర్ను ఎంచుకోండి + భ్రమణ + బాహ్యట ఆడియో ప్లేయర్ని ఉపయోగించండి + న్యూపై పాప్అప్ + సభ్యత్వ + సబ్ స్క్రైబ్ + అన్ సబ్స్క్రైబ్ చేయబడింది + సబ్ స్క్రైబ్ సాధ్యం కాలేదు + సబ్ స్క్రైబ్ నవీకరించలేరు + + ప్రధానంగా + సభ్యత్వం + + కొత్తది ఏమిటి + + వెనకవైపు + పాప్అప్ + + వీడియో డౌన్లోడ్ మార్గం + డౌన్లోడ్ చేసిన వీడియోలను నిల్వ చేయడానికి మార్గం + వీడియోల కోసం డౌన్లోడ్ మార్గాన్ని నమోదు చేయండి + + ఆడియో డౌన్లోడ్ మార్గం + ఆడియో కోసం డౌన్లోడ్ మార్గాన్ని నమోదు చేయండి + ఆడియో ఫైల్లకు డౌన్లోడ్ మార్గాన్ని ఇవ్వండి + + దానంతట అదే ఆడుతుంది + కోడితో ప్లే చేయండి + కోరే అనువర్తనం కనుగొనబడలేదు. దీన్ని ఇన్స్టాల్ చేయండి + కోరే అనువర్తనం కనుగొనబడలేదు. దీన్ని ఇన్స్టాల్ చేయండి + ఆడియో + డిఫాల్ట్ ఆడియో ఫార్మాట్ + థీమ్ + ప్రకాశం + చరిత్ర + డౌన్లోడ్ + తదుపరి వీడియో + తదుపరి వీడియో మరియు ఇలాంటి వీడియో + చిట్కాను అనుబంధించడానికి హోల్డ్ను చూపు + Url మద్దతు లేదు + డిఫాల్ట్ భాష + ప్లేయర్ + ప్రవర్తన + వీడియో & ఆడియో + చరిత్ర + పాప్అప్ + స్వరూపం + ఇతర + వెనకవైపులో ఆడుతున్నారు + పాపప్ రీతిలో ప్లే చేస్తోంది + "ఆటగాడిపై క్యూ" + ప్లే + కంటెంట్ + డౌన్ లోడ్ల + డౌన్ లోడ్ + లోపం నివేదిక + అన్ని + ఛానల్ + ప్లేజాబితా + అవును + తర్వాత + రిఫ్రెష్ + అన్నింటినీ ప్లే చేయండి + + న్యూప్యాప్ నోటిఫికేషన్ + లోపం + నెట్వర్క్ లోపం + అన్ని సూక్ష్మచిత్రాలను లోడ్ చేయలేకపోయాము + వెబ్సైట్ను అన్వయించడం సాధ్యం కాలేదు + పూర్తిగా వెబ్సైట్ని అన్వయించడం సాధ్యం కాలేదు + కంటెంట్ అందుబాటులో లేదు + డౌన్లోడ్ మెనుని సెటప్ చేయడం సాధ్యపడలేదు + ఏ స్ట్రీమ్ను పొందడం సాధ్యం కాలేదు + చిత్రాన్ని లోడ్ చేయడం సాధ్యపడలేదు + ఈ స్ట్రీమ్ని ప్లే చేయడం విఫలమైంది + ఆటగాడు లోపం నుండి పునరుద్ధరించడం + + క్షమించాలి, అది జరగకూడదు + ఇ-మెయిల్ ద్వారా నివేదన లోపం + క్షమించండి, కొన్ని లోపాలు సంభవించాయి + నివేదిక + సమాచారం + ఏం జరిగింది + మీ వ్యాఖ్య(ఆంగ్లం లో) + వివరాలు + + + వీడియో ప్రివ్యూ సూక్ష్మచిత్రం + Video preview thumbnail + ఇష్టాలు + మంది ఇష్టపడలేదు + టోర్ ఉపయోగించండి + లోపాన్ని నివేదించండి + వినియోగదారు నివేదిక + ఫలితాలు లేవు + వీడియో + ఆడియో + మళ్ళీ ప్రయత్నించు + నిల్వ అనుమతి తిరస్కరించబడింది + పాత ఆటగాడు ఉపయోగించండి + కె + ఎం + బి + + చందాదారులు లేరు + + %s సబ్స్క్రయిబ్ + %s సబ్స్క్రయిబలు + + + వీక్షణలు లేవు + + %s వీక్షణ + %s వీక్షణలు + + + వీడియోలు లేవు + + %s వీడియో + %s వీడియోలు + + + ప్రారంభం + ఆపు + ప్లే + తొలగించు + కొత్త మిషన్ + అలాగే + + ఫైలుపేరు + థ్రెడ్లు + లోపం + సర్వర్ మద్దతు లేదు + ఫైల్ ఇప్పటికే ఉంది + న్యూపిప్ డౌన్లోడ్ అవుతంది + వివరాల కోసం నొక్కండి + దయచేసి వేచి ఉండండి + క్లిప్బోర్డ్కు కాపీ చేయబడింది + దయచేసి అందుబాటులో ఉన్న డౌన్లోడ్ ఫోల్డర్ను ఎంచుకోండి + డౌన్లోడ్ + ఫైల్ పేర్లలో అనుమతించిన అక్షరాలు + చెల్లని అక్షరాలు ఈ విలువతో భర్తీ చేయబడతాయి + ప్రత్యామ్నాయం పాత్ర + + లెటర్స్ మరియు అంకెలు + న్యూపిప్ గురించి + సెట్టింగులు + గురించి + మూడవ పార్టీ లైసెన్స్ + లైసెన్స్ను లోడ్ చేయడం సాధ్యపడలేదు + వెబ్సైట్ని తెరవండి + గురించి + చందాదారులు + లైసెన్సుల + GitHub పై చూడండి + న్యూపెయిప్స్ లైసెన్స్ + మీరు ఆలోచనలు ఉన్నాయా లేదో; అనువాదం, డిజైన్ మార్పులు, కోడ్ క్లీనింగ్ లేదా రియల్ భారీ కోడ్ మార్పులు-సహాయం ఎల్లప్పుడూ స్వాగతం. మరింత అది గెట్స్ మంచి జరుగుతుంది + లైసెన్స్ చదువు + కాంట్రిబ్యూషన్ + + చరిత్ర + శోధించింది + వీక్షించారు + చరిత్ర నిలిపివేయబడింది + చరిత్ర + చరిత్ర ఖాళీగా ఉంది + చరిత్ర క్లియర్ చేయబడింది + అంశం తొలగించబడింది + మీరు ఈ అంశాన్ని శోధన చరిత్ర నుండి తొలగించాలనుకుంటున్నారా? + + ప్రధాన పేజీ యొక్క కంటెంట్ + ఖాళీ పేజీ + చందా పేజీ + ఫీడ్ పేజీ + ఛానెల్ పేజీ + ఛానెల్ని ఎంచుకోండి + ఇంకా ఛానెల్ ఏదీ చందా చేయలేదు + ట్రెండింగ్ + టాప్ 50 + క్రొత్తది మరియు వేడి + తొలగించు + వివరాలు + ఆడియో సెట్టింగ్లు + ఎన్క్యూలో పట్టుకోండి From 633137fd79eab10d98a58eec4dbf00050663f07f Mon Sep 17 00:00:00 2001 From: nautilusx Date: Fri, 10 Nov 2017 19:51:12 +0000 Subject: [PATCH 034/159] Translated using Weblate (German) Currently translated at 99.5% (232 of 233 strings) --- app/src/main/res/values-de/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 4e0f45332..36310dbba 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -5,7 +5,7 @@ Keinen Streamplayer gefunden. Möchtest du VLC installieren? Installieren Abbrechen - In Browser öffnen + Im Browser öffnen Teilen Download Suchen @@ -218,7 +218,7 @@ Verlauf bereinigt Fehler beim Ändern des Abos - Fehler beim Updaten des Abos + Fehler beim Aktualisieren des Abos Nach Unterbrechungen (z.B. Telefonaten) Wiedergabe fortsetzen @@ -277,7 +277,7 @@ Popup-Player Details Top 50 - Es ist ein unumgänglicher Fehler im Video-Spieler aufgetreten + Nicht behebbarer Wiedergabefehler aufgetreten Player-Fehler gelöst Kiosk-Seite From 6cb2c2a84e484a7581b01a4d07f20cc4c6623ccb Mon Sep 17 00:00:00 2001 From: Nick Undnick Date: Fri, 10 Nov 2017 19:53:27 +0000 Subject: [PATCH 035/159] Translated using Weblate (German) Currently translated at 99.5% (232 of 233 strings) --- app/src/main/res/values-de/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 36310dbba..c412ea1d3 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -15,7 +15,7 @@ Browser Rotation Downloadverzeichnis für Videos - Verzeichnis in dem heruntergeladene Videos gespeichert werden + Verzeichnis für heruntergeladene Videos Downloadverzeichnis für Videos eingeben Standardauflösung Mit Kodi abspielen From cb5cf9bb0934a03c90b4359ac6d493dc1154a897 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Fri, 10 Nov 2017 21:31:19 +0100 Subject: [PATCH 036/159] update support lib to 27.0.1 --- app/build.gradle | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 69504e2f9..c38bf8d4a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -57,11 +57,11 @@ dependencies { testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:1.10.19' - implementation 'com.android.support:appcompat-v7:27.0.0' - implementation 'com.android.support:support-v4:27.0.0' - implementation 'com.android.support:design:27.0.0' - implementation 'com.android.support:recyclerview-v7:27.0.0' - implementation 'com.android.support:preference-v14:27.0.0' + implementation 'com.android.support:appcompat-v7:27.0.1' + implementation 'com.android.support:support-v4:27.0.1' + implementation 'com.android.support:design:27.0.1' + implementation 'com.android.support:recyclerview-v7:27.0.1' + implementation 'com.android.support:preference-v14:27.0.1' implementation 'com.google.code.gson:gson:2.8.2' implementation 'ch.acra:acra:4.9.2' From 25e0b46396a4854815ffad56500502616a82a3a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Kru=C5=A1lin?= Date: Sat, 11 Nov 2017 17:55:25 +0000 Subject: [PATCH 037/159] Translated using Weblate (Croatian) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-hr/strings.xml | 27 +++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 9c671e439..15e76740f 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -255,4 +255,29 @@ Dogodila se neoporavljiva pogreška reproduktora Oporavljanje od pogreške reproduktora - + Prikaži savjet za držanje + Prikažite savjet kada je pritisnut gumb za pozadinsku ili skočnu reprodukciju na stranici detalja videozapisa + U redu čekanja za skočnu reprodukciju + Želite li izbrisati ovu stavku iz povijesti pretraživanja? + + Sadržaj + Prazna stranica + Kiosk stranica + Pretplate + Novosti + Kanal + Odaberite kanal + Niste pretplaćeni na nijedan kanal + Odaberite kiosk + + Nazivi kioska + U trendu + Top 50 + Novo i popularno + Red čekanja + Skočni reproduktor + Ukloni + Detalji + Postavke zvuka + Zadržite za dodavanje u red čekanja + From 372c2f2be0a705aabaf54c3f3cf644dadd4a4bc8 Mon Sep 17 00:00:00 2001 From: r2308145 Date: Sat, 11 Nov 2017 17:26:41 +0000 Subject: [PATCH 038/159] Translated using Weblate (Czech) Currently translated at 100.0% (233 of 233 strings) --- app/src/main/res/values-cs/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 085f06ffa..bb08433d3 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -136,7 +136,7 @@ Později - tis. + K Otevřít ve vyskakovacím okně mil. From 1f5eba59c5c0e1864932fa58dba6d44a9c379790 Mon Sep 17 00:00:00 2001 From: nautilusx Date: Fri, 10 Nov 2017 20:31:26 +0000 Subject: [PATCH 039/159] Translated using Weblate (German) Currently translated at 99.5% (232 of 233 strings) --- app/src/main/res/values-de/strings.xml | 30 +++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index c412ea1d3..b55494405 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -42,15 +42,15 @@ Spiele im Hintergrund ab Abspielen - Benutze TOR - (Experimentell) Erzwinge das Herunterladen durch TOR für verbesserte Privatsphäre (Videostream noch nicht unterstützt). + Benutze Tor + (Experimentell) Erzwinge das Herunterladen durch Tor für verbesserte Privatsphäre (Videostream noch nicht unterstützt). Netzwerkfehler - Downloadverzeichnis für Musik - Verzeichnis zum Speichern heruntergeladener Audiodateien - Pfad für heruntergeladene Audiodateien eingeben + Downloadverzeichnis für Audiodateien + Verzeichnis für heruntergeladene Audiodateien + Downloadverzeichnis für Audiodateien eingeben - Aussehen + Design Dunkel Hell @@ -61,7 +61,7 @@ Fehler Konnte nicht alle Vorschaubilder laden Konnte Video-URL-Signatur nicht entschlüsseln - Konnte Webseite nicht parsen + Konnte Webseite nicht analysieren Inhalt nicht verfügbar Durch die GEMA gesperrt @@ -73,7 +73,7 @@ Dies ist ein LIVESTREAM. Diese werden noch nicht unterstützt. - Konnte Webseite nicht vollständig parsen + Konnte Webseite nicht vollständig analysieren Fehler via E-Mail melden MELDEN Info: @@ -94,7 +94,7 @@ Einen Fehler melden Anwenderbericht - live + Live „Suchen“ antippen und loslegen Downloads @@ -163,13 +163,13 @@ Größe und Position des Popups merken Manche Auflösungen werden KEINE Tonspur haben, wenn diese Option eingeschaltet ist - Merke Position und Größe des Popups + Letzte Größe und Position des Popups merken Gestensteuerung Helligkeit und Lautstärke des Players mit Gesten steuern Durchsuche Vorschläge Zeige Vorschläge beim Suchen - Pop-up + Popup Filter Aktualisieren Leeren @@ -224,7 +224,7 @@ NewPipe Benachrichtigung - Benachrichtigungen für NewPipe Hintergrund- und Popup-Spieler + Benachrichtigungen für NewPipe Hintergrund- und Popup-Player Übersicht Verhalten @@ -258,12 +258,12 @@ Player Nichts hier außer Grillen - Möchten Sie dieses Element aus dem Suchverlauf löschen? + Möchtest du dieses Element aus dem Suchverlauf löschen? Leere Seite Wähle einen Kanal aus Noch kein Kanal abonniert Trends - Angereiht an Popup Player + In der Warteschlange des Popup-Players Alles abspielen Entfernen @@ -285,7 +285,7 @@ Kiosk Tipp anzeigen, wenn der Hintergrundwiedergabe-Button oder der Popup-Button auf der Videodetailseite gedrückt und gehalten wird - In der Warteschlange bei der Hintergrundwiedergabe + In der Warteschlange der Hintergrundwiedergabe Neu und brandheiß Halten, um in die Warteschlange einzureihen From 0b1eda30503b05753dcd5380bffffe4637c96d6b Mon Sep 17 00:00:00 2001 From: John Zhen Mo Date: Sun, 29 Oct 2017 12:39:53 -0700 Subject: [PATCH 040/159] -Improved null checks in player stream resolution. -Improved naming in MediaSourceManager --- .../newpipe/player/BackgroundPlayer.java | 3 ++- .../schabi/newpipe/player/VideoPlayer.java | 11 +++++---- .../player/playback/MediaSourceManager.java | 24 +++++++++++-------- .../player/playback/PlaybackListener.java | 1 + 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java index 863eaf3e8..25735330d 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java @@ -380,9 +380,10 @@ public final class BackgroundPlayer extends Service { } @Override + @Nullable public MediaSource sourceOf(final PlayQueueItem item, final StreamInfo info) { final int index = ListHelper.getDefaultAudioFormat(context, info.audio_streams); - if (index < 0) return null; + if (index < 0 || index >= info.audio_streams.size()) return null; final AudioStream audio = info.audio_streams.get(index); return buildMediaSource(audio.url, MediaFormat.getSuffixById(audio.format)); diff --git a/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java index 1a386d45d..07ead4f0e 100644 --- a/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java @@ -272,17 +272,18 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer. } @Override + @Nullable public MediaSource sourceOf(final PlayQueueItem item, final StreamInfo info) { final List videos = ListHelper.getSortedStreamVideosList(context, info.video_streams, info.video_only_streams, false); - final VideoStream video; + final int index; if (playbackQuality == null) { - final int index = getDefaultResolutionIndex(videos); - video = videos.get(index); + index = getDefaultResolutionIndex(videos); } else { - final int index = getOverrideResolutionIndex(videos, getPlaybackQuality()); - video = videos.get(index); + index = getOverrideResolutionIndex(videos, getPlaybackQuality()); } + if (index < 0 || index >= videos.size()) return null; + final VideoStream video = videos.get(index); final MediaSource streamSource = buildMediaSource(video.url, MediaFormat.getSuffixById(video.format)); final AudioStream audio = ListHelper.getHighestQualityAudio(info.audio_streams); diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java b/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java index 8c9ff1440..f7d267c50 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java @@ -29,7 +29,7 @@ import io.reactivex.subjects.PublishSubject; public class MediaSourceManager { private final String TAG = "MediaSourceManager@" + Integer.toHexString(hashCode()); // One-side rolling window size for default loading - // Effectively loads windowSize * 2 + 1 streams, must be greater than 0 + // Effectively loads windowSize * 2 + 1 streams per call to load, must be greater than 0 private final int windowSize; private final PlaybackListener playbackListener; private final PlayQueue playQueue; @@ -38,7 +38,7 @@ public class MediaSourceManager { // The higher it is, the less loading occurs during rapid noncritical timeline changes // Not recommended to go below 100ms private final long loadDebounceMillis; - private final PublishSubject loadSignal; + private final PublishSubject debouncedLoadSignal; private final Disposable debouncedLoader; private final DeferredMediaSource.Callback sourceBuilder; @@ -69,7 +69,7 @@ public class MediaSourceManager { this.loadDebounceMillis = loadDebounceMillis; this.syncReactor = new SerialDisposable(); - this.loadSignal = PublishSubject.create(); + this.debouncedLoadSignal = PublishSubject.create(); this.debouncedLoader = getDebouncedLoader(); this.sourceBuilder = getSourceBuilder(); @@ -101,7 +101,7 @@ public class MediaSourceManager { * Dispose the manager and releases all message buses and loaders. * */ public void dispose() { - if (loadSignal != null) loadSignal.onComplete(); + if (debouncedLoadSignal != null) debouncedLoadSignal.onComplete(); if (debouncedLoader != null) debouncedLoader.dispose(); if (playQueueReactor != null) playQueueReactor.cancel(); if (syncReactor != null) syncReactor.dispose(); @@ -118,7 +118,7 @@ public class MediaSourceManager { * Unblocks the player once the item at the current index is loaded. * */ public void load() { - loadSignal.onNext(System.currentTimeMillis()); + loadDebounced(); } /** @@ -195,14 +195,14 @@ public class MediaSourceManager { case REORDER: case ERROR: case APPEND: - loadInternal(); // low frequency, critical events + loadImmediate(); // low frequency, critical events break; case REMOVE: case SELECT: case MOVE: case RECOVERY: default: - load(); // high frequency or noncritical events + loadDebounced(); // high frequency or noncritical events break; } @@ -262,7 +262,11 @@ public class MediaSourceManager { syncReactor.set(currentItem.getStream().subscribe(syncPlayback, onError)); } - private void loadInternal() { + private void loadDebounced() { + debouncedLoadSignal.onNext(System.currentTimeMillis()); + } + + private void loadImmediate() { // The current item has higher priority final int currentIndex = playQueue.getIndex(); final PlayQueueItem currentItem = playQueue.getItem(currentIndex); @@ -307,13 +311,13 @@ public class MediaSourceManager { } private Disposable getDebouncedLoader() { - return loadSignal + return debouncedLoadSignal .debounce(loadDebounceMillis, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer() { @Override public void accept(Long timestamp) throws Exception { - loadInternal(); + loadImmediate(); } }); } diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/PlaybackListener.java b/app/src/main/java/org/schabi/newpipe/player/playback/PlaybackListener.java index 226c643d5..dfed04c01 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/PlaybackListener.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/PlaybackListener.java @@ -43,6 +43,7 @@ public interface PlaybackListener { * * May be called at any time. * */ + @Nullable MediaSource sourceOf(final PlayQueueItem item, final StreamInfo info); /** From 01e031e7e79dcc9aa7c0b68b50d5b976c1b30e1c Mon Sep 17 00:00:00 2001 From: John Zhen Mo Date: Tue, 31 Oct 2017 12:42:56 -0700 Subject: [PATCH 041/159] -Modified recovery to not set if progress position is 0 or less. -Modified queue item synchronization to no longer trigger update when the sync is run on the identical item. --- .../org/schabi/newpipe/player/BasePlayer.java | 29 +++++++++++-------- .../player/playback/MediaSourceManager.java | 17 +++++------ 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java index 8508bb237..748ef00c5 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java @@ -26,6 +26,7 @@ import android.content.IntentFilter; import android.graphics.Bitmap; import android.media.AudioManager; import android.net.Uri; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Log; @@ -76,7 +77,6 @@ import java.util.concurrent.TimeUnit; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.annotations.NonNull; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; import io.reactivex.functions.Predicate; @@ -193,7 +193,7 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen .observeOn(AndroidSchedulers.mainThread()) .filter(new Predicate() { @Override - public boolean test(@NonNull Long aLong) throws Exception { + public boolean test(Long aLong) throws Exception { return isProgressLoopRunning(); } }) @@ -235,7 +235,7 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen initPlayback(queue); } - protected void initPlayback(@NonNull final PlayQueue queue) { + protected void initPlayback(final PlayQueue queue) { playQueue = queue; playQueue.init(); playbackManager = new MediaSourceManager(this, playQueue); @@ -514,11 +514,10 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen } break; case Player.STATE_READY: //3 - recover(); - if (!isPrepared) { isPrepared = true; onPrepared(playWhenReady); + recover(); break; } if (currentState == STATE_PAUSED_SEEK) break; @@ -631,17 +630,21 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen } @Override - public void sync(@android.support.annotation.NonNull final PlayQueueItem item, + public void sync(@NonNull final PlayQueueItem item, @Nullable final StreamInfo info) { - if (simpleExoPlayer == null) return; - if (DEBUG) Log.d(TAG, "Syncing..."); - + if (currentItem == item && currentInfo == info) return; currentItem = item; currentInfo = info; + if (DEBUG) Log.d(TAG, "Syncing..."); + if (simpleExoPlayer == null) return; + // Check if on wrong window - final int currentSourceIndex = playQueue.getIndex(); - if (simpleExoPlayer.getCurrentWindowIndex() != currentSourceIndex) { + final int currentSourceIndex = playQueue.indexOf(item); + if (currentSourceIndex != playQueue.getIndex()) { + throw new IllegalStateException("Play Queue may be desynchronized: item index=[" + + currentSourceIndex + "], queue index=[" + playQueue.getIndex() + "]"); + } else if (simpleExoPlayer.getCurrentWindowIndex() != currentSourceIndex) { final long startPos = info != null ? info.start_position : 0; if (DEBUG) Log.d(TAG, "Rewinding to correct window: " + currentSourceIndex + " at: " + getTimeString((int)startPos)); simpleExoPlayer.seekTo(currentSourceIndex, startPos); @@ -900,7 +903,9 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen final int queuePos = playQueue.getIndex(); final long windowPos = simpleExoPlayer.getCurrentPosition(); - setRecovery(queuePos, windowPos); + if (windowPos > 0) { + setRecovery(queuePos, windowPos); + } } public void setRecovery(final int queuePos, final long windowPos) { diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java b/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java index f7d267c50..2e4e4af5c 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java @@ -52,7 +52,7 @@ public class MediaSourceManager { public MediaSourceManager(@NonNull final PlaybackListener listener, @NonNull final PlayQueue playQueue) { - this(listener, playQueue, 1, 1000L); + this(listener, playQueue, 1, 400L); } private MediaSourceManager(@NonNull final PlaybackListener listener, @@ -162,7 +162,7 @@ public class MediaSourceManager { return; } - // why no pattern matching in Java =( + // Event specific action switch (event.type()) { case INIT: case REORDER: @@ -172,31 +172,28 @@ public class MediaSourceManager { case APPEND: populateSources(); break; - case SELECT: - sync(); - break; case REMOVE: final RemoveEvent removeEvent = (RemoveEvent) event; remove(removeEvent.getRemoveIndex()); - // Sync only when the currently playing is removed - if (removeEvent.getQueueIndex() == removeEvent.getRemoveIndex()) sync(); break; case MOVE: final MoveEvent moveEvent = (MoveEvent) event; move(moveEvent.getFromIndex(), moveEvent.getToIndex()); break; + case SELECT: case RECOVERY: default: break; } + // Loading and Syncing switch (event.type()) { case INIT: case REORDER: case ERROR: - case APPEND: loadImmediate(); // low frequency, critical events break; + case APPEND: case REMOVE: case SELECT: case MOVE: @@ -294,7 +291,9 @@ public class MediaSourceManager { final DeferredMediaSource mediaSource = (DeferredMediaSource) sources.getMediaSource(playQueue.indexOf(item)); if (mediaSource.state() == DeferredMediaSource.STATE_PREPARED) mediaSource.load(); - if (tryUnblock()) sync(); + + tryUnblock(); + if (!isBlocked) sync(); } private void resetSources() { From 38b2ffd4504cefaa79885d2f6b90a9c129645445 Mon Sep 17 00:00:00 2001 From: John Zhen Mo Date: Tue, 31 Oct 2017 17:07:12 -0700 Subject: [PATCH 042/159] -Added fling to toss popup view when velocity is below shutdown. -Added string for unknown content. -Fixed NPE when UI element is touched after player shuts down in service activity. -Fixed shuffle reset caused by position discontinuity offsets index. -Moved some more player shared preferences to PlayerHelper. --- .../org/schabi/newpipe/player/BasePlayer.java | 24 ++++++++++------- .../newpipe/player/PopupVideoPlayer.java | 26 ++++++++++++++----- .../newpipe/player/ServicePlayerActivity.java | 24 +++++++++++------ .../newpipe/player/helper/PlayerHelper.java | 19 ++++++++++++++ app/src/main/res/values/strings.xml | 2 ++ 5 files changed, 71 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java index 748ef00c5..c24a46049 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java @@ -590,12 +590,12 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen if (DEBUG) Log.d(TAG, "onPositionDiscontinuity() called with window index = [" + newWindowIndex + "]"); // If the user selects a new track, then the discontinuity occurs after the index is changed. - // Therefore, the only source that causes a discrepancy would be autoplay, + // Therefore, the only source that causes a discrepancy would be gapless transition, // which can only offset the current track by +1. - if (newWindowIndex != playQueue.getIndex() && playbackManager != null) { + if (newWindowIndex == playQueue.getIndex() + 1) { playQueue.offsetIndex(+1); - playbackManager.load(); } + playbackManager.load(); } @Override @@ -612,6 +612,8 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen if (simpleExoPlayer == null) return; if (DEBUG) Log.d(TAG, "Blocking..."); + currentItem = null; + currentInfo = null; simpleExoPlayer.stop(); isPrepared = false; @@ -642,8 +644,8 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen // Check if on wrong window final int currentSourceIndex = playQueue.indexOf(item); if (currentSourceIndex != playQueue.getIndex()) { - throw new IllegalStateException("Play Queue may be desynchronized: item index=[" + - currentSourceIndex + "], queue index=[" + playQueue.getIndex() + "]"); + Log.e(TAG, "Play Queue may be desynchronized: item index=[" + currentSourceIndex + + "], queue index=[" + playQueue.getIndex() + "]"); } else if (simpleExoPlayer.getCurrentWindowIndex() != currentSourceIndex) { final long startPos = info != null ? info.start_position : 0; if (DEBUG) Log.d(TAG, "Rewinding to correct window: " + currentSourceIndex + " at: " + getTimeString((int)startPos)); @@ -829,15 +831,15 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen } public String getVideoUrl() { - return currentItem == null ? null : currentItem.getUrl(); + return currentItem == null ? context.getString(R.string.unknown_content) : currentItem.getUrl(); } public String getVideoTitle() { - return currentItem == null ? null : currentItem.getTitle(); + return currentItem == null ? context.getString(R.string.unknown_content) : currentItem.getTitle(); } public String getUploaderName() { - return currentItem == null ? null : currentItem.getUploader(); + return currentItem == null ? context.getString(R.string.unknown_content) : currentItem.getUploader(); } public boolean isCompleted() { @@ -873,8 +875,10 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen } public PlaybackParameters getPlaybackParameters() { + final PlaybackParameters defaultParameters = new PlaybackParameters(1f, 1f); + if (simpleExoPlayer == null) return defaultParameters; final PlaybackParameters parameters = simpleExoPlayer.getPlaybackParameters(); - return parameters == null ? new PlaybackParameters(1f, 1f) : parameters; + return parameters == null ? defaultParameters : parameters; } public void setPlaybackParameters(float speed, float pitch) { @@ -903,7 +907,7 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen final int queuePos = playQueue.getIndex(); final long windowPos = simpleExoPlayer.getCurrentPosition(); - if (windowPos > 0) { + if (windowPos > 0 && windowPos <= simpleExoPlayer.getDuration()) { setRecovery(queuePos, windowPos); } } diff --git a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java index 89d58141d..71068dbea 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java @@ -65,6 +65,7 @@ import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.player.event.PlayerEventListener; +import org.schabi.newpipe.player.helper.PlayerHelper; import org.schabi.newpipe.player.old.PlayVideoActivity; import org.schabi.newpipe.player.helper.LockManager; import org.schabi.newpipe.playlist.PlayQueueItem; @@ -96,7 +97,6 @@ import static org.schabi.newpipe.util.AnimationUtils.animateView; public final class PopupVideoPlayer extends Service { private static final String TAG = ".PopupVideoPlayer"; private static final boolean DEBUG = BasePlayer.DEBUG; - private static final int SHUTDOWN_FLING_VELOCITY = 10000; private static final int NOTIFICATION_ID = 40028922; public static final String ACTION_CLOSE = "org.schabi.newpipe.player.PopupVideoPlayer.CLOSE"; @@ -112,6 +112,9 @@ public final class PopupVideoPlayer extends Service { private WindowManager.LayoutParams windowLayoutParams; private GestureDetector gestureDetector; + private int shutdownFlingVelocity; + private int tossFlingVelocity; + private float screenWidth, screenHeight; private float popupWidth, popupHeight; @@ -211,12 +214,14 @@ public final class PopupVideoPlayer extends Service { View rootView = View.inflate(this, R.layout.player_popup, null); playerImpl.setup(rootView); + shutdownFlingVelocity = PlayerHelper.getShutdownFlingVelocity(this); + tossFlingVelocity = PlayerHelper.getTossFlingVelocity(this); + updateScreenSize(); + final boolean popupRememberSizeAndPos = PlayerHelper.isRememberingPopupDimensions(this); + final float defaultSize = getResources().getDimension(R.dimen.popup_default_width); SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); - boolean popupRememberSizeAndPos = sharedPreferences.getBoolean(getString(R.string.popup_remember_size_pos_key), true); - - float defaultSize = getResources().getDimension(R.dimen.popup_default_width); popupWidth = popupRememberSizeAndPos ? sharedPreferences.getFloat(POPUP_SAVED_WIDTH, defaultSize) : defaultSize; final int layoutParamType = Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O ? WindowManager.LayoutParams.TYPE_PHONE : WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; @@ -791,11 +796,20 @@ public final class PopupVideoPlayer extends Service { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + if (DEBUG) Log.d(TAG, "Fling velocity: dX=[" + velocityX + "], dY=[" + velocityY + "]"); if (playerImpl == null) return false; - if (Math.abs(velocityX) > SHUTDOWN_FLING_VELOCITY) { - if (DEBUG) Log.d(TAG, "Popup close fling velocity= " + velocityX); + + final float absVelocityX = Math.abs(velocityX); + final float absVelocityY = Math.abs(velocityY); + if (absVelocityX > shutdownFlingVelocity) { onClose(); return true; + } else if (Math.max(absVelocityX, absVelocityY) > tossFlingVelocity) { + if (absVelocityX > tossFlingVelocity) windowLayoutParams.x = (int) velocityX; + if (absVelocityY > tossFlingVelocity) windowLayoutParams.y = (int) velocityY; + checkPositionBounds(); + windowManager.updateViewLayout(playerImpl.getRootView(), windowLayoutParams); + return true; } return false; } diff --git a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java index ef77cdda2..4fe228dfc 100644 --- a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java +++ b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java @@ -286,6 +286,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { + if (player == null) return false; + player.setPlaybackSpeed(playbackSpeed); return true; } @@ -304,6 +306,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { + if (player == null) return false; + player.setPlaybackPitch(playbackPitch); return true; } @@ -317,6 +321,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity remove.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { + if (player == null) return false; + final int index = player.getPlayQueue().indexOf(item); if (index != -1) player.getPlayQueue().remove(index); return true; @@ -349,7 +355,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity final int sourceIndex = source.getLayoutPosition(); final int targetIndex = target.getLayoutPosition(); - player.getPlayQueue().move(sourceIndex, targetIndex); + if (player != null) player.getPlayQueue().move(sourceIndex, targetIndex); return true; } @@ -372,11 +378,13 @@ public abstract class ServicePlayerActivity extends AppCompatActivity return new PlayQueueItemBuilder.OnSelectedListener() { @Override public void selected(PlayQueueItem item, View view) { - player.onSelected(item); + if (player != null) player.onSelected(item); } @Override public void held(PlayQueueItem item, View view) { + if (player == null) return; + final int index = player.getPlayQueue().indexOf(item); if (index != -1) buildItemPopupMenu(item, view); } @@ -403,19 +411,19 @@ public abstract class ServicePlayerActivity extends AppCompatActivity @Override public void onClick(View view) { if (view.getId() == repeatButton.getId()) { - player.onRepeatClicked(); + if (player != null) player.onRepeatClicked(); } else if (view.getId() == backwardButton.getId()) { - player.onPlayPrevious(); + if (player != null) player.onPlayPrevious(); } else if (view.getId() == playPauseButton.getId()) { - player.onVideoPlayPause(); + if (player != null) player.onVideoPlayPause(); } else if (view.getId() == forwardButton.getId()) { - player.onPlayNext(); + if (player != null) player.onPlayNext(); } else if (view.getId() == shuffleButton.getId()) { - player.onShuffleClicked(); + if (player != null) player.onShuffleClicked(); } else if (view.getId() == playbackSpeedButton.getId()) { playbackSpeedPopupMenu.show(); @@ -450,7 +458,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity @Override public void onStopTrackingTouch(SeekBar seekBar) { - player.simpleExoPlayer.seekTo(seekBar.getProgress()); + if (player != null) player.simpleExoPlayer.seekTo(seekBar.getProgress()); seekDisplay.setVisibility(View.GONE); seeking = false; } 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 558f82b43..40063ba40 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 @@ -12,6 +12,8 @@ import java.text.NumberFormat; import java.util.Formatter; import java.util.Locale; +import javax.annotation.Nonnull; + public class PlayerHelper { private PlayerHelper() {} @@ -56,6 +58,10 @@ public class PlayerHelper { return isUsingOldPlayer(context, false); } + public static boolean isRememberingPopupDimensions(@Nonnull final Context context) { + return isRememberingPopupDimensions(context, true); + } + public static long getPreferredCacheSize(@NonNull final Context context) { return 64 * 1024 * 1024L; } @@ -83,6 +89,15 @@ public class PlayerHelper { public static boolean isUsingDSP(@NonNull final Context context) { return true; } + + public static int getShutdownFlingVelocity(@Nonnull final Context context) { + return 10000; + } + + public static int getTossFlingVelocity(@Nonnull final Context context) { + return 2500; + } + //////////////////////////////////////////////////////////////////////////// // Private helpers //////////////////////////////////////////////////////////////////////////// @@ -103,4 +118,8 @@ public class PlayerHelper { private static boolean isUsingOldPlayer(@NonNull final Context context, final boolean b) { return getPreferences(context).getBoolean(context.getString(R.string.use_old_player_key), b); } + + private static boolean isRememberingPopupDimensions(@Nonnull final Context context, final boolean b) { + return getPreferences(context).getBoolean(context.getString(R.string.popup_remember_size_pos_key), b); + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ad69915b9..7092feaf5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -122,6 +122,8 @@ NewPipe Notification Notifications for NewPipe Background and Popup Players + [Unknown] + Error Network error From 87febf8679e628bb93e30f96784d487fa7df14ae Mon Sep 17 00:00:00 2001 From: John Zhen Mo Date: Wed, 1 Nov 2017 22:33:13 -0700 Subject: [PATCH 043/159] -Added dropdown to start play for all StreamInfoItem. -Refactored NavigationHelper to allow service player control to open anywhere. -Refactored NavigationHelper to allow starting player at anywhere. --- .../fragments/detail/VideoDetailFragment.java | 30 +++--- .../fragments/list/BaseListFragment.java | 10 ++ .../list/playlist/PlaylistFragment.java | 11 +-- .../subscription/SubscriptionFragment.java | 4 + .../newpipe/info_list/InfoItemBuilder.java | 2 + .../holder/StreamMiniInfoItemHolder.java | 91 ++++++++++++++++++ .../newpipe/player/BackgroundPlayer.java | 13 +-- .../newpipe/player/PopupVideoPlayer.java | 11 +-- .../newpipe/playlist/SinglePlayQueue.java | 11 ++- .../schabi/newpipe/util/NavigationHelper.java | 48 ++++++++- .../drawable-hdpi/ic_more_vert_black_24dp.png | Bin 0 -> 132 bytes .../drawable-hdpi/ic_more_vert_white_24dp.png | Bin 0 -> 134 bytes .../drawable-mdpi/ic_more_vert_black_24dp.png | Bin 0 -> 108 bytes .../drawable-mdpi/ic_more_vert_white_24dp.png | Bin 0 -> 112 bytes .../ic_more_vert_black_24dp.png | Bin 0 -> 155 bytes .../ic_more_vert_white_24dp.png | Bin 0 -> 158 bytes .../ic_more_vert_black_24dp.png | Bin 0 -> 205 bytes .../ic_more_vert_white_24dp.png | Bin 0 -> 216 bytes .../ic_more_vert_black_24dp.png | Bin 0 -> 272 bytes .../ic_more_vert_white_24dp.png | Bin 0 -> 305 bytes app/src/main/res/layout/list_stream_item.xml | 29 +++++- .../main/res/layout/list_stream_mini_item.xml | 23 ++++- app/src/main/res/values/attrs.xml | 1 + app/src/main/res/values/strings.xml | 2 + app/src/main/res/values/styles.xml | 2 + 25 files changed, 240 insertions(+), 48 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/ic_more_vert_black_24dp.png create mode 100644 app/src/main/res/drawable-hdpi/ic_more_vert_white_24dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_more_vert_black_24dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_more_vert_white_24dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_more_vert_black_24dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_more_vert_white_24dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_more_vert_black_24dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_more_vert_white_24dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_more_vert_black_24dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_more_vert_white_24dp.png 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 63b7e9ace..265e22319 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 @@ -36,6 +36,7 @@ import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.PopupMenu; import android.widget.RelativeLayout; import android.widget.Spinner; import android.widget.TextView; @@ -459,6 +460,9 @@ public class VideoDetailFragment extends BaseStateFragment implement public void selected(StreamInfoItem selectedItem) { selectAndLoadVideo(selectedItem.service_id, selectedItem.url, selectedItem.name); } + + @Override + public void dropdownClicked(StreamInfoItem selectedItem, PopupMenu menu) {} }); videoTitleRoot.setOnClickListener(this); @@ -792,16 +796,12 @@ public class VideoDetailFragment extends BaseStateFragment implement ((HistoryListener) activity).onVideoPlayed(currentInfo, getSelectedVideoStream()); } - final PlayQueue playQueue = new SinglePlayQueue(currentInfo); - final Intent intent; + final PlayQueue itemQueue = new SinglePlayQueue(currentInfo); if (append) { - Toast.makeText(activity, R.string.popup_playing_append, Toast.LENGTH_SHORT).show(); - intent = NavigationHelper.getPlayerEnqueueIntent(activity, PopupVideoPlayer.class, playQueue); + NavigationHelper.enqueueOnPopupPlayer(activity, itemQueue); } else { - Toast.makeText(activity, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show(); - intent = NavigationHelper.getPlayerIntent(activity, PopupVideoPlayer.class, playQueue, getSelectedVideoStream().resolution); + NavigationHelper.playOnPopupPlayer(activity, itemQueue); } - activity.startService(intent); } private void openVideoPlayer() { @@ -820,13 +820,11 @@ public class VideoDetailFragment extends BaseStateFragment implement private void openNormalBackgroundPlayer(final boolean append) { - final PlayQueue playQueue = new SinglePlayQueue(currentInfo); + final PlayQueue itemQueue = new SinglePlayQueue(currentInfo); if (append) { - activity.startService(NavigationHelper.getPlayerEnqueueIntent(activity, BackgroundPlayer.class, playQueue)); - Toast.makeText(activity, R.string.background_player_append, Toast.LENGTH_SHORT).show(); + NavigationHelper.enqueueOnBackgroundPlayer(activity, itemQueue); } else { - activity.startService(NavigationHelper.getPlayerIntent(activity, BackgroundPlayer.class, playQueue)); - Toast.makeText(activity, R.string.background_player_playing_toast, Toast.LENGTH_SHORT).show(); + NavigationHelper.playOnBackgroundPlayer(activity, itemQueue); } } @@ -865,22 +863,20 @@ public class VideoDetailFragment extends BaseStateFragment implement } private void openNormalPlayer(VideoStream selectedVideoStream) { - Intent mIntent; boolean useOldPlayer = PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(getString(R.string.use_old_player_key), false) || (Build.VERSION.SDK_INT < 16); if (!useOldPlayer) { // ExoPlayer - final PlayQueue playQueue = new SinglePlayQueue(currentInfo); - mIntent = NavigationHelper.getPlayerIntent(activity, MainVideoPlayer.class, playQueue, getSelectedVideoStream().resolution); + NavigationHelper.playOnMainPlayer(activity, new SinglePlayQueue(currentInfo)); } else { // Internal Player - mIntent = new Intent(activity, PlayVideoActivity.class) + final Intent mIntent = new Intent(activity, PlayVideoActivity.class) .putExtra(PlayVideoActivity.VIDEO_TITLE, currentInfo.name) .putExtra(PlayVideoActivity.STREAM_URL, selectedVideoStream.url) .putExtra(PlayVideoActivity.VIDEO_URL, currentInfo.url) .putExtra(PlayVideoActivity.START_POSITION, currentInfo.start_position); + startActivity(mIntent); } - startActivity(mIntent); } private void openExternalVideoPlayer(VideoStream selectedVideoStream) { diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java index 35f6a08d3..e3a94a5e2 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java @@ -10,6 +10,7 @@ import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.View; +import android.widget.PopupMenu; import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.InfoItem; @@ -139,6 +140,9 @@ public abstract class BaseListFragment extends BaseStateFragment implem useAsFrontPage?getParentFragment().getFragmentManager():getFragmentManager(), selectedItem.service_id, selectedItem.url, selectedItem.name); } + + @Override + public void dropdownClicked(StreamInfoItem selectedItem, PopupMenu menu) {} }); infoListAdapter.setOnChannelSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener() { @@ -149,6 +153,9 @@ public abstract class BaseListFragment extends BaseStateFragment implem useAsFrontPage?getParentFragment().getFragmentManager():getFragmentManager(), selectedItem.service_id, selectedItem.url, selectedItem.name); } + + @Override + public void dropdownClicked(ChannelInfoItem selectedItem, PopupMenu menu) {} }); infoListAdapter.setOnPlaylistSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener() { @@ -159,6 +166,9 @@ public abstract class BaseListFragment extends BaseStateFragment implem useAsFrontPage?getParentFragment().getFragmentManager():getFragmentManager(), selectedItem.service_id, selectedItem.url, selectedItem.name); } + + @Override + public void dropdownClicked(PlaylistInfoItem selectedItem, PopupMenu menu) {} }); itemsList.clearOnScrollListeners(); diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java index b88d54524..9d57617d3 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java @@ -160,7 +160,7 @@ public class PlaylistFragment extends BaseListInfoFragment { headerPlayAllButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - startActivity(buildPlaylistIntent(MainVideoPlayer.class)); + NavigationHelper.playOnMainPlayer(activity, getPlayQueue()); } }); headerPopupButton.setOnClickListener(new View.OnClickListener() { @@ -173,26 +173,25 @@ public class PlaylistFragment extends BaseListInfoFragment { toast.show(); return; } - activity.startService(buildPlaylistIntent(PopupVideoPlayer.class)); + NavigationHelper.playOnPopupPlayer(activity, getPlayQueue()); } }); headerBackgroundButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - activity.startService(buildPlaylistIntent(BackgroundPlayer.class)); + NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue()); } }); } - private Intent buildPlaylistIntent(final Class targetClazz) { - final PlayQueue playQueue = new ExternalPlayQueue( + private PlayQueue getPlayQueue() { + return new ExternalPlayQueue( currentInfo.service_id, currentInfo.url, currentInfo.next_streams_url, infoListAdapter.getItemsList(), 0 ); - return NavigationHelper.getPlayerIntent(activity, targetClazz, playQueue); } @Override diff --git a/app/src/main/java/org/schabi/newpipe/fragments/subscription/SubscriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/subscription/SubscriptionFragment.java index 520586663..c3afa9620 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/subscription/SubscriptionFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/subscription/SubscriptionFragment.java @@ -10,6 +10,7 @@ import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.PopupMenu; import org.schabi.newpipe.R; import org.schabi.newpipe.database.subscription.SubscriptionEntity; @@ -134,6 +135,9 @@ public class SubscriptionFragment extends BaseStateFragment { void selected(T selectedItem); + void dropdownClicked(T selectedItem, PopupMenu menu); } private final Context context; diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java index 138503d39..1dea9633b 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java @@ -1,10 +1,16 @@ package org.schabi.newpipe.info_list.holder; +import android.content.Context; import android.support.v4.content.ContextCompat; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageButton; import android.widget.ImageView; +import android.widget.PopupMenu; import android.widget.TextView; +import android.widget.Toast; import com.nostra13.universalimageloader.core.DisplayImageOptions; @@ -13,7 +19,12 @@ import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.info_list.InfoItemBuilder; +import org.schabi.newpipe.player.BackgroundPlayer; +import org.schabi.newpipe.player.PopupVideoPlayer; +import org.schabi.newpipe.playlist.PlayQueue; +import org.schabi.newpipe.playlist.SinglePlayQueue; import org.schabi.newpipe.util.Localization; +import org.schabi.newpipe.util.NavigationHelper; public class StreamMiniInfoItemHolder extends InfoItemHolder { @@ -21,6 +32,7 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { public final TextView itemVideoTitleView; public final TextView itemUploaderView; public final TextView itemDurationView; + public final ImageButton itemActionDropdown; StreamMiniInfoItemHolder(InfoItemBuilder infoItemBuilder, int layoutId, ViewGroup parent) { super(infoItemBuilder, layoutId, parent); @@ -29,6 +41,7 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { itemVideoTitleView = itemView.findViewById(R.id.itemVideoTitleView); itemUploaderView = itemView.findViewById(R.id.itemUploaderView); itemDurationView = itemView.findViewById(R.id.itemDurationView); + itemActionDropdown = itemView.findViewById(R.id.itemActionDropdown); } public StreamMiniInfoItemHolder(InfoItemBuilder infoItemBuilder, ViewGroup parent) { @@ -67,6 +80,84 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { } } }); + + switch (item.stream_type) { + case AUDIO_STREAM: + case VIDEO_STREAM: + case FILE: + enableActionDropdown(item); + break; + case LIVE_STREAM: + case AUDIO_LIVE_STREAM: + case NONE: + default: + break; + } + } + + private void enableActionDropdown(final StreamInfoItem item) { + itemActionDropdown.setVisibility(View.VISIBLE); + itemActionDropdown.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + final PopupMenu actionMenu = getStreamDropdown(itemBuilder.getContext(), itemActionDropdown, item); + if (itemBuilder.getOnStreamSelectedListener() != null) { + itemBuilder.getOnStreamSelectedListener().dropdownClicked(item, actionMenu); + } + actionMenu.show(); + } + }); + } + + private PopupMenu getStreamDropdown(final Context context, final View anchor, final StreamInfoItem infoItem) { + PopupMenu actionMenu = new PopupMenu(context, anchor); + + final MenuItem mainPlay = actionMenu.getMenu().add(R.string.play_btn_text); + mainPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + NavigationHelper.playOnMainPlayer(context, new SinglePlayQueue(infoItem)); + return true; + } + }); + + final MenuItem popupPlay = actionMenu.getMenu().add(R.string.controls_popup_title); + popupPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + NavigationHelper.playOnPopupPlayer(context, new SinglePlayQueue(infoItem)); + return true; + } + }); + + final MenuItem backgroundPlay = actionMenu.getMenu().add(R.string.controls_background_title); + backgroundPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + NavigationHelper.playOnBackgroundPlayer(context, new SinglePlayQueue(infoItem)); + return true; + } + }); + + final MenuItem backgroundEnqueue = actionMenu.getMenu().add(R.string.enqueue_on_background); + backgroundEnqueue.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(infoItem)); + return true; + } + }); + + final MenuItem popupEnqueue = actionMenu.getMenu().add(R.string.enqueue_on_popup); + popupEnqueue.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + NavigationHelper.enqueueOnPopupPlayer(context, new SinglePlayQueue(infoItem)); + return true; + } + }); + + return actionMenu; } /** diff --git a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java index 25735330d..cfed78179 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java @@ -48,6 +48,7 @@ import org.schabi.newpipe.player.event.PlayerEventListener; import org.schabi.newpipe.player.helper.LockManager; import org.schabi.newpipe.playlist.PlayQueueItem; import org.schabi.newpipe.util.ListHelper; +import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.ThemeHelper; import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString; @@ -130,16 +131,6 @@ public final class BackgroundPlayer extends Service { /*////////////////////////////////////////////////////////////////////////// // Actions //////////////////////////////////////////////////////////////////////////*/ - - public void openControl(final Context context) { - Intent intent = new Intent(context, BackgroundPlayerActivity.class); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - } - context.startActivity(intent); - context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); - } - private void onClose() { if (DEBUG) Log.d(TAG, "onClose() called"); @@ -470,7 +461,7 @@ public final class BackgroundPlayer extends Service { onVideoPlayPause(); break; case ACTION_OPEN_CONTROLS: - openControl(getApplicationContext()); + NavigationHelper.openBackgroundPlayerControl(getApplicationContext()); break; case ACTION_REPEAT: onRepeatClicked(); diff --git a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java index 71068dbea..babbdbff5 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java @@ -318,15 +318,6 @@ public final class PopupVideoPlayer extends Service { stopSelf(); } - public void openControl(final Context context) { - Intent intent = new Intent(context, PopupVideoPlayerActivity.class); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - } - context.startActivity(intent); - context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); - } - /*////////////////////////////////////////////////////////////////////////// // Utils //////////////////////////////////////////////////////////////////////////*/ @@ -622,7 +613,7 @@ public final class PopupVideoPlayer extends Service { onVideoPlayPause(); break; case ACTION_OPEN_CONTROLS: - openControl(getApplicationContext()); + NavigationHelper.openPopupPlayerControl(getApplicationContext()); break; case ACTION_REPEAT: onRepeatClicked(); diff --git a/app/src/main/java/org/schabi/newpipe/playlist/SinglePlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/SinglePlayQueue.java index fc68e931a..ae74528eb 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/SinglePlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/SinglePlayQueue.java @@ -1,12 +1,21 @@ package org.schabi.newpipe.playlist; import org.schabi.newpipe.extractor.stream.StreamInfo; +import org.schabi.newpipe.extractor.stream.StreamInfoItem; import java.util.Collections; public final class SinglePlayQueue extends PlayQueue { + public SinglePlayQueue(final StreamInfoItem item) { + this(new PlayQueueItem(item)); + } + public SinglePlayQueue(final StreamInfo info) { - super(0, Collections.singletonList(new PlayQueueItem(info))); + this(new PlayQueueItem(info)); + } + + private SinglePlayQueue(final PlayQueueItem playQueueItem) { + super(0, Collections.singletonList(playQueueItem)); } @Override diff --git a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java index a68494706..07fc4ba7b 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -5,10 +5,11 @@ import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Build; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; -import android.support.v7.app.AppCompatActivity; +import android.widget.Toast; import com.nostra13.universalimageloader.core.ImageLoader; @@ -28,7 +29,12 @@ import org.schabi.newpipe.fragments.list.kiosk.KioskFragment; import org.schabi.newpipe.fragments.list.playlist.PlaylistFragment; import org.schabi.newpipe.fragments.list.search.SearchFragment; import org.schabi.newpipe.history.HistoryActivity; +import org.schabi.newpipe.player.BackgroundPlayer; +import org.schabi.newpipe.player.BackgroundPlayerActivity; import org.schabi.newpipe.player.BasePlayer; +import org.schabi.newpipe.player.MainVideoPlayer; +import org.schabi.newpipe.player.PopupVideoPlayer; +import org.schabi.newpipe.player.PopupVideoPlayerActivity; import org.schabi.newpipe.player.VideoPlayer; import org.schabi.newpipe.playlist.PlayQueue; import org.schabi.newpipe.settings.SettingsActivity; @@ -77,6 +83,29 @@ public class NavigationHelper { .putExtra(BasePlayer.PLAYBACK_PITCH, playbackPitch); } + public static void playOnMainPlayer(final Context context, final PlayQueue queue) { + context.startActivity(getPlayerIntent(context, MainVideoPlayer.class, queue)); + } + + public static void playOnPopupPlayer(final Context context, final PlayQueue queue) { + Toast.makeText(context, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show(); + context.startService(getPlayerIntent(context, PopupVideoPlayer.class, queue)); + } + + public static void playOnBackgroundPlayer(final Context context, final PlayQueue queue) { + Toast.makeText(context, R.string.background_player_playing_toast, Toast.LENGTH_SHORT).show(); + context.startService(getPlayerIntent(context, BackgroundPlayer.class, queue)); + } + + public static void enqueueOnPopupPlayer(final Context context, final PlayQueue queue) { + Toast.makeText(context, R.string.popup_playing_append, Toast.LENGTH_SHORT).show(); + context.startService(getPlayerEnqueueIntent(context, PopupVideoPlayer.class, queue)); + } + + public static void enqueueOnBackgroundPlayer(final Context context, final PlayQueue queue) { + Toast.makeText(context, R.string.background_player_append, Toast.LENGTH_SHORT).show(); + context.startService(getPlayerEnqueueIntent(context, BackgroundPlayer.class, queue)); + } /*////////////////////////////////////////////////////////////////////////// // Through FragmentManager //////////////////////////////////////////////////////////////////////////*/ @@ -230,6 +259,23 @@ public class NavigationHelper { return true; } + public static void openBackgroundPlayerControl(final Context context) { + openServicePlayerControl(context, BackgroundPlayerActivity.class); + } + + public static void openPopupPlayerControl(final Context context) { + openServicePlayerControl(context, PopupVideoPlayerActivity.class); + } + + private static void openServicePlayerControl(final Context context, final Class clazz) { + final Intent intent = new Intent(context, clazz); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + } + context.startActivity(intent); + context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); + } + /*////////////////////////////////////////////////////////////////////////// // Link handling //////////////////////////////////////////////////////////////////////////*/ diff --git a/app/src/main/res/drawable-hdpi/ic_more_vert_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_more_vert_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..22acc550088d98f9d98ced517de75b5e8ead3c7c GIT binary patch literal 132 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B5}8r;B4q1>@UGdwClSM3^70uIQ21 z47_&cJkx~*+Z%R2IKOxGVZM^fH+7^Mmwc{S?NKJ@tD@b{HffqWt7pJW9xm}`3bIR@ eOD6DrGLJi>8B(9~m^Tk-EQ6=3pUXO@geCy;;w$k0 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_more_vert_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_more_vert_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..67f07e473442d1f5bd5dc486a42ce4bedf40b425 GIT binary patch literal 134 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8K;ucwP+h{y4_mv-_VP!M4WR9aA@ zB9L2TV$k7bqBi~Tf{Y7K)@EPe&B(sMnUQ&cV?}1b!p)H;o34MJ iAa}{R%7g#se7OLo1Hz}Zd6xqXX7F_Nb6Mw<&;$T!hAw^p literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_more_vert_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_more_vert_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..0e4f2f6ea0564fe9d6ebdb4bea0df48aced9de0f GIT binary patch literal 108 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1V^0^ykP60RiERoU4^0niv(+!U z$~^Ty`=RMavMX4xeQ2uS{l}xxJ=eVCD820|N5W*kJjJ67$C*FG*QAUgq7iWp7Wo)^m*JsBN#kg L{an^LB{Ts5on9xv literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_more_vert_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_more_vert_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..9f10aa2759a2e53beb129849c9b0e6ee5f7ae97b GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}b0DBu^K|kP61PR}A@_6b0BGTJ|c& z&2zArUdgs%qoJD@@9neO|NgtXV7^DW)MQ81qkHN%-79zXF}ZeKv~Tuphvz#4Z3DJ9 zo+<2n{rTU)UWQJm<&*zc>PM$^=S_g|6%VwoI2{_d>%srJ7&|&vk-TbVh<5S;l;%8hhyk$Kc9U$ho zN!;a@as7tMKN^!>mP|UmC!qU^(pC>$p{$8fOT;)oR_iUC=UG0_`?VR+LIzJ)KbLh* G2~7aOZ8w1c literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_more_vert_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_more_vert_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..94d5ab98c6d3b3548536f04a2d635fb5c4a05b88 GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhawrg*wIhEy=Vy=KqV>>$DV@#Ph3 zmm-(IJxlAmHdKggydBZHA?LrN(f;zraK2yFla}<&ocsFTF&FO*>g+$WJLfsbvhR#o zqU5?6`INL2k&sND<*?!p=%CFlpb5%Rrp)D#!8^w7WtAYxjJ8qaZaq8!Lha3*C xpO9i0)g!jJUB|8aV$u`{=V%64OvRJ&URzP%pP$_?yn*gx@O1TaS?83{1OO~yQ~m$| literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_more_vert_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_more_vert_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..d32281307232fefc363e19d9d2728af62b440a8d GIT binary patch literal 216 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhaw=6kw0hGg7(d(E5ckb#KX!!teA z8+IJIbSd_mp~lgrEob_e9cxnR1kZ18I^5b~uj)DJpG>-%nby>)6J_QWKRvd(S?`Ri~_DWys(>8rgyQv zG%aCaz>Js9>y=L)eUVgRxJx3oN6$@sv5NTO?u&4dNh*K$SbOB%sZae;9uIUXgQu&X J%Q~loCIECSTxI|O literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_more_vert_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_more_vert_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..4642a3b66e690a25544c7a65b5484607c76e9e4d GIT binary patch literal 272 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD0wg^q?%xcgu6w#ThEy=Vz2TVE>>%O(aeKF| z&%}AAoaYX07I~@2Qzf){=E~b*b6q_X?JD-aXZn{o>8SH070*d=@0yRCD&F7PI4|Iy zgr>dT{)s<*uuMbP?bJzL!+Uj>du1MOpP(^y_vJlXtsXdjo_CdTHuJx`L9zyy z_bjw};Pttx=xP2JS*8CI?{O?lw)*qOUytSD#5&t0XL`98ez{Y*;jMY`-`}^VtDMwJ z5#Pjpv-OQrnIiiQFtvL^tj8o3AbA2TH#1Zw0j|Uo=)7NS4apHKER!-ifL>(qboFyt I=akR{05Df}#Q*>R literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_more_vert_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_more_vert_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..2f2cb3d004f6e828917b5f6b1decc7fe5d99b445 GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD0wg^q?%xcget5b#hE&{od&7{g$w9>R;>#mP zB_2gJIy{WxDHIfl;54zZ?(Dj(@bmNJ>M(=pX9D&J05vf@IA0RFIB;_s@2aW4t^P!s z?~T5q@wxa<`?f89Li_gpTlKB*dwsOb9#+$?m6!M>7BklVVk|aEPh1DJ$>V{EJl=XH?V({#-awY-(QL|0?dORlc*XtSl(} z&d3n4k$a}x{MZxU-fiZ-$+m%8aD#C}>V?${Gwe!OwoRt{8X v))3p#FqiR-(={Oe2E;4(u$C!;+}~cs6m#}#(>L)Q#vrbztDnm{r-UW|mL!4d literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/list_stream_item.xml b/app/src/main/res/layout/list_stream_item.xml index cb1ac6fe2..f09ab89be 100644 --- a/app/src/main/res/layout/list_stream_item.xml +++ b/app/src/main/res/layout/list_stream_item.xml @@ -7,7 +7,9 @@ android:layout_height="@dimen/video_item_search_height" android:background="?attr/selectableItemBackground" android:clickable="true" - android:padding="@dimen/video_item_search_padding"> + android:focusable="true" + android:paddingTop="@dimen/video_item_search_padding" + android:paddingBottom="@dimen/video_item_search_padding"> + + + android:focusable="true" + android:paddingTop="@dimen/video_item_search_padding" + android:paddingBottom="@dimen/video_item_search_padding"> + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7092feaf5..1d93b61f1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -310,4 +310,6 @@ Details Audio Settings Hold To Enqueue + Enqueue on Background + Enqueue on Popup diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 8f0bb02cd..85549c8c5 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -27,6 +27,7 @@ @drawable/ic_history_black_24dp @drawable/ic_drag_handle_black_24dp @drawable/ic_fiber_manual_record_black_24dp + @drawable/ic_more_vert_black_24dp @color/light_separator_color @color/light_contrast_background_color @@ -65,6 +66,7 @@ @drawable/ic_history_white_24dp @drawable/ic_drag_handle_white_24dp @drawable/ic_fiber_manual_record_white_24dp + @drawable/ic_more_vert_white_24dp @color/dark_separator_color @color/dark_contrast_background_color From b8a17580c5da46c4489ee7d6411dd71a9d8fe057 Mon Sep 17 00:00:00 2001 From: John Zhen Mo Date: Wed, 1 Nov 2017 23:38:18 -0700 Subject: [PATCH 044/159] -Added play queue dropdown to channel info items. -Added play queue dropdown to playlist info items. -Added Channel Play Queue. -Renamed External Play Queue to Playlist Play Queue. -Modified Playlist Play Queue to allow loading from initial state. --- .../list/playlist/PlaylistFragment.java | 8 +- .../holder/ChannelMiniInfoItemHolder.java | 57 +++++++ .../holder/PlaylistInfoItemHolder.java | 56 +++++++ .../holder/StreamMiniInfoItemHolder.java | 51 +++--- .../player/playback/MediaSourceManager.java | 2 +- .../newpipe/playlist/ChannelPlayQueue.java | 151 ++++++++++++++++++ ...lPlayQueue.java => PlaylistPlayQueue.java} | 64 ++++++-- app/src/main/res/layout/list_channel_item.xml | 33 +++- .../res/layout/list_channel_mini_item.xml | 26 ++- .../main/res/layout/list_playlist_item.xml | 26 ++- app/src/main/res/layout/list_stream_item.xml | 2 +- .../main/res/layout/list_stream_mini_item.xml | 2 + 12 files changed, 431 insertions(+), 47 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java rename app/src/main/java/org/schabi/newpipe/playlist/{ExternalPlayQueue.java => PlaylistPlayQueue.java} (55%) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java index 9d57617d3..0c5b002e3 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java @@ -1,6 +1,5 @@ package org.schabi.newpipe.fragments.list.playlist; -import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; @@ -24,10 +23,7 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.fragments.list.BaseListInfoFragment; -import org.schabi.newpipe.player.BackgroundPlayer; -import org.schabi.newpipe.player.MainVideoPlayer; -import org.schabi.newpipe.player.PopupVideoPlayer; -import org.schabi.newpipe.playlist.ExternalPlayQueue; +import org.schabi.newpipe.playlist.PlaylistPlayQueue; import org.schabi.newpipe.playlist.PlayQueue; import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.util.ExtractorHelper; @@ -185,7 +181,7 @@ public class PlaylistFragment extends BaseListInfoFragment { } private PlayQueue getPlayQueue() { - return new ExternalPlayQueue( + return new PlaylistPlayQueue( currentInfo.service_id, currentInfo.url, currentInfo.next_streams_url, diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java index 9aef6dbd2..30dc3d8bc 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java @@ -1,7 +1,11 @@ package org.schabi.newpipe.info_list.holder; +import android.content.Context; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageButton; +import android.widget.PopupMenu; import android.widget.TextView; import com.nostra13.universalimageloader.core.DisplayImageOptions; @@ -10,7 +14,9 @@ import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.info_list.InfoItemBuilder; +import org.schabi.newpipe.playlist.ChannelPlayQueue; import org.schabi.newpipe.util.Localization; +import org.schabi.newpipe.util.NavigationHelper; import de.hdodenhof.circleimageview.CircleImageView; @@ -18,6 +24,7 @@ public class ChannelMiniInfoItemHolder extends InfoItemHolder { public final CircleImageView itemThumbnailView; public final TextView itemTitleView; public final TextView itemAdditionalDetailView; + public final ImageButton itemActionDropdown; ChannelMiniInfoItemHolder(InfoItemBuilder infoItemBuilder, int layoutId, ViewGroup parent) { super(infoItemBuilder, layoutId, parent); @@ -25,6 +32,7 @@ public class ChannelMiniInfoItemHolder extends InfoItemHolder { itemThumbnailView = itemView.findViewById(R.id.itemThumbnailView); itemTitleView = itemView.findViewById(R.id.itemTitleView); itemAdditionalDetailView = itemView.findViewById(R.id.itemAdditionalDetails); + itemActionDropdown = itemView.findViewById(R.id.itemActionDropdown); } public ChannelMiniInfoItemHolder(InfoItemBuilder infoItemBuilder, ViewGroup parent) { @@ -50,6 +58,55 @@ public class ChannelMiniInfoItemHolder extends InfoItemHolder { } } }); + + enableActionDropdown(item); + } + + private void enableActionDropdown(final ChannelInfoItem item) { + itemActionDropdown.setVisibility(View.VISIBLE); + itemActionDropdown.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + final PopupMenu actionMenu = getStreamDropdown(itemBuilder.getContext(), itemActionDropdown, item); + if (itemBuilder.getOnChannelSelectedListener() != null) { + itemBuilder.getOnChannelSelectedListener().dropdownClicked(item, actionMenu); + } + actionMenu.show(); + } + }); + } + + private PopupMenu getStreamDropdown(final Context context, final View anchor, final ChannelInfoItem infoItem) { + PopupMenu actionMenu = new PopupMenu(context, anchor); + + final MenuItem mainPlay = actionMenu.getMenu().add(R.string.play_all); + mainPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + NavigationHelper.playOnMainPlayer(context, new ChannelPlayQueue(infoItem)); + return true; + } + }); + + final MenuItem popupPlay = actionMenu.getMenu().add(R.string.controls_popup_title); + popupPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + NavigationHelper.playOnPopupPlayer(context, new ChannelPlayQueue(infoItem)); + return true; + } + }); + + final MenuItem backgroundPlay = actionMenu.getMenu().add(R.string.controls_background_title); + backgroundPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + NavigationHelper.playOnBackgroundPlayer(context, new ChannelPlayQueue(infoItem)); + return true; + } + }); + + return actionMenu; } protected String getDetailLine(final ChannelInfoItem item) { diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistInfoItemHolder.java index 3c29a4b76..5e0f44939 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistInfoItemHolder.java @@ -1,8 +1,12 @@ package org.schabi.newpipe.info_list.holder; +import android.content.Context; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageButton; import android.widget.ImageView; +import android.widget.PopupMenu; import android.widget.TextView; import com.nostra13.universalimageloader.core.DisplayImageOptions; @@ -11,12 +15,15 @@ import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; import org.schabi.newpipe.info_list.InfoItemBuilder; +import org.schabi.newpipe.playlist.PlaylistPlayQueue; +import org.schabi.newpipe.util.NavigationHelper; public class PlaylistInfoItemHolder extends InfoItemHolder { public final ImageView itemThumbnailView; public final TextView itemStreamCountView; public final TextView itemTitleView; public final TextView itemUploaderView; + public final ImageButton itemActionDropdown; public PlaylistInfoItemHolder(InfoItemBuilder infoItemBuilder, ViewGroup parent) { super(infoItemBuilder, R.layout.list_playlist_item, parent); @@ -25,6 +32,7 @@ public class PlaylistInfoItemHolder extends InfoItemHolder { itemTitleView = itemView.findViewById(R.id.itemTitleView); itemStreamCountView = itemView.findViewById(R.id.itemStreamCountView); itemUploaderView = itemView.findViewById(R.id.itemUploaderView); + itemActionDropdown = itemView.findViewById(R.id.itemActionDropdown); } @Override @@ -47,8 +55,56 @@ public class PlaylistInfoItemHolder extends InfoItemHolder { } } }); + + enableActionDropdown(item); } + private void enableActionDropdown(final PlaylistInfoItem item) { + itemActionDropdown.setVisibility(View.VISIBLE); + itemActionDropdown.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + final PopupMenu actionMenu = getStreamDropdown(itemBuilder.getContext(), itemActionDropdown, item); + if (itemBuilder.getOnPlaylistSelectedListener() != null) { + itemBuilder.getOnPlaylistSelectedListener().dropdownClicked(item, actionMenu); + } + actionMenu.show(); + } + }); + } + + private PopupMenu getStreamDropdown(final Context context, final View anchor, final PlaylistInfoItem infoItem) { + PopupMenu actionMenu = new PopupMenu(context, anchor); + + final MenuItem mainPlay = actionMenu.getMenu().add(R.string.play_all); + mainPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + NavigationHelper.playOnMainPlayer(context, new PlaylistPlayQueue(infoItem)); + return true; + } + }); + + final MenuItem popupPlay = actionMenu.getMenu().add(R.string.controls_popup_title); + popupPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + NavigationHelper.playOnPopupPlayer(context, new PlaylistPlayQueue(infoItem)); + return true; + } + }); + + final MenuItem backgroundPlay = actionMenu.getMenu().add(R.string.controls_background_title); + backgroundPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + NavigationHelper.playOnBackgroundPlayer(context, new PlaylistPlayQueue(infoItem)); + return true; + } + }); + + return actionMenu; + } /** * Display options for playlist thumbnails */ diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java index 1dea9633b..6c399e481 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java @@ -2,7 +2,6 @@ package org.schabi.newpipe.info_list.holder; import android.content.Context; import android.support.v4.content.ContextCompat; -import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; @@ -10,7 +9,6 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.PopupMenu; import android.widget.TextView; -import android.widget.Toast; import com.nostra13.universalimageloader.core.DisplayImageOptions; @@ -19,9 +17,6 @@ import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.info_list.InfoItemBuilder; -import org.schabi.newpipe.player.BackgroundPlayer; -import org.schabi.newpipe.player.PopupVideoPlayer; -import org.schabi.newpipe.playlist.PlayQueue; import org.schabi.newpipe.playlist.SinglePlayQueue; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; @@ -91,11 +86,13 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { case AUDIO_LIVE_STREAM: case NONE: default: + disableActionDropdown(); break; } } private void enableActionDropdown(final StreamInfoItem item) { + itemActionDropdown.setClickable(true); itemActionDropdown.setVisibility(View.VISIBLE); itemActionDropdown.setOnClickListener(new View.OnClickListener() { @Override @@ -109,10 +106,34 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { }); } + private void disableActionDropdown() { + itemActionDropdown.setVisibility(View.GONE); + itemActionDropdown.setClickable(false); + itemActionDropdown.setOnClickListener(null); + } + private PopupMenu getStreamDropdown(final Context context, final View anchor, final StreamInfoItem infoItem) { PopupMenu actionMenu = new PopupMenu(context, anchor); - final MenuItem mainPlay = actionMenu.getMenu().add(R.string.play_btn_text); + final MenuItem backgroundEnqueue = actionMenu.getMenu().add(R.string.enqueue_on_background); + backgroundEnqueue.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(infoItem)); + return true; + } + }); + + final MenuItem popupEnqueue = actionMenu.getMenu().add(R.string.enqueue_on_popup); + popupEnqueue.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem menuItem) { + NavigationHelper.enqueueOnPopupPlayer(context, new SinglePlayQueue(infoItem)); + return true; + } + }); + + final MenuItem mainPlay = actionMenu.getMenu().add(R.string.play_all); mainPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { @@ -139,24 +160,6 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { } }); - final MenuItem backgroundEnqueue = actionMenu.getMenu().add(R.string.enqueue_on_background); - backgroundEnqueue.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem menuItem) { - NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(infoItem)); - return true; - } - }); - - final MenuItem popupEnqueue = actionMenu.getMenu().add(R.string.enqueue_on_popup); - popupEnqueue.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem menuItem) { - NavigationHelper.enqueueOnPopupPlayer(context, new SinglePlayQueue(infoItem)); - return true; - } - }); - return actionMenu; } diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java b/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java index 2e4e4af5c..04f1606fa 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java @@ -157,7 +157,7 @@ public class MediaSourceManager { } private void onPlayQueueChanged(final PlayQueueEvent event) { - if (playQueue.isEmpty()) { + if (playQueue.isEmpty() && playQueue.isComplete()) { playbackListener.shutdown(); return; } diff --git a/app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java new file mode 100644 index 000000000..c48f76127 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java @@ -0,0 +1,151 @@ +package org.schabi.newpipe.playlist; + +import android.util.Log; + +import org.schabi.newpipe.extractor.InfoItem; +import org.schabi.newpipe.extractor.ListExtractor; +import org.schabi.newpipe.extractor.channel.ChannelInfo; +import org.schabi.newpipe.extractor.channel.ChannelInfoItem; +import org.schabi.newpipe.extractor.stream.StreamInfoItem; +import org.schabi.newpipe.util.ExtractorHelper; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.annotations.NonNull; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; + +public final class ChannelPlayQueue extends PlayQueue { + private final String TAG = "ChannelPlayQueue@" + Integer.toHexString(hashCode()); + + private boolean isInitial; + private boolean isComplete; + + private int serviceId; + private String baseUrl; + private String nextUrl; + + private transient Disposable fetchReactor; + + public ChannelPlayQueue(final ChannelInfoItem item) { + this(item.service_id, item.url, item.url, Collections.emptyList(), 0); + } + + public ChannelPlayQueue(final int serviceId, + final String url, + final String nextPageUrl, + final List streams, + final int index) { + super(index, extractChannelItems(streams)); + + this.baseUrl = url; + this.nextUrl = nextPageUrl; + this.serviceId = serviceId; + + this.isInitial = streams.isEmpty(); + this.isComplete = !isInitial && (nextPageUrl == null || nextPageUrl.isEmpty()); + } + + @Override + public boolean isComplete() { + return isComplete; + } + + @Override + public void fetch() { + if (isInitial) { + ExtractorHelper.getChannelInfo(this.serviceId, this.baseUrl, false) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(getChannelInitialObserver()); + } else { + ExtractorHelper.getMoreChannelItems(this.serviceId, this.baseUrl, this.nextUrl) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(getChannelNextItemsObserver()); + } + } + + private SingleObserver getChannelInitialObserver() { + return new SingleObserver() { + @Override + public void onSubscribe(@NonNull Disposable d) { + if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { + d.dispose(); + } else { + fetchReactor = d; + } + } + + @Override + public void onSuccess(@NonNull ChannelInfo result) { + if (!result.has_more_streams) isComplete = true; + nextUrl = result.next_streams_url; + + append(extractChannelItems(result.related_streams)); + + isInitial = false; + fetchReactor.dispose(); + fetchReactor = null; + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e); + isComplete = true; + append(); // Notify change + } + }; + } + + private SingleObserver getChannelNextItemsObserver() { + return new SingleObserver() { + @Override + public void onSubscribe(@NonNull Disposable d) { + if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { + d.dispose(); + } else { + fetchReactor = d; + } + } + + @Override + public void onSuccess(@NonNull ListExtractor.NextItemsResult result) { + if (!result.hasMoreStreams()) isComplete = true; + nextUrl = result.nextItemsUrl; + + append(extractChannelItems(result.nextItemsList)); + + fetchReactor.dispose(); + fetchReactor = null; + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e); + isComplete = true; + append(); // Notify change + } + }; + } + + @Override + public void dispose() { + super.dispose(); + if (fetchReactor != null) fetchReactor.dispose(); + } + + private static List extractChannelItems(final List infos) { + List result = new ArrayList<>(); + for (final InfoItem stream : infos) { + if (stream instanceof StreamInfoItem) { + result.add(new PlayQueueItem((StreamInfoItem) stream)); + } + } + return result; + } +} diff --git a/app/src/main/java/org/schabi/newpipe/playlist/ExternalPlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/PlaylistPlayQueue.java similarity index 55% rename from app/src/main/java/org/schabi/newpipe/playlist/ExternalPlayQueue.java rename to app/src/main/java/org/schabi/newpipe/playlist/PlaylistPlayQueue.java index 019b684d4..39ac6517d 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/ExternalPlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/PlaylistPlayQueue.java @@ -4,6 +4,8 @@ import android.util.Log; import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.ListExtractor; +import org.schabi.newpipe.extractor.playlist.PlaylistInfo; +import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.util.ExtractorHelper; @@ -17,9 +19,10 @@ import io.reactivex.annotations.NonNull; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; -public final class ExternalPlayQueue extends PlayQueue { - private final String TAG = "ExternalPlayQueue@" + Integer.toHexString(hashCode()); +public final class PlaylistPlayQueue extends PlayQueue { + private final String TAG = "PlaylistPlayQueue@" + Integer.toHexString(hashCode()); + private boolean isInitial; private boolean isComplete; private int serviceId; @@ -28,7 +31,11 @@ public final class ExternalPlayQueue extends PlayQueue { private transient Disposable fetchReactor; - public ExternalPlayQueue(final int serviceId, + public PlaylistPlayQueue(final PlaylistInfoItem item) { + this(item.service_id, item.url, item.url, Collections.emptyList(), 0); + } + + public PlaylistPlayQueue(final int serviceId, final String url, final String nextPageUrl, final List streams, @@ -39,7 +46,8 @@ public final class ExternalPlayQueue extends PlayQueue { this.nextUrl = nextPageUrl; this.serviceId = serviceId; - this.isComplete = nextPageUrl == null || nextPageUrl.isEmpty(); + this.isInitial = streams.isEmpty(); + this.isComplete = !isInitial && (nextPageUrl == null || nextPageUrl.isEmpty()); } @Override @@ -49,13 +57,51 @@ public final class ExternalPlayQueue extends PlayQueue { @Override public void fetch() { - ExtractorHelper.getMorePlaylistItems(this.serviceId, this.baseUrl, this.nextUrl) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(getPlaylistObserver()); + if (isInitial) { + ExtractorHelper.getPlaylistInfo(this.serviceId, this.baseUrl, false) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(getInitialPlaylistObserver()); + } else { + ExtractorHelper.getMorePlaylistItems(this.serviceId, this.baseUrl, this.nextUrl) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(getPlaylistNextItemsObserver()); + } } - private SingleObserver getPlaylistObserver() { + private SingleObserver getInitialPlaylistObserver() { + return new SingleObserver() { + @Override + public void onSubscribe(@NonNull Disposable d) { + if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { + d.dispose(); + } else { + fetchReactor = d; + } + } + + @Override + public void onSuccess(@NonNull PlaylistInfo result) { + if (!result.has_more_streams) isComplete = true; + nextUrl = result.next_streams_url; + + append(extractPlaylistItems(result.related_streams)); + + fetchReactor.dispose(); + fetchReactor = null; + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e); + isComplete = true; + append(); // Notify change + } + }; + } + + private SingleObserver getPlaylistNextItemsObserver() { return new SingleObserver() { @Override public void onSubscribe(@NonNull Disposable d) { diff --git a/app/src/main/res/layout/list_channel_item.xml b/app/src/main/res/layout/list_channel_item.xml index 3b4b71dc9..90f88b26f 100644 --- a/app/src/main/res/layout/list_channel_item.xml +++ b/app/src/main/res/layout/list_channel_item.xml @@ -7,7 +7,9 @@ android:layout_height="@dimen/video_item_search_height" android:background="?attr/selectableItemBackground" android:clickable="true" - android:padding="@dimen/video_item_search_padding"> + android:focusable="true" + android:paddingTop="@dimen/video_item_search_padding" + android:paddingBottom="@dimen/video_item_search_padding"> + + + tools:text="Channel Title, Lorem ipsum" /> + tools:text="Channel description, Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tristique vitae sem vitae blanditLorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tristique vitae sem vitae blanditLorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tristique vitae sem vitae blandit" /> + android:focusable="true" + android:paddingTop="@dimen/video_item_search_padding" + android:paddingBottom="@dimen/video_item_search_padding"> + + + android:focusable="true" + android:paddingTop="@dimen/video_item_search_padding" + android:paddingBottom="@dimen/video_item_search_padding"> + + Date: Thu, 2 Nov 2017 12:30:26 -0700 Subject: [PATCH 045/159] -Added fast seeking on background notification when play queue size is 1. -Fixed player intent with quality selection not used in detail fragment. -Fixed window index not reset on sync when not playing. -Fix dropdown play string for stream info item. --- .../fragments/detail/VideoDetailFragment.java | 18 +++++--- .../holder/StreamMiniInfoItemHolder.java | 2 +- .../newpipe/player/BackgroundPlayer.java | 41 +++++++++++++++---- .../org/schabi/newpipe/player/BasePlayer.java | 6 +-- 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index 265e22319..f6753f128 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 @@ -66,6 +66,7 @@ import org.schabi.newpipe.info_list.InfoItemBuilder; import org.schabi.newpipe.player.BackgroundPlayer; import org.schabi.newpipe.player.MainVideoPlayer; import org.schabi.newpipe.player.PopupVideoPlayer; +import org.schabi.newpipe.player.helper.PlayerHelper; import org.schabi.newpipe.player.old.PlayVideoActivity; import org.schabi.newpipe.playlist.PlayQueue; import org.schabi.newpipe.playlist.SinglePlayQueue; @@ -800,7 +801,11 @@ public class VideoDetailFragment extends BaseStateFragment implement if (append) { NavigationHelper.enqueueOnPopupPlayer(activity, itemQueue); } else { - NavigationHelper.playOnPopupPlayer(activity, itemQueue); + Toast.makeText(activity, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show(); + final Intent intent = NavigationHelper.getPlayerIntent( + activity, PopupVideoPlayer.class, itemQueue, getSelectedVideoStream().resolution + ); + activity.startService(intent); } } @@ -863,20 +868,21 @@ public class VideoDetailFragment extends BaseStateFragment implement } private void openNormalPlayer(VideoStream selectedVideoStream) { - boolean useOldPlayer = PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(getString(R.string.use_old_player_key), false) - || (Build.VERSION.SDK_INT < 16); + Intent mIntent; + boolean useOldPlayer = PlayerHelper.isUsingOldPlayer(activity) || (Build.VERSION.SDK_INT < 16); if (!useOldPlayer) { // ExoPlayer - NavigationHelper.playOnMainPlayer(activity, new SinglePlayQueue(currentInfo)); + final PlayQueue playQueue = new SinglePlayQueue(currentInfo); + mIntent = NavigationHelper.getPlayerIntent(activity, MainVideoPlayer.class, playQueue, getSelectedVideoStream().resolution); } else { // Internal Player - final Intent mIntent = new Intent(activity, PlayVideoActivity.class) + mIntent = new Intent(activity, PlayVideoActivity.class) .putExtra(PlayVideoActivity.VIDEO_TITLE, currentInfo.name) .putExtra(PlayVideoActivity.STREAM_URL, selectedVideoStream.url) .putExtra(PlayVideoActivity.VIDEO_URL, currentInfo.url) .putExtra(PlayVideoActivity.START_POSITION, currentInfo.start_position); - startActivity(mIntent); } + startActivity(mIntent); } private void openExternalVideoPlayer(VideoStream selectedVideoStream) { diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java index 6c399e481..a910041d0 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java @@ -133,7 +133,7 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { } }); - final MenuItem mainPlay = actionMenu.getMenu().add(R.string.play_all); + final MenuItem mainPlay = actionMenu.getMenu().add(R.string.play_btn_text); mainPlay.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { diff --git a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java index cfed78179..dfbb98b95 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java @@ -69,6 +69,10 @@ public final class BackgroundPlayer extends Service { public static final String ACTION_REPEAT = "org.schabi.newpipe.player.BackgroundPlayer.REPEAT"; public static final String ACTION_PLAY_NEXT = "org.schabi.newpipe.player.BackgroundPlayer.ACTION_PLAY_NEXT"; public static final String ACTION_PLAY_PREVIOUS = "org.schabi.newpipe.player.BackgroundPlayer.ACTION_PLAY_PREVIOUS"; + public static final String ACTION_FAST_REWIND = "org.schabi.newpipe.player.BackgroundPlayer.ACTION_FAST_REWIND"; + public static final String ACTION_FAST_FORWARD = "org.schabi.newpipe.player.BackgroundPlayer.ACTION_FAST_FORWARD"; + + public static final String SET_IMAGE_RESOURCE_METHOD = "setImageResource"; private BasePlayerImpl basePlayerImpl; private LockManager lockManager; @@ -182,6 +186,8 @@ public final class BackgroundPlayer extends Service { } private void setupNotification(RemoteViews remoteViews) { + if (basePlayerImpl == null) return; + remoteViews.setTextViewText(R.id.notificationSongName, basePlayerImpl.getVideoTitle()); remoteViews.setTextViewText(R.id.notificationArtist, basePlayerImpl.getUploaderName()); @@ -194,10 +200,21 @@ public final class BackgroundPlayer extends Service { remoteViews.setOnClickPendingIntent(R.id.notificationRepeat, PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_REPEAT), PendingIntent.FLAG_UPDATE_CURRENT)); - remoteViews.setOnClickPendingIntent(R.id.notificationFRewind, - PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_PLAY_PREVIOUS), PendingIntent.FLAG_UPDATE_CURRENT)); - remoteViews.setOnClickPendingIntent(R.id.notificationFForward, - PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_PLAY_NEXT), PendingIntent.FLAG_UPDATE_CURRENT)); + if (basePlayerImpl.playQueue != null && basePlayerImpl.playQueue.size() > 1) { + remoteViews.setInt(R.id.notificationFRewind, SET_IMAGE_RESOURCE_METHOD, R.drawable.exo_controls_previous); + remoteViews.setInt(R.id.notificationFForward, SET_IMAGE_RESOURCE_METHOD, R.drawable.exo_controls_next); + remoteViews.setOnClickPendingIntent(R.id.notificationFRewind, + PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_PLAY_PREVIOUS), PendingIntent.FLAG_UPDATE_CURRENT)); + remoteViews.setOnClickPendingIntent(R.id.notificationFForward, + PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_PLAY_NEXT), PendingIntent.FLAG_UPDATE_CURRENT)); + } else { + remoteViews.setInt(R.id.notificationFRewind, SET_IMAGE_RESOURCE_METHOD, R.drawable.exo_controls_rewind); + remoteViews.setInt(R.id.notificationFForward, SET_IMAGE_RESOURCE_METHOD, R.drawable.exo_controls_fastforward); + remoteViews.setOnClickPendingIntent(R.id.notificationFRewind, + PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_FAST_REWIND), PendingIntent.FLAG_UPDATE_CURRENT)); + remoteViews.setOnClickPendingIntent(R.id.notificationFForward, + PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_FAST_FORWARD), PendingIntent.FLAG_UPDATE_CURRENT)); + } setRepeatModeIcon(remoteViews, basePlayerImpl.getRepeatMode()); } @@ -232,17 +249,15 @@ public final class BackgroundPlayer extends Service { //////////////////////////////////////////////////////////////////////////*/ private void setRepeatModeIcon(final RemoteViews remoteViews, final int repeatMode) { - final String methodName = "setImageResource"; - switch (repeatMode) { case Player.REPEAT_MODE_OFF: - remoteViews.setInt(R.id.notificationRepeat, methodName, R.drawable.exo_controls_repeat_off); + remoteViews.setInt(R.id.notificationRepeat, SET_IMAGE_RESOURCE_METHOD, R.drawable.exo_controls_repeat_off); break; case Player.REPEAT_MODE_ONE: - remoteViews.setInt(R.id.notificationRepeat, methodName, R.drawable.exo_controls_repeat_one); + remoteViews.setInt(R.id.notificationRepeat, SET_IMAGE_RESOURCE_METHOD, R.drawable.exo_controls_repeat_one); break; case Player.REPEAT_MODE_ALL: - remoteViews.setInt(R.id.notificationRepeat, methodName, R.drawable.exo_controls_repeat_all); + remoteViews.setInt(R.id.notificationRepeat, SET_IMAGE_RESOURCE_METHOD, R.drawable.exo_controls_repeat_all); break; } } @@ -441,6 +456,8 @@ public final class BackgroundPlayer extends Service { intentFilter.addAction(ACTION_REPEAT); intentFilter.addAction(ACTION_PLAY_PREVIOUS); intentFilter.addAction(ACTION_PLAY_NEXT); + intentFilter.addAction(ACTION_FAST_REWIND); + intentFilter.addAction(ACTION_FAST_FORWARD); intentFilter.addAction(Intent.ACTION_SCREEN_ON); intentFilter.addAction(Intent.ACTION_SCREEN_OFF); @@ -472,6 +489,12 @@ public final class BackgroundPlayer extends Service { case ACTION_PLAY_PREVIOUS: onPlayPrevious(); break; + case ACTION_FAST_FORWARD: + onFastForward(); + break; + case ACTION_FAST_REWIND: + onFastRewind(); + break; case Intent.ACTION_SCREEN_ON: onScreenOnOff(true); break; diff --git a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java index c24a46049..3da976991 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java @@ -646,7 +646,7 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen if (currentSourceIndex != playQueue.getIndex()) { Log.e(TAG, "Play Queue may be desynchronized: item index=[" + currentSourceIndex + "], queue index=[" + playQueue.getIndex() + "]"); - } else if (simpleExoPlayer.getCurrentWindowIndex() != currentSourceIndex) { + } else if (simpleExoPlayer.getCurrentWindowIndex() != currentSourceIndex || !isPlaying()) { final long startPos = info != null ? info.start_position : 0; if (DEBUG) Log.d(TAG, "Rewinding to correct window: " + currentSourceIndex + " at: " + getTimeString((int)startPos)); simpleExoPlayer.seekTo(currentSourceIndex, startPos); @@ -761,10 +761,6 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen } else { playQueue.setIndex(index); } - - if (!isPlaying()) { - onVideoPlayPause(); - } } public void seekBy(int milliSeconds) { From b32f149a1bd811598030ec3e128967d1fa576bce Mon Sep 17 00:00:00 2001 From: John Zhen Mo Date: Thu, 2 Nov 2017 20:34:12 -0700 Subject: [PATCH 046/159] -Refactored Channel and Playlist PlayQueue into AbstractInfo playQueue. -Increase list item action dropdown padding. --- .../fragments/detail/VideoDetailFragment.java | 1 - .../playlist/AbstractInfoPlayQueue.java | 131 ++++++++++++++++++ .../newpipe/playlist/ChannelPlayQueue.java | 130 ++--------------- .../newpipe/playlist/PlaylistPlayQueue.java | 129 ++--------------- app/src/main/res/layout/list_channel_item.xml | 8 +- .../res/layout/list_channel_mini_item.xml | 6 +- .../main/res/layout/list_playlist_item.xml | 6 +- app/src/main/res/layout/list_stream_item.xml | 6 +- .../main/res/layout/list_stream_mini_item.xml | 6 +- 9 files changed, 171 insertions(+), 252 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/playlist/AbstractInfoPlayQueue.java 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 f6753f128..cbb658025 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 @@ -63,7 +63,6 @@ import org.schabi.newpipe.fragments.BackPressable; import org.schabi.newpipe.fragments.BaseStateFragment; import org.schabi.newpipe.history.HistoryListener; import org.schabi.newpipe.info_list.InfoItemBuilder; -import org.schabi.newpipe.player.BackgroundPlayer; import org.schabi.newpipe.player.MainVideoPlayer; import org.schabi.newpipe.player.PopupVideoPlayer; import org.schabi.newpipe.player.helper.PlayerHelper; diff --git a/app/src/main/java/org/schabi/newpipe/playlist/AbstractInfoPlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/AbstractInfoPlayQueue.java new file mode 100644 index 000000000..74a4dc555 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/playlist/AbstractInfoPlayQueue.java @@ -0,0 +1,131 @@ +package org.schabi.newpipe.playlist; + +import android.util.Log; + +import org.schabi.newpipe.extractor.InfoItem; +import org.schabi.newpipe.extractor.ListExtractor; +import org.schabi.newpipe.extractor.ListInfo; +import org.schabi.newpipe.extractor.stream.StreamInfoItem; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import io.reactivex.SingleObserver; +import io.reactivex.annotations.NonNull; +import io.reactivex.disposables.Disposable; + +abstract class AbstractInfoPlayQueue extends PlayQueue { + boolean isInitial; + boolean isComplete; + + int serviceId; + String baseUrl; + String nextUrl; + + transient Disposable fetchReactor; + + AbstractInfoPlayQueue(final U item) { + this(item.service_id, item.url, item.url, Collections.emptyList(), 0); + } + + AbstractInfoPlayQueue(final int serviceId, + final String url, + final String nextPageUrl, + final List streams, + final int index) { + super(index, extractListItems(streams)); + + this.baseUrl = url; + this.nextUrl = nextPageUrl; + this.serviceId = serviceId; + + this.isInitial = streams.isEmpty(); + this.isComplete = !isInitial && (nextPageUrl == null || nextPageUrl.isEmpty()); + } + + abstract protected String getTag(); + + @Override + public boolean isComplete() { + return isComplete; + } + + SingleObserver getHeadListObserver() { + return new SingleObserver() { + @Override + public void onSubscribe(@NonNull Disposable d) { + if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { + d.dispose(); + } else { + fetchReactor = d; + } + } + + @Override + public void onSuccess(@NonNull T result) { + if (!result.has_more_streams) isComplete = true; + nextUrl = result.next_streams_url; + + append(extractListItems(result.related_streams)); + + fetchReactor.dispose(); + fetchReactor = null; + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e(getTag(), "Error fetching more playlist, marking playlist as complete.", e); + isComplete = true; + append(); // Notify change + } + }; + } + + SingleObserver getNextItemsObserver() { + return new SingleObserver() { + @Override + public void onSubscribe(@NonNull Disposable d) { + if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { + d.dispose(); + } else { + fetchReactor = d; + } + } + + @Override + public void onSuccess(@NonNull ListExtractor.NextItemsResult result) { + if (!result.hasMoreStreams()) isComplete = true; + nextUrl = result.nextItemsUrl; + + append(extractListItems(result.nextItemsList)); + + fetchReactor.dispose(); + fetchReactor = null; + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e(getTag(), "Error fetching more playlist, marking playlist as complete.", e); + isComplete = true; + append(); // Notify change + } + }; + } + + @Override + public void dispose() { + super.dispose(); + if (fetchReactor != null) fetchReactor.dispose(); + } + + private static List extractListItems(final List infos) { + List result = new ArrayList<>(); + for (final InfoItem stream : infos) { + if (stream instanceof StreamInfoItem) { + result.add(new PlayQueueItem((StreamInfoItem) stream)); + } + } + return result; + } +} diff --git a/app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java index c48f76127..239024f28 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java @@ -1,151 +1,45 @@ package org.schabi.newpipe.playlist; -import android.util.Log; - import org.schabi.newpipe.extractor.InfoItem; -import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.channel.ChannelInfo; import org.schabi.newpipe.extractor.channel.ChannelInfoItem; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.util.ExtractorHelper; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import io.reactivex.SingleObserver; import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.annotations.NonNull; -import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; -public final class ChannelPlayQueue extends PlayQueue { - private final String TAG = "ChannelPlayQueue@" + Integer.toHexString(hashCode()); - - private boolean isInitial; - private boolean isComplete; - - private int serviceId; - private String baseUrl; - private String nextUrl; - - private transient Disposable fetchReactor; - +public final class ChannelPlayQueue extends AbstractInfoPlayQueue { public ChannelPlayQueue(final ChannelInfoItem item) { - this(item.service_id, item.url, item.url, Collections.emptyList(), 0); + super(item); } public ChannelPlayQueue(final int serviceId, - final String url, - final String nextPageUrl, - final List streams, - final int index) { - super(index, extractChannelItems(streams)); - - this.baseUrl = url; - this.nextUrl = nextPageUrl; - this.serviceId = serviceId; - - this.isInitial = streams.isEmpty(); - this.isComplete = !isInitial && (nextPageUrl == null || nextPageUrl.isEmpty()); + final String url, + final String nextPageUrl, + final List streams, + final int index) { + super(serviceId, url, nextPageUrl, streams, index); } @Override - public boolean isComplete() { - return isComplete; + protected String getTag() { + return "ChannelPlayQueue@" + Integer.toHexString(hashCode()); } @Override public void fetch() { - if (isInitial) { + if (this.isInitial) { ExtractorHelper.getChannelInfo(this.serviceId, this.baseUrl, false) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(getChannelInitialObserver()); + .subscribe(getHeadListObserver()); } else { ExtractorHelper.getMoreChannelItems(this.serviceId, this.baseUrl, this.nextUrl) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(getChannelNextItemsObserver()); + .subscribe(getNextItemsObserver()); } } - - private SingleObserver getChannelInitialObserver() { - return new SingleObserver() { - @Override - public void onSubscribe(@NonNull Disposable d) { - if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { - d.dispose(); - } else { - fetchReactor = d; - } - } - - @Override - public void onSuccess(@NonNull ChannelInfo result) { - if (!result.has_more_streams) isComplete = true; - nextUrl = result.next_streams_url; - - append(extractChannelItems(result.related_streams)); - - isInitial = false; - fetchReactor.dispose(); - fetchReactor = null; - } - - @Override - public void onError(@NonNull Throwable e) { - Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e); - isComplete = true; - append(); // Notify change - } - }; - } - - private SingleObserver getChannelNextItemsObserver() { - return new SingleObserver() { - @Override - public void onSubscribe(@NonNull Disposable d) { - if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { - d.dispose(); - } else { - fetchReactor = d; - } - } - - @Override - public void onSuccess(@NonNull ListExtractor.NextItemsResult result) { - if (!result.hasMoreStreams()) isComplete = true; - nextUrl = result.nextItemsUrl; - - append(extractChannelItems(result.nextItemsList)); - - fetchReactor.dispose(); - fetchReactor = null; - } - - @Override - public void onError(@NonNull Throwable e) { - Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e); - isComplete = true; - append(); // Notify change - } - }; - } - - @Override - public void dispose() { - super.dispose(); - if (fetchReactor != null) fetchReactor.dispose(); - } - - private static List extractChannelItems(final List infos) { - List result = new ArrayList<>(); - for (final InfoItem stream : infos) { - if (stream instanceof StreamInfoItem) { - result.add(new PlayQueueItem((StreamInfoItem) stream)); - } - } - return result; - } } diff --git a/app/src/main/java/org/schabi/newpipe/playlist/PlaylistPlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/PlaylistPlayQueue.java index 39ac6517d..30edcec7c 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/PlaylistPlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/PlaylistPlayQueue.java @@ -1,150 +1,45 @@ package org.schabi.newpipe.playlist; -import android.util.Log; - import org.schabi.newpipe.extractor.InfoItem; -import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; -import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.util.ExtractorHelper; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import io.reactivex.SingleObserver; import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.annotations.NonNull; -import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; -public final class PlaylistPlayQueue extends PlayQueue { - private final String TAG = "PlaylistPlayQueue@" + Integer.toHexString(hashCode()); - - private boolean isInitial; - private boolean isComplete; - - private int serviceId; - private String baseUrl; - private String nextUrl; - - private transient Disposable fetchReactor; - +public final class PlaylistPlayQueue extends AbstractInfoPlayQueue { public PlaylistPlayQueue(final PlaylistInfoItem item) { - this(item.service_id, item.url, item.url, Collections.emptyList(), 0); + super(item); } public PlaylistPlayQueue(final int serviceId, - final String url, - final String nextPageUrl, - final List streams, - final int index) { - super(index, extractPlaylistItems(streams)); - - this.baseUrl = url; - this.nextUrl = nextPageUrl; - this.serviceId = serviceId; - - this.isInitial = streams.isEmpty(); - this.isComplete = !isInitial && (nextPageUrl == null || nextPageUrl.isEmpty()); + final String url, + final String nextPageUrl, + final List streams, + final int index) { + super(serviceId, url, nextPageUrl, streams, index); } @Override - public boolean isComplete() { - return isComplete; + protected String getTag() { + return "PlaylistPlayQueue@" + Integer.toHexString(hashCode()); } @Override public void fetch() { - if (isInitial) { + if (this.isInitial) { ExtractorHelper.getPlaylistInfo(this.serviceId, this.baseUrl, false) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(getInitialPlaylistObserver()); + .subscribe(getHeadListObserver()); } else { ExtractorHelper.getMorePlaylistItems(this.serviceId, this.baseUrl, this.nextUrl) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(getPlaylistNextItemsObserver()); + .subscribe(getNextItemsObserver()); } } - - private SingleObserver getInitialPlaylistObserver() { - return new SingleObserver() { - @Override - public void onSubscribe(@NonNull Disposable d) { - if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { - d.dispose(); - } else { - fetchReactor = d; - } - } - - @Override - public void onSuccess(@NonNull PlaylistInfo result) { - if (!result.has_more_streams) isComplete = true; - nextUrl = result.next_streams_url; - - append(extractPlaylistItems(result.related_streams)); - - fetchReactor.dispose(); - fetchReactor = null; - } - - @Override - public void onError(@NonNull Throwable e) { - Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e); - isComplete = true; - append(); // Notify change - } - }; - } - - private SingleObserver getPlaylistNextItemsObserver() { - return new SingleObserver() { - @Override - public void onSubscribe(@NonNull Disposable d) { - if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { - d.dispose(); - } else { - fetchReactor = d; - } - } - - @Override - public void onSuccess(@NonNull ListExtractor.NextItemsResult result) { - if (!result.hasMoreStreams()) isComplete = true; - nextUrl = result.nextItemsUrl; - - append(extractPlaylistItems(result.nextItemsList)); - - fetchReactor.dispose(); - fetchReactor = null; - } - - @Override - public void onError(@NonNull Throwable e) { - Log.e(TAG, "Error fetching more playlist, marking playlist as complete.", e); - isComplete = true; - append(); // Notify change - } - }; - } - - @Override - public void dispose() { - super.dispose(); - if (fetchReactor != null) fetchReactor.dispose(); - } - - private static List extractPlaylistItems(final List infos) { - List result = new ArrayList<>(); - for (final InfoItem stream : infos) { - if (stream instanceof StreamInfoItem) { - result.add(new PlayQueueItem((StreamInfoItem) stream)); - } - } - return result; - } } diff --git a/app/src/main/res/layout/list_channel_item.xml b/app/src/main/res/layout/list_channel_item.xml index 90f88b26f..4fa74387e 100644 --- a/app/src/main/res/layout/list_channel_item.xml +++ b/app/src/main/res/layout/list_channel_item.xml @@ -31,13 +31,13 @@ android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" - android:layout_marginLeft="@dimen/video_item_search_image_right_margin" - android:layout_marginStart="@dimen/video_item_search_image_right_margin" + android:paddingLeft="@dimen/video_item_search_padding" + android:paddingStart="@dimen/video_item_search_padding" android:background="?attr/selectableItemBackground" android:src="?attr/more_vertical" android:visibility="gone" - tools:ignore="ContentDescription" - tools:visibility="visible" /> + tools:visibility="visible" + tools:ignore="ContentDescription,RtlSymmetry"/> + tools:ignore="ContentDescription,RtlSymmetry"/> + tools:ignore="ContentDescription,RtlSymmetry"/> + tools:ignore="ContentDescription,RtlSymmetry"/> + tools:ignore="ContentDescription,RtlSymmetry"/> Date: Fri, 3 Nov 2017 20:32:10 -0700 Subject: [PATCH 047/159] -Added scroll to fetch for external play queues. -Modified service player activity scrolling to be instantaneous when difference is too large. -Modified service player activity to no longer update metadata if nothing change when sync is called. --- .../newpipe/player/BackgroundPlayer.java | 1 + .../newpipe/player/MainVideoPlayer.java | 19 +++++++++- .../newpipe/player/PopupVideoPlayer.java | 1 + .../newpipe/player/ServicePlayerActivity.java | 36 ++++++++++++++++++- .../playlist/AbstractInfoPlayQueue.java | 8 ++--- 5 files changed, 59 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java index dfbb98b95..443da74d4 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java @@ -378,6 +378,7 @@ public final class BackgroundPlayer extends Service { @Override public void sync(@NonNull final PlayQueueItem item, @Nullable final StreamInfo info) { + if (currentItem == item && currentInfo == info) return; super.sync(item, info); resetNotification(); diff --git a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java index c275e55a7..b91a0814b 100644 --- a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java @@ -48,6 +48,7 @@ import com.google.android.exoplayer2.Player; import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.VideoStream; +import org.schabi.newpipe.fragments.OnScrollBelowItemsListener; import org.schabi.newpipe.player.helper.PlayerHelper; import org.schabi.newpipe.playlist.PlayQueueItem; import org.schabi.newpipe.playlist.PlayQueueItemBuilder; @@ -397,7 +398,7 @@ public final class MainVideoPlayer extends Activity { getControlsRoot().setVisibility(View.INVISIBLE); queueLayout.setVisibility(View.VISIBLE); - itemsList.smoothScrollToPosition(playQueue.getIndex()); + itemsList.scrollToPosition(playQueue.getIndex()); } private void onQueueClosed() { @@ -565,6 +566,9 @@ public final class MainVideoPlayer extends Activity { itemsList.setClickable(true); itemsList.setLongClickable(true); + itemsList.clearOnScrollListeners(); + itemsList.addOnScrollListener(getQueueScrollListener()); + itemTouchHelper = new ItemTouchHelper(getItemTouchCallback()); itemTouchHelper.attachToRecyclerView(itemsList); @@ -578,6 +582,19 @@ public final class MainVideoPlayer extends Activity { }); } + private OnScrollBelowItemsListener getQueueScrollListener() { + return new OnScrollBelowItemsListener() { + @Override + public void onScrolledDown(RecyclerView recyclerView) { + if (playQueue != null && !playQueue.isComplete()) { + playQueue.fetch(); + } else if (itemsList != null) { + itemsList.clearOnScrollListeners(); + } + } + }; + } + private ItemTouchHelper.SimpleCallback getItemTouchCallback() { return new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0) { @Override diff --git a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java index babbdbff5..48a435d37 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java @@ -573,6 +573,7 @@ public final class PopupVideoPlayer extends Service { @Override public void sync(@NonNull PlayQueueItem item, @Nullable StreamInfo info) { + if (currentItem == item && currentInfo == info) return; super.sync(item, info); updateMetadata(); } diff --git a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java index 4fe228dfc..98595b358 100644 --- a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java +++ b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java @@ -28,6 +28,7 @@ import com.google.android.exoplayer2.Player; import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.stream.StreamInfo; +import org.schabi.newpipe.fragments.OnScrollBelowItemsListener; import org.schabi.newpipe.player.event.PlayerEventListener; import org.schabi.newpipe.playlist.PlayQueueItem; import org.schabi.newpipe.playlist.PlayQueueItemBuilder; @@ -57,6 +58,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity private static final int PLAYBACK_SPEED_POPUP_MENU_GROUP_ID = 61; private static final int PLAYBACK_PITCH_POPUP_MENU_GROUP_ID = 97; + private static final int SMOOTH_SCROLL_MAXIMUM_DISTANCE = 80; + private View rootView; private RecyclerView itemsList; @@ -225,6 +228,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity itemsList.setAdapter(player.getPlayQueueAdapter()); itemsList.setClickable(true); itemsList.setLongClickable(true); + itemsList.clearOnScrollListeners(); + itemsList.addOnScrollListener(getQueueScrollListener()); itemTouchHelper = new ItemTouchHelper(getItemTouchCallback()); itemTouchHelper.attachToRecyclerView(itemsList); @@ -345,6 +350,19 @@ public abstract class ServicePlayerActivity extends AppCompatActivity // Component Helpers //////////////////////////////////////////////////////////////////////////// + private OnScrollBelowItemsListener getQueueScrollListener() { + return new OnScrollBelowItemsListener() { + @Override + public void onScrolledDown(RecyclerView recyclerView) { + if (player != null && player.getPlayQueue() != null && !player.getPlayQueue().isComplete()) { + player.getPlayQueue().fetch(); + } else if (itemsList != null) { + itemsList.clearOnScrollListeners(); + } + } + }; + } + private ItemTouchHelper.SimpleCallback getItemTouchCallback() { return new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0) { @Override @@ -401,7 +419,23 @@ public abstract class ServicePlayerActivity extends AppCompatActivity } private void scrollToSelected() { - itemsList.smoothScrollToPosition(player.getPlayQueue().getIndex()); + if (player == null) return; + + final int currentPlayingIndex = player.getPlayQueue().getIndex(); + final int currentVisibleIndex; + if (itemsList.getLayoutManager() instanceof LinearLayoutManager) { + final LinearLayoutManager layout = ((LinearLayoutManager) itemsList.getLayoutManager()); + currentVisibleIndex = layout.findFirstVisibleItemPosition(); + } else { + currentVisibleIndex = 0; + } + + final int distance = Math.abs(currentPlayingIndex - currentVisibleIndex); + if (distance < SMOOTH_SCROLL_MAXIMUM_DISTANCE) { + itemsList.smoothScrollToPosition(currentPlayingIndex); + } else { + itemsList.scrollToPosition(currentPlayingIndex); + } } //////////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/org/schabi/newpipe/playlist/AbstractInfoPlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/AbstractInfoPlayQueue.java index 74a4dc555..b35271b8f 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/AbstractInfoPlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/AbstractInfoPlayQueue.java @@ -30,10 +30,10 @@ abstract class AbstractInfoPlayQueue ext } AbstractInfoPlayQueue(final int serviceId, - final String url, - final String nextPageUrl, - final List streams, - final int index) { + final String url, + final String nextPageUrl, + final List streams, + final int index) { super(index, extractListItems(streams)); this.baseUrl = url; From b883f313bae6aa81491661654dc43814554938e8 Mon Sep 17 00:00:00 2001 From: John Zhen Mo Date: Sat, 4 Nov 2017 10:12:38 -0700 Subject: [PATCH 048/159] -Fixed NPE when popup is updated during shutdown. --- .../main/java/org/schabi/newpipe/player/PopupVideoPlayer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java index 48a435d37..a3fd0f7a7 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java @@ -362,6 +362,7 @@ public final class PopupVideoPlayer extends Service { } private void updatePopupSize(int width, int height) { + if (playerImpl == null) return; if (DEBUG) Log.d(TAG, "updatePopupSize() called with: width = [" + width + "], height = [" + height + "]"); width = (int) (width > maximumWidth ? maximumWidth : width < minimumWidth ? minimumWidth : width); From 7700cff5e51ea9d7b91e0d47ff80d9956e63da62 Mon Sep 17 00:00:00 2001 From: John Zhen Mo Date: Sat, 4 Nov 2017 11:30:01 -0700 Subject: [PATCH 049/159] -Added play buttons to channel fragment similar to playlist fragment. -Fixed abstract info play queue reloading the same initial page. -Fixed OOB on get item for abstract play queue. --- .../list/channel/ChannelFragment.java | 51 +++++ .../playlist/AbstractInfoPlayQueue.java | 7 +- .../newpipe/playlist/ChannelPlayQueue.java | 8 +- .../schabi/newpipe/playlist/PlayQueue.java | 2 +- .../newpipe/playlist/PlaylistPlayQueue.java | 8 +- app/src/main/res/layout/channel_header.xml | 192 ++++++++++++------ 6 files changed, 191 insertions(+), 77 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 64875b17f..908997a11 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 android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -10,6 +11,7 @@ import android.support.v4.content.ContextCompat; import android.support.v7.app.ActionBar; import android.text.TextUtils; import android.util.Log; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -19,6 +21,7 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; +import android.widget.Toast; import com.jakewharton.rxbinding2.view.RxView; @@ -30,10 +33,14 @@ import org.schabi.newpipe.extractor.channel.ChannelInfo; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.fragments.list.BaseListInfoFragment; import org.schabi.newpipe.fragments.subscription.SubscriptionService; +import org.schabi.newpipe.playlist.ChannelPlayQueue; +import org.schabi.newpipe.playlist.PlayQueue; import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.util.AnimationUtils; import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.Localization; +import org.schabi.newpipe.util.NavigationHelper; +import org.schabi.newpipe.util.PermissionHelper; import java.util.List; import java.util.concurrent.TimeUnit; @@ -69,6 +76,10 @@ public class ChannelFragment extends BaseListInfoFragment { private TextView headerSubscribersTextView; private Button headerSubscribeButton; + private Button headerPlayAllButton; + private Button headerPopupButton; + private Button headerBackgroundButton; + private MenuItem menuRssButton; public static ChannelFragment getInstance(int serviceId, String url, String name) { @@ -125,6 +136,10 @@ public class ChannelFragment extends BaseListInfoFragment { headerSubscribersTextView = headerRootLayout.findViewById(R.id.channel_subscriber_view); headerSubscribeButton = headerRootLayout.findViewById(R.id.channel_subscribe_button); + headerPlayAllButton = headerRootLayout.findViewById(R.id.playlist_play_all_button); + headerPopupButton = headerRootLayout.findViewById(R.id.playlist_play_popup_button); + headerBackgroundButton = headerRootLayout.findViewById(R.id.playlist_play_bg_button); + return headerRootLayout; } @@ -391,6 +406,42 @@ public class ChannelFragment extends BaseListInfoFragment { if (subscribeButtonMonitor != null) subscribeButtonMonitor.dispose(); updateSubscription(result); monitorSubscription(result); + + headerPlayAllButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + NavigationHelper.playOnMainPlayer(activity, getPlayQueue()); + } + }); + headerPopupButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PermissionHelper.checkSystemAlertWindowPermission(activity)) { + Toast toast = Toast.makeText(activity, R.string.msg_popup_permission, Toast.LENGTH_LONG); + TextView messageView = toast.getView().findViewById(android.R.id.message); + if (messageView != null) messageView.setGravity(Gravity.CENTER); + toast.show(); + return; + } + NavigationHelper.playOnPopupPlayer(activity, getPlayQueue()); + } + }); + headerBackgroundButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue()); + } + }); + } + + private PlayQueue getPlayQueue() { + return new ChannelPlayQueue( + currentInfo.service_id, + currentInfo.url, + currentInfo.next_streams_url, + infoListAdapter.getItemsList(), + 0 + ); } @Override diff --git a/app/src/main/java/org/schabi/newpipe/playlist/AbstractInfoPlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/AbstractInfoPlayQueue.java index b35271b8f..74a68b880 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/AbstractInfoPlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/AbstractInfoPlayQueue.java @@ -26,7 +26,7 @@ abstract class AbstractInfoPlayQueue ext transient Disposable fetchReactor; AbstractInfoPlayQueue(final U item) { - this(item.service_id, item.url, item.url, Collections.emptyList(), 0); + this(item.service_id, item.url, null, Collections.emptyList(), 0); } AbstractInfoPlayQueue(final int serviceId, @@ -55,7 +55,7 @@ abstract class AbstractInfoPlayQueue ext return new SingleObserver() { @Override public void onSubscribe(@NonNull Disposable d) { - if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { + if (isComplete || !isInitial || (fetchReactor != null && !fetchReactor.isDisposed())) { d.dispose(); } else { fetchReactor = d; @@ -64,6 +64,7 @@ abstract class AbstractInfoPlayQueue ext @Override public void onSuccess(@NonNull T result) { + isInitial = false; if (!result.has_more_streams) isComplete = true; nextUrl = result.next_streams_url; @@ -86,7 +87,7 @@ abstract class AbstractInfoPlayQueue ext return new SingleObserver() { @Override public void onSubscribe(@NonNull Disposable d) { - if (isComplete || (fetchReactor != null && !fetchReactor.isDisposed())) { + if (isComplete || isInitial || (fetchReactor != null && !fetchReactor.isDisposed())) { d.dispose(); } else { fetchReactor = d; diff --git a/app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java index 239024f28..3c615608c 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/ChannelPlayQueue.java @@ -16,10 +16,10 @@ public final class ChannelPlayQueue extends AbstractInfoPlayQueue streams, - final int index) { + final String url, + final String nextPageUrl, + final List streams, + final int index) { super(serviceId, url, nextPageUrl, streams, index); } diff --git a/app/src/main/java/org/schabi/newpipe/playlist/PlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/PlayQueue.java index 4d73e1cfd..b86450b10 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/PlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/PlayQueue.java @@ -123,7 +123,7 @@ public abstract class PlayQueue implements Serializable { * May throw {@link IndexOutOfBoundsException}. * */ public PlayQueueItem getItem(int index) { - if (index >= streams.size() || streams.get(index) == null) return null; + if (index < 0 || index >= streams.size() || streams.get(index) == null) return null; return streams.get(index); } diff --git a/app/src/main/java/org/schabi/newpipe/playlist/PlaylistPlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/PlaylistPlayQueue.java index 30edcec7c..64d263346 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/PlaylistPlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/PlaylistPlayQueue.java @@ -16,10 +16,10 @@ public final class PlaylistPlayQueue extends AbstractInfoPlayQueue streams, - final int index) { + final String url, + final String nextPageUrl, + final List streams, + final int index) { super(serviceId, url, nextPageUrl, streams, index); } diff --git a/app/src/main/res/layout/channel_header.xml b/app/src/main/res/layout/channel_header.xml index a817f7f79..7f08e5932 100644 --- a/app/src/main/res/layout/channel_header.xml +++ b/app/src/main/res/layout/channel_header.xml @@ -5,76 +5,138 @@ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/channel_header_layout" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginBottom="12dp"> + android:layout_height="wrap_content"> - + android:layout_height="wrap_content"> - + - + + + + + + + + + - - - - + android:layout_marginEnd="2dp" + android:layout_below="@+id/channel_metadata"> + +