diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 361c8057f..6664ed276 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -5,10 +5,9 @@ labels: enhancement assignees: '' --- - + - - + ### Checklist @@ -17,30 +16,9 @@ assignees: '' - [ ] I have read the contribution guidelines given at https://github.com/TeamNewPipe/NewPipe/blob/HEAD/.github/CONTRIBUTING.md. - [ ] This issue contains only one feature request. I will open one issue for every feature I want to request. - -#### Describe the feature you want - +#### What feature do you want? + - -#### Is your feature request related to a problem? Please describe it - - - - -#### Additional context - - - - -#### How will you/everyone benefit from this feature? - - +#### Why do you want this feature? + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a876df8fd..b87219f4f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,10 +33,10 @@ jobs: if: github.event_name == 'pull_request' run: git checkout -B ${{ github.head_ref }} - - name: set up JDK 8 + - name: set up JDK 11 uses: actions/setup-java@v2 with: - java-version: 8 + java-version: 11 distribution: "temurin" cache: 'gradle' @@ -59,10 +59,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: set up JDK 8 + - name: set up JDK 11 uses: actions/setup-java@v2 with: - java-version: 8 + java-version: 11 distribution: "temurin" cache: 'gradle' diff --git a/README.es.md b/README.es.md index 3920545d5..4408f170a 100644 --- a/README.es.md +++ b/README.es.md @@ -1,30 +1,30 @@

NewPipe

-

Una interfaz de streaming lijera y libre para Android.

+

Una interfaz de streaming ligera y libre para Android.

-

+

- - - - - - + + + + + +


-

Capturas de pantallaDescripciónCaracterísticasInstallación y actualizacionesContribuciónDonarLicencias

-

Sitio webBlogPreguntas FrecuentesPrensa

+

Capturas de PantallaDescripciónCaracterísticasInstalación y ActualizacionesContribuciónDonarLicencia

+

Sitio WebBlogPreguntas FrecuentesPrensa


*Lea esto en otros idiomas: [English](README.md), [한국어](README.ko.md), [Soomaali](README.so.md), [Português Brasil](README.pt_BR.md), [日本語](README.ja.md), [Română](README.ro.md), [Türkçe](README.tr.md).* -AVISO: ESTA ES UNA VERSIÓN BETA, POR LO TANTO, PUEDE ENCONTRAR BUGS (ERRORES). SI ENCUENTRA UNO, ABRA UN ISSUE A TRAVÉS DE NUESTRO REPOSITORIO GITHUB. +AVISO: ESTA ES UNA VERSIÓN BETA, POR LO TANTO, PUEDE ENCONTRAR BUGS. SI ENCUENTRA UNO ABRA UN ISSUE A TRAVÉS DE NUESTRO REPOSITORIO DE GITHUB. -COLOCAR NEWPIPE O CUALQUIER FORK (BIFURCACIÓN) REALIZADO DE ELLO EN GOOGLE PLAY STORE VIOLA SUS TÉRMINOS Y CONDICIONES. +COLOCAR NEWPIPE O CUALQUIER FORK DE NEWPIPE EN LA GOOGLE PLAY STORE VIOLARÁ SUS TÉRMINOS Y CONDICIONES. -## Capturas de pantalla +## Capturas de Pantalla [](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) [](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) @@ -40,39 +40,43 @@ [](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) ## Descripción -NewPipe no usa ninguna librería de framework de Google, ni la API de YouTube. Los sitios web solamente se analizan para extraer la información requerida, asi que esta app se puede usar sin los servicios de Google instalados. Además, no se necesita una cuenta de YouTube para usar NewPipe, lo cual es un software libre de copyleft. + +NewPipe no usa ninguna librería del framework de Google, ni la API de YouTube. Los sitios web solamente se analizan para extraer la información requerida, por lo que esta app se puede usar sin los servicios de Google instalados. Además, no se necesita una cuenta de YouTube para usar NewPipe, lo cual es un software libre de copyleft. ### Características + * Buscar videos +* No requiere inicio de sesión * Mostrar información general sobre videos * Mirar videos de YouTube -* Escuchar audio de YouTube -* Modo popup (reproductor flotante) -* Elegir reproductor para mirar el video +* Modo de solo audio en videos de YouTube +* Modo pop-up (reproductor flotante) +* Elegir un reproductor de video externo para mirar videos * Descargar videos -* Descargar solamente audio -* Abrir video en Kodi +* Descargar solo audio +* Abrir videos en Kodi * Mostrar videos próximos/relacionados * Buscar a través de YouTube en un idioma específico -* Mirar/Bloquear materiales restringidas por edad. +* Mirar/Bloquear videos restringidos por edad * Mostrar información general sobre canales -* Buscar canales +* Buscar de canales * Mirar videos de un canal -* Apoyo Orbot/Tor (todavía no directamente) -* Apoyo 1080p/2K/4K -* Ver historias -* Subscribirse a canales -* Buscar historias -* Buscar/mirar listas de reproducción -* Mirar listas de reproducción en fila -* Poner videos en fila -* Listas locales de reproducción +* Soporte Orbot/Tor (todavía no directamente) +* Soporte para videos en 1080p/2K/4K +* Historial de videos vistos +* Suscripción a canales +* Historial de búsquedas +* Buscar/Mirar listas de reproducción +* Mirar listas de reproducción en cola +* Poner videos en cola +* Listas de reproducción locales * Subtítulos -* Apoyo de medios en directo +* Soporte para transmisiones en vivo * Mostrar comentarios -### Servicios apoyados -NewPipe apoya varios servicios. Nuestras [documentaciones](https://teamnewpipe.github.io/documentation/) proveen más información en como se puede agregar un servicio nuevo a la app y el extractor. Por favor contáctenos si pretende agregar uno nuevo. Actualmente los servicios apoyados son: +### Servicios Soportados + +NewPipe soporta varios servicios. Nuestras [documentaciones](https://teamnewpipe.github.io/documentation/) ofrecen más información sobre cómo se puede agregar un servicio nuevo a la app y al extractor. Por favor ponte en contacto con nosotros si tienes pensado agregar uno nuevo. Actualmente los servicios soportados son: * YouTube * SoundCloud \[beta\] @@ -80,61 +84,60 @@ NewPipe apoya varios servicios. Nuestras [documentaciones](https://teamnewpipe.g * PeerTube instances \[beta\] * Bandcamp \[beta\] - - +## Instalación y Actualizaciones -## Installación y actualizaciones Se puede instalar NewPipe usando uno de los métodos siguientes: - 1. Agregar nuestro repositorio personalizado a F-Droid e instalarlo desde allí. Las instrucciones están aquí: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/ - 2. Descargar el archivo APK del enlace [Github Releases](https://github.com/TeamNewPipe/NewPipe/releases) e instalarlo. - 3. Actualizar a través de F-Droid. Este es el método más lento para obtener la actualización, como F-Droid debe reconocer cambios, construir el APK aparte, firmarlo con una clave, y finalmente empujar la actualización a los usuarios. - 4. Construir un APK de depuración por si mismo. Este es el modo más rápido para realizar nuevas características en su dispositivo, pero es mucho más complicado, asi que recomendamos uno de los otros métodos. -Recomendamos el método 1 para la mayoría de usuarios. Los APKs instalados usando método 1 o 2 son compatibles el uno con el otro, pero no con las instalaciones usando método 3. Esta es debida a la misma clave digital (la nuestra), siendo utilizado en los métodos 1 y 2, pero una clave digital diferente (la de F-Droid) siendo utilizado en el método 3. Construir un APK de depuración usando método 4 excluye una clave enteramente. Firmando con claves digitales ayuda a asegurar de que un -usuario no esté engañado para instalar una actualización maliciosa a una app. + 1. Agregando nuestro repositorio personalizado a F-Droid e instalarlo desde allí. Las instrucciones están [aquí](https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/). + 2. Descargando el archivo APK de [aquí](https://github.com/TeamNewPipe/NewPipe/releases) y posteriormente instalarlo. + 3. Usando el repositorio oficial de F-Droid. Este es el método más lento para obtener actualizaciones, ya que F-Droid debe reconocer los cambios, construir el APK aparte, firmarlo con una clave, y finalmente publicar la actualización. + 4. Construyendo la app usted mismo. Este es el modo más rápido para obtener nuevas características en su dispositivo, pero es mucho más complicado, así que recomendamos uno de los otros métodos. -Mientras tanto, si quiere cambiar los fuentes por alguna razón (por ejemplo, la funcionalidad del nucleo de NewPipe se rompe y F-Droid aun no tiene la actualización), recomendamos el siguiente procedimiento: -1. Repaldear sus datos a través de Ajustes > Contenido > Exporta base de datos para guardar su historia, subscripciones, y listas de reproducción -2. Desinstalar NewPipe -3. Descargar el APK del nuevo fuente e instalarlo. -4. Importar los datos del paso 1 a través de Ajustes > Contenido > Importa base de datos. +Recomendamos el método 1 para la mayoría de usuarios. Los APKs instalados usando método 1 y 2 son compatibles entre sí, pero no lo son con los instalados usando el método 3. Esto es debido a la clave de firmado, ya que los métodos 1 y 2 usan la misma clave (la nuestra), pero el método 3 usa una clave diferente (la de F-Droid). El método 4 excluye totalmente una clave de firmado. Las claves de firmado aseguran que el usuario no esté siendo engañado para instalar/actualizar una APK maliciosa. + +Además, si quiere cambiar el método de instalación por alguna razón (por ejemplo: la funcionalidad del núcleo de NewPipe se rompe o F-Droid aún no publica la actualización), recomendamos el siguiente procedimiento: +1. Respalde su información a través de Ajustes > Contenido > Exportar base de datos; esto guardará su historial (videos vistos y búsquedas), suscripciones, listas de reproducción y ajustes. +2. Desinstale NewPipe. +3. Descargue el APK con un método distinto e instálelo. +4. Importe la información (la base de datos extraída del paso 1) a través de Ajustes > Contenido > Importar base de datos. Tenga en cuenta que esta opción superpondrá su historial actual (tanto de vídeos como de búsquedas), sus listas de reproducción y (opcionalmente) sus configuraciones. ## Contribución -Si tiene ideas, traducciónes, cambios de diseño, limpieza de código, o cambios grandes de código, su ayuda es siempre bienvenida. -Cuanto más realizamos, mejor se pone la aplicación! + +Si tiene ideas, traducciones, cambios de diseño, limpieza de código o cambios grandes de código, su ayuda es siempre bienvenida. ¡Cuanto más hagamos, NewPipe será mucho mejor! Si quiere involucrarse, fíjese en nuestras [notas de contribución](.github/CONTRIBUTING.md). -Estado de la traducción +Estado de la Traducción ## Donar -Si le gusta el NewPipe estaremos felices con una donación. O puede enviar bitcoin o donar a través de Bountysource o Liberapay. Para obtener más información sobre como donar a NewPipe, por favor visita nuestro [sitio web](https://newpipe.net/donate). +Si te gusta NewPipe, estaremos felices con una donación. Puede enviar bitcoin o donar a través de Bountysource o Liberapay. Visita nuestro [sitio web](https://newpipe.net/donate) para más información. - + - - + + - - + +
BitcoinBitcoin QR codeCódigo QR del Bitcoin 16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
LiberapayVisit NewPipe at liberapay.comDonate via LiberapayVisita NewPipe en liberapay.comDona vía Liberapay
BountysourceVisit NewPipe at bountysource.comCheck out how many bounties you can earn.Visita NewPipe en bountysource.comRevisa cuántas recompensas puedes obtener.
-## Política de privacidad -El proyecto NewPipe tiene como objetivo proveer una experience privada y anónima para usar servicios de medios web. -Por lo tanto, la app no colecciona ningunos datos sin su consentimiento. La politica de privacidad de NewPipe explica en detalle los datos enviados y almacenados cuando envia un informe de error, o comentario en nuestro blog. Puede encontrar el documento [aqui](https://newpipe.net/legal/privacy/). +## Política de Privacidad + +El proyecto NewPipe tiene como objetivo ofrecer una experience privada y anónima al usar servicios web multimedia. Por lo tanto, la app no recoleta ningún tipo de información sin su consentimiento. La politica de privacidad de NewPipe explica en detalle qué información es enviada y almacenada cuando envía un informe de error o comenta en [nuestro blog](https://newpipe.net/blog/). Puede encontrar el documento [aquí](https://newpipe.net/legal/privacy/). ## Licencia -[![GNU GPLv3 Image](https://www.gnu.org/graphics/gplv3-127x51.png)](https://www.gnu.org/licenses/gpl-3.0.en.html) -NewPipe es Software Libre: Puede usar, estudiar, compartir, y mejorarlo a su voluntad. Especificamente puede redistribuir y/o modificarlo bajo los términos de la [GNU General Public License](https://www.gnu.org/licenses/gpl.html) como publicado por la Free Software Foundation, o versión 3 de la licencia, o (en su opción) cualquier versión posterior. +[![GNU GPLv3 Image](https://www.gnu.org/graphics/gplv3-127x51.png)](https://www.gnu.org/licenses/gpl-3.0.html) + +NewPipe es Software Libre: Puede usarlo, estudiarlo, compartirlo y mejorarlo a su voluntad. Más específicamente, puede redistribuirlo y/o modificarlo bajo los términos de la [GNU General Public License](https://www.gnu.org/licenses/gpl.html) publicada por la Free Software Foundation tanto si usa la versión 3 o posterior de la licencia. diff --git a/README.ko.md b/README.ko.md index 269cfda49..8cddaafe9 100644 --- a/README.ko.md +++ b/README.ko.md @@ -89,7 +89,7 @@ NewPipe 코드의 변경이 있을 때(기능 추가 또는 버그 수정으로 따라서 우리는 다른 방법들 중 하나를 사용하는 것을 추천합니다. 2. 우리의 커스텀 저장소를 F-Droid에 추가하고 우리가 릴리즈를 게시하는 대로 저곳에서 릴리즈를 설치할 수 있습니다. 이에 대한 설명서는 이곳에서 확인할 수 있습니다: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/ - 3. 우리가 릴리즈를 게시하는 대로 [Github Releases](https://github.com/TeamNewPipe/NewPipe/releases)에서 APK를 다운받고 이것을 설치할 수 있습니다. + 3. 우리가 릴리즈를 게시하는 대로 [GitHub Releases](https://github.com/TeamNewPipe/NewPipe/releases)에서 APK를 다운받고 이것을 설치할 수 있습니다. 4. F-Droid를 통해 업데이트 할 수 있습니다. F-Droid는 변화를 인식하고, 스스로 APK를 생성하고, 이것에 서명하고, 사용자들에서 업데이트를 전달해야만 하기 때문에, 이것은 업데이트를 받는 가장 느린 방법입니다. diff --git a/README.md b/README.md index 93c70a532..845b47d33 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ NewPipe supports multiple services. Our [docs](https://teamnewpipe.github.io/doc ## Installation and updates You can install NewPipe using one of the following methods: 1. Add our custom repo to F-Droid and install it from there. The instructions are here: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/ - 2. Download the APK from [Github Releases](https://github.com/TeamNewPipe/NewPipe/releases) and install it. + 2. Download the APK from [GitHub Releases](https://github.com/TeamNewPipe/NewPipe/releases) and install it. 3. Update via F-Droid. This is the slowest method of getting updates, as F-Droid must recognize changes, build the APK itself, sign it, then push the update to users. 4. Build a debug APK yourself. This is the fastest way to get new features on your device, but is much more complicated, so we recommend using one of the other methods. diff --git a/README.pt_BR.md b/README.pt_BR.md index 5cdd8ae13..10907cbd4 100644 --- a/README.pt_BR.md +++ b/README.pt_BR.md @@ -87,7 +87,7 @@ O NewPipe suporta vários serviços. Nosso [documentação](https://teamnewpipe. Quando uma alteração no código NewPipe (devido à adição de recursos ou fixação de bugs), eventualmente ocorrerá uma versão. Estes estão no formato x.xx.x . A fim de obter esta nova versão, você pode: 1. Construa um APK de depuração você mesmo. Esta é a maneira mais rápida de obter novos recursos em seu dispositivo, mas é muito mais complicado, por isso recomendamos usar um dos outros métodos. 2. Adicione nosso repo personalizado ao F-Droid e instale-o a partir daí assim que publicarmos um lançamento. As instruções estão aqui.: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/ - 3. Baixe o APK do [Github Releases](https://github.com/TeamNewPipe/NewPipe/releases) e instalá-lo assim que publicarmos um lançamento. + 3. Baixe o APK do [GitHub Releases](https://github.com/TeamNewPipe/NewPipe/releases) e instalá-lo assim que publicarmos um lançamento. 4. Atualização via F-droid. Este é o método mais lento para obter atualizações, pois o F-Droid deve reconhecer alterações, construir o próprio APK, assiná-lo e, em seguida, enviar a atualização para os usuários. Recomendamos o método 2 para a maioria dos usuários. Os APKs instalados usando o método 2 ou 3 são compatíveis entre si, mas não com aqueles instalados usando o método 4. Isso se deve à mesma chave de assinatura (nossa) sendo usada para 2 e 3, mas uma chave de assinatura diferente (F-Droid's) está sendo usada para 4. Construir um APK depuração usando o método 1 exclui totalmente uma chave. Assinar chaves ajudam a garantir que um usuário não seja enganado para instalar uma atualização maliciosa em um aplicativo. diff --git a/README.ro.md b/README.ro.md index a53019c9c..8edae325a 100644 --- a/README.ro.md +++ b/README.ro.md @@ -89,7 +89,7 @@ NewPipe suportă servicii multiple. [Documentele](https://teamnewpipe.github.io/ ## Instalare şi actualizări Puteţi instala NewPipe folosind una dintre următoarele metode: 1. Adăugaţi depozitul nostru F-droid personalizat. Instrucţiunile sunt aici: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/ - 2. Descărcaţi APK-ul din [Github Releases](https://github.com/TeamNewPipe/NewPipe/releases) şi instalaţi-l. + 2. Descărcaţi APK-ul din [GitHub Releases](https://github.com/TeamNewPipe/NewPipe/releases) şi instalaţi-l. 3. Actualizaţi via F-Droid. Aceasta este cea mai lentă metodă de a obţine actualizări, deoarece F-Droid trebuie să recunoască schimbările, să constriască APK-ul, să îl semneze, iar apoi să îl trimită utilizatorilor. 4. Construiţi un APK de depanare. Aceasta este cea mai rapidă metodă de a primi funcţii noi, dar este mult mai complicată, aşa că vă recomandăm să folosiţi una dintre celelalte metode. diff --git a/README.so.md b/README.so.md index ed42fde0d..3282f59c9 100644 --- a/README.so.md +++ b/README.so.md @@ -86,7 +86,7 @@ NewPipe wuxuu taageeraa adeegyo badan. [warqadan](https://teamnewpipe.github.io/ Marka koodhka NewPipe isbadal ku dhaco (wax cusub oo lagusoo kordhiyay ama cilad bixin), ugu dambayn waxaa lasii daayaa mid cusub (Siidayn). Siidaynta qaabkeedu waa x.xx.x . Si aad midka cusub u hesho, waxaad samayn kartaa: 1. Inaad mid cusub (APK) adigu dhisato. Tani waa mida ugu dagdag badan eed waxyaabaha cusub ku heli karto, laakiin way adagtahay, sidaa darteed waxaan soojeedinaynaa inaad isticmaasho qababka kale. 2. Ku dar qayb gaar ah xaganaga F-Droid oo xagaas kaga shub isla markay siidayn soobaxdo. Hagitaanka xagan ka eeg: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/ - 3. Kasoo dajiso APK-ga xaga [Siidaynta Github](https://github.com/TeamNewPipe/NewPipe/releases) oo ku shubo isla markay siidayn soobaxdo. + 3. Kasoo dajiso APK-ga xaga [Siidaynta GitHub](https://github.com/TeamNewPipe/NewPipe/releases) oo ku shubo isla markay siidayn soobaxdo. 4. Ka cusboonaysii xaga F-Droid. Tani waa mida ugu daahitaanka badan, sababtoo ah F-Droid waxay fiirin isbadalka waxayna iyadu dhisi mid (app), sixiixi, kadibna ay cusboonaysiinta usiidayn isticmaalayaasha. Waxaan usoojeedinaynaa isticmaaalka qaabka 2 dadka badankood. APK-yada loogu shubo qaabka 2 ama 3 way isqaadan karaan, laakiin isma qaadan karaan kuwa loogu shubay qaabka 4. Sababtuna waxaa weeye furaha sixiixa oo iskumid ah (kaanaga weeye) oo loo isticmaalay 2 iyo 3, laakiin furo sixiixeed ka duwan (midka F-Droid) oo loo isticmaalay 4. Dhisida APK ayadoo la isticmaalayo qaabka 1 waxay gabi ahaanba ka reebtaa wax fure ah. Furayaasha sixiixa waxay xaqiijiyaan in isticmaalaha aan lagu khaldin inuu ku shubto cusboonaysiin khalad ah (wax lasoo dhexraaciyay) app-ka. diff --git a/README.tr.md b/README.tr.md index 0bd644934..70f9fe672 100644 --- a/README.tr.md +++ b/README.tr.md @@ -23,7 +23,7 @@ GOOGLE PLAY STORE'A NEWPIPE VEYA BAŞKA BİR KOPYASINI KOYMAK, PLAY STORE ŞARTLARINI VE KOŞULLARINI İHLAL EDER. -## Ekran fotoğrafları +## Ekran görüntüleri [](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_01.png) [](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_02.png) @@ -88,7 +88,7 @@ NewPipe birden fazla hizmeti destekler. Uygulamaya ve ayıklayıcıya yeni bir h ## Kurulum ve güncellemeler Aşağıdaki yöntemlerden birini kullanarak NewPipe'ı kurabilirsiniz: 1. Özel depomuzu F-Droid'e ekleyin ve oradan yükleyin. Kılavuzu şurada bulabilirsiniz: https://newpipe.net/FAQ/tutorials/install-add-fdroid-repo/ - 2. APK'yı [Github sürümlerinden](https://github.com/TeamNewPipe/NewPipe/releases) indirin ve kurun. + 2. APK'yı [GitHub sürümlerinden](https://github.com/TeamNewPipe/NewPipe/releases) indirin ve kurun. 3. F-Droid ile güncelleyin. Bu, güncellemeleri almanın en yavaş yöntemidir, çünkü F-Droid değişiklikleri tanımalı, APK'yı kendisi oluşturmalı, imzalamalı ve ardından güncellemeyi kullanıcılara dağıtmalıdır. 4. Kendiniz bir APK derleyin. Bu yöntem, cihazınızda yeni özellikler edinmenin en hızlı yoludur, ancak çok daha karmaşıktır, bu nedenle diğer yöntemlerden birini kullanmanızı öneririz. diff --git a/app/build.gradle b/app/build.gradle index 9bdb4e71e..25493490a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,8 +17,8 @@ android { resValue "string", "app_name", "NewPipe" minSdkVersion 19 targetSdkVersion 29 - versionCode 976 - versionName "0.21.10" + versionCode 977 + versionName "0.21.11" multiDexEnabled true @@ -54,6 +54,11 @@ android { // debug build. This seems to be a Gradle bug, therefore // TODO: update Gradle version release { + if (System.properties.containsKey('packageSuffix')) { + applicationIdSuffix System.getProperty('packageSuffix') + resValue "string", "app_name", "NewPipe " + System.getProperty('packageSuffix') + archivesBaseName = 'NewPipe_' + System.getProperty('packageSuffix') + } minifyEnabled true shrinkResources false // disabled to fix F-Droid's reproducible build proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' @@ -102,7 +107,7 @@ ext { icepickVersion = '3.2.0' exoPlayerVersion = '2.12.3' googleAutoServiceVersion = '1.0' - groupieVersion = '2.8.1' + groupieVersion = '2.9.0' markwonVersion = '4.6.2' leakCanaryVersion = '2.5' @@ -184,7 +189,7 @@ dependencies { // name and the commit hash with the commit hash of the (pushed) commit you want to test // This works thanks to JitPack: https://jitpack.io/ implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751' - implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.21.10' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.21.11' /** Checkstyle **/ checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}" diff --git a/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt b/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt index 24563d1c1..0a00b0443 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt +++ b/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt @@ -43,10 +43,11 @@ class LocalPlaylistManagerTest { @Test fun createPlaylist() { + val NEWPIPE_URL = "https://newpipe.net/" val stream = StreamEntity( - serviceId = 1, url = "https://newpipe.net/", title = "title", + serviceId = 1, url = NEWPIPE_URL, title = "title", streamType = StreamType.VIDEO_STREAM, duration = 1, uploader = "uploader", - uploaderUrl = "https://newpipe.net/" + uploaderUrl = NEWPIPE_URL ) val result = manager.createPlaylist("name", listOf(stream)) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 75479345d..d92d0b5bf 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -146,6 +146,7 @@ + @@ -224,6 +225,7 @@ + @@ -309,6 +311,7 @@ + @@ -358,6 +361,9 @@ + diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java index 766ebe834..35b0b2674 100644 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ b/app/src/main/java/org/schabi/newpipe/App.java @@ -5,7 +5,6 @@ import android.content.SharedPreferences; import android.util.Log; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.core.app.NotificationChannelCompat; import androidx.core.app.NotificationManagerCompat; import androidx.multidex.MultiDexApplication; @@ -37,7 +36,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.exceptions.CompositeException; import io.reactivex.rxjava3.exceptions.MissingBackpressureException; import io.reactivex.rxjava3.exceptions.OnErrorNotImplementedException; @@ -45,6 +43,8 @@ import io.reactivex.rxjava3.exceptions.UndeliverableException; import io.reactivex.rxjava3.functions.Consumer; import io.reactivex.rxjava3.plugins.RxJavaPlugins; +import static org.schabi.newpipe.CheckForNewAppVersion.startNewVersionCheckService; + /* * Copyright (C) Hans-Christoph Steiner 2016 * App.java is part of NewPipe. @@ -68,9 +68,6 @@ public class App extends MultiDexApplication { private static final String TAG = App.class.toString(); private static App app; - @Nullable - private Disposable disposable = null; - @NonNull public static App getApp() { return app; @@ -118,14 +115,11 @@ public class App extends MultiDexApplication { configureRxJavaErrorHandler(); // Check for new version - disposable = CheckForNewAppVersion.checkNewVersion(this); + startNewVersionCheckService(); } @Override public void onTerminate() { - if (disposable != null) { - disposable.dispose(); - } super.onTerminate(); PicassoHelper.terminate(); } diff --git a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java index c8fa02186..64874cd93 100644 --- a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java +++ b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java @@ -1,6 +1,7 @@ package org.schabi.newpipe; import android.app.Application; +import android.app.IntentService; import android.app.PendingIntent; import android.content.Intent; import android.content.SharedPreferences; @@ -25,8 +26,11 @@ import com.grack.nanojson.JsonParserException; import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.UserAction; +import org.schabi.newpipe.extractor.downloader.Response; +import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -36,13 +40,10 @@ import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.List; -import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; -import io.reactivex.rxjava3.core.Maybe; -import io.reactivex.rxjava3.disposables.Disposable; -import io.reactivex.rxjava3.schedulers.Schedulers; - -public final class CheckForNewAppVersion { - private CheckForNewAppVersion() { } +public final class CheckForNewAppVersion extends IntentService { + public CheckForNewAppVersion() { + super("CheckForNewAppVersion"); + } private static final boolean DEBUG = MainActivity.DEBUG; private static final String TAG = CheckForNewAppVersion.class.getSimpleName(); @@ -168,78 +169,87 @@ public final class CheckForNewAppVersion { return getCertificateSHA1Fingerprint(app).equals(GITHUB_APK_SHA1); } - @Nullable - public static Disposable checkNewVersion(@NonNull final App app) { + private void checkNewVersion() throws IOException, ReCaptchaException { + final App app = App.getApp(); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app); final NewVersionManager manager = new NewVersionManager(); // Check if user has enabled/disabled update checking // and if the current apk is a github one or not. if (!prefs.getBoolean(app.getString(R.string.update_app_key), true) || !isGithubApk(app)) { - return null; + return; } // Check if the last request has happened a certain time ago // to reduce the number of API requests. final long expiry = prefs.getLong(app.getString(R.string.update_expiry_key), 0); if (!manager.isExpired(expiry)) { - return null; + return; } - return Maybe - .fromCallable(() -> { - if (!isConnected(app)) { - return null; - } + // Make a network request to get latest NewPipe data. + final Response response = DownloaderImpl.getInstance().get(NEWPIPE_API_URL); + handleResponse(response, manager, prefs, app); + } - // Make a network request to get latest NewPipe data. - return DownloaderImpl.getInstance().get(NEWPIPE_API_URL); - }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe( - response -> { - try { - // Store a timestamp which needs to be exceeded, - // before a new request to the API is made. - final long newExpiry = manager - .coerceExpiry(response.getHeader("expires")); - prefs.edit() - .putLong(app.getString(R.string.update_expiry_key), newExpiry) - .apply(); - } catch (final Exception e) { - if (DEBUG) { - Log.w(TAG, "Could not extract and save new expiry date", e); - } - } + private void handleResponse(@NonNull final Response response, + @NonNull final NewVersionManager manager, + @NonNull final SharedPreferences prefs, + @NonNull final App app) { + try { + // Store a timestamp which needs to be exceeded, + // before a new request to the API is made. + final long newExpiry = manager + .coerceExpiry(response.getHeader("expires")); + prefs.edit() + .putLong(app.getString(R.string.update_expiry_key), newExpiry) + .apply(); + } catch (final Exception e) { + if (DEBUG) { + Log.w(TAG, "Could not extract and save new expiry date", e); + } + } - // Parse the json from the response. - try { - final JsonObject githubStableObject = JsonParser.object() - .from(response.responseBody()).getObject("flavors") - .getObject("github").getObject("stable"); + // Parse the json from the response. + try { + final JsonObject githubStableObject = JsonParser.object() + .from(response.responseBody()).getObject("flavors") + .getObject("github").getObject("stable"); - final String versionName = githubStableObject - .getString("version"); - final int versionCode = githubStableObject - .getInt("version_code"); - final String apkLocationUrl = githubStableObject - .getString("apk"); + final String versionName = githubStableObject + .getString("version"); + final int versionCode = githubStableObject + .getInt("version_code"); + final String apkLocationUrl = githubStableObject + .getString("apk"); + + compareAppVersionAndShowNotification(app, versionName, + apkLocationUrl, versionCode); + } catch (final JsonParserException e) { + // Most likely something is wrong in data received from NEWPIPE_API_URL. + // Do not alarm user and fail silently. + if (DEBUG) { + Log.w(TAG, "Could not get NewPipe API: invalid json", e); + } + } + } + + public static void startNewVersionCheckService() { + final Intent intent = new Intent(App.getApp().getApplicationContext(), + CheckForNewAppVersion.class); + App.getApp().startService(intent); + } + + @Override + protected void onHandleIntent(@Nullable final Intent intent) { + try { + checkNewVersion(); + } catch (final IOException e) { + Log.w(TAG, "Could not fetch NewPipe API: probably network problem", e); + } catch (final ReCaptchaException e) { + Log.e(TAG, "ReCaptchaException should never happen here.", e); + } - compareAppVersionAndShowNotification(app, versionName, - apkLocationUrl, versionCode); - } catch (final JsonParserException e) { - // connectivity problems, do not alarm user and fail silently - if (DEBUG) { - Log.w(TAG, "Could not get NewPipe API: invalid json", e); - } - } - }, - e -> { - // connectivity problems, do not alarm user and fail silently - if (DEBUG) { - Log.w(TAG, "Could not get NewPipe API: network problem", e); - } - }); } } 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 324ee37a8..5a30ea0f3 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 @@ -77,6 +77,7 @@ import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; import org.schabi.newpipe.local.dialog.PlaylistCreationDialog; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.player.MainPlayer; +import org.schabi.newpipe.player.MainPlayer.PlayerType; import org.schabi.newpipe.player.Player; import org.schabi.newpipe.player.event.OnKeyDownListener; import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener; @@ -1095,8 +1096,8 @@ public final class VideoDetailFragment toggleFullscreenIfInFullscreenMode(); final PlayQueue queue = setupPlayQueueForIntent(append); - if (append) { - NavigationHelper.enqueueOnPopupPlayer(activity, queue, false); + if (append) { //resumePlayback: false + NavigationHelper.enqueueOnPlayer(activity, queue, PlayerType.POPUP); } else { replaceQueueIfUserConfirms(() -> NavigationHelper .playOnPopupPlayer(activity, queue, true)); @@ -1154,7 +1155,7 @@ public final class VideoDetailFragment final PlayQueue queue = setupPlayQueueForIntent(append); if (append) { - NavigationHelper.enqueueOnBackgroundPlayer(activity, queue, false); + NavigationHelper.enqueueOnPlayer(activity, queue, PlayerType.AUDIO); } else { replaceQueueIfUserConfirms(() -> NavigationHelper .playOnBackgroundPlayer(activity, queue, true)); @@ -1180,7 +1181,7 @@ public final class VideoDetailFragment addVideoPlayerView(); final Intent playerIntent = NavigationHelper.getPlayerIntent(requireContext(), - MainPlayer.class, queue, true, autoPlayEnabled); + MainPlayer.class, queue, autoPlayEnabled); ContextCompat.startForegroundService(activity, playerIntent); } 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 ae661cfa3..c30b6fc05 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 @@ -350,12 +350,16 @@ public abstract class BaseListFragment extends BaseStateFragment if (context == null || context.getResources() == null || activity == null) { return; } - final List entries = new ArrayList<>(); - if (PlayerHolder.getInstance().getType() != null) { + if (PlayerHolder.getInstance().isPlayerOpen()) { entries.add(StreamDialogEntry.enqueue); + + if (PlayerHolder.getInstance().getQueueSize() > 1) { + entries.add(StreamDialogEntry.enqueue_next); + } } + if (item.getStreamType() == StreamType.AUDIO_STREAM) { entries.addAll(Arrays.asList( StreamDialogEntry.start_here_on_background, 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 548ae7b2c..1d16559ac 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 @@ -37,6 +37,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.fragments.list.BaseListInfoFragment; import org.schabi.newpipe.ktx.AnimationType; import org.schabi.newpipe.local.subscription.SubscriptionManager; +import org.schabi.newpipe.player.MainPlayer.PlayerType; import org.schabi.newpipe.player.playqueue.ChannelPlayQueue; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.util.ExtractorHelper; @@ -495,12 +496,12 @@ public class ChannelFragment extends BaseListInfoFragment .playOnBackgroundPlayer(activity, getPlayQueue(), false)); playlistControlBinding.playlistCtrlPlayPopupButton.setOnLongClickListener(view -> { - NavigationHelper.enqueueOnPopupPlayer(activity, getPlayQueue(), true); + NavigationHelper.enqueueOnPlayer(activity, getPlayQueue(), PlayerType.POPUP); return true; }); playlistControlBinding.playlistCtrlPlayBgButton.setOnLongClickListener(view -> { - NavigationHelper.enqueueOnBackgroundPlayer(activity, getPlayQueue(), true); + NavigationHelper.enqueueOnPlayer(activity, getPlayQueue(), PlayerType.AUDIO); return true; }); } 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 513fbbc91..f3aa2e306 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 @@ -37,6 +37,7 @@ import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.fragments.list.BaseListInfoFragment; import org.schabi.newpipe.info_list.InfoItemDialog; import org.schabi.newpipe.local.playlist.RemotePlaylistManager; +import org.schabi.newpipe.player.MainPlayer.PlayerType; import org.schabi.newpipe.player.helper.PlayerHolder; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue; @@ -148,9 +149,14 @@ public class PlaylistFragment extends BaseListInfoFragment { final ArrayList entries = new ArrayList<>(); - if (PlayerHolder.getInstance().getType() != null) { + if (PlayerHolder.getInstance().isPlayerOpen()) { entries.add(StreamDialogEntry.enqueue); + + if (PlayerHolder.getInstance().getQueueSize() > 1) { + entries.add(StreamDialogEntry.enqueue_next); + } } + if (item.getStreamType() == StreamType.AUDIO_STREAM) { entries.addAll(Arrays.asList( StreamDialogEntry.start_here_on_background, @@ -347,12 +353,12 @@ public class PlaylistFragment extends BaseListInfoFragment { NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue(), false)); playlistControlBinding.playlistCtrlPlayPopupButton.setOnLongClickListener(view -> { - NavigationHelper.enqueueOnPopupPlayer(activity, getPlayQueue(), true); + NavigationHelper.enqueueOnPlayer(activity, getPlayQueue(), PlayerType.POPUP); return true; }); playlistControlBinding.playlistCtrlPlayBgButton.setOnLongClickListener(view -> { - NavigationHelper.enqueueOnBackgroundPlayer(activity, getPlayQueue(), true); + NavigationHelper.enqueueOnPlayer(activity, getPlayQueue(), PlayerType.AUDIO); return true; }); } diff --git a/app/src/main/java/org/schabi/newpipe/info_list/StreamSegmentAdapter.kt b/app/src/main/java/org/schabi/newpipe/info_list/StreamSegmentAdapter.kt index 62a06e29b..9fb4bfbb3 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/StreamSegmentAdapter.kt +++ b/app/src/main/java/org/schabi/newpipe/info_list/StreamSegmentAdapter.kt @@ -1,8 +1,7 @@ package org.schabi.newpipe.info_list import android.util.Log -import com.xwray.groupie.GroupAdapter -import com.xwray.groupie.GroupieViewHolder +import com.xwray.groupie.GroupieAdapter import org.schabi.newpipe.extractor.stream.StreamInfo import kotlin.math.max @@ -11,7 +10,7 @@ import kotlin.math.max */ class StreamSegmentAdapter( private val listener: StreamSegmentListener -) : GroupAdapter() { +) : GroupieAdapter() { var currentIndex: Int = 0 private set diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt index 42fb8915d..965075bf3 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt @@ -40,8 +40,7 @@ import androidx.core.view.isVisible import androidx.lifecycle.ViewModelProvider import androidx.preference.PreferenceManager import androidx.recyclerview.widget.GridLayoutManager -import com.xwray.groupie.GroupAdapter -import com.xwray.groupie.GroupieViewHolder +import com.xwray.groupie.GroupieAdapter import com.xwray.groupie.Item import com.xwray.groupie.OnItemClickListener import com.xwray.groupie.OnItemLongClickListener @@ -91,7 +90,7 @@ class FeedFragment : BaseStateFragment() { private var groupName = "" private var oldestSubscriptionUpdate: OffsetDateTime? = null - private lateinit var groupAdapter: GroupAdapter + private lateinit var groupAdapter: GroupieAdapter @State @JvmField var showPlayedItems: Boolean = true private var onSettingsChangeListener: SharedPreferences.OnSharedPreferenceChangeListener? = null @@ -131,7 +130,7 @@ class FeedFragment : BaseStateFragment() { viewModel = ViewModelProvider(this, factory).get(FeedViewModel::class.java) viewModel.stateLiveData.observe(viewLifecycleOwner, { it?.let(::handleResult) }) - groupAdapter = GroupAdapter().apply { + groupAdapter = GroupieAdapter().apply { setOnItemClickListener(listenerStreamItem) setOnItemLongClickListener(listenerStreamItem) } @@ -326,9 +325,14 @@ class FeedFragment : BaseStateFragment() { if (context == null || context.resources == null || activity == null) return val entries = ArrayList() - if (PlayerHolder.getInstance().getType() != null) { + if (PlayerHolder.getInstance().isPlayerOpen) { entries.add(StreamDialogEntry.enqueue) + + if (PlayerHolder.getInstance().queueSize > 1) { + entries.add(StreamDialogEntry.enqueue_next) + } } + if (item.streamType == StreamType.AUDIO_STREAM) { entries.addAll( listOf( diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt b/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt index c454f7eec..0d2caf126 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt @@ -17,6 +17,7 @@ import org.schabi.newpipe.extractor.stream.StreamType.LIVE_STREAM import org.schabi.newpipe.extractor.stream.StreamType.VIDEO_STREAM import org.schabi.newpipe.util.Localization import org.schabi.newpipe.util.PicassoHelper +import org.schabi.newpipe.util.StreamTypeUtil import java.util.concurrent.TimeUnit data class StreamItem( @@ -58,8 +59,6 @@ data class StreamItem( viewBinding.itemVideoTitleView.text = stream.title viewBinding.itemUploaderView.text = stream.uploader - val isLiveStream = stream.streamType == LIVE_STREAM || stream.streamType == AUDIO_LIVE_STREAM - if (stream.duration > 0) { viewBinding.itemDurationView.text = Localization.getDurationString(stream.duration) viewBinding.itemDurationView.setBackgroundColor( @@ -77,7 +76,7 @@ data class StreamItem( } else { viewBinding.itemProgressView.visibility = View.GONE } - } else if (isLiveStream) { + } else if (StreamTypeUtil.isLiveStream(stream.streamType)) { viewBinding.itemDurationView.setText(R.string.duration_live) viewBinding.itemDurationView.setBackgroundColor( ContextCompat.getColor( diff --git a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java index 6a7a300ca..9632b47f7 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java @@ -338,9 +338,14 @@ public class StatisticsPlaylistFragment final ArrayList entries = new ArrayList<>(); - if (PlayerHolder.getInstance().getType() != null) { + if (PlayerHolder.getInstance().isPlayerOpen()) { entries.add(StreamDialogEntry.enqueue); + + if (PlayerHolder.getInstance().getQueueSize() > 1) { + entries.add(StreamDialogEntry.enqueue_next); + } } + if (infoItem.getStreamType() == StreamType.AUDIO_STREAM) { entries.addAll(Arrays.asList( StreamDialogEntry.start_here_on_background, diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index 40a7b26e2..21da9e571 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -42,6 +42,7 @@ import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.info_list.InfoItemDialog; import org.schabi.newpipe.local.BaseLocalListFragment; import org.schabi.newpipe.local.history.HistoryRecordManager; +import org.schabi.newpipe.player.MainPlayer.PlayerType; import org.schabi.newpipe.player.helper.PlayerHolder; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.SinglePlayQueue; @@ -493,12 +494,12 @@ public class LocalPlaylistFragment extends BaseLocalListFragment { - NavigationHelper.enqueueOnPopupPlayer(activity, getPlayQueue(), true); + NavigationHelper.enqueueOnPlayer(activity, getPlayQueue(), PlayerType.POPUP); return true; }); playlistControlBinding.playlistCtrlPlayBgButton.setOnLongClickListener(view -> { - NavigationHelper.enqueueOnBackgroundPlayer(activity, getPlayQueue(), true); + NavigationHelper.enqueueOnPlayer(activity, getPlayQueue(), PlayerType.AUDIO); return true; }); @@ -752,8 +753,12 @@ public class LocalPlaylistFragment extends BaseLocalListFragment entries = new ArrayList<>(); - if (PlayerHolder.getInstance().getType() != null) { + if (PlayerHolder.getInstance().isPlayerOpen()) { entries.add(StreamDialogEntry.enqueue); + + if (PlayerHolder.getInstance().getQueueSize() > 1) { + entries.add(StreamDialogEntry.enqueue_next); + } } if (infoItem.getStreamType() == StreamType.AUDIO_STREAM) { entries.addAll(Arrays.asList( diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/FeedGroupIcon.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/FeedGroupIcon.kt index 83a90213d..ac7197b48 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/FeedGroupIcon.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/FeedGroupIcon.kt @@ -22,7 +22,7 @@ enum class FeedGroupIcon( COMPUTER(5, R.drawable.ic_computer), GAMING(6, R.drawable.ic_videogame_asset), SPORTS(7, R.drawable.ic_directions_bike), - NEWS(8, R.drawable.ic_megaphone), + NEWS(8, R.drawable.ic_campaign), FAVORITES(9, R.drawable.ic_favorite), CAR(10, R.drawable.ic_directions_car), MOTORCYCLE(11, R.drawable.ic_motorcycle), diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt index 69d4c8819..851e84f9f 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt @@ -21,8 +21,7 @@ import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.xwray.groupie.GroupAdapter -import com.xwray.groupie.GroupieViewHolder +import com.xwray.groupie.GroupieAdapter import com.xwray.groupie.OnItemClickListener import com.xwray.groupie.Section import icepick.Icepick @@ -78,7 +77,7 @@ class FeedGroupDialog : DialogFragment(), BackPressable { private val subscriptionMainSection = Section() private val subscriptionEmptyFooter = Section() - private lateinit var subscriptionGroupAdapter: GroupAdapter + private lateinit var subscriptionGroupAdapter: GroupieAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -153,7 +152,7 @@ class FeedGroupDialog : DialogFragment(), BackPressable { } } - subscriptionGroupAdapter = GroupAdapter().apply { + subscriptionGroupAdapter = GroupieAdapter().apply { add(subscriptionMainSection) add(subscriptionEmptyFooter) spanCount = 4 @@ -379,7 +378,7 @@ class FeedGroupDialog : DialogFragment(), BackPressable { } private fun setupIconPicker() { - val groupAdapter = GroupAdapter() + val groupAdapter = GroupieAdapter() groupAdapter.addAll(FeedGroupIcon.values().map { PickerIconItem(it) }) feedGroupCreateBinding.iconSelector.apply { diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt index 57815ea90..58547afd2 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt @@ -11,8 +11,7 @@ import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper.SimpleCallback import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.xwray.groupie.GroupAdapter -import com.xwray.groupie.GroupieViewHolder +import com.xwray.groupie.GroupieAdapter import com.xwray.groupie.TouchCallback import icepick.Icepick import icepick.State @@ -38,7 +37,7 @@ class FeedGroupReorderDialog : DialogFragment() { @State @JvmField var groupOrderedIdList = ArrayList() - private val groupAdapter = GroupAdapter() + private val groupAdapter = GroupieAdapter() private val itemTouchHelper = ItemTouchHelper(getItemTouchCallback()) override fun onCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index c10307b98..22e66e793 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -1,5 +1,53 @@ package org.schabi.newpipe.player; +import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_AD_INSERTION; +import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_INTERNAL; +import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_PERIOD_TRANSITION; +import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK; +import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT; +import static com.google.android.exoplayer2.Player.DiscontinuityReason; +import static com.google.android.exoplayer2.Player.EventListener; +import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL; +import static com.google.android.exoplayer2.Player.REPEAT_MODE_OFF; +import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE; +import static com.google.android.exoplayer2.Player.RepeatMode; +import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu; +import static org.schabi.newpipe.extractor.ServiceList.YouTube; +import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; +import static org.schabi.newpipe.ktx.ViewUtils.animate; +import static org.schabi.newpipe.ktx.ViewUtils.animateRotation; +import static org.schabi.newpipe.player.MainPlayer.ACTION_CLOSE; +import static org.schabi.newpipe.player.MainPlayer.ACTION_FAST_FORWARD; +import static org.schabi.newpipe.player.MainPlayer.ACTION_FAST_REWIND; +import static org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_NEXT; +import static org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_PAUSE; +import static org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_PREVIOUS; +import static org.schabi.newpipe.player.MainPlayer.ACTION_RECREATE_NOTIFICATION; +import static org.schabi.newpipe.player.MainPlayer.ACTION_REPEAT; +import static org.schabi.newpipe.player.MainPlayer.ACTION_SHUFFLE; +import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_BACKGROUND; +import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_NONE; +import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_POPUP; +import static org.schabi.newpipe.player.helper.PlayerHelper.buildCloseOverlayLayoutParams; +import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed; +import static org.schabi.newpipe.player.helper.PlayerHelper.getMinimizeOnExitAction; +import static org.schabi.newpipe.player.helper.PlayerHelper.getMinimumVideoHeight; +import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString; +import static org.schabi.newpipe.player.helper.PlayerHelper.globalScreenOrientationLocked; +import static org.schabi.newpipe.player.helper.PlayerHelper.isPlaybackResumeEnabled; +import static org.schabi.newpipe.player.helper.PlayerHelper.nextRepeatMode; +import static org.schabi.newpipe.player.helper.PlayerHelper.nextResizeModeAndSaveToPrefs; +import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePlaybackParametersFromPrefs; +import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePlayerTypeFromIntent; +import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePopupLayoutParamsFromPrefs; +import static org.schabi.newpipe.player.helper.PlayerHelper.retrieveSeekDurationFromPreferences; +import static org.schabi.newpipe.player.helper.PlayerHelper.savePlaybackParametersToPrefs; +import static org.schabi.newpipe.util.ListHelper.getPopupResolutionIndex; +import static org.schabi.newpipe.util.ListHelper.getResolutionIndex; +import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; +import static org.schabi.newpipe.util.Localization.containsCaseInsensitive; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; @@ -94,7 +142,6 @@ import org.schabi.newpipe.databinding.PlayerPopupCloseOverlayBinding; import org.schabi.newpipe.extractor.MediaFormat; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamSegment; -import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.fragments.OnScrollBelowItemsListener; import org.schabi.newpipe.fragments.detail.VideoDetailFragment; @@ -127,12 +174,13 @@ import org.schabi.newpipe.player.resolver.MediaSourceTag; import org.schabi.newpipe.player.resolver.VideoPlaybackResolver; import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHelper; import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHolder; +import org.schabi.newpipe.util.StreamTypeUtil; import org.schabi.newpipe.util.DeviceUtils; -import org.schabi.newpipe.util.external_communication.KoreUtils; import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.PicassoHelper; import org.schabi.newpipe.util.SerializedCache; +import org.schabi.newpipe.util.external_communication.KoreUtils; import org.schabi.newpipe.util.external_communication.ShareUtils; import org.schabi.newpipe.views.ExpandableSurfaceView; @@ -140,6 +188,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.Optional; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Observable; @@ -147,54 +196,6 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.disposables.SerialDisposable; -import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_AD_INSERTION; -import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_INTERNAL; -import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_PERIOD_TRANSITION; -import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK; -import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT; -import static com.google.android.exoplayer2.Player.DiscontinuityReason; -import static com.google.android.exoplayer2.Player.EventListener; -import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL; -import static com.google.android.exoplayer2.Player.REPEAT_MODE_OFF; -import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE; -import static com.google.android.exoplayer2.Player.RepeatMode; -import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu; -import static org.schabi.newpipe.extractor.ServiceList.YouTube; -import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; -import static org.schabi.newpipe.ktx.ViewUtils.animate; -import static org.schabi.newpipe.ktx.ViewUtils.animateRotation; -import static org.schabi.newpipe.player.MainPlayer.ACTION_CLOSE; -import static org.schabi.newpipe.player.MainPlayer.ACTION_FAST_FORWARD; -import static org.schabi.newpipe.player.MainPlayer.ACTION_FAST_REWIND; -import static org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_NEXT; -import static org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_PAUSE; -import static org.schabi.newpipe.player.MainPlayer.ACTION_PLAY_PREVIOUS; -import static org.schabi.newpipe.player.MainPlayer.ACTION_RECREATE_NOTIFICATION; -import static org.schabi.newpipe.player.MainPlayer.ACTION_REPEAT; -import static org.schabi.newpipe.player.MainPlayer.ACTION_SHUFFLE; -import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_BACKGROUND; -import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_NONE; -import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_POPUP; -import static org.schabi.newpipe.player.helper.PlayerHelper.buildCloseOverlayLayoutParams; -import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed; -import static org.schabi.newpipe.player.helper.PlayerHelper.getMinimizeOnExitAction; -import static org.schabi.newpipe.player.helper.PlayerHelper.getMinimumVideoHeight; -import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString; -import static org.schabi.newpipe.player.helper.PlayerHelper.globalScreenOrientationLocked; -import static org.schabi.newpipe.player.helper.PlayerHelper.isPlaybackResumeEnabled; -import static org.schabi.newpipe.player.helper.PlayerHelper.nextRepeatMode; -import static org.schabi.newpipe.player.helper.PlayerHelper.nextResizeModeAndSaveToPrefs; -import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePlaybackParametersFromPrefs; -import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePlayerTypeFromIntent; -import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePopupLayoutParamsFromPrefs; -import static org.schabi.newpipe.player.helper.PlayerHelper.retrieveSeekDurationFromPreferences; -import static org.schabi.newpipe.player.helper.PlayerHelper.savePlaybackParametersToPrefs; -import static org.schabi.newpipe.util.ListHelper.getPopupResolutionIndex; -import static org.schabi.newpipe.util.ListHelper.getResolutionIndex; -import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; -import static org.schabi.newpipe.util.Localization.containsCaseInsensitive; - public final class Player implements EventListener, PlaybackListener, @@ -226,10 +227,10 @@ public final class Player implements public static final String REPEAT_MODE = "repeat_mode"; public static final String PLAYBACK_QUALITY = "playback_quality"; public static final String PLAY_QUEUE_KEY = "play_queue_key"; - public static final String APPEND_ONLY = "append_only"; + public static final String ENQUEUE = "enqueue"; + public static final String ENQUEUE_NEXT = "enqueue_next"; public static final String RESUME_PLAYBACK = "resume_playback"; public static final String PLAY_WHEN_READY = "play_when_ready"; - public static final String SELECT_ON_APPEND = "select_on_append"; public static final String PLAYER_TYPE = "player_type"; public static final String IS_MUTED = "is_muted"; @@ -608,16 +609,16 @@ public final class Player implements setPlaybackQuality(intent.getStringExtra(PLAYBACK_QUALITY)); } - // Resolve append intents - if (intent.getBooleanExtra(APPEND_ONLY, false) && playQueue != null) { - final int sizeBeforeAppend = playQueue.size(); + // Resolve enqueue intents + if (intent.getBooleanExtra(ENQUEUE, false) && playQueue != null) { playQueue.append(newQueue.getStreams()); + return; - if ((intent.getBooleanExtra(SELECT_ON_APPEND, false) - || currentState == STATE_COMPLETED) && !newQueue.getStreams().isEmpty()) { - playQueue.setIndex(sizeBeforeAppend); - } - + // Resolve enqueue next intents + } else if (intent.getBooleanExtra(ENQUEUE_NEXT, false) && playQueue != null) { + final int currentIndex = playQueue.getIndex(); + playQueue.append(newQueue.getStreams()); + playQueue.move(playQueue.size() - 1, currentIndex + 1); return; } @@ -1596,10 +1597,7 @@ public final class Player implements setVideoDurationToControls(duration); } if (currentState != STATE_PAUSED) { - if (currentState != STATE_PAUSED_SEEK) { - binding.playbackSeekBar.setProgress(currentProgress); - } - binding.playbackCurrentTime.setText(getTimeString(currentProgress)); + updatePlayBackElementsCurrentDuration(currentProgress); } if (simpleExoPlayer.isLoading() || bufferPercent > 90) { binding.playbackSeekBar.setSecondaryProgress( @@ -1622,12 +1620,6 @@ public final class Player implements if (isQueueVisible) { updateQueueTime(currentProgress); } - - final boolean showThumbnail = prefs.getBoolean( - context.getString(R.string.show_thumbnail_key), true); - // setMetadata only updates the metadata when any of the metadata keys are null - mediaSessionManager.setMetadata(getVideoTitle(), getUploaderName(), - showThumbnail ? getThumbnail() : null, duration); } private void startProgressLoop() { @@ -1652,10 +1644,10 @@ public final class Player implements // TODO: revert #6307 when introducing proper HLS support final int duration; if (currentItem != null - && currentItem.getStreamType() != StreamType.AUDIO_LIVE_STREAM - && currentItem.getStreamType() != StreamType.LIVE_STREAM) { + && !StreamTypeUtil.isLiveStream(currentItem.getStreamType()) + ) { // convert seconds to milliseconds - duration = (int) (currentItem.getDuration() * 1000); + duration = (int) (currentItem.getDuration() * 1000); } else { duration = (int) simpleExoPlayer.getDuration(); } @@ -2253,6 +2245,9 @@ public final class Player implements stopProgressLoop(); } + // When a (short) video ends the elements have to display the correct values - see #6180 + updatePlayBackElementsCurrentDuration(binding.playbackSeekBar.getMax()); + showControls(500); animate(binding.currentDisplaySeek, false, 200, AnimationType.SCALE_AND_ALPHA); binding.loadingPanel.setVisibility(View.GONE); @@ -2595,6 +2590,18 @@ public final class Player implements //////////////////////////////////////////////////////////////////////////*/ //region Playback position and seek + /** + * Sets the current duration into the corresponding elements. + * @param currentProgress + */ + private void updatePlayBackElementsCurrentDuration(final int currentProgress) { + // Don't set seekbar progress while user is seeking + if (currentState != STATE_PAUSED_SEEK) { + binding.playbackSeekBar.setProgress(currentProgress); + } + binding.playbackCurrentTime.setText(getTimeString(currentProgress)); + } + @Override // own playback listener (this is a getter) public boolean isApproachingPlaybackEdge(final long timeToEndMillis) { // If live, then not near playback edge @@ -2946,6 +2953,18 @@ public final class Player implements tag.getMetadata().getPreviewFrames()); NotificationUtil.getInstance().createNotificationIfNeededAndUpdate(this, false); + + final boolean showThumbnail = prefs.getBoolean( + context.getString(R.string.show_thumbnail_key), true); + mediaSessionManager.setMetadata( + getVideoTitle(), + getUploaderName(), + showThumbnail ? Optional.ofNullable(getThumbnail()) : Optional.empty(), + StreamTypeUtil.isLiveStream(tag.getMetadata().getStreamType()) + ? -1 + : tag.getMetadata().getDuration() + ); + notifyMetadataUpdateToListeners(); if (areSegmentsVisible) { @@ -3023,9 +3042,11 @@ public final class Player implements @Nullable public Bitmap getThumbnail() { - return currentThumbnail == null - ? BitmapFactory.decodeResource(context.getResources(), R.drawable.dummy_thumbnail) - : currentThumbnail; + if (currentThumbnail == null) { + currentThumbnail = BitmapFactory.decodeResource( + context.getResources(), R.drawable.dummy_thumbnail); + } + return currentThumbnail; } //endregion diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java b/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java index c7f1f9c8c..ef0d84029 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/MediaSessionManager.java @@ -21,6 +21,8 @@ import org.schabi.newpipe.player.mediasession.MediaSessionCallback; import org.schabi.newpipe.player.mediasession.PlayQueueNavigator; import org.schabi.newpipe.player.mediasession.PlayQueuePlaybackController; +import java.util.Optional; + public class MediaSessionManager { private static final String TAG = MediaSessionManager.class.getSimpleName(); public static final boolean DEBUG = MainActivity.DEBUG; @@ -30,6 +32,9 @@ public class MediaSessionManager { @NonNull private final MediaSessionConnector sessionConnector; + private int lastTitleHashCode; + private int lastArtistHashCode; + private long lastDuration; private int lastAlbumArtHashCode; public MediaSessionManager(@NonNull final Context context, @@ -65,47 +70,127 @@ public class MediaSessionManager { return mediaSession.getSessionToken(); } - public void setMetadata(final String title, - final String artist, - final Bitmap albumArt, - final long duration) { - if (albumArt == null || !mediaSession.isActive()) { + /** + * sets the Metadata - if required. + * + * @param title {@link MediaMetadataCompat#METADATA_KEY_TITLE} + * @param artist {@link MediaMetadataCompat#METADATA_KEY_ARTIST} + * @param optAlbumArt {@link MediaMetadataCompat#METADATA_KEY_ALBUM_ART} + * @param duration {@link MediaMetadataCompat#METADATA_KEY_DURATION} + * - should be a negative value for unknown durations, e.g. for livestreams + */ + public void setMetadata(@NonNull final String title, + @NonNull final String artist, + @NonNull final Optional optAlbumArt, + final long duration + ) { + if (DEBUG) { + Log.d(TAG, "setMetadata called:" + + " t: " + title + + " a: " + artist + + " thumb: " + ( + optAlbumArt.isPresent() + ? optAlbumArt.get().hashCode() + : "") + + " d: " + duration); + } + + if (!mediaSession.isActive()) { + if (DEBUG) { + Log.d(TAG, "setMetadata: mediaSession not active - exiting"); + } + return; + } + + if (!checkIfMetadataShouldBeSet(title, artist, optAlbumArt, duration)) { + if (DEBUG) { + Log.d(TAG, "setMetadata: No update required - exiting"); + } return; } if (DEBUG) { - if (getMetadataAlbumArt() == null) { - Log.d(TAG, "N_getMetadataAlbumArt: thumb == null"); - } - if (getMetadataTitle() == null) { - Log.d(TAG, "N_getMetadataTitle: title == null"); - } - if (getMetadataArtist() == null) { - Log.d(TAG, "N_getMetadataArtist: artist == null"); - } - if (getMetadataDuration() <= 1) { - Log.d(TAG, "N_getMetadataDuration: duration <= 1; " + getMetadataDuration()); - } + Log.d(TAG, "setMetadata: N_Metadata update:" + + " t: " + title + + " a: " + artist + + " thumb: " + ( + optAlbumArt.isPresent() + ? optAlbumArt.get().hashCode() + : "") + + " d: " + duration); } - if (getMetadataAlbumArt() == null || getMetadataTitle() == null - || getMetadataArtist() == null || getMetadataDuration() <= 1 - || albumArt.hashCode() != lastAlbumArtHashCode) { - if (DEBUG) { - Log.d(TAG, "setMetadata: N_Metadata update: t: " + title + " a: " + artist - + " thumb: " + albumArt.hashCode() + " d: " + duration); - } + final MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder() + .putString(MediaMetadataCompat.METADATA_KEY_TITLE, title) + .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artist) + .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, duration); - mediaSession.setMetadata(new MediaMetadataCompat.Builder() - .putString(MediaMetadataCompat.METADATA_KEY_TITLE, title) - .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artist) - .putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt) - .putBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, albumArt) - .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, duration).build()); - lastAlbumArtHashCode = albumArt.hashCode(); + if (optAlbumArt.isPresent()) { + builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, optAlbumArt.get()); + builder.putBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, optAlbumArt.get()); + } + + mediaSession.setMetadata(builder.build()); + + lastTitleHashCode = title.hashCode(); + lastArtistHashCode = artist.hashCode(); + lastDuration = duration; + if (optAlbumArt.isPresent()) { + lastAlbumArtHashCode = optAlbumArt.get().hashCode(); } } + private boolean checkIfMetadataShouldBeSet( + @NonNull final String title, + @NonNull final String artist, + @NonNull final Optional optAlbumArt, + final long duration + ) { + // Check if the values have changed since the last time + if (title.hashCode() != lastTitleHashCode + || artist.hashCode() != lastArtistHashCode + || duration != lastDuration + || (optAlbumArt.isPresent() && optAlbumArt.get().hashCode() != lastAlbumArtHashCode) + ) { + if (DEBUG) { + Log.d(TAG, + "checkIfMetadataShouldBeSet: true - reason: changed values since last"); + } + return true; + } + + // Check if the currently set metadata is valid + if (getMetadataTitle() == null + || getMetadataArtist() == null + // Note that the duration can be <= 0 for live streams + ) { + if (DEBUG) { + if (getMetadataTitle() == null) { + Log.d(TAG, + "N_getMetadataTitle: title == null"); + } else if (getMetadataArtist() == null) { + Log.d(TAG, + "N_getMetadataArtist: artist == null"); + } + } + return true; + } + + // If we got an album art check if the current set AlbumArt is null + if (optAlbumArt.isPresent() && getMetadataAlbumArt() == null) { + if (DEBUG) { + if (getMetadataAlbumArt() == null) { + Log.d(TAG, "N_getMetadataAlbumArt: thumb == null"); + } + } + return true; + } + + // Default - no update required + return false; + } + + private Bitmap getMetadataAlbumArt() { return mediaSession.getController().getMetadata() .getBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART); @@ -121,11 +206,6 @@ public class MediaSessionManager { .getString(MediaMetadataCompat.METADATA_KEY_ARTIST); } - private long getMetadataDuration() { - return mediaSession.getController().getMetadata() - .getLong(MediaMetadataCompat.METADATA_KEY_DURATION); - } - /** * Should be called on player destruction to prevent leakage. */ diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java index 68de8ce9f..46239cab1 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java @@ -70,6 +70,10 @@ public final class PlayerHolder { return player != null; } + public int getQueueSize() { + return isPlayerOpen() ? player.getPlayQueue().size() : 0; + } + public void setListener(@Nullable final PlayerServiceExtendedEventListener newListener) { listener = newListener; diff --git a/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java b/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java index a6dcadd5e..81e629c2f 100644 --- a/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java +++ b/app/src/main/java/org/schabi/newpipe/player/resolver/PlaybackResolver.java @@ -14,6 +14,7 @@ import com.google.android.exoplayer2.util.Util; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.player.helper.PlayerDataSource; +import org.schabi.newpipe.util.StreamTypeUtil; public interface PlaybackResolver extends Resolver { @@ -21,7 +22,7 @@ public interface PlaybackResolver extends Resolver { default MediaSource maybeBuildLiveMediaSource(@NonNull final PlayerDataSource dataSource, @NonNull final StreamInfo info) { final StreamType streamType = info.getStreamType(); - if (!(streamType == StreamType.AUDIO_LIVE_STREAM || streamType == StreamType.LIVE_STREAM)) { + if (!StreamTypeUtil.isLiveStream(streamType)) { return null; } diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt index cb4c14796..6bc63a56a 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt @@ -91,6 +91,11 @@ class ContentSettingsManager(private val fileLocator: NewPipeFileLocator) { is String -> { preferenceEditor.putString(key, value) } + is Set<*> -> { + // There are currently only Sets with type String possible + @Suppress("UNCHECKED_CAST") + preferenceEditor.putStringSet(key, value as Set?) + } } } preferenceEditor.commit() diff --git a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java index 0ca15e245..d2f56b487 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java @@ -6,11 +6,21 @@ import androidx.preference.Preference; import org.schabi.newpipe.R; +import static org.schabi.newpipe.CheckForNewAppVersion.startNewVersionCheckService; + public class UpdateSettingsFragment extends BasePreferenceFragment { private final Preference.OnPreferenceChangeListener updatePreferenceChange - = (preference, newValue) -> { + = (preference, checkForUpdates) -> { defaultPreferences.edit() - .putBoolean(getString(R.string.update_app_key), (boolean) newValue).apply(); + .putBoolean(getString(R.string.update_app_key), (boolean) checkForUpdates).apply(); + + if ((boolean) checkForUpdates) { + // Search for updates immediately when update checks are enabled. + // Reset the expire time. This is necessary to check for an update immediately. + defaultPreferences.edit() + .putLong(getString(R.string.update_expiry_key), 0).apply(); + startNewVersionCheckService(); + } return true; }; diff --git a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java index 73bc4d6bb..bdf5e8ce4 100644 --- a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java @@ -33,6 +33,9 @@ public final class DeviceUtils { // Zephir TS43UHD-2 private static final boolean CVT_MT5886_EU_1G = Build.VERSION.SDK_INT == 24 && Build.DEVICE.equals("cvt_mt5886_eu_1g"); + // Hilife TV + private static final boolean REALTEKATV = Build.VERSION.SDK_INT == 25 + && Build.DEVICE.equals("RealtekATV"); private DeviceUtils() { } @@ -129,7 +132,8 @@ public final class DeviceUtils { public static boolean shouldSupportMediaTunneling() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !HI3798MV200 - && !CVT_MT5886_EU_1G; + && !CVT_MT5886_EU_1G + && !REALTEKATV; } public static boolean isLandscape(final Context context) { 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 ae1e6cede..afa826677 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -45,6 +45,7 @@ import org.schabi.newpipe.local.playlist.LocalPlaylistFragment; import org.schabi.newpipe.local.subscription.SubscriptionFragment; import org.schabi.newpipe.local.subscription.SubscriptionsImportFragment; import org.schabi.newpipe.player.MainPlayer; +import org.schabi.newpipe.player.MainPlayer.PlayerType; import org.schabi.newpipe.player.PlayQueueActivity; import org.schabi.newpipe.player.Player; import org.schabi.newpipe.player.helper.PlayerHelper; @@ -64,18 +65,19 @@ public final class NavigationHelper { public static final String MAIN_FRAGMENT_TAG = "main_fragment_tag"; public static final String SEARCH_FRAGMENT_TAG = "search_fragment_tag"; + private static final String TAG = NavigationHelper.class.getSimpleName(); + private NavigationHelper() { } /*////////////////////////////////////////////////////////////////////////// // Players //////////////////////////////////////////////////////////////////////////*/ - + /* INTENT */ @NonNull public static Intent getPlayerIntent(@NonNull final Context context, @NonNull final Class targetClazz, - @Nullable final PlayQueue playQueue, - final boolean resumePlayback) { + @Nullable final PlayQueue playQueue) { final Intent intent = new Intent(context, targetClazz); if (playQueue != null) { @@ -84,7 +86,6 @@ public final class NavigationHelper { intent.putExtra(Player.PLAY_QUEUE_KEY, cacheKey); } } - intent.putExtra(Player.RESUME_PLAYBACK, resumePlayback); intent.putExtra(Player.PLAYER_TYPE, MainPlayer.PlayerType.VIDEO.ordinal()); return intent; @@ -94,23 +95,28 @@ public final class NavigationHelper { public static Intent getPlayerIntent(@NonNull final Context context, @NonNull final Class targetClazz, @Nullable final PlayQueue playQueue, - final boolean resumePlayback, final boolean playWhenReady) { - return getPlayerIntent(context, targetClazz, playQueue, resumePlayback) + return getPlayerIntent(context, targetClazz, playQueue) .putExtra(Player.PLAY_WHEN_READY, playWhenReady); } @NonNull public static Intent getPlayerEnqueueIntent(@NonNull final Context context, @NonNull final Class targetClazz, - @Nullable final PlayQueue playQueue, - final boolean selectOnAppend, - final boolean resumePlayback) { - return getPlayerIntent(context, targetClazz, playQueue, resumePlayback) - .putExtra(Player.APPEND_ONLY, true) - .putExtra(Player.SELECT_ON_APPEND, selectOnAppend); + @Nullable final PlayQueue playQueue) { + return getPlayerIntent(context, targetClazz, playQueue) + .putExtra(Player.ENQUEUE, true); } + @NonNull + public static Intent getPlayerEnqueueNextIntent(@NonNull final Context context, + @NonNull final Class targetClazz, + @Nullable final PlayQueue playQueue) { + return getPlayerIntent(context, targetClazz, playQueue) + .putExtra(Player.ENQUEUE_NEXT, true); + } + + /* PLAY */ public static void playOnMainPlayer(final AppCompatActivity activity, @NonNull final PlayQueue playQueue) { final PlayQueueItem item = playQueue.getItem(); @@ -156,56 +162,38 @@ public final class NavigationHelper { ContextCompat.startForegroundService(context, intent); } - public static void enqueueOnVideoPlayer(final Context context, final PlayQueue queue, - final boolean resumePlayback) { - enqueueOnVideoPlayer(context, queue, false, resumePlayback); - } - - public static void enqueueOnVideoPlayer(final Context context, final PlayQueue queue, - final boolean selectOnAppend, - final boolean resumePlayback) { - + /* ENQUEUE */ + public static void enqueueOnPlayer(final Context context, + final PlayQueue queue, + final PlayerType playerType) { Toast.makeText(context, R.string.enqueued, Toast.LENGTH_SHORT).show(); - final Intent intent = getPlayerEnqueueIntent( - context, MainPlayer.class, queue, selectOnAppend, resumePlayback); + final Intent intent = getPlayerEnqueueIntent(context, MainPlayer.class, queue); - intent.putExtra(Player.PLAYER_TYPE, MainPlayer.PlayerType.VIDEO.ordinal()); + intent.putExtra(Player.PLAYER_TYPE, playerType.ordinal()); ContextCompat.startForegroundService(context, intent); } - public static void enqueueOnPopupPlayer(final Context context, final PlayQueue queue, - final boolean resumePlayback) { - enqueueOnPopupPlayer(context, queue, false, resumePlayback); - } - - public static void enqueueOnPopupPlayer(final Context context, final PlayQueue queue, - final boolean selectOnAppend, - final boolean resumePlayback) { - if (!PermissionHelper.isPopupEnabled(context)) { - PermissionHelper.showPopupEnablementToast(context); - return; + public static void enqueueOnPlayer(final Context context, final PlayQueue queue) { + PlayerType playerType = PlayerHolder.getInstance().getType(); + if (!PlayerHolder.getInstance().isPlayerOpen()) { + Log.e(TAG, "Enqueueing but no player is open; defaulting to background player"); + playerType = MainPlayer.PlayerType.AUDIO; } - Toast.makeText(context, R.string.enqueued, Toast.LENGTH_SHORT).show(); - final Intent intent = getPlayerEnqueueIntent( - context, MainPlayer.class, queue, selectOnAppend, resumePlayback); - intent.putExtra(Player.PLAYER_TYPE, MainPlayer.PlayerType.POPUP.ordinal()); - ContextCompat.startForegroundService(context, intent); + enqueueOnPlayer(context, queue, playerType); } - public static void enqueueOnBackgroundPlayer(final Context context, final PlayQueue queue, - final boolean resumePlayback) { - enqueueOnBackgroundPlayer(context, queue, false, resumePlayback); - } + /* ENQUEUE NEXT */ + public static void enqueueNextOnPlayer(final Context context, final PlayQueue queue) { + PlayerType playerType = PlayerHolder.getInstance().getType(); + if (!PlayerHolder.getInstance().isPlayerOpen()) { + Log.e(TAG, "Enqueueing next but no player is open; defaulting to background player"); + playerType = MainPlayer.PlayerType.AUDIO; + } + Toast.makeText(context, R.string.enqueued_next, Toast.LENGTH_SHORT).show(); + final Intent intent = getPlayerEnqueueNextIntent(context, MainPlayer.class, queue); - public static void enqueueOnBackgroundPlayer(final Context context, - final PlayQueue queue, - final boolean selectOnAppend, - final boolean resumePlayback) { - Toast.makeText(context, R.string.enqueued, Toast.LENGTH_SHORT).show(); - final Intent intent = getPlayerEnqueueIntent( - context, MainPlayer.class, queue, selectOnAppend, resumePlayback); - intent.putExtra(Player.PLAYER_TYPE, MainPlayer.PlayerType.AUDIO.ordinal()); + intent.putExtra(Player.PLAYER_TYPE, playerType.ordinal()); ContextCompat.startForegroundService(context, intent); } @@ -348,7 +336,7 @@ public final class NavigationHelper { final boolean autoPlay; @Nullable final MainPlayer.PlayerType playerType = PlayerHolder.getInstance().getType(); - if (playerType == null) { + if (!PlayerHolder.getInstance().isPlayerOpen()) { // no player open autoPlay = PlayerHelper.isAutoplayAllowedByUser(context); } else if (switchingPlayers) { diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java index 6245d6f14..ec51cc370 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java +++ b/app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java @@ -12,8 +12,6 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; import org.schabi.newpipe.local.dialog.PlaylistCreationDialog; import org.schabi.newpipe.local.history.HistoryRecordManager; -import org.schabi.newpipe.player.MainPlayer; -import org.schabi.newpipe.player.helper.PlayerHolder; import org.schabi.newpipe.player.playqueue.SinglePlayQueue; import org.schabi.newpipe.util.external_communication.KoreUtils; import org.schabi.newpipe.util.external_communication.ShareUtils; @@ -25,8 +23,6 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.schedulers.Schedulers; import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; -import static org.schabi.newpipe.player.MainPlayer.PlayerType.AUDIO; -import static org.schabi.newpipe.player.MainPlayer.PlayerType.POPUP; public enum StreamDialogEntry { ////////////////////////////////////// @@ -43,7 +39,7 @@ public enum StreamDialogEntry { .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { - NewPipeDatabase.getInstance(fragment.getContext()).streamDAO() + NewPipeDatabase.getInstance(fragment.requireContext()).streamDAO() .setUploaderUrl(serviceId, url, result.getUploaderUrl()) .subscribeOn(Schedulers.io()).subscribe(); openChannelFragment(fragment, item, result.getUploaderUrl()); @@ -64,18 +60,11 @@ public enum StreamDialogEntry { * Info: Add this entry within showStreamDialog. */ enqueue(R.string.enqueue_stream, (fragment, item) -> { - final MainPlayer.PlayerType type = PlayerHolder.getInstance().getType(); + NavigationHelper.enqueueOnPlayer(fragment.getContext(), new SinglePlayQueue(item)); + }), - if (type == AUDIO) { - NavigationHelper.enqueueOnBackgroundPlayer(fragment.getContext(), - new SinglePlayQueue(item), false); - } else if (type == POPUP) { - NavigationHelper.enqueueOnPopupPlayer(fragment.getContext(), - new SinglePlayQueue(item), false); - } else /* type == VIDEO */ { - NavigationHelper.enqueueOnVideoPlayer(fragment.getContext(), - new SinglePlayQueue(item), false); - } + enqueue_next(R.string.enqueue_next_stream, (fragment, item) -> { + NavigationHelper.enqueueNextOnPlayer(fragment.getContext(), new SinglePlayQueue(item)); }), start_here_on_background(R.string.start_here_on_background, (fragment, item) -> @@ -108,16 +97,16 @@ public enum StreamDialogEntry { try { NavigationHelper.playWithKore(fragment.requireContext(), videoUrl); } catch (final Exception e) { - KoreUtils.showInstallKoreDialog(fragment.getActivity()); + KoreUtils.showInstallKoreDialog(fragment.requireActivity()); } }), share(R.string.share, (fragment, item) -> - ShareUtils.shareText(fragment.getContext(), item.getName(), item.getUrl(), + ShareUtils.shareText(fragment.requireContext(), item.getName(), item.getUrl(), item.getThumbnailUrl())), open_in_browser(R.string.open_in_browser, (fragment, item) -> - ShareUtils.openUrlInBrowser(fragment.getContext(), item.getUrl())), + ShareUtils.openUrlInBrowser(fragment.requireContext(), item.getUrl())), mark_as_watched(R.string.mark_as_watched, (fragment, item) -> { diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamTypeUtil.java b/app/src/main/java/org/schabi/newpipe/util/StreamTypeUtil.java new file mode 100644 index 000000000..87b3eed4f --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/StreamTypeUtil.java @@ -0,0 +1,24 @@ +package org.schabi.newpipe.util; + +import org.schabi.newpipe.extractor.stream.StreamType; + +/** + * Utility class for {@link org.schabi.newpipe.extractor.stream.StreamType}. + */ +public final class StreamTypeUtil { + private StreamTypeUtil() { + // No impl pls + } + + /** + * Checks if the streamType is a livestream. + * + * @param streamType + * @return true when the streamType is a + * {@link StreamType#LIVE_STREAM} or {@link StreamType#AUDIO_LIVE_STREAM} + */ + public static boolean isLiveStream(final StreamType streamType) { + return streamType == StreamType.LIVE_STREAM + || streamType == StreamType.AUDIO_LIVE_STREAM; + } +} diff --git a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java index 22ab6cf2b..c4f1675cf 100644 --- a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java @@ -9,6 +9,7 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Build; +import android.text.TextUtils; import android.widget.Toast; import androidx.annotation.NonNull; @@ -246,7 +247,7 @@ public final class ShareUtils { final Intent shareIntent = new Intent(Intent.ACTION_SEND); shareIntent.setType("text/plain"); shareIntent.putExtra(Intent.EXTRA_TEXT, content); - if (!title.isEmpty()) { + if (!TextUtils.isEmpty(title)) { shareIntent.putExtra(Intent.EXTRA_TITLE, title); shareIntent.putExtra(Intent.EXTRA_SUBJECT, title); } diff --git a/app/src/main/res/drawable-night/ic_campaign.xml b/app/src/main/res/drawable-night/ic_campaign.xml new file mode 100644 index 000000000..eabaddaee --- /dev/null +++ b/app/src/main/res/drawable-night/ic_campaign.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-night/ic_drag_handle.xml b/app/src/main/res/drawable-night/ic_drag_handle.xml index 9378f4b23..a6d3b5270 100644 --- a/app/src/main/res/drawable-night/ic_drag_handle.xml +++ b/app/src/main/res/drawable-night/ic_drag_handle.xml @@ -2,9 +2,9 @@ android:width="24dp" android:height="24dp" android:tint="#FFFFFF" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M20,9H4v2h16V9zM4,15h16v-2H4V15z" /> diff --git a/app/src/main/res/drawable-night/ic_edit.xml b/app/src/main/res/drawable-night/ic_edit.xml deleted file mode 100644 index 85d32985f..000000000 --- a/app/src/main/res/drawable-night/ic_edit.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable-night/ic_expand_less.xml b/app/src/main/res/drawable-night/ic_expand_less.xml deleted file mode 100644 index 4ff5565fa..000000000 --- a/app/src/main/res/drawable-night/ic_expand_less.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable-night/ic_import_export.xml b/app/src/main/res/drawable-night/ic_import_export.xml deleted file mode 100644 index bab84a60d..000000000 --- a/app/src/main/res/drawable-night/ic_import_export.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable-night/ic_info_outline.xml b/app/src/main/res/drawable-night/ic_info_outline.xml index d772001df..085665e4b 100644 --- a/app/src/main/res/drawable-night/ic_info_outline.xml +++ b/app/src/main/res/drawable-night/ic_info_outline.xml @@ -2,9 +2,9 @@ android:width="24dp" android:height="24dp" android:tint="#FFFFFF" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M11,7h2v2h-2zM11,11h2v6h-2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z" /> diff --git a/app/src/main/res/drawable-night/ic_megaphone.xml b/app/src/main/res/drawable-night/ic_megaphone.xml deleted file mode 100644 index dd87fde17..000000000 --- a/app/src/main/res/drawable-night/ic_megaphone.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable-night/ic_motorcycle.xml b/app/src/main/res/drawable-night/ic_motorcycle.xml index 2a42a1d09..4ffd8b451 100644 --- a/app/src/main/res/drawable-night/ic_motorcycle.xml +++ b/app/src/main/res/drawable-night/ic_motorcycle.xml @@ -2,9 +2,9 @@ android:width="24dp" android:height="24dp" android:tint="#FFFFFF" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M17.42,10L13.41,6H9V8H12.59L14.59,10H6.5C4,10 2,12 2,14.5C2,17 4,19 6.5,19C8.72,19 10.56,17.38 10.92,15.27L13.04,14C13,14.17 13,14.33 13,14.5C13,17 15,19 17.5,19C20,19 22,17 22,14.5C22,12 20,10 17.5,10M8.84,15.26C8.5,16.27 7.58,17 6.47,17C5.09,17 3.97,15.88 3.97,14.5C3.97,13.12 5.09,12 6.47,12C7.59,12 8.5,12.74 8.84,13.75H6V15.25L8.84,15.26M17.47,17C16.09,17 14.97,15.88 14.97,14.5C14.97,13.12 16.09,12 17.47,12A2.5,2.5 0 0,1 19.97,14.5A2.5,2.5 0 0,1 17.47,17Z" /> diff --git a/app/src/main/res/drawable-night/ic_palette.xml b/app/src/main/res/drawable-night/ic_palette.xml index a6cdb536e..8edcceb76 100644 --- a/app/src/main/res/drawable-night/ic_palette.xml +++ b/app/src/main/res/drawable-night/ic_palette.xml @@ -2,9 +2,9 @@ android:width="24dp" android:height="24dp" android:tint="#FFFFFF" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M12,2C6.49,2 2,6.49 2,12s4.49,10 10,10c1.38,0 2.5,-1.12 2.5,-2.5c0,-0.61 -0.23,-1.2 -0.64,-1.67c-0.08,-0.1 -0.13,-0.21 -0.13,-0.33c0,-0.28 0.22,-0.5 0.5,-0.5H16c3.31,0 6,-2.69 6,-6C22,6.04 17.51,2 12,2zM17.5,13c-0.83,0 -1.5,-0.67 -1.5,-1.5c0,-0.83 0.67,-1.5 1.5,-1.5s1.5,0.67 1.5,1.5C19,12.33 18.33,13 17.5,13zM14.5,9C13.67,9 13,8.33 13,7.5C13,6.67 13.67,6 14.5,6S16,6.67 16,7.5C16,8.33 15.33,9 14.5,9zM5,11.5C5,10.67 5.67,10 6.5,10S8,10.67 8,11.5C8,12.33 7.33,13 6.5,13S5,12.33 5,11.5zM11,7.5C11,8.33 10.33,9 9.5,9S8,8.33 8,7.5C8,6.67 8.67,6 9.5,6S11,6.67 11,7.5z" /> diff --git a/app/src/main/res/drawable-night/ic_playlist_add.xml b/app/src/main/res/drawable-night/ic_playlist_add.xml index 1ea41dc22..bf86fd24a 100644 --- a/app/src/main/res/drawable-night/ic_playlist_add.xml +++ b/app/src/main/res/drawable-night/ic_playlist_add.xml @@ -2,9 +2,9 @@ android:width="24dp" android:height="24dp" android:tint="#FFFFFF" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M14,10H3v2h11V10zM14,6H3v2h11V6zM18,14v-4h-2v4h-4v2h4v4h2v-4h4v-2H18zM3,16h7v-2H3V16z" /> diff --git a/app/src/main/res/drawable-night/ic_playlist_add_check.xml b/app/src/main/res/drawable-night/ic_playlist_add_check.xml index 0581bbe4b..a69d284a1 100644 --- a/app/src/main/res/drawable-night/ic_playlist_add_check.xml +++ b/app/src/main/res/drawable-night/ic_playlist_add_check.xml @@ -2,9 +2,18 @@ android:width="24dp" android:height="24dp" android:tint="#FFFFFF" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M3,10h11v2h-11z" /> + + + diff --git a/app/src/main/res/drawable-night/ic_search_add.xml b/app/src/main/res/drawable-night/ic_search_add.xml index 57c8a1ada..856433e41 100644 --- a/app/src/main/res/drawable-night/ic_search_add.xml +++ b/app/src/main/res/drawable-night/ic_search_add.xml @@ -1,9 +1,9 @@ + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M19,17.59L17.59,19L7,8.41V15H5V5H15V7H8.41L19,17.59Z" /> diff --git a/app/src/main/res/drawable-night/ic_settings.xml b/app/src/main/res/drawable-night/ic_settings.xml index bc30c52d8..61ee02ee0 100644 --- a/app/src/main/res/drawable-night/ic_settings.xml +++ b/app/src/main/res/drawable-night/ic_settings.xml @@ -6,5 +6,5 @@ android:viewportHeight="24"> + android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z" /> diff --git a/app/src/main/res/drawable-night/ic_thumb_down.xml b/app/src/main/res/drawable-night/ic_thumb_down.xml index 0303551c7..1ee3ed018 100644 --- a/app/src/main/res/drawable-night/ic_thumb_down.xml +++ b/app/src/main/res/drawable-night/ic_thumb_down.xml @@ -2,9 +2,9 @@ android:width="24dp" android:height="24dp" android:tint="#FFFFFF" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M15,3L6,3c-0.83,0 -1.54,0.5 -1.84,1.22l-3.02,7.05c-0.09,0.23 -0.14,0.47 -0.14,0.73v2c0,1.1 0.9,2 2,2h6.31l-0.95,4.57 -0.03,0.32c0,0.41 0.17,0.79 0.44,1.06L9.83,23l6.59,-6.59c0.36,-0.36 0.58,-0.86 0.58,-1.41L17,5c0,-1.1 -0.9,-2 -2,-2zM19,3v12h4L23,3h-4z" /> diff --git a/app/src/main/res/drawable-night/ic_thumb_up.xml b/app/src/main/res/drawable-night/ic_thumb_up.xml index f83de1ecc..c4e387866 100644 --- a/app/src/main/res/drawable-night/ic_thumb_up.xml +++ b/app/src/main/res/drawable-night/ic_thumb_up.xml @@ -2,9 +2,9 @@ android:width="24dp" android:height="24dp" android:tint="#FFFFFF" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M1,21h4L5,9L1,9v12zM23,10c0,-1.1 -0.9,-2 -2,-2h-6.31l0.95,-4.57 0.03,-0.32c0,-0.41 -0.17,-0.79 -0.44,-1.06L14.17,1 7.59,7.59C7.22,7.95 7,8.45 7,9v10c0,1.1 0.9,2 2,2h9c0.83,0 1.54,-0.5 1.84,-1.22l3.02,-7.05c0.09,-0.23 0.14,-0.47 0.14,-0.73v-2z" /> diff --git a/app/src/main/res/drawable-night/ic_watch_later.xml b/app/src/main/res/drawable-night/ic_watch_later.xml index b7991f0c7..ff93ce2d7 100644 --- a/app/src/main/res/drawable-night/ic_watch_later.xml +++ b/app/src/main/res/drawable-night/ic_watch_later.xml @@ -1,9 +1,9 @@ + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M12,2C6.5,2 2,6.5 2,12s4.5,10 10,10s10,-4.5 10,-10S17.5,2 12,2zM16.2,16.2L11,13V7h1.5v5.2l4.5,2.7L16.2,16.2z" /> diff --git a/app/src/main/res/drawable/ic_campaign.xml b/app/src/main/res/drawable/ic_campaign.xml new file mode 100644 index 000000000..4a0e2ddbb --- /dev/null +++ b/app/src/main/res/drawable/ic_campaign.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_drag_handle.xml b/app/src/main/res/drawable/ic_drag_handle.xml index 8f7f335a3..416631324 100644 --- a/app/src/main/res/drawable/ic_drag_handle.xml +++ b/app/src/main/res/drawable/ic_drag_handle.xml @@ -1,9 +1,9 @@ + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M20,9H4v2h16V9zM4,15h16v-2H4V15z" /> diff --git a/app/src/main/res/drawable/ic_info_outline.xml b/app/src/main/res/drawable/ic_info_outline.xml index 9c51a4ffb..6c6060619 100644 --- a/app/src/main/res/drawable/ic_info_outline.xml +++ b/app/src/main/res/drawable/ic_info_outline.xml @@ -1,9 +1,9 @@ + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M11,7h2v2h-2zM11,11h2v6h-2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z" /> diff --git a/app/src/main/res/drawable/ic_megaphone.xml b/app/src/main/res/drawable/ic_megaphone.xml deleted file mode 100644 index f75a104db..000000000 --- a/app/src/main/res/drawable/ic_megaphone.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_motorcycle.xml b/app/src/main/res/drawable/ic_motorcycle.xml index 185d6992c..e354f8bda 100644 --- a/app/src/main/res/drawable/ic_motorcycle.xml +++ b/app/src/main/res/drawable/ic_motorcycle.xml @@ -1,9 +1,9 @@ + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M17.42,10L13.41,6H9V8H12.59L14.59,10H6.5C4,10 2,12 2,14.5C2,17 4,19 6.5,19C8.72,19 10.56,17.38 10.92,15.27L13.04,14C13,14.17 13,14.33 13,14.5C13,17 15,19 17.5,19C20,19 22,17 22,14.5C22,12 20,10 17.5,10M8.84,15.26C8.5,16.27 7.58,17 6.47,17C5.09,17 3.97,15.88 3.97,14.5C3.97,13.12 5.09,12 6.47,12C7.59,12 8.5,12.74 8.84,13.75H6V15.25L8.84,15.26M17.47,17C16.09,17 14.97,15.88 14.97,14.5C14.97,13.12 16.09,12 17.47,12A2.5,2.5 0 0,1 19.97,14.5A2.5,2.5 0 0,1 17.47,17Z" /> diff --git a/app/src/main/res/drawable/ic_next.xml b/app/src/main/res/drawable/ic_next.xml index 1459bff0a..9f3462892 100644 --- a/app/src/main/res/drawable/ic_next.xml +++ b/app/src/main/res/drawable/ic_next.xml @@ -7,5 +7,5 @@ + android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z" /> diff --git a/app/src/main/res/drawable/ic_palette.xml b/app/src/main/res/drawable/ic_palette.xml index 71c37ddac..568f8e4de 100644 --- a/app/src/main/res/drawable/ic_palette.xml +++ b/app/src/main/res/drawable/ic_palette.xml @@ -1,9 +1,9 @@ + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M12,2C6.49,2 2,6.49 2,12s4.49,10 10,10c1.38,0 2.5,-1.12 2.5,-2.5c0,-0.61 -0.23,-1.2 -0.64,-1.67c-0.08,-0.1 -0.13,-0.21 -0.13,-0.33c0,-0.28 0.22,-0.5 0.5,-0.5H16c3.31,0 6,-2.69 6,-6C22,6.04 17.51,2 12,2zM17.5,13c-0.83,0 -1.5,-0.67 -1.5,-1.5c0,-0.83 0.67,-1.5 1.5,-1.5s1.5,0.67 1.5,1.5C19,12.33 18.33,13 17.5,13zM14.5,9C13.67,9 13,8.33 13,7.5C13,6.67 13.67,6 14.5,6S16,6.67 16,7.5C16,8.33 15.33,9 14.5,9zM5,11.5C5,10.67 5.67,10 6.5,10S8,10.67 8,11.5C8,12.33 7.33,13 6.5,13S5,12.33 5,11.5zM11,7.5C11,8.33 10.33,9 9.5,9S8,8.33 8,7.5C8,6.67 8.67,6 9.5,6S11,6.67 11,7.5z" /> diff --git a/app/src/main/res/drawable/ic_playlist_add.xml b/app/src/main/res/drawable/ic_playlist_add.xml index f30f29557..341894ba9 100644 --- a/app/src/main/res/drawable/ic_playlist_add.xml +++ b/app/src/main/res/drawable/ic_playlist_add.xml @@ -1,9 +1,9 @@ + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M14,10H3v2h11V10zM14,6H3v2h11V6zM18,14v-4h-2v4h-4v2h4v4h2v-4h4v-2H18zM3,16h7v-2H3V16z" /> diff --git a/app/src/main/res/drawable/ic_playlist_add_check.xml b/app/src/main/res/drawable/ic_playlist_add_check.xml index d99e6e75c..de5924f60 100644 --- a/app/src/main/res/drawable/ic_playlist_add_check.xml +++ b/app/src/main/res/drawable/ic_playlist_add_check.xml @@ -1,9 +1,18 @@ + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M3,10h11v2h-11z" /> + + + diff --git a/app/src/main/res/drawable/ic_playlist_play.xml b/app/src/main/res/drawable/ic_playlist_play.xml index 4e31a4dde..34b0f05bf 100644 --- a/app/src/main/res/drawable/ic_playlist_play.xml +++ b/app/src/main/res/drawable/ic_playlist_play.xml @@ -2,9 +2,18 @@ android:width="24dp" android:height="24dp" android:tint="#FFFFFF" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M3,10h11v2h-11z" /> + + + diff --git a/app/src/main/res/drawable/ic_previous.xml b/app/src/main/res/drawable/ic_previous.xml index e9fe7448d..f18ad469e 100644 --- a/app/src/main/res/drawable/ic_previous.xml +++ b/app/src/main/res/drawable/ic_previous.xml @@ -7,5 +7,5 @@ + android:pathData="M6,6h2v12L6,18zM9.5,12l8.5,6L18,6z" /> diff --git a/app/src/main/res/drawable/ic_search_add.xml b/app/src/main/res/drawable/ic_search_add.xml index 398f1407d..889ea4c6f 100644 --- a/app/src/main/res/drawable/ic_search_add.xml +++ b/app/src/main/res/drawable/ic_search_add.xml @@ -1,9 +1,9 @@ + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M19,17.59L17.59,19L7,8.41V15H5V5H15V7H8.41L19,17.59Z" /> diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml index a671514fc..e50f6fe3a 100644 --- a/app/src/main/res/drawable/ic_settings.xml +++ b/app/src/main/res/drawable/ic_settings.xml @@ -5,5 +5,5 @@ android:viewportHeight="24"> + android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z" /> diff --git a/app/src/main/res/drawable/ic_thumb_down.xml b/app/src/main/res/drawable/ic_thumb_down.xml index 0484764da..103e5fea3 100644 --- a/app/src/main/res/drawable/ic_thumb_down.xml +++ b/app/src/main/res/drawable/ic_thumb_down.xml @@ -1,9 +1,9 @@ + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M15,3L6,3c-0.83,0 -1.54,0.5 -1.84,1.22l-3.02,7.05c-0.09,0.23 -0.14,0.47 -0.14,0.73v2c0,1.1 0.9,2 2,2h6.31l-0.95,4.57 -0.03,0.32c0,0.41 0.17,0.79 0.44,1.06L9.83,23l6.59,-6.59c0.36,-0.36 0.58,-0.86 0.58,-1.41L17,5c0,-1.1 -0.9,-2 -2,-2zM19,3v12h4L23,3h-4z" /> diff --git a/app/src/main/res/drawable/ic_thumb_up.xml b/app/src/main/res/drawable/ic_thumb_up.xml index 58dbfafe4..2b9fbdf4c 100644 --- a/app/src/main/res/drawable/ic_thumb_up.xml +++ b/app/src/main/res/drawable/ic_thumb_up.xml @@ -1,9 +1,9 @@ + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M1,21h4L5,9L1,9v12zM23,10c0,-1.1 -0.9,-2 -2,-2h-6.31l0.95,-4.57 0.03,-0.32c0,-0.41 -0.17,-0.79 -0.44,-1.06L14.17,1 7.59,7.59C7.22,7.95 7,8.45 7,9v10c0,1.1 0.9,2 2,2h9c0.83,0 1.54,-0.5 1.84,-1.22l3.02,-7.05c0.09,-0.23 0.14,-0.47 0.14,-0.73v-2z" /> diff --git a/app/src/main/res/drawable/ic_watch_later.xml b/app/src/main/res/drawable/ic_watch_later.xml index 5fe8273d9..72952bcaa 100644 --- a/app/src/main/res/drawable/ic_watch_later.xml +++ b/app/src/main/res/drawable/ic_watch_later.xml @@ -1,9 +1,9 @@ + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M12,2C6.5,2 2,6.5 2,12s4.5,10 10,10s10,-4.5 10,-10S17.5,2 12,2zM16.2,16.2L11,13V7h1.5v5.2l4.5,2.7L16.2,16.2z" /> diff --git a/app/src/main/res/layout-large-land/fragment_video_detail.xml b/app/src/main/res/layout-large-land/fragment_video_detail.xml index 7f664f5d4..3bee4bf9a 100644 --- a/app/src/main/res/layout-large-land/fragment_video_detail.xml +++ b/app/src/main/res/layout-large-land/fragment_video_detail.xml @@ -695,10 +695,8 @@ diff --git a/app/src/main/res/layout/activity_player_queue_control.xml b/app/src/main/res/layout/activity_player_queue_control.xml index ec47992bb..60beb75be 100644 --- a/app/src/main/res/layout/activity_player_queue_control.xml +++ b/app/src/main/res/layout/activity_player_queue_control.xml @@ -31,84 +31,78 @@ android:id="@+id/play_queue" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_above="@id/center" + android:layout_above="@id/metadata" android:layout_below="@id/appbar" android:scrollbars="vertical" app:layoutManager="LinearLayoutManager" tools:listitem="@layout/play_queue_item" /> - + + - - - - - - - + android:layout_above="@id/progress_bar" + android:background="?attr/selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:orientation="vertical" + android:padding="8dp" + tools:ignore="RtlHardcoded,RtlSymmetry"> - + android:ellipsize="marquee" + android:fadingEdge="horizontal" + android:marqueeRepeatLimit="marquee_forever" + android:scrollHorizontally="true" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceLarge" + android:textSize="14sp" + tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis nec aliquam augue, eget cursus est. Ut id tristique enim, ut scelerisque tellus. Sed ultricies ipsum non mauris ultricies, commodo malesuada velit porta." /> + + + + android:paddingRight="12dp" + android:layout_above="@+id/playback_controls"> - diff --git a/app/src/main/res/layout/fragment_video_detail.xml b/app/src/main/res/layout/fragment_video_detail.xml index 202a64725..165c690dd 100644 --- a/app/src/main/res/layout/fragment_video_detail.xml +++ b/app/src/main/res/layout/fragment_video_detail.xml @@ -672,10 +672,8 @@ @@ -722,7 +722,7 @@ android:layout_height="70dp" android:layout_centerInParent="true" tools:ignore="ContentDescription" - tools:src="@drawable/ic_brightness" /> + tools:src="@drawable/ic_brightness_high" /> diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 220738f83..f90a82c44 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -42,7 +42,7 @@ رابط غير مدعوم استخدام مشغل صوت خارجي استخدام مشغل فيديو خارجي - محتوى غير متوفر + المحتوى غير متوفر تعذر تحميل كافة الصور المصغرة خطأ تعذر تحليل الموقع @@ -56,7 +56,7 @@ أسود سجل المشاهدة سجل المشاهدة و ذاكرة التخزين المؤقت - محتوى + المحتوى التحميلات الملفات المحملة الجميع @@ -554,7 +554,7 @@ مساعدة هذا المحتوى ليس مدعوم من قبل NewPipe. \n -\nنامل ان يكون مدعوما في التحديثات القادمة. +\nنأمل أن يكون مدعوما في التحديثات القادمة. ∞ فيديو +100 فيديو الفنانين @@ -631,7 +631,7 @@ قم بإيقاف التشغيل لإخفاء وصف الفيديو والمعلومات الإضافية إظهار الوصف فتح مع - يتوفر هذا المحتوى فقط للمستخدمين الذين قاموا بالدفع، لذلك لا يمكن بثها أو تنزيلها من قبل NewPipe. + يتوفر هذا المحتوى فقط للمستخدمين الذين قاموا بالدفع، لذلك لا يمكن بثه أو تنزيله عبر NewPipe. يتوفر هذا الفيديو فقط لأعضاء YouTube Music Premium ، لذلك لا يمكن بثه أو تنزيله من قبل NewPipe. هذا المحتوى خاص، لذلك لا يمكن دفقه أو تنزيله بواسطة NewPipe. هذا هو مسار SoundCloud Go+ ، على الأقل في بلدك ، لذلك لا يمكن بثها أو تنزيلها من قبل NewPipe. @@ -715,4 +715,6 @@ لا تبدأ تشغيل مقاطع الفيديو في المشغل المصغر، ولكن قم بتدوير وضع ملء الشاشة مباشرة، إذا تم تأمين التدوير التلقائي. لا يزال بإمكانك الوصول إلى المشغل المصغر عن طريق الخروج من ملء الشاشة بدء تشغيل المشغل الرئيسي في وضع ملء الشاشة + وضع التالي على قائمة الانتظار + تم وضع التالي على قائمة الانتظار \ No newline at end of file diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index b1675d6de..1791c1794 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -189,7 +189,7 @@ [Neznámý] Začít přehrávat na pozadí Začít přehrávat v pop-upu - Donate + Přispět NewPipe je vyvíjen dobrovolníky, kteří tráví svůj volný čas, aby vaše zkušenost s aplikací byla co nejlepší. Vraťte vývojářům něco zpět, aby mohli NewPipe dále zlepšovat a zároveň si vychutnat šálek kávy. Daruj Webová stránka @@ -283,7 +283,8 @@ \n3. Klikněte na \"Jsou zahrnuta všechna data z YouTube\" pak na \"Zrušit výběr všech\" a pak vyberte jen \"odběry\" a klikněte na OK \n4. Klikněte na \"Další krok\" a pak na \"Vytvořit export\" \n5. Vyčkejte než se objeví tlačítko \"Stáhnout\" a klikněte na něj -\n6. Ze staženého zip archivu extrahujte .json soubor (nejčastěji na cestě \"Takeout/YouTube a YouTube Music/odběry/odběry.json\") a importujte jej. +\n6. Klikněte IMPORTOVAT SOUBOR a vyberte stažený .zip soubor z předchozího kroku +\n7. [Pokud se import .zip souboru nezdaří] Rozbalte soubor subscriptions.csv (měl by se nacházet v adresáři \"YouTube and YouTube Music/subscriptions/subscriptions.csv\"), stiskněte IMPORTOVAT SOUBOR níže a vyberte rozbalený soubor subscriptions.csv Importovat SoundCloud profil zadáním URL adresy nebo vašeho ID: \n \n1. Ve svém prohlížeči povolte \"režim pro PC\" (pro mobilní zařízení není stránka dostupná) @@ -659,7 +660,7 @@ Komentáře jsou vypnuty Srdíčko od tvůrce Označit jako zhlédnuté - Načítám podrobnosti kanálu… + Načítání podrobností kanálu… Chyba při zobrazení prodrobností kanálu %1$s stažení smazáno @@ -675,4 +676,9 @@ Ukázat indikátory obrázků Vzdálené návrhy vyhledávání Lokální návrhy vyhledávání + Pokud je vypnuté automatické otáčení, nespouštějte video v mini přehrávači, ale přepněte se přímo do režimu celé obrazovky. Do mini přehrávače se lze i nadále dostat ukončením režimu celé obrazovky + Další ve frontě + Přidat do fronty (další) + Tažením položky odstraníte + Spustit hlavní přehrávač na celé obrazovce \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 6fc93fb69..ca4d3e4d9 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -544,7 +544,7 @@ Nur nicht gruppierte Abonnements anzeigen Wiedergabelisten-Seite Bisher keine Lesezeichen für Wiedergabelisten - Playlist auswählen + Wiedergabeliste auswählen Bitte überprüfen Sie, ob es schon Fragen zu diesem Thema gibt. Doppelt erstellte Tickets kosten uns Zeit, die wir nutzen könnten, um diesen Fehler zu beheben. Zeige Ergebnisse für: %s Wiedergabe automatisch starten — %s diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 79807facf..1e0d406a1 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -190,7 +190,7 @@ NewPipe es desarrollado por voluntarios que emplean su tiempo libre para brindarle la mejor experiencia. Haz una aportación para ayudarlos a crear un NewPipe mejor mientras disfrutan de una taza de café. Dar de vuelta Sitio web - Visite el sitio web de NewPipe para más información y noticias. + Visita el sitio web de NewPipe para más información y noticias. País predefinido del contenido Cambiar a segundo plano Cambiar a emergente @@ -314,11 +314,11 @@ Se ha borrado 1 elemento. NewPipe es un software copyleft libre: puedes usarlo, estudiarlo, compartirlo y mejorarlo a voluntad. Específicamente, puedes redistribuirlo y/o modificarlo bajo los términos de la Licencia Pública General GNU publicada por la Free Software Foundation, ya sea la versión 3 de la licencia, o (a tu elección) cualquier versión posterior. ¿Quieres importar también los ajustes\? - Normativa de privacidad de NewPipe + Política de privacidad de NewPipe El proyecto NewPipe toma tu privacidad muy en serio. Por ello, la aplicación no recopila ningún dato sin tu consentimiento. -\nLa normativa de privacidad de NewPipe explica en detalle qué datos se envían y almacenan al enviar un informe de fallo. - Leer la normativa de privacidad - Para cumplir con el «Reglamento general europeo de protección de datos (GDPR)», atraemos tu atención sobre la normativa de privacidad de NewPipe. Por favor léase cuidadosamente. +\nLa política de privacidad de NewPipe explica en detalle qué datos se envían y almacenan al enviar un informe de fallo. + Leer política de privacidad + Para cumplir con el «Reglamento general europeo de protección de datos (GDPR)», atraemos tu atención sobre la política de privacidad de NewPipe. Por favor léase cuidadosamente. \nDebes aceptarlo para enviarnos el informe de error. Aceptar Declinar @@ -670,4 +670,6 @@ Desliza los elementos para removerlos Si la rotación automática está bloqueada, no inicie los videos en el mini reproductor, sino pase directamente a modo de pantalla completa. Aún podrá acceder al mini reproductor al salir del modo pantalla completa Iniciar reproductor principal en pantalla completa + Añadido el siguiente vídeo a la cola + Añadir el siguiente vídeo a la cola \ No newline at end of file diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index dec03feef..1321806f5 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -240,7 +240,7 @@ Eemalda Üksikasjad Heli seaded - Hoia järjekorda lisamiseks + Järjekorda lisamiseks vajuta Hakka taustal mängima Hakka mängima hüpikaknas Ava sahtel @@ -367,7 +367,7 @@ peatatud järjekorras järeltöötlus - Järjekord + Esitusjärjekord Tegevus keelati süsteemi poolt Allalaadimine nurjus Loo kordumatu nimi @@ -667,4 +667,6 @@ Kui ekraani pööramine on lukustatud, siis videote esitamisel ära käivita väikest vaadet, vaid käivita kohe täisekraanivaade. Viimasest väljumisel näed väikest esitusvaadet Käivita meediamängija täisekraanivaates + Lisasin esitamiseks järgmisena + Lisa esitamiseks järgmisena \ No newline at end of file diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index d79c6ce27..9ca4bfae6 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -488,7 +488,7 @@ Talde izena hutsik %d hautatuta - %d hautatuta + %d hautatutak Ez da harpidetzarik aukeratu Hautatu harpidetzak @@ -667,4 +667,6 @@ Lerratu elementuak aldetara ezabatzeko Ez hasi bideoak mini erreproduzitzailean eta hasi bideoak pantaila osoan zuzenean, auto biraketa blokeatuta badago. Mini erreproduzitzailea erabili dezakezu pantaila osotik irtetzean Hasi erreproduzitzaile nagusia pantaila osoan + Isatsari bideo hau erantsita + Gehitu bideo hau isatsari \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 91f07827b..f4226497a 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -253,7 +253,7 @@ Aucun dossier de ce type Aucun fichier ou contenu de ce type Le fichier n’existe pas ou n’est pas accessible en lecture ou en écriture - Le nom du fichier ne peut être vide + Le nom du fichier ne peut pas être vide Une erreur est survenue : %1$s Télécharger le flux Ajouter automatiquement le flux suivant à la liste de lecture @@ -670,4 +670,5 @@ Ne pas lancer les vidéos dans le mini lecteur mais directement en plein écran si la rotation automatique est verrouillée. Vous pouvez toujours accéder au mini-lecteur en quittant le mode plein écran Lancer le lecteur principal en plein écran Mettre en file d’attente la suivante + Placé comme suivant dans liste de lecture \ No newline at end of file diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index a2388b8a0..88e79451e 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -49,7 +49,7 @@ Zapamti veličinu i poziciju skočnog prozora Zapamti posljednju veličinu i poziciju skočnog prozora Prijedlozi pri traženju - Prikaži prijedloge pri traženju + Odaberi prijedloge koji se prikazuju pri traženju Povijest pretraživanja Svaku pretragu spremi lokalno Prati povijest diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index b6cd2a7e2..82c867f86 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -104,7 +104,7 @@ Ingat properti popup Ingat ukuran dan posisi terakhir popup Saran pencarian - Tampilkan saran pencarian saat mencari + Menampilkan saran pencarian saat mencari Resolusi terbaik Unduhan Karakter yang diizinkan sebagai nama berkas @@ -638,4 +638,16 @@ Komentar dinonaktifkan Pratinjau thumbnail bilah laju Tandai ditonton + Buka pemutar utama dalam layar penuh + + %s unduhan selesai + + Geser item untuk membuangnya + Disukai oleh kreator + Saran pencarian lokal + Saran pencarian remote + Tampilkan indikator gambar + + Menghapus %1$s unduhan + \ No newline at end of file diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 191b6581d..aaf02a5dd 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -16,7 +16,7 @@ 비디오 파일이 다운로드 될 폴더를 선택하세요 기본 해상도 Kodi로 재생 - Kore 앱이 발견되지 않았습니다. Kore를 설치할까요? + Kore를 설치할까요\? \"Kodi로 재생\" 옵션 표시 비디오를 Kodi 미디어 센터를 사용해 재생하는 옵션을 표시합니다 오디오 @@ -282,7 +282,7 @@ \n \n계속하시겠습니까\? 썸네일 로드하기 - 동영상 썸네일을 로드하지 않으며, 데이터와 메모리 사용을 최대한 줄입니다. 이 옵션을 선택 시 모든 메모리 캐시와 저장소 캐시를 삭제합니다. + 동영상 썸네일을 로드하지 않으며, 데이터와 메모리 사용을 최대한 줄입니다. 이 옵션을 선택 시 모든 메모리 캐시와 저장소 캐시를 삭제합니다 이미지 캐시 지워짐 캐시된 메타데이터 지우기 캐시된 모든 웹페이지 데이터 지우기 @@ -501,7 +501,7 @@ 재생목록 실행 알림 URL을 인식할 수 없습니다. 다른 앱으로 여시겠습니까\? - 스트림을 비우기 전 확인을 요청합니다. + 대기열을 비우기 전 확인하도록 합니다. 안드로이드에서 썸네일의 색상에 따라 알림 색상을 조절합니다. (지원되지 않는 기기가 있을 수 있습니다.) 버퍼링 다섯번째 버튼 @@ -514,4 +514,10 @@ 활성화된 플레이어 대기열이 교체됩니다. 으로(로) 열기 시청한 것으로 처리 + 비활성화하면 비디오 설명과 추가 정보를 표시하지 않습니다 + 설명 표시 + 원래 플레이어에서 다른 플레이어로 바꾸면 대기열이 지워집니다 + 어두운 테마 + 최대 3개까지 축소 알림에 표시될 항목을 고를 수 있습니다! + 아래 항목을 터치해서 편집하세요. 위에서부터 체크된 3개 항목은 축소 알림일 때도 표시됩니다 \ No newline at end of file diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 05f480d73..f33e5d9cd 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -274,7 +274,8 @@ \n3. Klik op \"Alle YouTube-gegevens inbegrepen\", dan op \"Selectie van alle items ongedaan maken\", dan selecteer alleen \"abonnementen\" en klik op \"OK\" \n4. Klik op \"Volgende stap\", dan op \"Export maken\" \n5. Klik op de knop \"Downloaden\" nadat deze verschijnt -\n6. Uit de Takeout zipfile, pak de .json uit (gebruikelijk in de folder \"YouTube en YouTube Music/abonnementen/abonnementen.json\") en importeer deze hier. +\n6. Klik onder op \"Bestand importeren\" en selecteer de gedownloade zip file +\n7. [Als de zip import faalt] Uit de zip file, pak de .csv uit (gebruikelijk in de folder \"YouTube en YouTube Music/abonnementen/abonnementen.csv\"), klik onder op \"Bestand importeren\" en selecteer de uitgepakte zip file Importeer een SoundCloud-profiel door de URL of het ID ervan in te voeren: \n \n1. Kies een webbrowser en schakel bureaubladmodus in (de website is niet beschikbaar voor mobiele apparaten) @@ -574,9 +575,9 @@ Toon inhoud die mogelijk niet geschikt is voor kinderen omwille van een leeftijdslimiet (zoals 18+) Laat Android de kleur van de notificatie aanpassen, op basis van de meest voorkomende kleur in de thumbnail (let op: niet beschikbaar op elk apparaat) Notificatie kleur aanpassen - Toon miniatuurafbeelding op het vergrendelscherm als achtergrond en in de meldingen + Toon miniatuurafbeelding op het vergrendelscherm als achtergrond en in de notificaties Toon miniatuurafbeelding - Recent + Recente Hash berekenen Meldingen over de voortgang van video hashing Video Hash Melding @@ -588,7 +589,7 @@ Hoofdstukken Gerelateerde streams Reacties - Zet uit om video beschrijving en extra informatie te verbergen + Zet uit om video omschrijving en andere informatie te verbergen Open met Radio Uitgelicht @@ -606,7 +607,7 @@ Selecteer uw favoriete nacht thema — %s Automatisch (toestel thema) Toon details van kanaal - Nachtmodus + Nacht Thema Intern Privé Niet vermeld @@ -655,4 +656,17 @@ Zoeksuggesties op afstand Lokale zoeksuggesties Markeer als bekeken + + %1$s download verwijderd + %1$s downloads verwijderd + + + Download voltooid + %s downloads voltooid + + Volgende item in de wachtrij geplaatst + Plaats volgende item in de wachtrij + Veeg items om ze te verwijderen + Start geen video\'s in de minispeler, maar ga direct naar de volledige schermmodus, als automatisch draaien is vergrendeld. Je hebt nog steeds toegang tot de minispeler door de volledige schermmodus af te sluiten + Start hoofdspeler als volledig scherm \ No newline at end of file diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 7c988ee3e..0de5abcf0 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -117,7 +117,7 @@ Lekkie przesyłanie strumieniowe w systemie Android. Zobacz na GitHubie Licencja NewPipe - Niezależnie od tego, czy masz pomysł na tłumaczenie, zmiany w projekcie, oczyszczenie kodu źródłowego, czy na naprawdę ciężkie zmiany w kodzie - pomoc jest zawsze mile widziana. Im więcej jest zrobione, tym lepiej! + Niezależnie od tego, czy masz pomysł na tłumaczenie, zmiany w projekcie, oczyszczenie kodu źródłowego, czy na naprawdę ciężkie zmiany w kodzie — pomoc jest zawsze mile widziana. Im więcej jest zrobione, tym lepiej! Przeczytaj licencję Wkład Dozwolone znaki w nazwach plików @@ -304,7 +304,7 @@ \n4. Skopiuj adres URL profilu, na który zostałeś(-aś) przekierowany(-na). Brak strumieni do pobrania Preferowana akcja „otwórz” - Domyślna akcja podczas otwierania zawartości - %s + Domyślna akcja podczas otwierania zawartości — %s Napisy Zmodyfikuj rozmiar tekstu napisów odtwarzacza i style tła. Wymaga ponownego uruchomienia aplikacji, aby zmiany zostały uwzględnione Wyczyść historię oglądania diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 1080ee24b..1f53db3ce 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -105,7 +105,7 @@ Lembrar último tamanho e posição do popup Remove o som em algumas resoluções Sugestões de pesquisa - Mostra sugestões ao pesquisar + Escolha as sugestões a serem exibidas enquanto estiver buscando Melhor resolução Licenças de Terceiros Sobre @@ -264,14 +264,15 @@ Exportação anterior Não foi possível importar inscrições Não foi possível exportar inscrições - Importe inscrições do YouTubedo pelo Google takeout: + Importe inscrições do YouTube pelo Google takeout: \n \n1. Acesse este link: %1$s \n2. Logue quando solicitado \n3. Clique em \"Todos os dados incluídos\", em seguida, em \"Desmarque todos\", em seguida, selecione apenas \"assinaturas\" e clique em \"OK\" \n4. Clique em \"Próximo passo\" e, em seguida, em \"Criar exportação\" -\n5. Clique no botão \"Baixar\" depois de aparecer e -\n6. A partir do arquivo zip baixado, retire o arquivo .json (geralmente em \"YouTube e YouTube Music/assinaturas/assinaturas.json\") e importe aqui. +\n5. Clique no botão \"Baixar\" quando ele aparecer +\n6. Clique em Importar Arquivo abaixo e selecione o arquivo zip baixado +\n7. Caso a importação do arquivo zip falhe: Extraia o arquivo .csv (normalmente em \"YouTube e YouTube Music/subscriptions/subscriptions.csv\", clique em Importar Arquivo abaixo e selecione o arquivo cvs extraído Importe um perfil do SoundCloud digitando o URL ou seu ID: \n \n1. Ative o \"modo desktop\" no navegador (o site está indisponível em celulares) @@ -649,4 +650,23 @@ Comentários estão desabilitados Marcar como visto Curtido pelo criador + Exibir fitas coloridas de picasso no topo das imagens indicando sua fonte: vermelho para rede, azul para disco e verde para memória + Carregando detalhes do canal… + Erro ao exibir detalhes do canal + + %1$s download apagado + %1$s downloads apagados + + + Download finalizado + %s downloads finalizados + + Exibir indicadores com imagem + Adicionado na próxima posição da fila + Adicionar a próxima posição da fila + Deslize items para remove-los + Não iniciar o reprodutor pequeno, mas sim iniciar no modo tela cheia, caso rotação automática estiver bloqueada. Você pode ainda acessar o reprodutor pequeno saindo do modo tela cheia + Iniciar o reprodutor principal em tela cheia + Sugestões de busca remotas + Sugestões de busca locais \ No newline at end of file diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 0fc71d1fd..ad4bb5061 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -24,7 +24,7 @@ Progresso perdido, o ficheiro foi eliminado Canal não subscrito Nome do ficheiro - Mostrar indicadores de posição de reprodução em listas + Mostrar indicadores de posição de reprodução nas listas Notificações para NewPipe e para os reprodutores popup Desvincular (pode causar distorção) Escolha as sugestões a mostrar ao pesquisar @@ -68,7 +68,7 @@ Deseja apagar este grupo\? Não foi possível encontrar o servidor Não foi possível importar as subscrições - Descargas + Transferências A processar… Gestos para controlo de volume Este vídeo está restringido a idades. @@ -82,7 +82,7 @@ Remover todas as posições de reprodução\? Limitar fila de descargas Mostrar conteúdo com restrição de idade - O projeto NewPipe leva a sua privacidade muito a sério. Sendo assim, não recolhe quaisquer dados sem o seu consentimento. + O projeto NewPipe leva a sua privacidade muito a sério. Por isso, não recolhe nenhum dado sem o seu consentimento. \nA polícia de privacidade do NewPipe explica, em detalhe, os tipos de dados enviados sempre que submete um relatório de erro. Ficheiro Adicionar a @@ -93,7 +93,7 @@ Não foi possível ligar ao servidor Mostrar uma opção para reproduzir o vídeo no Kodi Modo de exibição - A pesquisa inexata permite que esta seja mais rápida mas reduz a precisão. Procurar por 5, 15 ou 25 segundos não funciona corretamente + A pesquisa inexata permite que esta seja mais rápida, mas reduz a precisão. Procurar por 5, 15 ou 25 segundos não funciona corretamente Permitir sobreposição a outras aplicações Exportar para Acerca de NewPipe @@ -129,8 +129,8 @@ Não existem canais subscritos Comportamento Tem que definir, nas definições, uma pasta para as descargas - Posições nas listas - Uma descarga será executada ao mesmo tempo + Posições em listas + Permitir apenas uma descarga de cada vez Não encontrado Reprodução em segundo plano Mostrar resoluções mais altas @@ -264,7 +264,7 @@ Deseja repor as predefinições\? Os reprodutores externos não suportam este tipo de hiperligações Mudar nome - \'Storage Access Framework\' permite descargas para um cartão SD externo + \'Storage Access Framework\' permite transferências para um cartão SD externo Duração da pesquisa de avanço/recuo rápido Ficheiro movido ou eliminado Última reprodução @@ -313,7 +313,7 @@ Mais caracteres especiais Pasta para ficheiros de áudio Detalhes: - Descargas + Transferências Fonte Página da lista de reprodução Definições @@ -323,7 +323,7 @@ Álbuns Exportação anterior Já existe um ficheiro com este nome - O servidor não aceita descargas multi-processo, tente novamente com @string/msg_threads = 1 + O servidor não aceita transferências multi-processo, tente novamente com @string/msg_threads = 1 Arraste para reordenar a recuperar Rejeitar @@ -341,7 +341,7 @@ %d dia %d dias - Pausa nas descargas + Pausa nas transferências Desafio reCAPTCHA Importar de 1 item eliminado. @@ -361,7 +361,7 @@ Não foi possível configurar o menu de descargas Sem limite Erro - Remover posições de reprodução + Limpar posições de reprodução A importar… Novidades Local @@ -372,7 +372,7 @@ ∞ vídeos A exportar… Mais apreciados - Utilizar a escolha de pastas do sistema (SAF) + Utilizar seletor de pastas do sistema (SAF) Detalhes Erro de rede Histórico de pesquisa @@ -403,7 +403,7 @@ Histórico de pesquisa removido Limpar histórico de pesquisas Erro - Lembrar propriedades de popup + Lembrar propriedades do popup Os ficheiros de vídeo descarregados serão guardados aqui Mudar para principal Esta permissão é necessária @@ -425,9 +425,9 @@ k MM Remover marcador - Útil ao trocar para dados móveis, mas algumas descargas não podem ser suspensas + Útil ao trocar para dados móveis, mas algumas transferências não podem ser suspensas Toque longo para colocar na fila - Descargas + Transferências Não foi possível criar o ficheiro Conferências Não foi possível ler as guias gravadas, portanto usando as guias predefinidas @@ -446,7 +446,7 @@ Atualizações Miniatura do vídeo Atualizações - Iniciar descarga + Iniciar transferências Guardar termos de pesquisa localmente URL não suportado Descarregar @@ -457,7 +457,7 @@ Reprodutor \'popup\' Disponível em alguns serviços, é geralmente muito mais rápido, mas pode devolver uma quantidade limitada de itens e muitas vezes informações incompletas (por exemplo, sem duração, tipo de item, sem estado ativo) Posições de reprodução removidas - Perguntar localização + Perguntar para onde transferir Mostrar informação Limpar histórico de visualizações Não é possível guardar no cartão SD. Repor pasta de descargas\? @@ -470,7 +470,7 @@ Formato padrão de vídeo Mostrar dica \"Toque longo para colocar na fila\" Escolha uma instância - Remover todos os dados da página web + Limpar todos os dados da página web Fechar menu Utilizar gestos para controlar o brilho do reprodutor Remover visualizados @@ -481,9 +481,9 @@ Vídeos Meta-dados em cache limpos Mostrar dica ao premir em segundo plano ou no botão \"Detalhes:\" da janela popup - Nenhum reprodutor foi encontrado (pode instalar VLC para reproduzir). - Ser-lhe-á perguntado onde guardar cada descarga. -\nAtive o seletor de pastas do sistema (SAF) se quiser descarregar para um cartão SD externo + Não foi encontrado um reprodutor (pode instalar VLC para reproduzir). + Ser-lhe-á perguntado onde guardar cada transferência. +\nAtive o seletor de pastas do sistema (SAF) se quiser transferir para um cartão SD externo Mostrar opção \"Reproduzir no Kodi\" Sem resultados Desativado @@ -517,7 +517,7 @@ \nO YouTube é um exemplo de um serviço que oferece este método rápido com a sua fonte RSS. \n \nAssim, a escolha resume-se ao que prefere: velocidade ou informação precisa. - Abrir em modo popup + Abrir no modo popup Pausa A carregar o conteúdo solicitado Página do canal @@ -529,7 +529,7 @@ Modificar escala de legendas e estilo de fundo. Tem que reiniciar a aplicação para aplicar as alterações Ação recusada pelo sistema Músicas - O idioma será alterado assim que reiniciar a aplicação + O idioma será alterado assim que reiniciar a app Adicionar instância Faixas Reproduzir no Kodi @@ -551,13 +551,13 @@ A fila do reprodutor ativo será substituída Mudar de um reprodutor para outro pode substituir a sua fila Pedir confirmação antes de limpar uma fila - Lembrar do último tamanho e posição do popup + Lembrar último tamanho e posição do popup Nada A carregar Baralhar Repetir Pode selecionar, no máximo, três ações para mostrar na notificação compacta! - Edite cada ação de notificação abaixo tocando nela. Selecione até três delas para serem mostrados na notificação compacta usando as caixas de seleção à direita + Edite cada ação de notificação abaixo tocando nela. Selecione até três delas para serem mostrados na notificação compacta a usar as caixas de seleção à direita Quinto botão de ação Quarto botão de ação Terceiro botão de ação @@ -573,7 +573,7 @@ Limpar cookies reCAPTCHA O YouTube fornece um \"Modo restrito\" que oculta o conteúdo destinado a adultos Mostrar conteúdo possivelmente impróprio para crianças porque tem um limite de idade (como 18+) - Fazer com que o Android personalize a cor da notificação de acordo com a cor principal na miniatura (esta opção não está disponível em todos os dispositivos) + Fazer com que o Android personalize a cor da notificação conforme a cor principal na miniatura (esta opção não está disponível em todos os dispositivos) Colorir notificação Usar miniaturas no fundo do ecrã de bloqueio e em notificações Mostrar miniatura @@ -600,13 +600,13 @@ Este vídeo tem uma restrição de idade. \nDevido às novas políticas do YouTube com vídeos com restrição de idade, o NewPipe não pode acessar nenhum dos seus fluxos de vídeo, portanto, é incapaz de reproduzi-lo. Rádio - Destaque + Destaques Resolver Descarga iniciada Pode escolher o seu tema escuro favorito abaixo Escolha o seu tema escuro favorito — %s - Automático (Tema do aparelho) - Tema Escuro + Automático (Tema do dispositivo) + Tema escuro Mostrar detalhes do canal Desative esta opção se estiverem a ocorrer erros de ecrã escuro ou paragens durante a reprodução Desativar túnel multimédia @@ -641,12 +641,12 @@ Não foi possível carregar o feed para \'%s\'. Erro ao carregar o feed A partir do Android 10, apenas o \'Storage Access Framework\' é compatível - O \'Storage Access Framework\' não é compatível com Android KitKat e versões anteriores - Sempre que descarregar um ficheiro, terá que indicar o local para o guardar + \'Storage Access Framework\' não é compatível com Android KitKat e versões anteriores + Sempre que transferir um ficheiro, terá que indicar o local para o guardar Não mostrar Baixa qualidade (menor) Alta qualidade (maior) - Pré visualização da miniatura da barra de busca + Pré-visualização da miniatura da barra de pesquisa Ainda sem pasta de descarregas definida, escolha agora a pasta de descarregas padrão Comentários estão desativados Marcar como visto @@ -665,8 +665,8 @@ %s descargas concluídas Deslizar itens para removê-los - Não iniciar vídeos no reprodutor mini, mas ir diretamente ao modo de ecrã cheio, se a rotação automática estiver bloqueada. Ainda pode acessar o reprodutor mini por sair do modo de ecrã cheio - Iniciar o reprodutor principal em ecrã cheio + Não iniciar vídeos no reprodutor mini, mas ir diretamente para ecrã completo se a rotação automática estiver bloqueada. Ainda pode aceder o reprodutor mini se sair do modo de ecrã completo. + Iniciar reprodutor principal em ecrã completo Enfileirado o próximo Enfileirar o próximo \ No newline at end of file diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index a1b9bd296..7b8cd4cdc 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -81,7 +81,7 @@ Descarga NewPipe Aplicação terminou em erro O quê:\\nPedido:\\nIdioma do conteúdo:\\nPaís do conteúdo\\nIdioma da app\\nServiço:\\nHora GMT:\\nPacote:\\nVersão:\\nVersão do SO: - Abrir em modo popup + Abrir no modo popup Preto Tudo Sim @@ -97,13 +97,13 @@ Desativado Resolução padrão para janela popup Mostrar resoluções mais altas - Apenas alguns aparelhos conseguem reproduzir vídeos em 2K/4K + Apenas alguns dispositivos conseguem reproduzir vídeos em 2K/4K Popup - Lembrar propriedades de popup + Lembrar propriedades do popup Limpar Segundo plano Remove o áudio em algumas resoluções - Lembrar do último tamanho e posição do popup + Lembrar último tamanho e posição do popup Sugestões de pesquisa Escolha as sugestões a mostrar ao pesquisar Melhor resolução @@ -229,7 +229,7 @@ Fechar menu Nome Limpar meta-dados em cache - Remover todos os dados da página web + Limpar todos os dados da página web Meta-dados em cache limpos Ficheiro Última reprodução @@ -273,7 +273,7 @@ \n7. [Se a importação do zip falhar] Extraia o ficheiro .csv (geralmente em \"YouTube e YouTube Music/subscriptions/subscriptions.csv\"), clique em IMPORT FILE abaixo e selecione o ficheiro csv extraído Importe o seu perfil SoundCloud digitando o URL ou a ID.: \n -\n1. Ative o modo desktop do seu navegador web (o site não está disponível para aparelhos móveis) +\n1. Ative o modo desktop do seu navegador web (o site não está disponível para dispositivos móveis) \n2. Aceda a este URL: %1$s \n3. Inicie a sessão \n4. Copie o URL do seu perfil. @@ -397,8 +397,8 @@ Fechar Continuar reprodução Restaurar última posição de reprodução - Posições nas listas - Mostrar indicadores de posição de reprodução em listas + Posições em listas + Mostrar indicadores de posição de reprodução nas listas Limpar dados Posições de reprodução removidas Ficheiro movido ou eliminado @@ -406,20 +406,20 @@ não é possível sobrescrever o ficheiro Existe uma descarga pendente com este nome NewPipe foi fechado enquanto trabalhava no ficheiro - Não há espaço livre no aparelho + Não há espaço livre no dispositivo Progresso perdido, o ficheiro foi eliminado Ligação expirada Deseja limpar o histórico de descargas ou remover todos os ficheiros descarregados\? Limitar fila de descargas - Uma descarga será executada ao mesmo tempo + Permitir apenas uma descarga de cada vez Iniciar transferências Pausa nas transferências Perguntar para onde transferir Ser-lhe-á perguntado onde guardar cada transferência. \nAtive o seletor de pastas do sistema (SAF) se quiser transferir para um cartão SD externo - Usar o seletor de pastas do sistema (SAF) + Utilizar seletor de pastas do sistema (SAF) \'Storage Access Framework\' permite transferências para um cartão SD externo - Remover posições de reprodução + Limpar posições de reprodução Remove todas as posições de reprodução Remover todas as posições de reprodução\? Alternar serviço, agora selecionado: @@ -573,7 +573,7 @@ Limpar cookies reCAPTCHA O YouTube fornece um \"Modo restrito\" que oculta o conteúdo destinado a adultos Mostrar conteúdo possivelmente impróprio para crianças porque tem um limite de idade (como 18+) - Fazer com que o Android personalize a cor da notificação conforme a cor principal na miniatura (esta opção não está disponível em todos os aparelhos) + Fazer com que o Android personalize a cor da notificação conforme a cor principal na miniatura (esta opção não está disponível em todos os dispositivos) Colorir notificação Usar miniaturas no fundo do ecrã de bloqueio e em notificações Mostrar miniatura @@ -605,8 +605,8 @@ Escolha o seu tema escuro favorito — %s Descarga iniciada Pode escolher o seu tema escuro favorito abaixo - Automático (Tema do aparelho) - Tema Escuro + Automático (Tema do dispositivo) + Tema escuro Mostrar detalhes do canal Desative esta opção se estiverem a ocorrer erros de ecrã escuro ou paragens durante a reprodução Desativar túnel multimédia @@ -622,8 +622,8 @@ Não foi possível carregar o feed para \'%s\'. Erro ao carregar o feed A partir do Android 10, apenas o \'Storage Access Framework\' é compatível - O \'Storage Access Framework\' não é compatível com Android KitKat e versões anteriores - Pré-visualização da miniatura da barra de busca + \'Storage Access Framework\' não é compatível com Android KitKat e versões anteriores + Pré-visualização da miniatura da barra de pesquisa Marcar como visto Desligado Ligado @@ -665,8 +665,8 @@ %s descargas concluídas Deslizar itens para removê-los - Não iniciar vídeos no reprodutor mini, mas ir diretamente ao modo de ecrã cheio, se a rotação automática estiver bloqueada. Ainda pode acessar o reprodutor mini por sair do modo de ecrã cheio - Iniciar o reprodutor principal em ecrã cheio + Não iniciar vídeos no reprodutor mini, mas ir diretamente para ecrã completo se a rotação automática estiver bloqueada. Ainda pode aceder o reprodutor mini se sair do modo de ecrã completo. + Iniciar reprodutor principal em ecrã completo Enfileirado o próximo Enfileirar o próximo \ No newline at end of file diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 2ed8891c7..c1a8e784f 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -37,17 +37,17 @@ Aspect Redare în fundal Conținut - Arată conținutul restricționat în funcție de vârstă + Afișați conținutul restricționat de vârstă Eroare Eroare de rețea - Nu s-au putut încărca toate thumbnail-urile - Nu s-a putut decripta semnătura URL a videoclipului - Nu s-a putut analiza website-ul + Nu s-au putut încărca toate miniaturile + Nu s-a putut deobfusca semnătura URL-ului video + Nu s-a putut analiza site-ul web Conținut indisponibil - Imposibil de inițializat meniul pentru descărcări - Thumbnail-ul videoclipului - Redare videoclip, durată: - Thumbnail-ul avatarului autorului + Nu s-a putut configura meniul de descărcare + Miniatura de previzualizare video + Redare video, durata: + Miniatura avatarului autorului Au apreciat Nu au apreciat Apăsați pe lupă pentru a începe. @@ -55,46 +55,46 @@ Descărcări Descărcări Raport de erori - Scuze, asta n-ar fi trebui să se întâmple. - Raportează această eroare prin e-mail - Scuze, ceva nu a mers bine. + Ne pare rău, asta nu trebuia să se întâmple. + Raportați această eroare prin e-mail + Ne pare rău, ceva a mers prost. Raportați Informații: Ce s-a întâmplat: - Comentariul tău (în engleză): + Comentariul dvs. (în engleză): Detalii: Video Audio - Reîncearcă + Reîncercare Start Pauză - Șterge + Ștergeți Suma de control OK Numele fișierului - Thread-uri + Fire Eroare - NewPipe Descarcă - Apasă pentru detalii + NewPipe descarcă + Atingeți pentru detalii Vă rugăm așteptați… Copiat în clipboard - Definiți un dosar de descărcare mai târziu în setări - Deschide in modul popup + Vă rugăm să definiți un folder de descărcare mai târziu în setări + Deschide în modul popup Această permisiune este necesară pentru a \ndeschide în mod pop-up Provocare reCAPTCHA - reCAPTCHA nouă cerută + Provocare reCAPTCHA solicitată Rezoluția implicită a ferestrei pop-up Afișează rezoluții mai mari Doar anumite dispozitive suportă redarea videoclipurilor 2K/4K Format video implicit Negru Redare în mod pop-up - Tot + Toate Da Dezactivat - App/UI eroare - Ce:\\nRequest:\\nContent Language:\\nContent Country:\\nApp Language:\\nService:\\nGMT Time:\\nPackage:\\nVersion:\\nOS version: + Aplicația/UI s-a oprit + Ce:\\nSolicitare:\\nLimba conținutului:\\nȚara conținutului:\\nLimba aplicației:\\nServiciu:\\nOra GMT:\\nPachet:\\nVersiune: \\nVersiune OS: k mil. mld. @@ -103,9 +103,9 @@ Pop-up Reține dimensiunea și poziția pop-up-ului Reține ultima dimensiune și poziție a pop-up-ului - Arată sugestii - Arată sugestii în timpul căutării - Curăță + Sugestii de căutare + Alegeți sugestiile care vor fi afișate la căutare + Ștergeți Rezoluție maximă Abonează-te Abonat(ă) @@ -116,40 +116,40 @@ Ce este nou Istoric de căutări Stochează local căutările - Istoric vizualizări + Istoricul vizionărilor Reține videoclipurile vizionate Reluați redarea Continuă redarea după întreruperi (ex: după apeluri) Player Comportament Istoric și cache - Anulează + Anulare Notificare NewPipe - Notificări pentru playere de fundal și pop-up + Notificări pentru playerele de fundal și popup NewPipe Fără rezultate Nimic aici în afară de sunetul greierilor - Niciun abonat + Fără abonați %s abonat %s abonați - %s abonați + %s de abonați Nicio vizionare %s vizionare %s vizionări - %s vizionări + %s de vizionări - Niciun videoclip + Nu există videoclipuri %s videoclip %s videoclipuri %s de videoclipuri - Descarcă + Descărcați Caractere permise în numele fișierelor - Caracterele invalide sunt înlocuite cu această valoare - Caracter înlocuitor + Caracterele nevalabile sunt înlocuite cu această valoare + Caracter de înlocuire Litere și cifre Caracterele cele mai speciale Despre NewPipe @@ -160,29 +160,29 @@ Un player de streaming „uşor” liber, pentru Android. Vedeți pe GitHub Licența NewPipe - Dacă aveți idei, doriți să traduceți, să schimbați design-ul, să curățați codul sau să schimbați codul, ajutorul este mereu bine primit. Cu cât mai mult, cu atât mai bine! + Fie că aveți idei de: traducere, modificări de design, curățare a codului sau modificări de cod cu adevărat importante - ajutorul este întotdeauna binevenit. Cu cât se face mai mult, cu atât mai bine devine! Citiți licența - Contribuie + Contribuiți Istoric Istoric Doriți să ștergeți acest element din istoricul de căutare? Conținutul pagini principale Pagină Goală - Pagină Chioșc + Pagina de chioșc Pagină Canale Alegeți un canal Nu v-ați abonat la niciun canal deocamdată Alegeți un chioșc - Trenduri + Tendințe Top 50 - Tendințe + Noi și populare Niciun player pentru streaming găsit. (Totuși, puteți instala VLC). Descărcați fișierul de vizionat Arată informații Playlist-uri salvate Salvează în - Folosește parcurgerea inexactă - Derularea inexactă permite player-ului să deruleze mai rapid, cu o precizie redusă. Derularea timp de 5, 15 sau 25 de secunde nu funcționează cu aceasta. + Folosește parcurgerea rapidă inexactă + Derularea inexactă permite player-ului să deruleze mai rapid, cu o precizie redusă. Derularea timp de 5, 15 sau 25 de secunde nu funcționează cu aceasta Încarcă miniaturi Dezactivați pentru a preveni încărcarea miniaturilor, economisirea datelor și utilizarea memoriei. Modificările șterg atât memoria cache a imaginilor în memorie, cât și pe disc Datele cache de imagini au fost șterse @@ -191,64 +191,64 @@ Cache pentru metadata șters Adaugă următorul stream în coadă automat Continuă coadă de redare (care nu se repetă) prin adăugarea unui flux asemănător - Arată sfatul „Țineți apăsat pentru a adăuga” - Arată un sfat când apeși butonul de redare în fundal sau de popup în secțiunea video \"Detalii\" + Afișați sfatul \"Țineți apăsat pentru a adăuga\" + Afișați un sfat la apăsarea fundalului sau a butonului popup în videoclipul \"Detalii:\" Țara implicită pentru conținut - Debug - Redă Tot + Depanare + Redă toate Întotdeauna - Doar Odată + Doar o dată Fișier [Necunoscut] - Schimbă pe Modul fundal - Schimbă pe modul popup - Schimbă pe modul principal - Importează baza de date - Exportează baza de date - Înlocuiește istoric, abonamente curente, playlisturi și (opțional setări) + Treceți la fundal + Treceți la Popup + Treceți la principal + Importați baza de date + Exportați baza de date + Suprascrie istoricul, abonamentele, listele de redare și (opțional) setările curente Exportează istoricul, abonamentele, playlist-urile și setările - Nu s-a putut reda acest stream - A apărut o eroare de player irecuperabilă - Recuperare după eroare player - Playerele externe nu suportă acest tip de link-uri + Nu a putut reda acest flux + A apărut o eroare irecuperabilă a player-ului + Se recuperează din eroarea player-ului + Player-ele externi nu acceptă aceste tipuri de linkuri Niciun stream video găsit Niciun stream audio găsit Director Invalid - Nu există acest fișier ori sursă - Fișierul nu există, sau nu dețineți suficiente permisiuni pentru a îl citi sau scrie + Nu există un astfel de fișier/conținut sursă + Fișierul nu există sau lipsește permisiunea de a citi sau scrie în el Numele fișierului nu poate fi gol - O eroare a apărut: %1$s - NewPipe este dezvoltat de voluntari care își petrec timpul liber aducându-vă cea mai bună experiență de utilizare. Dați înapoi pentru a ajuta dezvoltatorii să facă NewPipe mai bun în timp ce se bucură de o cafea. - A da înapoi - Site-ul - Vizitaţi site-ul nostru pentru mai multe informaţi şi ultimele ştiri despre NewPipe. + A survenit o eroare: %1$s + NewPipe este dezvoltat de voluntari care își petrec timpul liber pentru a vă oferi cea mai bună experiență de utilizare. Donează pentru a ajuta dezvoltatorii să facă NewPipe și mai bun în timp ce ei se bucură de o ceașcă de cafea. + Dăruiește înapoi + Site web + Vizitați site-ul NewPipe pentru mai multe informații și noutăți. Ultimele vizionări Cele mai multe vizionări Exportat Importat - Nici-un fişier ZIP valid - Avertisment: Nu se pot importa fişierele. - Acest lucru o să vă reseteze setup-ul curent. - Şterge + Nici un fișier ZIP valid + Avertisment: Nu s-au putut importa toate fișierele. + Acest lucru va anula configurația curentă. + Eliminați Detalii Setări Audio - Apăsaţi pentru a adăuga în lista de redare - Începe redarea în fundal + Apăsaţi pentru a adăuga în coadă + Începeți redarea în fundal Începeți redarea în popup Deschdeţi sertarul Închideţi sertarul Opţiunea de deschidere preferată - Opţiunea prestabilită când se deschide contentul -%s + Acțiune implicită la deschiderea conținutului - %s Player Video Player Fundal Player Popup - Întreabă întotdeauna - Niciun stream disponbil pentru descărcare + Întrebați întotdeauna + Nu există fluxuri disponibile pentru descărcare Trageţi pentru a reordona - Crează - Ignoraţi + Creați + Respingeți Redenumiţi - Nicio aplicație instalată nu poate reda acest fişier + Nici o aplicație instalată pentru a reda acest fișier Donaţi De asemenea, doriți să importați setări? Nume @@ -259,111 +259,111 @@ Controlul vitezei de redare Canale Utilizatori - Playlist-uri + Liste de redare Titluri - Șterge istoricul vizionărilor - Șterge istoricul stream-urilor redate și pozițiile memorate - Șterge întregul istoric al vizionărilor\? + Ștergeți istoricul vizionărilor + Șterge istoricul fluxurilor redate și pozițiile de redare + Ștergeți întregul istoric al vizionărilor\? 1 element șters. Playlist nou Adăugați la playlist - Importă - Importă din - Exportă spre + Importare + Importați din + Exportați în Se importă… Se exportă… - Ultimul export + Export anterior Nu s-au putut importa abonamentele Nu s-au putut exporta abonamentele Viteză - Acceptă - Refuză + Acceptați + Refuzați Dezabonează-te Alegeți fila - Gesturi control volum - Utilizează gesturi pentru controlul volumului - Gesturi control strălucire - Utilizează gesturi pentru controlul luminozități + Controlul prin gesturi al volumului + Utilizați gesturi pentru a controla volumul + Controlul prin gesturi a luminozității + Utilizați gesturi pentru a controla luminozitatea Actualizări Evenimente Fișier șters - Notificare actualizare aplicație + Notificare de actualizare a aplicației Notificări pentru noi versiuni NewPipe - Afișare istoric șters. - Șterge istoric căutare - Ștergere istoric căutare cuvinte cheie - Șterge întregul istoric căutare\? - Istoric căutare șters. + Istoricul de vizionări a fost șters + Ștergeți istoricul căutărilor + Șterge istoricul cuvintelor cheie de căutare + Ștergeți întregul istoric de căutare\? + Istoric de căutare șters Stocare externă indisponibilă - Descărcarea pe cardul SD extern nu este posibilă. Se resetează locația directorului de descărcări\? + Descărcarea pe cardul SD extern nu este posibilă. Resetați locația folderului de descărcare\? Se obțin informații… Se încarcă conținutul solicitat Redenumiți - Setați ca miniatură playlistului - Ștergeți acest playlist\? - Miniatura playlist-ului a fost schimbată. + Setați ca miniatura listei de redare + Ștergeți această listă de redare\? + Miniatura listei de redare a fost schimbată. Fără subtitrări Potrivire Umplere - Mărește + Mărire Subtitrări - Modifică mărimea textului și stilurilor de fundal ale subtitrărilor. Necesită repornirea aplicației pentru a intra în vigoare. - NewPipe este un software copyleft gratuit: îl puteți utiliza, studia, distribui și îl puteți îmbunătăți după bunul plac. În mod special, îl puteți redistribui și/sau modifica în condițiile Licenței publice generale GNU, publicată de Free Software Foundation, fie versiunea 3 a Licenței, fie (la opțiunea dvs.) orice versiune ulterioară. + Modificați scara textului de legendă a playerului și stilurile de fundal. Necesită repornirea aplicației pentru a intra în vigoare + NewPipe este un software liber cu copyleft: îl puteți folosi, studia, partaja și îmbunătăți în voie. Mai exact, îl puteți redistribui și/sau modifica în conformitate cu termenii Licenței Publice Generale GNU, așa cum a fost publicată de Free Software Foundation, fie versiunea 3 a Licenței, fie (la alegerea dumneavoastră) orice versiune ulterioară. Politica de confidențialitate a NewPipe - Proiectul NewPipe ia confidențialitatea în serios. Prin urmare, aplicația nu colectează date fără consimțământul dumneavoastră. -\nPolitica de confidențialitate a NewPipe explică în detaliu ce date sunt trimise și stocate atunci când trimiteți un raport de avarie. - Citește politica de confidențialitate - Nu se pot citi filele salvate, se folosesc filele implicite - Restaurează valorile implicite + Proiectul NewPipe ia foarte în serios confidențialitatea dumneavoastră. Prin urmare, aplicația nu colectează niciun fel de date fără consimțământul dumneavoastră. +\nPolitica de confidențialitate a NewPipe explică în detaliu ce date sunt trimise și stocate atunci când trimiteți un raport de eroare. + Citiți politica de confidențialitate + Nu s-au putut citi filele salvate, deci se folosesc cele implicite + Restaurați valorile implicite Doriți să restaurați valorile implicite\? - Numărul abonaților nu este disponibil + Numărul de abonați nu este disponibil Ce file vor fi afișate pe pagina principală Conferințe Arată comentariile Dezactivează pentru oprirea afișării comentariilor Redare automată - Niciun comentariu + Fără comentarii Nu s-au putut încărca comentariile Reluare redare - Se restabilește ultima poziție de redare + Restabilirea ultimei poziții de redare Poziții în liste Afișează indicatorii de poziție de redare în liste - Eliminare date - Pozițiile de redare șterse. + Ștergeți datele + Poziții de redare șterse Fișier mutat sau șters Șterge pozițiile de redare memorate - Salvează playlist-ul - Limitați rezoluția când folosiți date mobile - Acordă permisiunea de a afișa peste alte aplicații + Marcați lista de redare + Limitați rezoluția atunci când utilizați date mobile + Acordați permisiunea de a afișa peste alte aplicații Ștergeți toate pozițiile din playback\? - Șterge toate pozițiile din playback + Ștergeți toate pozițiile de redare Videoclipuri Instanța există deja - Doar adresele URL HTTPS sunt suportate - Nu sa putut valida instanța - Introdu adresa URL a instanței - Adaugă instanță - Găsește instanța care îți place în %s - Selectează instanța preferată PeerTube + Sunt acceptate numai URL-urile HTTPS + Nu s-a putut valida instanța + Introduceți URL-ul instanței + Adăugați o instanță + Găsiți instanțele care vă plac pe %s + Selectați instanțele PeerTube preferate Instanțe PeerTube Durată derulare rapidă înainte/înapoi Gata - Apăsați \"Gata\" când ați terminat - Raportează pe Github + Apăsați \"Gata\" după ce ați rezolvat problema + Raportați pe GitHub Ajutor - Ștergeți modulele cookie pe care NewPipe le stochează atunci când rezolvați o reCAPTCHA + Ștergeți cookie-urile pe care NewPipe le stochează atunci când rezolvați un reCAPTCHA Cookie-urile reCAPTCHA au fost șterse Ștergeți cookie-urile reCAPTCHA Notificări pentru progresul hashing-ului video - Notificare hash video + Notificare video Hash Artiști Albume Melodii Acest videoclip este restricționat în funcție de vârstă. \n -\nActivați „%1$s” în setări dacă doriți să îl vedeți. - YouTube oferă un „Mod restricționat” care ascunde conținut potențial matur - Activează \"Mod restricționat\" de pe YouTube +\nActivați \"%1$s\" în setări dacă doriți să îl vedeți. + YouTube oferă un \"Mod restricționat\" care ascunde conținutul potențial matur + Activați \"Modul restricționat\" de pe YouTube Afișați conținut posibil nepotrivit pentru copii, deoarece are o limită de vârstă (cum ar fi 18+) Notificare Adresa URL nu a putut fi recunoscută. Deschideți cu o altă aplicație\? @@ -384,35 +384,35 @@ Scalați miniatura video afișată în notificare de la raportul de aspect 16:9 la 1:1 (poate introduce distorsiuni) Scalare miniatură la raport aspect 1:1 Se arată rezultate pentru:%s - Nicio aplicație de pe dispozitiv nu poate deschide această + Nicio aplicație de pe dispozitivul dvs. nu poate deschide acesta Capitole Recente Utilizați miniatura atât pentru fundalul ecranului de blocare, cât și pentru notificări - Arată thumbnail-urile - Pagina Playlist-ului + Afișați miniatura + Pagina listei de redare De %s Creat de %s - Miniatura thumbnail-ului canalului + Miniatura de avatar a canalului Acest conținut nu este încă acceptat de NewPipe. \n \nSperăm că va fi acceptat într-o versiune viitoare. - Crezi că încărcarea feedului este prea lentă\? Dacă da, încercați să activați încărcarea rapidă (o puteți modifica în setări sau apăsând butonul de mai jos). + Credeți că încărcarea fluxului este prea lentă\? Dacă da, încercați să activați încărcarea rapidă (puteți schimba acest lucru în setări sau apăsând butonul de mai jos). \n -\nNewPipe oferă două strategii de încărcare a feedului: +\nNewPipe oferă două strategii de încărcare a fluxului: \n• Preluarea întregului canal de abonament, care este lent, dar complet. \n• Utilizarea unui punct final de serviciu dedicat, care este rapid, dar de obicei nu este complet. \n -\nDiferența dintre cele două este că cea rapidă de obicei nu are informații, cum ar fi durata sau tipul articolului (nu poate face distincția între videoclipurile live și cele normale) și poate returna mai puține articole. +\nDiferența dintre cele două este că în cazul celei rapide lipsesc de obicei unele informații, cum ar fi durata sau tipul articolului (nu poate face distincția între videoclipurile live și cele normale) și poate returna mai puține articole. \n -\nYouTube este un exemplu de serviciu care oferă această metodă rapidă cu fluxul său RSS. +\nYouTube este un exemplu de serviciu care oferă această metodă rapidă prin intermediul fluxului său RSS. \n -\nAșadar, alegerea se reduce la ceea ce preferați: viteză sau informații precise. +\nAșadar, alegerea se reduce la ceea ce preferați: rapiditate sau informații precise. Dezactivați modul rapid Activați modul rapid - Disponibil în unele servicii, este de obicei mult mai rapid, dar poate returna o cantitate limitată de elemente și informații adesea incomplete (de exemplu, fără durată, tip de articol, fără stare live). + Disponibilă în unele servicii, este, de obicei, mult mai rapidă, dar poate returna un număr limitat de articole și adesea informații incomplete (de exemplu, fără durată, fără tipul de articol, fără stare în direct) Preluare din fluxul dedicat atunci când este disponibil Actualizați întotdeauna - Timpul după ultima actualizare înainte ca un abonament să fie considerat învechit - %s + Timpul de la ultima actualizare înainte ca un abonament să fie considerat învechit - %s Prag de actualizare a fluxului Flux Se afișează numai abonamentele negrupate @@ -434,36 +434,36 @@ %d zi %d zile - %d zile + %d de zile %d oră %d ore - %d ore + %d de ore %d secundă %d secunde - %d secunde + %d de secunde Datorită constrângerilor ExoPlayer, durata de căutare a fost setată la %d secunde Da, și videoclipuri vizionate parțial - Videoclipurile care au fost vizionate înainte și după ce au fost adăugate în lista de redare vor fi eliminate. -\neşti sigur\? Acest lucru nu poate fi anulat! + Videoclipurile care au fost vizionate înainte și după ce au fost adăugate la lista de redare vor fi eliminate. +\nSunteți sigur\? Acest lucru nu poate fi anulat! Eliminați videoclipurile vizionate\? Eliminare cele urmărite Prestabilită de sistem Limba aplicației Alegeți o instanță - \"Storage Access Framework\" permite descărcări pe un card SD extern. -\nUnele dispozitive sunt incompatibile - Folosiți SAF - Veți fi întrebat unde să salvați fiecare descărcare + \"Storage Access Framework\" permite descărcări pe un card SD extern + Utilizați selectorul de dosare de sistem (SAF) + Veți fi întrebat unde să salvați fiecare descărcare. +\nActivați selectorul de foldere de sistem (SAF) dacă doriți să descărcați pe un card SD extern Întrebați unde să descărcați Întrerupeți descărcările - Reîncercări maxime - Afișarea timpului inițial în urmă pentru elemente - Raportarea forțată a excepțiilor Rx nelivrabile în afara ciclului de viață al fragmentului sau al activității după eliminare + Numărul maxim de încercări + Afișați timpul inițial pe articole + Forțarea raportării excepțiilor de Rx nedistribuibile în afara ciclului de viață al fragmentului sau al activității după eliminare Coadă automată Coada de redare activă va fi înlocuită Trecerea de la un player la altul vă poate înlocui coada de redare @@ -471,16 +471,16 @@ %d minut %d minute - %d minute + %d de minute Începeți descărcările O descărcare va rula în același timp Limitarea cozii de descărcare Închideți - Util la trecerea la date mobile, deși unele descărcări nu pot fi suspendate + Util atunci când treceți la date mobile, deși unele descărcări nu pot fi suspendate Întrerupeți pe rețelele măsurate - Numărul maxim de încercări înainte de anularea descărcării - Oprește + Numărul maxim de încercări înainte de a anula descărcarea + Opriți Ștergeți fișierele descărcate Doriți să ștergeți istoricul descărcărilor sau să ștergeți toate fișierele descărcate\? Șterge istoricul descărcărilor @@ -490,15 +490,15 @@ Nu a mai rămas spațiu pe dispozitiv NewPipe a fost închis în timp ce lucra la fișier Post-procesarea a eșuat - Nu s-a găsit - Serverul nu acceptă descărcări multi-threaded, reîncercați cu @string/msg_threads = 1 + Nu a fost găsit + Serverul nu acceptă descărcări cu mai multe fire, încercați din nou cu @string/msg_threads = 1 Serverul nu trimite date Nu se poate conecta la server Nu s-a putut găsi server-ul Nu s-a putut stabili o conexiune sigură Folderul de destinație nu poate fi creat Fișierul nu poate fi creat - Afișare eroare + Afișați eroarea Există o descărcare în așteptare cu acest nume Există o descărcare în curs cu acest nume nu poate suprascrie fișierul @@ -508,7 +508,7 @@ Generați un nume unic Descărcare eșuată Acțiune refuzată de sistem - Fila de așteptare + Coadă Se recuperează post-procesare În așteptare @@ -516,62 +516,63 @@ În așteptare Finalizat Atingeți pentru a descărca - Actualizare a Newpipe este disponibilă! + Actualizare NewPipe disponibilă! Automat Grilă Listă Mod vizualizare listă Niciodată Numai pe Wi-Fi - Porniți redarea automat - %s - Minimizare la pop-up player + Începeți automat redarea - %s + Minimizare la playerul popup Minimizați la playerul de fundal - Niciunul - Acțiune când comutați la altă aplicație de pe playerul video principal — %s + Niciuna + Acțiune la trecerea la altă aplicație de la playerul video principal - %s Minimalizați la comutarea aplicației Afișați o notificare pentru a solicita actualizarea aplicației atunci când este disponibilă o nouă versiune Actualizări Fără limită - Pentru a respecta Regulamentul general european privind protecția datelor (GDPR), vă atragem atenția asupra politicii de confidențialitate a NewPipe. Vă rugăm să-l citiți cu atenție. -\nTrebuie să îl acceptați pentru a ne trimite raportul de eroare. - Resetează + Pentru a respecta Regulamentul general european privind protecția datelor (GDPR), vă atragem atenția asupra politicii de confidențialitate a NewPipe. Vă rugăm să o citiți cu atenție. +\nTrebuie să o acceptați pentru a ne trimite raportul de eroare. + Resetare Etapă - Înaintează rapid în timpul tăcerii + Înaintare rapidă în timpul tăcerii Decuplați (poate provoca distorsiuni) - Ton + Înălțime Rețineți că această operațiune poate fi costisitoare în rețea. \n \nContinuați\? ID-ul dvs., soundcloud.com/yourid - Importați un profil SoundCloud tastând fie adresa URL, fie ID-ul dvs.: + Importați un profil SoundCloud introducând fie URL-ul, fie ID-ul dvs: \n -\n1. Activați „modul desktop” într-un browser web (site-ul nu este disponibil pentru dispozitivele mobile) -\n2. Accesați această adresă URL: %1$s -\n3. Conectați-vă când vi se solicită -\n4. Copiați adresa URL a profilului către care ați fost redirecționat. - Importați abonamente YouTube de la Google Takeout: +\n1. Activați \"modul desktop\" într-un browser web (site-ul nu este disponibil pentru dispozitive mobile) +\n2. Mergeți la acest URL: %1$s +\n3. Conectați-vă atunci când vi se cere +\n4. Copiați URL-ul profilului la care ați fost redirecționat. + Importați abonamentele YouTube din Google takeout: \n -\n1. Accesați această adresă URL: %1$s -\n2. Conectați-vă când vi se solicită -\n3. Faceți clic pe „Toate datele incluse”, apoi pe „Deselectați toate”, apoi selectați doar „abonamente” și faceți clic pe „OK” -\n4. Faceți clic pe „Pasul următor” și apoi pe „Creați export” -\n5. Faceți clic pe butonul „Descărcați” după ce apare și -\n6. Din fișierul zip Takeout descărcat extrageți fișierul .json (de obicei sub „YouTube și YouTube Music / subscriptions / subscriptions.json”) și importați-l aici. - Textele originale de la servicii vor fi vizibile în elementele de flux +\n1. Mergeți la această adresă URL: %1$s +\n2. Autentificați-vă atunci când vi se cere +\n3. Faceți clic pe \"Toate datele incluse\", apoi pe \"Deselectați totul\", apoi selectați doar \"Abonamente\" și faceți clic pe \"OK\" +\n4. Faceți clic pe \"Pasul următor\" și apoi pe \"Creați exportul\" +\n5. Faceți clic pe butonul \"Descărcare\" după ce acesta apare +\n6. Faceți clic pe IMPORT FIȘIER de mai jos și selectați fișierul zip descărcat +\n7. [În cazul în care importul zip eșuează] Extrageți fișierul .csv (de obicei sub \"YouTube and YouTube Music/subscriptions/subscriptions.csv\"), faceți clic pe IMPORT FIȘIER de mai jos și selectați fișierul csv extras + Textele originale din servicii vor fi vizibile în elementele de flux Raportați erori în afara ciclului de viață Afișați scurgeri de memorie - Monitorizarea scurgerilor de memorie poate face ca aplicația să nu mai răspundă la descărcarea heap-ului - Generat automat (nu s-a găsit niciun uploader) + Monitorizarea scurgerilor de memorie poate face ca aplicația să nu mai răspundă atunci când se face heap dumping + Generat automat (nu a fost găsit niciun uploader) Eliminați marcajul Activați sunetul Dezactivați sunetul - Adăugat în lista de redare - Adăugați în lista de redare - Rulați lista de redare + Pus în coadă + Puneți în coadă + Coadă de redare Cele mai apreciate Adăugate recent Local - Limba se va schimba odată cu repornirea aplicației. + Limba se va schimba odată ce aplicația este repornită Nu există încă marcaje în playlist Selectați un playlist Chioșc implicit @@ -579,33 +580,33 @@ ∞ videoclipuri Peste 100 de videoclipuri - %s auditor - %s auditori - %s auditori + %s ascultător + %s ascultători + %s de ascultători Nimeni nu ascultă - %s privește - %s privesc - %s privesc + %s vizionează + %s vizionează + %s vizionează Nimeni nu se uită Comutare serviciu, selectat în prezent: Descriere - Fluxuri corelate + Articole similare Comentarii - Vă rugăm să verificați dacă există deja o problemă legată de crash-ul dvs. Când creați bilete duplicat, ne luați timp pe care l-am putea petrece cu remedierea erorii. + Vă rugăm să verificați dacă nu există deja o problemă în care se discută despre eroarea dumneavoastră. Atunci când creați tichete duplicate, ne consumați timp pe care l-am putea dedica rezolvării problemei actuale. Copiați raportul formatat Dezactivați pentru a ascunde casetele de informații meta cu informații suplimentare despre creatorul fluxului, conținutul fluxului sau o cerere de căutare Dezactivați pentru a ascunde descrierea videoclipului și informațiile suplimentare Arată descrierea Deschideți cu Blocați aplicația - Rezolvează - În evidență + Rezolvați + Evidențiate Puteți selecta tema de noapte preferată mai jos Acest videoclip este restricționat în funcție de vârstă. -\nDin cauza noilor politicile YouTube privind videoclipurile cu restricție de vârstă, NewPipe nu poate accesa niciunul dintre fluxurile sale video și, astfel, nu îl poate reda. +\nDin cauza noilor politici YouTube privind videoclipurile cu restricții de vârstă, NewPipe nu poate accesa niciunul dintre fluxurile sale video și, prin urmare, nu îl poate reda. Descărcarea a început Selectați tema de noapte preferată — %s Automat (tema dispozitivului) @@ -613,8 +614,71 @@ Acest conținut este disponibil doar pentru utilizatorii care au plătit, ca atare nu poate fi difuzat sau descărcat de NewPipe. Acest videoclip este disponibil doar pentru membrii YouTube Music Premium, ca atare nu poate fi difuzat sau descărcat de NewPipe. Acest conținut este privat, ca atare nu poate fi difuzat sau descărcat de NewPipe. - Aceasta este o piesă SoundCloud Go+, cel puțin în țara ta, ca atare nu poate fi difuzată sau descărcată de NewPipe. + Aceasta este o piesă SoundCloud Go+, cel puțin în țara ta, deci nu poate fi difuzată sau descărcată de NewPipe. Acest conținut nu este disponibil în țara dumneavoastră. - Arată detaliile canalului + Afișați detaliile canalului Temă Nocturnă + Următorul pus în coadă + Adăugați în coadă pe următorul + Marcare ca vizionat + Încărcare Detalii canal… + Eroare la Afișare detalii canal + Oprit + Pornit + Mod tabletă + Deschideți site-ul web + Inimă de la creator + Intern + Privat + Nelistat + Public + URL miniatură + Gazdă + Sprijin + Limbă + Limita de vârstă + Vizibilitate + Liciență + Etichete + Categorie + Dezactivați selectarea textului în descriere + Activați selectarea textului în descriere + Acum puteți selecta text în interiorul descrierii. Rețineți că este posibil ca pagina să pâlpâie, iar link-urile să nu poată fi accesate în modul de selecție. + %s oferă acest motiv: + Contul a fost închis + Afișați elementele vizionate + Modul rapid nu furnizează mai multe informații în acest sens. + Contul autorului a fost închis. +\nNewPipe nu va mai putea încărca acest flux în viitor. +\nDoriți să vă dezabonați de la acest canal\? + Nu s-a putut încărca fluxul pentru \"%s\". + Eroare la încărcarea fluxului + Începând cu Android 10, este acceptat doar \"Storage Access Framework\" + \"Storage Access Framework\" nu este acceptat pe Android KitKat și versiunile ulterioare + Veți fi întrebat unde să salvați fiecare descărcare + + S-a șters %1$s descărcare + S-au șters %1$s descărcări + S-au șters %1$s de descărcări + + + Descărcare finalizată + %s descărcări finalizate + %s de descărcări finalizate + + Dezactivați tunelarea media + Glisați elementele pentru a le elimina + Încă nu este setat niciun folder de descărcare, alegeți acum folderul de descărcare implicit + Comentariile sunt dezactivate + Nu porniți videoclipurile în mini player, ci treceți direct la modul ecran complet, dacă rotația automată este blocată. Puteți accesa în continuare mini playerul ieșind din modul fullscreen + Porniți playerul principal în ecran complet + Sugestii de căutare la distanță + Sugestii de căutare locală + Nu afișa + Calitate scăzută (mai mică) + Calitate înaltă (mai mare) + Miniatură de previzualizare în bara de derulare + Afișați panglici colorate de Picasso deasupra imaginilor, indicând sursa acestora: roșu pentru rețea, albastru pentru disc și verde pentru memorie + Afișați indicatorii de imagine + Dezactivați tunelarea media dacă întâmpinați un ecran negru sau blocaje la redarea video \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 41c0ac36d..f895cea27 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -238,7 +238,7 @@ Произошла ошибка: %1$s Перетащите, чтобы изменить порядок Создать - Отклонить + Скрыть Переименовать Недавно проигранные Часто проигрываемые @@ -664,7 +664,7 @@ Пометить как проигранные Не удалось отобразить сведения о канале Загрузка сведений о канале… - Picasso: указать цветом источник изображений (красный - сеть, синий - диск, зелёный - память) + Picasso: указать цветом источник изображений (красный — сеть, синий — диск, зелёный — память) Цветные метки на изображениях Серверные предложения поиска Локальные предложения поиска @@ -683,4 +683,6 @@ Удалять элементы смахиванием Запускать видео во весь экран, если отключён автоповорот. Мини-плеер доступен при выходе из полноэкранного режима Начинать просмотр в полноэкранном режиме + Добавлено следующим + Добавить следующим \ No newline at end of file diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index 0f5fd4bdf..95ba064a5 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -667,4 +667,6 @@ Trìsina sos elementos pro los bogare Si sa rotatzione automàtica est blocada no avies sos vìdeos in su riproduidore mini ma diretamente in sa modalidade a ischermu intreu. Podes atzèdere su matessi a su riproduidore mini essende dae s\'ischermu intreu Allughe su letore printzipale a ischermu intreu + Postu in lista comente imbeniente + Pone in lista comente imbeniente \ No newline at end of file diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index fcb37456c..f802302ab 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -667,4 +667,6 @@ Ögeleri kaldırmak için kaydır Videoları küçük oynatıcıda başlatma, kendiliğinden döndürme kilitliyse doğrudan tam ekran kipine geç. Tam ekrandan çıkarak küçük oynatıcıya erişmeye devam edebilirsiniz Ana oynatıcıyı tam ekranda başlat + Sonrakini sıraya ekle + Sonraki sıraya eklendi \ No newline at end of file diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index f658900aa..83aea33c0 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -654,4 +654,6 @@ Vuốt các mục để xóa chúng Không bắt đầu video ở trình phát mini, mà chuyển trực tiếp thành chế độ toàn màn hình, nếu tự động xoay bị khóa. Bạn vẫn có thể truy cập trình phát mini bằng cách thoát khỏi toàn màn hình Khởi động trình phát chính ở toàn màn hình + Đã cho mục tiếp vào hàng đợi + Cho mục tiếp vào hàng đợi \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 3c7e39409..576f9d480 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -655,4 +655,6 @@ 滑動項目以刪除它們 如果自動旋轉被鎖定,請不要在迷你播放器中啟動影片,而是直接切換到全螢幕模式。您仍然可以透過結束全螢幕存取迷你播放器 以全螢幕開始主播放器 + 已將下一個加入佇列 + 將下一個加入佇列 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2c0e25bb0..225ccd126 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -416,6 +416,8 @@ Show channel details Enqueue Enqueued + Enqueue next + Enqueued next Start playing in the background Start playing in a popup @@ -701,4 +703,4 @@ Error at Show Channel Details Loading Channel Details… - \ No newline at end of file + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 95368b572..7c1265580 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -16,7 +16,6 @@ @color/white @style/FloatingActionButtonTheme @color/white - @style/PreferenceThemeOverlay.v14.Material ?attr/colorPrimary